• Andreas Rheinhardt's avatar
    avformat/mux: Preserve sync even if later packet has negative ts · c602deb1
    Andreas Rheinhardt authored
    write_packet() has code to shift the packets timestamps
    to make them nonnegative or even make them start at ts zero;
    this code inspects every packet that is written and if a packet
    with negative timestamp (whether this is dts or pts depends upon
    another flag; basically: Matroska uses pts, everyone else dts)
    is encountered, this is offset to make the timestamp zero.
    All further packets will be offset accordingly (with the offset
    converted according to the streams' timebases).
    
    This is based around an assumption, namely that the timestamps
    are indeed non-decreasing, so that the first packet with negative
    timestamps is the first packet with timestamps. This assumption
    is often fulfilled given that the default interleavement function
    by default interleaves per dts; yet there are scenarios in which
    it may not be fulfilled:
    a) av_write_frame() instead of av_interleaved_write_frame() is used.
    b) The audio_preload option is used.
    c) When the timestamps that are made nonnegative/zero are pts
    (i.e. with Matroska), because the packet with the smallest dts
    is not necessarily the packet with the smallest pts.
    d) Possibly with custom interleavement functions.
    In these cases the relative sync of the first few packet(s) is offset
    relative to the later packets. This contradicts the documentation
    ("When shifting is enabled, all output timestamps are shifted by
    the same amount").
    
    Therefore this commit changes this: As soon as the first packet
    with valid timestamps is output, it is checked and recorded whether
    the timestamps need to be shifted. Further packets are no longer
    checked for needing to be offset; instead they are simply offset.
    In the cases above this leads to packets with negative timestamps
    (and the appropriate warnings) instead of desync. This will mostly
    be fixed in the next commit.
    
    This commit also factors handling the avoid_negative_ts stuff out
    of write_packet() in order to be able to return immediately.
    
    Tickets #4536 and #5784 as well as the matroska-avoid-negative-ts-test
    are examples of c); as has been said, some timestamps are now negative,
    yet the ref file update does not show it because ffmpeg.c sanitizes
    the timestamps (-copyts disables it; ffprobe and mkvinfo also show
    the original timestamps).
    Signed-off-by: 's avatarAndreas Rheinhardt <andreas.rheinhardt@outlook.com>
    c602deb1
internal.h 31.8 KB