diff mbox series

[FFmpeg-devel,6/8] avformat/mux: Allow muxers to set custom min timestamp

Message ID GV1P250MB0737EF326DBB7DFADAEDBD228F7B9@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM
State Accepted
Commit 1a8309e954b894675aa450db5c117240195385a9
Headers show
Series [FFmpeg-devel,1/8] fftools/ffprobe: Report initial and trailing padding | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Andreas Rheinhardt Sept. 1, 2022, 9:24 p.m. UTC
Matroska requires pts to be >= 0 with a slight exception:
It has a mechanism to deal with codec delay, i.e. with
the data added at the beginning that does not correspond
to actual input data and should be discarded by the player.
Only the audio actually intended to be output needs to have
a timestamp >= 0.
In order to avoid unnecessary timestamp shifting, this patch
allows muxers to inform the shifting code about this so that
it can take it into account.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavformat/internal.h | 7 +++++++
 libavformat/mux.c      | 7 +++++--
 2 files changed, 12 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/internal.h b/libavformat/internal.h
index 9b07cfb271..23757dc4fc 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -310,6 +310,13 @@  typedef struct FFStream {
      */
     int64_t mux_ts_offset;
 
+    /**
+     * This is the lowest ts allowed in this track; it may be set by the muxer
+     * during init or write_header and influences the automatic timestamp
+     * shifting code.
+     */
+    int64_t lowest_ts_allowed;
+
     /**
      * Internal data to check for wrapping of the time stamp
      */
diff --git a/libavformat/mux.c b/libavformat/mux.c
index a3b50dadb6..5d89458f82 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -632,6 +632,8 @@  static void handle_avoid_negative_ts(FFFormatContext *si, FFStream *sti,
         if (ts == AV_NOPTS_VALUE)
             return;
 
+        ts -= sti->lowest_ts_allowed;
+
         /* Peek into the muxing queue to improve our estimate
          * of the lowest timestamp if av_interleaved_write_frame() is used. */
         for (const PacketListEntry *pktl = si->packet_buffer.head;
@@ -640,6 +642,7 @@  static void handle_avoid_negative_ts(FFFormatContext *si, FFStream *sti,
             int64_t cmp_ts = use_pts ? pktl->pkt.pts : pktl->pkt.dts;
             if (cmp_ts == AV_NOPTS_VALUE)
                 continue;
+            cmp_ts -= ffstream(s->streams[pktl->pkt.stream_index])->lowest_ts_allowed;
             if (s->output_ts_offset)
                 cmp_ts += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, cmp_tb);
             if (av_compare_ts(cmp_ts, cmp_tb, ts, tb) < 0) {
@@ -669,7 +672,7 @@  static void handle_avoid_negative_ts(FFFormatContext *si, FFStream *sti,
         pkt->pts += offset;
 
     if (si->avoid_negative_ts_use_pts) {
-        if (pkt->pts != AV_NOPTS_VALUE && pkt->pts < 0) {
+        if (pkt->pts != AV_NOPTS_VALUE && pkt->pts < sti->lowest_ts_allowed) {
             av_log(s, AV_LOG_WARNING, "failed to avoid negative "
                    "pts %s in stream %d.\n"
                    "Try -avoid_negative_ts 1 as a possible workaround.\n",
@@ -678,7 +681,7 @@  static void handle_avoid_negative_ts(FFFormatContext *si, FFStream *sti,
             );
         }
     } else {
-        if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) {
+        if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < sti->lowest_ts_allowed) {
             av_log(s, AV_LOG_WARNING,
                    "Packets poorly interleaved, failed to avoid negative "
                    "timestamp %s in stream %d.\n"