anthwlock / untrunc

Restore a truncated mp4/mov. Improved version of ponchio/untrunc
GNU General Public License v2.0
1.87k stars 182 forks source link

How to repair "moov" missing? #136

Closed rajhlinux closed 1 year ago

rajhlinux commented 1 year ago

Here is the proper video clip as reference:

AtomicParsley /compat/ubuntu/untrunc/20230309061733_000000.MP4 -T 1
Atom ftyp @ 0 of size: 28, ends @ 28
Atom skip @ 28 of size: 28968, ends @ 28996
Atom mdat @ 28996 of size: 1623098676, ends @ 1623127672
Atom moov @ 1623127672 of size: 846461, ends @ 1623974133
     Atom mvhd @ 1623127680 of size: 108, ends @ 1623127788
     Atom trak @ 1623127788 of size: 552555, ends @ 1623680343
         Atom tkhd @ 1623127796 of size: 92, ends @ 1623127888
         Atom mdia @ 1623127888 of size: 552455, ends @ 1623680343
             Atom mdhd @ 1623127896 of size: 32, ends @ 1623127928
             Atom hdlr @ 1623127928 of size: 45, ends @ 1623127973
             Atom minf @ 1623127973 of size: 552370, ends @ 1623680343
                 Atom vmhd @ 1623127981 of size: 20, ends @ 1623128001
                 Atom hdlr @ 1623128001 of size: 44, ends @ 1623128045
                 Atom dinf @ 1623128045 of size: 36, ends @ 1623128081
                     Atom dref @ 1623128053 of size: 28, ends @ 1623128081
                         Atom url  @ 1623128069 of size: 12, ends @ 1623128081
                 Atom stbl @ 1623128081 of size: 552262, ends @ 1623680343
                     Atom stsd @ 1623128089 of size: 150, ends @ 1623128239
                         Atom avc1 @ 1623128105 of size: 134, ends @ 1623128239
                             Atom avcC @ 1623128191 of size: 48, ends @ 1623128239
                     Atom stts @ 1623128239 of size: 24, ends @ 1623128263
                     Atom stss @ 1623128263 of size: 12016, ends @ 1623140279
                     Atom stsc @ 1623140279 of size: 28, ends @ 1623140307
                     Atom stsz @ 1623140307 of size: 180020, ends @ 1623320327
                     Atom co64 @ 1623320327 of size: 360016, ends @ 1623680343
     Atom trak @ 1623680343 of size: 281720, ends @ 1623962063
         Atom tkhd @ 1623680351 of size: 92, ends @ 1623680443
         Atom mdia @ 1623680443 of size: 281620, ends @ 1623962063
             Atom mdhd @ 1623680451 of size: 32, ends @ 1623680483
             Atom hdlr @ 1623680483 of size: 45, ends @ 1623680528
             Atom minf @ 1623680528 of size: 281535, ends @ 1623962063
                 Atom smhd @ 1623680536 of size: 16, ends @ 1623680552
                 Atom hdlr @ 1623680552 of size: 44, ends @ 1623680596
                 Atom dinf @ 1623680596 of size: 36, ends @ 1623680632
                     Atom dref @ 1623680604 of size: 28, ends @ 1623680632
                         Atom url  @ 1623680620 of size: 12, ends @ 1623680632
                 Atom stbl @ 1623680632 of size: 281431, ends @ 1623962063
                     Atom stsd @ 1623680640 of size: 91, ends @ 1623680731
                         Atom mp4a @ 1623680656 of size: 75, ends @ 1623680731
                             Atom esds @ 1623680692 of size: 39, ends @ 1623680731
                     Atom stts @ 1623680731 of size: 24, ends @ 1623680755
                     Atom stsc @ 1623680755 of size: 28, ends @ 1623680783
                     Atom stsz @ 1623680783 of size: 93768, ends @ 1623774551
                     Atom co64 @ 1623774551 of size: 187512, ends @ 1623962063
     Atom udta @ 1623962063 of size: 54, ends @ 1623962117
         Atom user @ 1623962071 of size: 46, ends @ 1623962117                                   ~
     Atom gps  @ 1623962117 of size: 12016, ends @ 1623974133                                            ~

 ~ denotes an unknown atom
