anthwlock / untrunc

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

Failing assert: assert(tag == 5); #8

Closed jleclanche closed 5 years ago

jleclanche commented 5 years ago

I have a file which is failing this assert. It goes straight to tag == 6.

If I just remove the assert I then get this:

[mp3 @ 0x55fb59e6a560] Multiple frames in a packet.
[mp3 @ 0x55fb59e6a560] Got unexpected packet size after a partial decode
jleclanche commented 5 years ago

Starting at esds, here's a dump of the chunk of the (good) file:

65 73 64 73 00 00 00 00 03 80 80 80 1B 00 02 00 04 80 80 80 0D 6B 15 00 00 00 00 00 BB 80 00 00 7C FE 06 80 80 80 01 02 00 09 56 68 73 74 74 73 00 00 00 00 00 01 2A CB 00 00 00 02 00 00 04 80 00 00 00 01 00 00 04 73 00 00 00 01 00 00 04 72 00 00 00 01 00 00 04 6E 00 00 00 01 00 00 04 5C 00 00 00 01 00 00 04 64 00 00 00 01 00 00 04 5F 00 00 00 02 00 00 04 5C 00 00 00 01 00 00 04 59 00 00 00 01 00 00 04 5B 00 00 00 02 00 00 04 5C 00 00 00 01 00 00 04 5D 00 00 00 01 00 00 04 60 00 00 00 01 00 00 04 62 00 00 00 01 00 00 04 63 00 00 00 01 00 00 04 6C 00 00 00 01 00 00 04 70 00 00 00 01 00 00 04 74 00 00 00 01 00 00 04 75 00 00 00 01 00 00 04 79 00 00 00 01 00 00 04 7C 00 00 00 01 00 00 04 7D 00
anthwlock commented 5 years ago

You can just comment out the section which creates the esds decoder. This is codec.cpp:56-63. But since libavcodec has trouble decoding your audio packet(s) the payload might be corrupt. The other possibility is that untrunc did choose the wrong codec. If you upload the file somewhere I might take a look.

jleclanche commented 5 years ago

The good mp4 file is played correctly by ffmpeg / mpv. I've asked if I can upload the file but haven't gotten a response yet.

jleclanche commented 5 years ago

I can get you non-data chunks of the file for now if that helps at all.

jleclanche commented 5 years ago

I get a floating point exception if I comment out that portion of the code.

Info: reading ok3.mp4
Info: parsing healthy moov atom ... 

start_ = 0
requests: 4 at offset : 0
length_ = 32
requests: 4 at offset : 4
name_ = ftyp
requests: 24 at offset : 8

start_ = 32
requests: 4 at offset : 32
length_ = 8
requests: 4 at offset : 36
name_ = free
requests: 0 at offset : 40

start_ = 40
requests: 4 at offset : 40
length_ = 505803065
requests: 4 at offset : 44
name_ = mdat
requests: 505803057 at offset : 48
reallocating the file buffer

start_ = 505803105
requests: 4 at offset : 0
length_ = 3126351
requests: 4 at offset : 4
name_ = moov

start_ = 505803113
requests: 4 at offset : 8
length_ = 108
requests: 4 at offset : 12
name_ = mvhd
requests: 100 at offset : 16

start_ = 505803221
requests: 4 at offset : 116
length_ = 1369773
requests: 4 at offset : 120
name_ = trak

start_ = 505803229
requests: 4 at offset : 124
length_ = 92
requests: 4 at offset : 128
name_ = tkhd
requests: 84 at offset : 132

start_ = 505803321
requests: 4 at offset : 216
length_ = 36
requests: 4 at offset : 220
name_ = edts

start_ = 505803329
requests: 4 at offset : 224
length_ = 28
requests: 4 at offset : 228
name_ = elst
requests: 20 at offset : 232

start_ = 505803357
requests: 4 at offset : 252
length_ = 1369637
requests: 4 at offset : 256
name_ = mdia

start_ = 505803365
requests: 4 at offset : 260
length_ = 32
requests: 4 at offset : 264
name_ = mdhd
requests: 24 at offset : 268

start_ = 505803397
requests: 4 at offset : 292
length_ = 45
requests: 4 at offset : 296
name_ = hdlr
requests: 37 at offset : 300

