From ce18c36ed9328b4b5d376562594d8acb13a6723d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 18 Mar 2014 08:19:05 +0100 Subject: [PATCH] decoder/ffmpeg: handle unknown stream start time --- NEWS | 1 + src/decoder/FfmpegDecoderPlugin.cxx | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 5abed4964..66db1f6d8 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.18.10 (not yet released) * decoder - ffmpeg: fix seeking bug + - ffmpeg: handle unknown stream start time - gme: fix memory leak ver 0.18.9 (2014/03/02) diff --git a/src/decoder/FfmpegDecoderPlugin.cxx b/src/decoder/FfmpegDecoderPlugin.cxx index e1e848bf3..bcb1ae3c9 100644 --- a/src/decoder/FfmpegDecoderPlugin.cxx +++ b/src/decoder/FfmpegDecoderPlugin.cxx @@ -197,6 +197,29 @@ time_to_ffmpeg(double t, const AVRational time_base) time_base); } +/** + * Replace #AV_NOPTS_VALUE with the given fallback. + */ +static constexpr int64_t +timestamp_fallback(int64_t t, int64_t fallback) +{ + return gcc_likely(t != int64_t(AV_NOPTS_VALUE)) + ? t + : fallback; +} + +/** + * Accessor for AVStream::start_time that replaces AV_NOPTS_VALUE with + * zero. We can't use AV_NOPTS_VALUE in calculations, and we simply + * assume that the stream's start time is zero, which appears to be + * the best way out of that situation. + */ +static int64_t +start_time_fallback(const AVStream &stream) +{ + return timestamp_fallback(stream.start_time, 0); +} + static void copy_interleave_frame2(uint8_t *dest, uint8_t **src, unsigned nframes, unsigned nchannels, @@ -263,7 +286,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is, { if (packet->pts >= 0 && packet->pts != (int64_t)AV_NOPTS_VALUE) decoder_timestamp(decoder, - time_from_ffmpeg(packet->pts - stream->start_time, + time_from_ffmpeg(packet->pts - start_time_fallback(*stream), stream->time_base)); AVPacket packet2 = *packet; @@ -493,7 +516,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) int64_t where = time_to_ffmpeg(decoder_seek_where(decoder), av_stream->time_base) + - av_stream->start_time; + start_time_fallback(*av_stream); if (av_seek_frame(format_context, audio_stream, where, AVSEEK_FLAG_ANY) < 0)