[FFmpeg-devel] [PATCH] lavf/utils: Fix DTS for short H264 streams.

Sasi Inguva isasi at google.com
Sat Mar 12 11:40:25 CET 2016


Fill DTS if all packets have been read in avformat_find_stream_info, and still
has_decode_delay_been_guessed returns false.

Signed-off-by: Sasi Inguva <isasi at google.com>
---
 libavformat/utils.c             |  77 ++++++++++++++++++-------
 tests/fate/h264.mak             |   3 +
 tests/ref/fate/h264-dts_5frames | 125 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 184 insertions(+), 21 deletions(-)
 create mode 100644 tests/ref/fate/h264-dts_5frames

diff --git a/libavformat/utils.c b/libavformat/utils.c
index 5f48de1..e027302 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -936,14 +936,44 @@ static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t
     return dts;
 }
 
+/**
+ * Updates the dts of packets of a stream in pkt_buffer, by re-ordering the pts
+ * of the packets in a window.
+ */
+static void update_dts_from_pts(AVFormatContext *s, int stream_index,
+                                AVPacketList *pkt_buffer)
+{
+    AVStream *st       = s->streams[stream_index];
+    int delay          = st->codec->has_b_frames;
+    int i;
+
+    int64_t pts_buffer[MAX_REORDER_DELAY+1];
+
+    for (i = 0; i<MAX_REORDER_DELAY+1; i++)
+        pts_buffer[i] = AV_NOPTS_VALUE;
+
+    for (; pkt_buffer; pkt_buffer = get_next_pkt(s, st, pkt_buffer)) {
+        if (pkt_buffer->pkt.stream_index != stream_index)
+            continue;
+
+        if (pkt_buffer->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) {
+            pts_buffer[0] = pkt_buffer->pkt.pts;
+            for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
+                FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
+
+            pkt_buffer->pkt.dts = select_from_pts_buffer(st, pts_buffer, pkt_buffer->pkt.dts);
+        }
+    }
+}
+
 static void update_initial_timestamps(AVFormatContext *s, int stream_index,
                                       int64_t dts, int64_t pts, AVPacket *pkt)
 {
     AVStream *st       = s->streams[stream_index];
     AVPacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue;
-    int64_t pts_buffer[MAX_REORDER_DELAY+1];
+    AVPacketList *pktl_it;
+
     uint64_t shift;
-    int i, delay;
 
     if (st->first_dts != AV_NOPTS_VALUE ||
         dts           == AV_NOPTS_VALUE ||
@@ -951,36 +981,28 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
         is_relative(dts))
         return;
 
-    delay         = st->codec->has_b_frames;
     st->first_dts = dts - (st->cur_dts - RELATIVE_TS_BASE);
     st->cur_dts   = dts;
     shift         = (uint64_t)st->first_dts - RELATIVE_TS_BASE;
 
-    for (i = 0; i<MAX_REORDER_DELAY+1; i++)
-        pts_buffer[i] = AV_NOPTS_VALUE;
-
     if (is_relative(pts))
         pts += shift;
 
-    for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
-        if (pktl->pkt.stream_index != stream_index)
+    for (pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) {
+        if (pktl_it->pkt.stream_index != stream_index)
             continue;
-        if (is_relative(pktl->pkt.pts))
-            pktl->pkt.pts += shift;
+        if (is_relative(pktl_it->pkt.pts))
+            pktl_it->pkt.pts += shift;
 
-        if (is_relative(pktl->pkt.dts))
-            pktl->pkt.dts += shift;
+        if (is_relative(pktl_it->pkt.dts))
+            pktl_it->pkt.dts += shift;
 
-        if (st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE)
-            st->start_time = pktl->pkt.pts;
-
-        if (pktl->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)) {
-            pts_buffer[0] = pktl->pkt.pts;
-            for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
-                FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
+        if (st->start_time == AV_NOPTS_VALUE && pktl_it->pkt.pts != AV_NOPTS_VALUE)
+            st->start_time = pktl_it->pkt.pts;
+    }
 
-            pktl->pkt.dts = select_from_pts_buffer(st, pts_buffer, pktl->pkt.dts);
-        }
+    if (has_decode_delay_been_guessed(st)) {
+        update_dts_from_pts(s, stream_index, pktl);
     }
 
     if (st->start_time == AV_NOPTS_VALUE)