start_ = 505803442
requests: 4 at offset : 337
length_ = 1369552
requests: 4 at offset : 341
name_ = minf

start_ = 505803450
requests: 4 at offset : 345
length_ = 20
requests: 4 at offset : 349
name_ = vmhd
requests: 12 at offset : 353

start_ = 505803470
requests: 4 at offset : 365
length_ = 36
requests: 4 at offset : 369
name_ = dinf

start_ = 505803478
requests: 4 at offset : 373
length_ = 28
requests: 4 at offset : 377
name_ = dref
requests: 20 at offset : 381

start_ = 505803506
requests: 4 at offset : 401
length_ = 1369488
requests: 4 at offset : 405
name_ = stbl

start_ = 505803514
requests: 4 at offset : 409
length_ = 152
requests: 4 at offset : 413
name_ = stsd
requests: 144 at offset : 417

start_ = 505803666
requests: 4 at offset : 561
length_ = 24
requests: 4 at offset : 565
name_ = stts
requests: 16 at offset : 569

start_ = 505803690
requests: 4 at offset : 585
length_ = 1392
requests: 4 at offset : 589
name_ = stss
requests: 1384 at offset : 593

start_ = 505805082
requests: 4 at offset : 1977
length_ = 681384
requests: 4 at offset : 1981
name_ = ctts
requests: 681376 at offset : 1985

start_ = 506486466
requests: 4 at offset : 683361
length_ = 40
requests: 4 at offset : 683365
name_ = stsc
requests: 32 at offset : 683369

start_ = 506486506
requests: 4 at offset : 683401
length_ = 343248
requests: 4 at offset : 683405
name_ = stsz
requests: 343240 at offset : 683409

start_ = 506829754
requests: 4 at offset : 1026649
length_ = 343240
requests: 4 at offset : 1026653
name_ = stco
requests: 343232 at offset : 1026657

start_ = 507172994
requests: 4 at offset : 1369889
length_ = 1756365
requests: 4 at offset : 1369893
name_ = trak

start_ = 507173002
requests: 4 at offset : 1369897
length_ = 92
requests: 4 at offset : 1369901
name_ = tkhd
requests: 84 at offset : 1369905

start_ = 507173094
requests: 4 at offset : 1369989
length_ = 36
requests: 4 at offset : 1369993
name_ = edts

start_ = 507173102
requests: 4 at offset : 1369997
length_ = 28
requests: 4 at offset : 1370001
name_ = elst
requests: 20 at offset : 1370005

start_ = 507173130
requests: 4 at offset : 1370025
length_ = 1756229
requests: 4 at offset : 1370029
name_ = mdia

start_ = 507173138
requests: 4 at offset : 1370033
length_ = 32
requests: 4 at offset : 1370037
name_ = mdhd
requests: 24 at offset : 1370041

start_ = 507173170
requests: 4 at offset : 1370065
length_ = 45
requests: 4 at offset : 1370069
name_ = hdlr
requests: 37 at offset : 1370073

start_ = 507173215
requests: 4 at offset : 1370110
length_ = 1756144
requests: 4 at offset : 1370114
name_ = minf

start_ = 507173223
requests: 4 at offset : 1370118
length_ = 16
requests: 4 at offset : 1370122
name_ = smhd
requests: 8 at offset : 1370126

start_ = 507173239
requests: 4 at offset : 1370134
length_ = 36
requests: 4 at offset : 1370138
name_ = dinf

start_ = 507173247
requests: 4 at offset : 1370142
length_ = 28
requests: 4 at offset : 1370146
name_ = dref
requests: 20 at offset : 1370150

start_ = 507173275
requests: 4 at offset : 1370170
length_ = 1756084
requests: 4 at offset : 1370174
name_ = stbl

start_ = 507173283
requests: 4 at offset : 1370178
length_ = 96
requests: 4 at offset : 1370182
name_ = stsd
requests: 88 at offset : 1370186

start_ = 507173379
requests: 4 at offset : 1370274
length_ = 611944
requests: 4 at offset : 1370278
name_ = stts
requests: 611936 at offset : 1370282

start_ = 507785323
requests: 4 at offset : 1982218
length_ = 800776
requests: 4 at offset : 1982222
name_ = stsc
requests: 800768 at offset : 1982226

