| 40 | | Additionally, there's a media header box with a duration set to 97024 - and subtracting the 1024 from the edit list box yields 96000: |
| 41 | | |
| 42 | | {{{ |
| 43 | | [mdhd: Media Header Box] |
| 44 | | position = 889 |
| 45 | | size = 32 |
| 46 | | version = 0 |
| 47 | | flags = 0x000000 |
| 48 | | creation_time = UTC 1904/01/01, 00:00:00 |
| 49 | | modification_time = UTC 1904/01/01, 00:00:00 |
| 50 | | timescale = 48000 |
| 51 | | duration = 97024 (00:00:02.021) |
| 52 | | language = und |
| 53 | | pre_defined = 0x0000 |
| 54 | | }}} |
| 55 | | |
| 56 | | and the Decoding Time to Sample Box also adds up to 97024 - 94 samples at 1024 frames and 1 sample at 768 frames. |
| | 42 | The Decoding Time to Sample Box specifies the final sample is 768 frames. Doing the math: (94 samples * 1024 frames) + 768 = 97024 frames. Subtract the 1024 frames from the previous Edit List Box and you should have 96000 samples. |
| | 59 | I think the issue may be the MP4 demuxer not signaling the final decoded packet's duration. This occurs if I use other codecs as well, for example mp3: |
| | 60 | |
| | 61 | {{{ |
| | 62 | |
| | 63 | # using the same source.wav as above that's 96000 samples: |
| | 64 | % ffmpeg -i source.wav -c:a libmp3lame encoded-in-mp3.mp4 |
| | 65 | % ffmpeg -i encoded-in-mp3.mp4 decoded-from-mp3.wav |
| | 66 | % soxi -s decoded-from-mp3.wav |
| | 67 | 96815 |
| | 68 | |
| | 69 | }}} |
| | 70 | |
| | 71 | Here's the edts box and stts from encoded-in-mp3.mp4: |
| | 72 | |
| | 73 | {{{ |
| | 74 | [edts: Edit Box] |
| | 75 | position = 32900 |
| | 76 | size = 36 |
| | 77 | [elst: Edit List Box] |
| | 78 | position = 32908 |
| | 79 | size = 28 |
| | 80 | version = 0 |
| | 81 | flags = 0x000000 |
| | 82 | entry_count = 1 |
| | 83 | entry[0] |
| | 84 | segment_duration = 2000 |
| | 85 | media_time = 1105 |
| | 86 | media_rate = 1.000000 |
| | 87 | |
| | 88 | [stts: Decoding Time to Sample Box] |
| | 89 | position = 33205 |
| | 90 | size = 32 |
| | 91 | version = 0 |
| | 92 | flags = 0x000000 |
| | 93 | entry_count = 2 |
| | 94 | entry[0] |
| | 95 | sample_count = 84 |
| | 96 | sample_delta = 1152 |
| | 97 | entry[1] |
| | 98 | sample_count = 1 |
| | 99 | sample_delta = 337 |
| | 100 | }}} |
| | 101 | |
| | 102 | So again doing some math: (84 samples * 1152 frames) + 337 frames = 97105 frames. Subtract the 1105 frames from the edit list - 96000 frames. |
| | 103 | |
| | 104 | Another example with opus: |
| | 105 | |
| | 106 | {{{ |
| | 107 | % ffmpeg -i source.wav -c:a libopus encoded-in-opus.mp4 |
| | 108 | % ffmpeg -i encoded-in-opus.mp4 decoded-from-opus.wav |
| | 109 | % soxi -s decoded-from-opus.wav |
| | 110 | 96648 |
| | 111 | }}} |
| | 112 | |
| | 113 | Same issue with a fragmented mp4 - which doesn't have the Decoding Time to Sample Box and instead relies on either the Track Fragment Header Box or the Track Fragment Run Box for sample duration signaling. |
| | 114 | |
| | 115 | This does not seem to apply to codecs that carry their own duration signaling, like FLAC in mp4. |
| | 116 | |