Eyevinn / mp4ff

Library and tools for parsing and writing MP4 files including video, audio and subtitles. The focus is on fragmented files. Includes mp4ff-info, mp4ff-encrypt, mp4ff-decrypt and other tools.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GetSampleNrAtTime fails on VBR mp4 files with last keyframe with 0 duration

alttagil opened this issue · comments

Having last keyframe with 0 duration:
[stts]
...
- entry[113]: sampleCount=1 sampleDelta=95024
- entry[114]: sampleCount=1 sampleDelta=0
[stss]
- syncSampleCount: 10
...
- syncSample[10]: sampleNumber=114
[stsz]
- sample[113] size=2238
- sample[114] size=80726

GetSampleNrAtTime fails with "no matching sample found for time" for the two last cops times.

Proposed solution is to change line
if sampleStartTime < accTime+uint64(b.SampleCount[i])*timeDelta {
to
if sampleStartTime <= accTime+uint64(b.SampleCount[i])*timeDelta {

Hi @alttagil,

In my view, it is rather pathological to have a duration of zero for any mp4 sample, since each sample should always be played out during a certain amount of time. For example, video with 50 frames/s should always have a sample duration of 20ms, so that one can sum up the durations of 100frames and arrive at a duration of 2s exactly.

Having a single last segment with duration zero, should not be too harmful in the calculations, but currently the algorithm assumes that the end time (based on duration) of a sample is the first end time after the sought time.

The GetSampleNrAtTime method returns an error if one asks for a time that is too late after all samples have ended.
Your suggested fix will break that test in TestGetSampleNrAtTime, so I don't think that is the right way to handle this case.

In PR #260 I instead made an extra check for a single trailing zero-duration and made a mapping to that number if the time was not bigger than that value. I hope that solves your issue?

I think that the reason for having last segment's duration set to zero is the nature of the original bitstream source. It is a screencast with variable bitrate with all samples having different durations which were calculated based on the pts of the next sample. The last sample does not have next sample and that's why FFMPEG sets 0 as the duration. I personally would set any sample duration different from zero, like 20ms.
And I believe that there should be no samples in the middle with 0 duration because of that, so checking the last sample to 0 durations seems ok.

I checked the fix and it seems to be working. Thank you for fast reaction! :)

OK. Thanks for checking! Great that it works. Being compatible with ffmpeg output is always useful.

It is true that MPEG-TS doesn't have a duration, but when I make a conversion between the formats, I still set a non-zero value.

I'll merge the PR, and plan to make a new version of the software in August.