start_ = 508586099
requests: 4 at offset : 2782994
length_ = 20
requests: 4 at offset : 2782998
name_ = stsz
requests: 12 at offset : 2783002

start_ = 508586119
requests: 4 at offset : 2783014
length_ = 343240
requests: 4 at offset : 2783018
name_ = stco
requests: 343232 at offset : 2783022

start_ = 508929359
requests: 4 at offset : 3126254
length_ = 97
requests: 4 at offset : 3126258
name_ = udta
requests: 89 at offset : 3126262
Composition time offset atom found. Out of order samples possible.
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'ok3.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf54.6.100
  Duration: 00:47:40.23, start: 0.000000, bitrate: 1423 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1024x576, 1382 kb/s, 30 fps, 30 tbr, 30 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 31 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
found avcC after: 102
remaining len:50
parsing avcC ...
len_sps: 25
decoding SPS ...
log2_max_frame_num: 4
Info: avcC got decoded
Info: parsing mdat from truncated file ... 
start_ = 0
requests: 4 at offset : 0
length_ = 32
requests: 4 at offset : 4
name_ = ftyp
start_ = 32
requests: 4 at offset : 32
length_ = 8
requests: 4 at offset : 36
name_ = free
start_ = 40
requests: 4 at offset : 40
length_ = 0
requests: 4 at offset : 44
name_ = mdat
mdat->contentSize = 426751584

(reading element from mdat)
Offset: 0 8d020000 ffff0506
Track codec: mp4a
Failure because of NULL header
Track codec: avc1
avc1: Match with 0 header
sps_info (before): 1 4 5 0
sps_info (after):  1 4 5 0
---
Length: 657
Ref idc: 0
Nal type: 6
Partial avc1-length: 657
---
Length: 31889
Ref idc: 3
Nal type: 5
First mb: 0
pic paramter set id: 0
Frame num: 0
Poc lsb: 0
Partial avc1-length: 32546
---
Length: 14266
Ref idc: 2
Nal type: 1
First mb: 0
pic paramter set id: 0
Frame num: 1
Poc lsb: 2
Different frame number
frame-length: 32546
- found as avc1

(reading element from mdat)
Offset: 32546 b6370000 6c229a41
Track codec: mp4a
Failure because of NULL header
Track codec: avc1
avc1: Match with 0 header
---
Length: 14266
Ref idc: 2
Nal type: 1
First mb: 0
pic paramter set id: 0
Frame num: 1
Poc lsb: 2
Partial avc1-length: 14266
---
First byte expected 0
failed parsing nal-header
frame-length: 14266
- found as avc1

(reading element from mdat)
Offset: 46812 64c4fbff ddf10000
Track codec: mp4a
Success for no particular reason....
[mp3float @ 0x55c2c4f3b900] Multiple frames in a packet.
nb_samples: 1152                                                                                                                                                                                                                       
frame-length: 672
- found as mp4a

(reading element from mdat)
Offset: 47484 870f0000 79419e01
Track codec: mp4a
Failure because of NULL header
Track codec: avc1
avc1: Match with 0 header
---
Length: 3979
Ref idc: 0
Nal type: 1
First mb: 0
pic paramter set id: 0
Frame num: 2
Poc lsb: 1
Partial avc1-length: 3979
---
First byte expected 0
failed parsing nal-header
frame-length: 3979
- found as avc1

(reading element from mdat)
Offset: 51463 6494fbff f9f300df
Track codec: mp4a
Success for no particular reason....
[mp3float @ 0x55c2c4f3b900] Got unexpected packet size after a partial decode
nb_samples: 0                                                                                                                                                                                                                          
frame-length: -22
Error: Invalid length: -22. Wrong match in track: 0
Track codec: avc1
avc1: no match because of nal type: 31
Error: unable to find correct codec -> premature end
mdat->file_end: 51511
Info: Found 4 packets ( mp4a: 1 avc1: 3 avc1-keyframes: 1 )
Info: Duration of mp4a: 24ms  (24 ms)
zsh: floating point exception (core dumped)  ./untrunc -vv ok3.mp4 bad.mp4

gdb:

Program received signal SIGFPE, Arithmetic exception.
0x00005555555689b9 in Mp4::saveVideo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
(gdb) bt
#0  0x00005555555689b9 in Mp4::saveVideo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#1  0x000055555556b545 in Mp4::repair(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#2  0x000055555555df97 in main ()
jleclanche commented 5 years ago

Removing this piece of code gets past the float exc:


        int hour, min, sec, msec;
        int bmsec = track.duration_ / (track.timescale_ / 1000);
        auto x = div(bmsec, 1000); msec = x.rem; sec = x.quot;
        x = div(sec, 60); sec = x.rem; min = x.quot;
        x = div(min, 60); min = x.rem; hour = x.quot;
        string s_msec = (msec?to_string(msec)+"ms ":"");
        string s_sec = (sec?to_string(sec)+"s ":"");
        string s_min = (min?to_string(min)+"min ":"");
        string s_hour = (hour?to_string(hour)+"h ":"");
        logg(I, "Duration of ", track.codec_.name_, ": ", s_hour, s_min, s_sec, s_msec, " (", bmsec, " ms)\n");

Unfortunately, the fixed file is still 2 frames, just like in https://github.com/ponchio/untrunc/issues/140 :(

anthwlock commented 5 years ago

There is a -a flag. It shows you weither untrunc would be able to repair the good file, and if not why not. Do you have an idea why this code triggered a float exception? Devided by zero?

jleclanche commented 5 years ago

Possibly .. not sure, sounds like the duration might be wrong

I also see this:

avc1: no match because of nal type: 31
Error: unable to find correct codec -> premature end
mdat->file_end: 426751143
Info: Found 4 packets ( mp4a: 1 avc1: 3 avc1-keyframes: 1 )
Info: saving bad.mp4_fixed.mp4

Relevant code:

        //TODO use the first byte of the nal: forbidden bit and type!
        int nal_type = (start[4] & 0x1f);
        //the other values are really uncommon on cameras...
        if(nal_type > 21) {
            //      if(nal_type != 1 && nal_type != 5 && nal_type != 6 && nal_type != 7 &&
            //              nal_type != 8 && nal_type != 9 && nal_type != 10 && nal_type != 11 && nal_type != 12) {
            logg(V, "avc1: no match because of nal type: ", nal_type, '\n');
            return false;
        }
        //if nal is equal 7, the other fragments (starting with nal type 7)
        //should be part of the same packet
        //(we cannot recover time information, remember)
        if(start[0] == 0) {
            logg(V, "avc1: Match with 0 header\n");
            return true;
        }
        logg(V, "avc1: failed for not particular reason\n");
        return false;

Could have to do with it? It's finding 4 packets, which is an improvement over the 2 packets it was finding in the upstream version.

jleclanche commented 5 years ago

Running with -a over the good file, I get a bunch of output and then:

 Track 1
Track codec: mp4a
Keyframes  0
0 Size: 96 offset 57678  begin: fffb1464 ff000 end: 55555555
[mp3float @ 0x5606dc933900] Multiple frames in a packet.
Length: 96 true length: 96
1 Size: 96 offset 58121  begin: fffb1464 1e0ff000 end: 55555555
[mp3float @ 0x5606dc933900] Got unexpected packet size after a partial decode
Length: -22 true length: 96 
jleclanche commented 5 years ago