------------------------------------------------------
Total size: 1623974133 bytes; 46 atoms total.
Media data: 1623098676 bytes; 875457 bytes all other atoms (0.054% atom overhead).
Total free atom space: 0 bytes; 0.000% waste.
------------------------------------------------------
AtomicParsley version:   (utf8)
------------------------------------------------------
Movie duration: 1500.000 seconds (25:0.00) - 8656.53* kbp/sec bitrate (*=approximate)
Low-level details. Total tracks: 2
Trk  Type  Handler                    Kind  Lang  Bytes
1    vide  VideoHandler               avc1  ```   1572856842
     8388.57* kbp/s  1500.000 sec  AVC High Profile,  Level 5.1  1920x1080  (8040 macroblocks)
2    soun  SoundHandler               mp4a  ```   11999744
     64.00* kbp/s  1499.968 sec  MPEG-4 AAC Low Complexity/LC Profile    channels: [1]

Here is the corrupted video clip:

Atom ftyp @ 0 of size: 28, ends @ 28
Atom skip @ 28 of size: 14700, ends @ 14728
Atom mdat @ 14728 of size: 1345570424, ends @ 1345585152
------------------------------------------------------
Total size: 1345585152 bytes; 2 atoms total.
Media data: 1345570424 bytes; 14728 bytes all other atoms (0.001% atom overhead).
Total free atom space: 0 bytes; 0.000% waste.
------------------------------------------------------
AtomicParsley version:   (utf8)
------------------------------------------------------
Low-level details. Total tracks: 0
Trk  Type  Handler                    Kind  Lang  Bytes

I got a preview sample from a website: https://fix.video/

And they actually fixed the video but the audio is completely messed up with noise. So I know it is repairable.

Thanks.

rajhlinux commented 1 year ago

Thank You for replying and your support.

Just wow, I had to learn the art of MP4 container how encoding are packaged. It is super interesting. I have successfully recovered 100% of the video, I was able to watch the recovered video right at the moment I shutdown the camera.

Using epic reverse engineering tactics (I dislike it) I spent 8 days x 13 hours = 104 hours in total to learn all of this.

I created some tools in pure c code to do this. So far I have only spent time in recovering the 1 first track which is the video. The video file was seriously corrupted, the "mdat" atom had the wrong payload header, this leads me to think that the camcorder must provide the correct mdat payload during the end of the video recording session. The camcorder seems to not complete the video session, I possibly haven't turned off the camorder and therefore video file ended corrupted.

Next is to recover the 2nd track which is the audio. I'm sure the process is same as to the first track.

I used some MP4 parser tools like: mp4analyser.py and MP4Box.js

MP4Box.js have an online platform which the videos can be played and analysed: https://gpac.github.io/mp4box.js/test/filereader.html

Atomic Parsley

bento4 "mp4dump".

The hex editor I used was "imhex" and "rehex". I used rehex to do range selection of hex code. Imhex to do searching of binary.

For some reason bento4 "mp4edit" makes it difficult to replace moov atom, it creates a new mdat atom when replacing/inserting moov atom. So I had to manually copy and replace the moov at to the corrupted video using a hex editor.

I created few c programs to find, evaluate, extract and write the start code offsets in the mp4 file (which uses H254 codec encoding, it seems to not use the MP4 annex-b protocol): 0x658880 and 0x219A00

The c program does all the important tasks in 5 seconds for a 20 min video. I literally created a new moov atom from scratch. The most important atoms in the moov atoms are: stts atom stss atom stsz atom co64 atom

I also had to modify the duration in the atom, since a valid working video from the same camcorder has a different duration. The corrupted video length is different. I had to create some few simple formulas to calculate accurate values for many parameters.