@@ -3165,6 +3187,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     int64_t max_stream_analyze_duration;
     int64_t max_subtitle_analyze_duration;
     int64_t probesize = ic->probesize;
+    int eof_reached = 0;
 
     flush_codecs = probesize > 0;
 
@@ -3331,6 +3354,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
 
         if (ret < 0) {
             /* EOF or error*/
+            eof_reached = 1;
             break;
         }
 
@@ -3454,6 +3478,17 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         count++;
     }
 
+    if (eof_reached && ic->internal->packet_buffer) {
+        int stream_index;
+        for (stream_index = 0; stream_index < ic->nb_streams; stream_index++) {
+            // EOF already reached while reading the stream above.
+            // So continue with reoordering DTS with whatever delay we have.
+            if (!has_decode_delay_been_guessed(st)) {
+                update_dts_from_pts(ic, stream_index, ic->internal->packet_buffer);
+            }
+        }
+    }
+
     if (flush_codecs) {
         AVPacket empty_pkt = { 0 };
         int err = 0;
diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak
index 46178cd..86f9f37 100644
--- a/tests/fate/h264.mak
+++ b/tests/fate/h264.mak
@@ -192,6 +192,7 @@ FATE_H264  := $(FATE_H264:%=fate-h264-conformance-%)                    \
               $(FATE_H264_REINIT_TESTS:%=fate-h264-reinit-%)            \
               fate-h264-extreme-plane-pred                              \
               fate-h264-lossless                                        \
+              fate-h264-dts_5frames                                     \
 
 FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264)
 FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-crop-to-container
@@ -395,3 +396,5 @@ fate-h264-lossless:                               CMD = framecrc -i $(TARGET_SAM
 fate-h264-direct-bff:                             CMD = framecrc -i $(TARGET_SAMPLES)/h264/direct-bff.mkv
 
 fate-h264-reinit-%:                               CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf format=yuv444p10le,scale=w=352:h=288
+
+fate-h264-dts_5frames:				  CMD = probeframes $(TARGET_SAMPLES)/h264/dts_5frames.mkv
diff --git a/tests/ref/fate/h264-dts_5frames b/tests/ref/fate/h264-dts_5frames
new file mode 100644
index 0000000..1c4c349
--- /dev/null
+++ b/tests/ref/fate/h264-dts_5frames
@@ -0,0 +1,125 @@
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=1
+pkt_pts=0
+pkt_pts_time=0.000000
+pkt_dts=0
+pkt_dts_time=0.000000
+best_effort_timestamp=0
+best_effort_timestamp_time=0.000000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=651
+pkt_size=14428
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=I
+coded_picture_number=0
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=167
+pkt_pts_time=0.167000
+pkt_dts=167
+pkt_dts_time=0.167000
+best_effort_timestamp=167
+best_effort_timestamp_time=0.167000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15085
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=1
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=333
+pkt_pts_time=0.333000
+pkt_dts=333
+pkt_dts_time=0.333000
+best_effort_timestamp=333
+best_effort_timestamp_time=0.333000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15102
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=2
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=500
+pkt_pts_time=0.500000
+pkt_dts=500
+pkt_dts_time=0.500000
+best_effort_timestamp=500
+best_effort_timestamp_time=0.500000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15119
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=3
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=667
+pkt_pts_time=0.667000
+pkt_dts=667
+pkt_dts_time=0.667000
+best_effort_timestamp=667
+best_effort_timestamp_time=0.667000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15136
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=4
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
-- 
2.7.0.rc3.207.g0ac5344



More information about the ffmpeg-devel mailing list