Here's the successful output past the floating point exception btw.

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'ok.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf54.6.100
  Duration: 00:20:08.37, start: 0.000000, bitrate: 2680 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1024x576, 2585 kb/s, 30 fps, 30 tbr, 30 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: mp3 (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 87 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
found avcC after: 102
remaining len:50
parsing avcC ...
len_sps: 25
decoding SPS ...
log2_max_frame_num: 4
Info: avcC got decoded
Info: parsing mdat from truncated file ... 
start_ = 0
requests: 4 at offset : 0
length_ = 32
requests: 4 at offset : 4
name_ = ftyp
start_ = 32
requests: 4 at offset : 32
length_ = 8
requests: 4 at offset : 36
name_ = free
start_ = 40
requests: 4 at offset : 40
length_ = 0
requests: 4 at offset : 44
name_ = mdat
mdat->contentSize = 426751584

(reading element from mdat)
Offset: 0 8d020000 ffff0506
Track codec: mp4a
Failure because of NULL header
Track codec: avc1
avc1: Match with 0 header
sps_info (before): 1 4 5 0
sps_info (after):  1 4 5 0
---
Length: 657
Ref idc: 0
Nal type: 6
Partial avc1-length: 657
---
Length: 31889
Ref idc: 3
Nal type: 5
First mb: 0
pic paramter set id: 0
Frame num: 0
Poc lsb: 0
Partial avc1-length: 32546
---
Length: 14266
Ref idc: 2
Nal type: 1
First mb: 0
pic paramter set id: 0
Frame num: 1
Poc lsb: 2
Different frame number
frame-length: 32546
- found as avc1

(reading element from mdat)
Offset: 32546 b6370000 6c229a41
Track codec: mp4a
Failure because of NULL header
Track codec: avc1
avc1: Match with 0 header
---
Length: 14266
Ref idc: 2
Nal type: 1
First mb: 0
pic paramter set id: 0
Frame num: 1
Poc lsb: 2
Partial avc1-length: 14266
---
First byte expected 0
failed parsing nal-header
frame-length: 14266
- found as avc1

(reading element from mdat)
Offset: 46812 64c4fbff ddf10000
Track codec: mp4a
Success for no particular reason....
[mp3float @ 0x564dfe197380] Multiple frames in a packet.
nb_samples: 1152                                                                                                                                                                                                                       
frame-length: 672
- found as mp4a

(reading element from mdat)
Offset: 47484 870f0000 79419e01
Track codec: mp4a
Failure because of NULL header
Track codec: avc1
avc1: Match with 0 header
---
Length: 3979
Ref idc: 0
Nal type: 1
First mb: 0
pic paramter set id: 0
Frame num: 2
Poc lsb: 1
Partial avc1-length: 3979
---
First byte expected 0
failed parsing nal-header
frame-length: 3979
- found as avc1

(reading element from mdat)
Offset: 51463 6494fbff f9f300df
Track codec: mp4a
Success for no particular reason....
[mp3float @ 0x564dfe197380] Got unexpected packet size after a partial decode
nb_samples: 0                                                                                                                                                                                                                          
frame-length: -22
Error: Invalid length: -22. Wrong match in track: 0
Track codec: avc1
avc1: failed for not particular reason
Error: unable to find correct codec -> premature end
mdat->file_end: 51511
Info: Found 4 packets ( mp4a: 1 avc1: 3 avc1-keyframes: 1 )
Info: saving bad.mp4_fixed.mp4
requests: 51463 at offset : 48
jleclanche commented 5 years ago

This looks weird:

frame-length: -22
Error: Invalid length: -22. Wrong match in track: 0
anthwlock commented 5 years ago

I made some commits regarding Mp4::analyze to the branch 'better_analyze'. It is interesting how your packets always end with 55555555. I dont think this is normal.

anthwlock commented 5 years ago

You could try to just make Codec::getLength() return 96 whenever the codec is not avc1. However it is new to me that audio packets have constant size.

jleclanche commented 5 years ago

It's dumping a ton of these:

(140) Size: 96 offset 742899  begin: fffb1464 e18ff000 end: 55555555
detected size: -558323010 true: 96
detected duration: 0 true: 1158
detected size or duration are wrong!
jleclanche commented 5 years ago

Getting another floating point exception, again duration-related:

Program received signal SIGFPE, Arithmetic exception.
0x000055555556d93c in Track::getDurationInMs() ()
(gdb) bt
#0  0x000055555556d93c in Track::getDurationInMs() ()
#1  0x000055555556ce63 in Mp4::repair(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#2  0x000055555556954f in main ()
anthwlock commented 5 years ago

Ok, this makes sense, duration_ is zero. You should try to return 96 as your packet size if codec == mp4a/mp3. I made a new commit in case you also want to analyze avc1 without the "duration = 0" message all the time.

jleclanche commented 5 years ago

Yeah I just tried that. I had to change getDurationInMs() but it generates a 3.7M file with only a single readable frame. Let me see if I can play with it some more.

What should getDurationInMs() return?

jleclanche commented 5 years ago

mpv output for the 3.7M file: http://dpaste.com/3225SQ2.txt

I then removed the sound track using ffmpeg -i bad.mp4_fixed.mp4 -c copy -an nosound.mp4. here's the mpv and vlc outputs: http://dpaste.com/30XVA5Q.txt

anthwlock commented 5 years ago

In codec.cpp:216 set duration to n, where n is the correct number of frames as reported by untrunc -i in the "sample to decode time" aka stts Atom section. Usually n is constant.

jleclanche commented 5 years ago
------stts "sample to decode time" [507173379, 611944]
       Entries: 76491
       samples: 2 for: 1152
       samples: 1 for: 1139
       samples: 1 for: 1138
       samples: 1 for: 1134
       samples: 1 for: 1116
       samples: 1 for: 1124
       samples: 1 for: 1119
       samples: 2 for: 1116
       samples: 1 for: 1113
       samples: 1 for: 1115
       samples: 2 for: 1116
       samples: 1 for: 1117
       samples: 1 for: 1120
       samples: 1 for: 1122
       samples: 1 for: 1123
       samples: 1 for: 1132
       samples: 1 for: 1136
       samples: 1 for: 1140
       samples: 1 for: 1141
       samples: 1 for: 1145
       samples: 1 for: 1148
       samples: 1 for: 1149
       samples: 1 for: 1152
       samples: 1 for: 1154
       samples: 1 for: 1155
       samples: 1 for: 1156
       samples: 1 for: 1158
       samples: 1 for: 1161
       samples: 3 for: 1160
       samples: 1 for: 1161
jleclanche commented 5 years ago

That'd be eg. 1152?

Edit: Still getting the getDurationInMs() exception if I set it to 1152.

anthwlock commented 5 years ago

Compile with '-g' and check with gdb. What does times_ look like in Track::fixTimes?

jleclanche commented 5 years ago

Is this what you want? http://dpaste.com/26K4T5Q

anthwlock commented 5 years ago

I wonder why for mp4a times[i] is not constant, since you set it to 1152, did you? And I wonder why for avc1 times[i] = 1 ... Is that the output from the corrupt file? It says it found 12333 mp4a packets but only 22 avc1. So the codec matching seems to be wrong.

jleclanche commented 5 years ago

No this is after resetting the change to 1152. With the change it's constant.

jleclanche commented 5 years ago

This is the output from ./untrunc -vv ok.mp4 bad.mp4.

jleclanche commented 5 years ago

BTW, it's very possible the audio is borked, but the file itself is supposed to be a ~40 min video so it sounds like 22 avc1 packets is not enough?

anthwlock commented 5 years ago

Yes, that is why I say the codec matching seems to fail. You could try to figure out why, using 'untrunc -a'. And paste the output of 'untrunc -a -n' somewhere. Use the master branch.

jleclanche commented 5 years ago

First 12M of ./untrunc -vv -a -n ok.mp4 bad.mp4 &> out... afterwards it gets very slow and I don't know how long it'll take to finish.

out.gz

anthwlock commented 5 years ago

Hmm... There it looks fine. Where is the audio track comming from? Try to run it again without '-v'. What do you mean with "gets very slow"? It doesn't print anything?

anthwlock commented 5 years ago

Have you tried to debug the floating point exception you said is related to the duration?

jleclanche commented 5 years ago

Not particularly. timescale_ is 48000 and duration looks ok too, so I don't know why it's throwing a fit.

And yes it does print but like 1-2 offset every second or so. It's the same without -vv, just with less text.

jleclanche commented 5 years ago
...

(318) Size: 336 offset 3028811  begin: fffb8464 fa00f531 end: 54422119
detected size: -558323010 true: 336
detected duration: 0 true: 1147
detected size or duration are wrong!

(319) Size: 336 offset 3029653  begin: fffb8464 ed00f4ef end: 44f7cd20
detected size: -558323010 true: 336
detected duration: 0 true: 1148
detected size or duration are wrong!

(320) Size: 384 offset 3029989  begin: fffb9464 e800f4f5 end: c3b321a8
^C
jleclanche commented 5 years ago

These definitely look wrong.

Track 1 codec: mp4a

(0) Size: 96 offset 49292  begin: fffb1464 000ff000 end: 04c07a60
[mp3float @ 0x55b4f605ae80] Multiple frames in a packet.
detected size: 96 true: 96                                                                                                                                                                                                             
detected duration: 1152 true: 1152

(1) Size: 96 offset 49776  begin: fffb1464 1e0ff000 end: 689f8c50
[mp3float @ 0x55b4f605ae80] Got unexpected packet size after a partial decode
detected size: -22 true: 96                                                                                                                                                                                                            
detected duration: 0 true: 1147
detected size or duration are wrong!

(2) Size: 96 offset 49872  begin: fffb1464 3c0ff000 end: 3b2f831a
[mp3float @ 0x55b4f605ae80] Header missing
detected size: -1094995529 true: 96                                                                                                                                                                                                    
detected duration: 0 true: 1149
detected size or duration are wrong!

(3) Size: 576 offset 73716  begin: fffbb464 5a000000 end: 3ac88008
detected size: -558323010 true: 576
detected duration: 0 true: 1145
detected size or duration are wrong!
jleclanche commented 5 years ago

I don't really know how to use gdb, but if these are the actual values in the bt then that would cause a division by zero (30 / 1000 is 0 as int):

(gdb) p duration_
$22 = 3
(gdb) p timescale_ 
$23 = 30
anthwlock commented 5 years ago

Yes, but you can make getDurationInMs return anything you want. This is just a symptom of a deeper issue. Again, I could help you if you'd upload the file somewhere. Maybe you can create a similar file where you dont have to ask for permission. Does 3fdd868 fix the 'untrunc -a -n' getting slow issues?

In case you didn't know yet: gdb has a tui wich you can access by typing '-'. Use 'up'/'down' to go up/down the stackframe, aka. function calls. Try out 'info [local|args|...]'. For more check this

anthwlock commented 5 years ago

closing because inactive

jleclanche commented 4 years ago

Sorry for being inactive. This year has been busy. I'm catching up on old emails.

I gave untrunc another shot, looks like it got a lot of improvements. Sadly I'm still hitting the getDurationInMs issue:

…
Info: version '7f0a58c' using ffmpeg 'n4.2.1'
Info: reading files/ok.mp4
Info: parsing healthy moov atom ... 
Composition time offset atom found. Out of order samples possible.

Info: reading mdat from truncated file ...
Info: Muted ffmpeg to reduce redundant warnings/errors. Use '-v' to see them.
Info: Found 128214 packets ( mp4a: 74541 avc1: 53673 avc1-keyframes: 217 )

Program received signal SIGFPE, Arithmetic exception.
0x000055555558da58 in HasHeaderAtom::getDurationInMs (this=0x55555565a270) at src/common.cpp:267
267             return duration_ / (timescale_ / 1000);
(gdb) bt
#0  0x000055555558da58 in HasHeaderAtom::getDurationInMs (this=0x55555565a270) at src/common.cpp:267
#1  0x000055555559216e in Mp4::chkStrechFactor (this=0x7fffffffd790) at src/mp4.cpp:222
#2  0x0000555555592677 in Mp4::saveVideo (this=0x7fffffffd790, filename="files/bad.mp4_fixed.mp4") at src/mp4.cpp:277
#3  0x0000555555599fee in Mp4::repair (this=0x7fffffffd790, filename="files/bad.mp4") at src/mp4.cpp:1269
#4  0x00005555555b40ab in main (argc=3, argv=0x7fffffffda28) at src/main.cpp:169
(gdb) p duration_
$1 = 53673
(gdb) p timescale_
$2 = 30

(timescale_ / 1000 is 0, hence the crash)

And now, here's the great news: Fixing that by returning 0 gets me a fixed video! Wow. Holy shit. The audio works, too.

Thank you. I'll PR the result.

anthwlock commented 4 years ago

Thank you, but timescale_ < 0 does not imply that the track has 0ms length. I guess ce47b5a47 fixes this too?

jleclanche commented 4 years ago

I can't check right now, should be easy enough to test as you have the values now. But timescale_ was not < 0, it was 30, which meant timescale_ / 1000 was 0, which meant you were doing duration_ / 0, which is a division by zero.

anthwlock commented 4 years ago

Sorry, I meant timescale_ < 1000. Your patch makes 30 / (30 / 1000) be 0, when it should be 1000 instead.

jleclanche commented 4 years ago

Oh I see. Should I early-return 1000 in my patch instead then? I think yours may still fail if timescale_ is 0.

anthwlock commented 4 years ago

Since timescale_ is read from the healthy file, and timescale_ == 0 is (AFAIK) an invalid value, we can assert that timescale_ > 0.

I realized that casting to double is not needed, as multiplying with 1000 instead of dividing the dividend does the same thing. Multiplication should be done first though, for the sake of precision.