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 <is...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel