From 3a163db8106e2a36b48d265ae9f2b3a6f60f14cf Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 May 2013 09:29:44 +0200 Subject: libav decoder plugin: improve timestamps handling Make sure the timestamps start at zero. --- src/decoder/libav_decoder_plugin.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/decoder/libav_decoder_plugin.c b/src/decoder/libav_decoder_plugin.c index eaeecd60..c27a4187 100644 --- a/src/decoder/libav_decoder_plugin.c +++ b/src/decoder/libav_decoder_plugin.c @@ -54,6 +54,11 @@ typedef struct LibavDecContext { AVIOContext *io; AVFormatContext *fmt_ctx; AVStream *ast; + + /* offset to be added to timestamps so they start at 0 */ + int64_t pts_offset; + /* pts of the last frame sent to the player */ + int64_t last_pts; } LibavDecContext; static const struct tag_table libav_tags[] = { @@ -194,13 +199,6 @@ fail: return ret; } -static double time_from_libav(int64_t t, const AVRational time_base) -{ - assert(t != (int64_t)AV_NOPTS_VALUE); - - return (double)av_rescale_q(t, time_base, (AVRational){1, 1024}) / (double)1024; -} - static int64_t time_to_libav(double t, const AVRational time_base) { return av_rescale_q((int64_t)(t * 1024), (AVRational){1, 1024}, time_base); @@ -212,9 +210,6 @@ static enum decoder_command libav_send_packet(LibavDecContext *s, AVPacket packet2 = *packet; enum decoder_command cmd = DECODE_COMMAND_NONE; - if (packet->pts != (int64_t)AV_NOPTS_VALUE) - decoder_timestamp(decoder, time_from_libav(packet->pts, *time_base)); - while (packet2.size > 0 && cmd == DECODE_COMMAND_NONE) { AVFrame *frame = av_frame_alloc(); @@ -242,6 +237,22 @@ static enum decoder_command libav_send_packet(LibavDecContext *s, continue; } + if (s->pts_offset == AV_NOPTS_VALUE) { + s->pts_offset = (frame->pkt_pts == AV_NOPTS_VALUE) ? + 0 : -frame->pkt_pts; + } + + if (frame->pkt_pts != AV_NOPTS_VALUE) { + int64_t timestamp = frame->pkt_pts + s->pts_offset; + if (timestamp < s->last_pts) { + g_warning("Non-monotonous timestamps: previous %"PRId64 + ", current %"PRId64"\n", s->last_pts, timestamp); + } else { + decoder_timestamp(s->decoder, timestamp * av_q2d(s->ast->time_base)); + s->last_pts = timestamp; + } + } + cmd = decoder_data(s->decoder, s->input, frame, s->ast->codec->bit_rate / 1000); } return cmd; @@ -249,7 +260,7 @@ static enum decoder_command libav_send_packet(LibavDecContext *s, static void libav_decode(struct decoder *decoder, struct input_stream *input) { - LibavDecContext s = { .decoder = decoder }; + LibavDecContext s = { .decoder = decoder, .pts_offset = AV_NOPTS_VALUE }; AVCodecContext *dec = NULL; const AVCodec *codec; struct audio_format audio_format; @@ -317,6 +328,7 @@ static void libav_decode(struct decoder *decoder, struct input_stream *input) AV_TIME_BASE) < 0) decoder_seek_error(decoder); else { + s.last_pts = 0; avcodec_flush_buffers(dec); decoder_command_finished(decoder); } -- cgit v1.2.3