]> granicus.if.org Git - handbrake/commit
libav: fix mp4 audio sync problem
authorJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 10 Feb 2017 18:26:59 +0000 (11:26 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 10 Feb 2017 18:32:10 +0000 (11:32 -0700)
commit370b0608e9db31db5522fce707ce1b612a01fe8d
tree29353f0b18cb8333dd8c9062fd1f03b6a2bbd022
parent4a02065222ecc0ff3dede5d2cd0632a224ac14e7
libav: fix mp4 audio sync problem

Initial CTS (composition offset) was essentially getting added twice to
the computed PTS

Fixes https://github.com/HandBrake/HandBrake/issues/568

Here's a description of how mp4 timestamps work and what is going wrong
for the curious.

Terminology:
pts = presentation timestamp, when a frame is displayed
dts = decode timestamp, when a frame is decoded
cts = composition offset, pts - dts
empty edit = defines the pts of the first frame in an mp4 track

mp4 timestamps are computed from 3 primary values that are in the mp4
stream.

    An "empty edit" in the track edit list
    per frame duration
    per frame cts

Here's where things get messy. How do you compute pts(N) and dts(N) for
some frame N from only the above 3 values in the mp4 file?

    empty edit == pts(0) and is read from the mp4 file (EDTS table)
    duration(N) is read from the mp4 file (STTS table)
    cts(N) is read from the mp4 file (CTTS table)

We know cts(0) = pts(0) - dts(0) by definition of cts
And cts(0) and pts(0) are known since they can be read from the mp4 file

This is the step libav gets wrong!
Therefore we can compute dts(0) = pts(0) - cts(0).
libav computes dts(0) = pts(0) which shifts all frames by cts(0)

After that dts(N) = dts(0) + duration(0) + ... + duration(N-1)
And finally pts(N) = dts(N) + cts(N)

(cherry picked from commit 88343d5a0ee9969071bb8a263dab0e0a66c4c8ff)
contrib/ffmpeg/A06-edit-list-offset.patch [new file with mode: 0644]