The co64 offset first starts with the start codes of "0x658880" frames and then continues with "0x219A00" frames. The process repeats for each sample. Each sample contains 15 frames.

I'll now focus in recovering the audio, if I can't do it I'll email them to you.

I'll possibly make an open source github, the processes I use seems to be exactly the same how some automated commercial video recovery implements. They look into the mdat and extract data from there on (this is what I'm assuming).

Honestly for $17, I would seriously spent the money and save 8 days, however the commercial guys didn't give me the proper audio which is just as important if not more important than the video. (had some police incident that I recorded with my bodycam)

Also ChatGPT helped me a lot if finding and correcting bugs and giving some ideas.

Here is the recovered atom structure:

 $ AtomicParsley /home/user/Desktop/corrupt_video/20230309064234_000001_modified.MP4 -T

Atom ftyp @ 0 of size: 28, ends @ 28
Atom skip @ 28 of size: 14700, ends @ 14728
Atom mdat @ 14728 of size: 1345570428, ends @ 1345585156
Atom moov @ 1345585156 of size: 458575, ends @ 1346043731
     Atom mvhd @ 1345585164 of size: 108, ends @ 1345585272
     Atom trak @ 1345585272 of size: 458459, ends @ 1346043731
         Atom tkhd @ 1345585280 of size: 92, ends @ 1345585372
         Atom mdia @ 1345585372 of size: 458359, ends @ 1346043731
             Atom mdhd @ 1345585380 of size: 32, ends @ 1345585412
             Atom hdlr @ 1345585412 of size: 45, ends @ 1345585457
             Atom minf @ 1345585457 of size: 458274, ends @ 1346043731
                 Atom vmhd @ 1345585465 of size: 20, ends @ 1345585485
                 Atom hdlr @ 1345585485 of size: 44, ends @ 1345585529
                 Atom dinf @ 1345585529 of size: 36, ends @ 1345585565
                     Atom dref @ 1345585537 of size: 28, ends @ 1345585565
                         Atom url  @ 1345585553 of size: 12, ends @ 1345585565
                 Atom stbl @ 1345585565 of size: 458166, ends @ 1346043731
                     Atom stsd @ 1345585573 of size: 150, ends @ 1345585723
                         Atom avc1 @ 1345585589 of size: 134, ends @ 1345585723
                             Atom avcC @ 1345585675 of size: 48, ends @ 1345585723
                     Atom stts @ 1345585723 of size: 24, ends @ 1345585747
                     Atom stss @ 1345585747 of size: 9972, ends @ 1345595719
                     Atom stsc @ 1345595719 of size: 28, ends @ 1345595747
                     Atom stsz @ 1345595747 of size: 149336, ends @ 1345745083
                     Atom co64 @ 1345745083 of size: 298648, ends @ 1346043731
------------------------------------------------------
Total size: 1346043731 bytes; 24 atoms total.
Media data: 1345570428 bytes; 473303 bytes all other atoms (0.035% atom overhead).
Total free atom space: 0 bytes; 0.000% waste.
------------------------------------------------------
AtomicParsley version:   (utf8)
------------------------------------------------------

re_video_recovery

rajhlinux commented 1 year ago

I was able to to recover about 97% of the audio.

For my purpose seems to be 100%. There seems to be some sync issue. However I can extract the audio and sync it with the video.

Recovering the audio is much more difficult and tricky than recovering the video. Because finding the child samples is more random and difficult to find in simple searches.

The child audio samples have no specific set identification, it's identification varies for each child sample. However it doesn't vary by much and can be identified to as much as 97% of the audio track.

By the way I had to create my own tools to do this.

The parent audio samples always starts with the hex code: 0x0012C35 While child audio samples uses some form of algo to be identified: child sample hex structure: [01 aa bb] where "bb" is always constant of the following hex values 35, 55, 9F, F5 and "aa" is random.

Lygggggg commented 1 year ago

hey, can u provide your c program?