We have moved to a new Sailfish OS Forum. Please start new discussions there.
7

Camera - interruped video recording

asked 2015-04-19 21:48:19 +0300

pan tau gravatar image

the problem is that file remains in ~/Videos/Camera/.recording/

recording was important and must be recovered, the file header looks same like new recordings, but i quess its missing footer or some finalpass,

can somebody help what to do with file to get recorded movie? what exact format is for .recording state?

jolla uptime more than week, video recording about 6minutes then whole ui went crazy - no email account in email app, no keyboard even in terminal, phone app crash , like out of memory

edit retag flag offensive close delete

Comments

What's the file extension on that file? Is it already .mp4?

Sandoz ( 2015-04-19 23:52:26 +0300 )edit

yes it is .mp4 in hex it has header like file which is actualy recording until finish capture,

header of file from .recording:

   ftypqt    qt     mdat        ┌ Lavc53.35.0 BX

file missing also xml "footer" and who knows what else..

normaly stored file from galery:

   ftypqt    qt     free  Ú(mdat┌ Lavc53.35.0 B@
pan tau ( 2015-04-20 01:33:39 +0300 )edit
1

@pan tau: With normal mp4 files the needed muxer data (moov index table) is written at the end of the file if the recording is stopped correctly. As in your case the last part and maybe small header update is missing.

You could try to play with ffmpeg to recover the file. Treat it like a raw h.264 data stream. You need to set some parameters (width, height, framerate, ..) to read it correctly with ffmpeg and than you should be able to store it as a normal mp4 file and play it back with any player.

axaq ( 2015-04-23 03:11:27 +0300 )edit

PLS remove spammer jenengbingung posts. He is just providing useless comments with a link. And remove this when its done.

miqu ( 2016-03-23 09:37:06 +0300 )edit

I am experiencing this problem when phone has only 2Gb of space free. I suppose the fixes should be to make recording show max video time or / and just gracefully stop video when space is becoming scarce.

miqu ( 2016-03-23 09:41:42 +0300 )edit

3 Answers

Sort by » oldest newest most voted
9

answered 2015-08-29 06:05:25 +0300

ovekaaven gravatar image

Man, it took me forever to find a way to repair a video from when recording crashed on my Jolla.

There's a tool called "untrunc" that is supposed to be able to rebuild the missing "moov" index. You can find it at http://vcg.isti.cnr.it/~ponchio/untrunc.php

Unfortunately, when I tried it, it did not yet support straight mp4v video. But eventually, I managed to beat it into working with the following changes:

diff --git a/track.cpp b/track.cpp
index 2afd0ad..e00414e 100644
--- a/track.cpp
+++ b/track.cpp
@@ -206,9 +206,25 @@ int Codec::getLength(unsigned char *start, int maxlength) {
         return consumed;

     } else if(name == "mp4v") {
-        //found no way to guess size, probably the only way is to use some functions in ffmpeg
-        //to decode the stream
-        return -1;
+
+        AVFrame *frame = avcodec_alloc_frame();
+        if(!frame)
+            throw string("Could not create AVFrame");
+        AVPacket avp;
+        av_init_packet(&avp);
+
+        int got_frame;
+        avp.data=(uint8_t *)(start);
+        avp.size = maxlength;
+        int consumed = avcodec_decode_video2(context, frame, &got_frame, &avp);
+        av_freep(&frame);
+
+        if (consumed <= 0 || consumed >= maxlength) return consumed;
+
+        if (start[consumed] == 0x7f)
+            consumed++; // hack
+
+        return consumed;

     } else if(name == "avc1") {

@@ -359,6 +375,8 @@ void Track::parse(Atom *t, Atom *mdat) {
     codec.codec = avcodec_find_decoder(codec.context->codec_id);
     //if audio use next?

+    codec.context->thread_type = 0; // if you're using ffmpeg's libavcodec
+
     if(!codec.codec) throw string("No codec found!");
     if(avcodec_open2(codec.context, codec.codec, NULL)<0)
         throw string("Could not open codec: ") + codec.context->codec_name;
edit flag offensive delete publish link more

Comments

1

Thank you very much for that useful hint, exactly what I just needed, as the video app freezed while recroding and so didn't finish the video file. Used Virtualbox with a debian vm and cloned from github, added your changes, compiled, works.

mobile ( 2015-09-01 19:59:10 +0300 )edit
0

answered 2016-06-06 00:55:53 +0300

rastakajakwanna gravatar image

updated 2016-06-06 01:10:24 +0300

Extending the previous (working) answer with all-in-one solution in Docker :)

Dockerfile

FROM ubuntu:xenial
ENV TERM xterm
ENV UNTRUNC /opt/video-recovery
WORKDIR $UNTRUNC

RUN apt-get update && \
  apt-get -y install build-essential curl unzip libavformat-dev libavcodec-dev libavutil-dev && \
  apt-get -y autoremove && apt-get clean
RUN curl -SLO https://github.com/ponchio/untrunc/archive/master.zip && \
  unzip *.zip -d $UNTRUNC && \
  rm *.zip && \
  mv untrunc-master/* ./ && \
  rm -R untrunc-master
COPY track.cpp.patch ./
RUN patch track.cpp track.cpp.patch
RUN g++ -o untrunc file.cpp main.cpp track.cpp atom.cpp mp4.cpp -L/usr/local/lib -lavformat -lavcodec -lavutil
CMD ["./untrunc"]

track.cpp.patch

219,236c219,236
<       /*     THIS DOES NOT SEEM TO WORK FOR SOME UNKNOWN REASON. IT JUST CONSUMES ALL BYTES.
<   *     AVFrame *frame = avcodec_alloc_frame();
<       if(!frame)
<           throw string("Could not create AVFrame");
<       AVPacket avp;
<       av_init_packet(&avp);
< 
<       int got_frame;
<       avp.data=(uint8_t *)(start);
<       avp.size = maxlength;
<       int consumed = avcodec_decode_video2(context, frame, &got_frame, &avp);
<       av_freep(&frame);
<       return consumed; */
< 
<       //found no way to guess size, probably the only way is to use some functions in ffmpeg
<       //to decode the stream
<       cout << "Unfortunately I found no way to guess size of mp4v packets. Sorry\n";
<       return -1;
---
>          AVFrame *frame = avcodec_alloc_frame();
>          if(!frame)
>              throw string("Could not create AVFrame");
>          AVPacket avp;
>          av_init_packet(&avp);
> 
>          int got_frame;
>          avp.data=(uint8_t *)(start);
>          avp.size = maxlength;
>          int consumed = avcodec_decode_video2(context, frame, &got_frame, &avp);
>          av_freep(&frame);
> 
>          if (consumed <= 0 || consumed >= maxlength) return consumed;
> 
>          if (start[consumed] == 0x7f)
>              consumed++; // hack
> 
>          return consumed;
387a388
>   codec.context->thread_type = 0; // if you're using ffmpeg's libavcodec

Usage:

  • paste the code above to the respective files

  • cd to the folder with Dockerfile and track.cpp.patch

docker build -t video-recovery .
docker run --rm -it -v /your/path/to/broken_and_template/videos:/untrunc --name video-recovery video-recovery bash
(or adjust that command to your needs) however, you are in the container now, you may run
 ./untrunc /untrunc/functionalSample.mp4 /untrunc/brokenVideo.mp4
you should see the result at the following path:
/your/path/to/broken_and_template/videos/brokenVideo.mp4_fixed.mp4
the following error (with different numbers) is somehow ok:
[aac @ 0x1a07da0] decode_band_types: Input buffer exhausted before END element found

Invalid length. -1094995529. Wrong match in track: 1
Found 2814 packets
edit flag offensive delete publish link more
0

answered 2016-06-06 19:20:38 +0300

Thoric gravatar image

Please for your safety: The described symptoms correspond to a lack of space on your device. Verify that and apply the btrfs balance proposed to solve it. Then go ahead with your recording problem. There is some priorities to respect if you do not want to increase the difficulties. Hope to help you! Best regards Thoric

edit flag offensive delete publish link more
Login/Signup to Answer

Question tools

Follow
1 follower

Stats

Asked: 2015-04-19 21:48:19 +0300

Seen: 1,557 times

Last updated: Jun 06 '16