aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2013-05-10 09:29:44 +0200
committerAnton Khirnov <anton@khirnov.net>2015-02-20 09:18:30 +0100
commit3a163db8106e2a36b48d265ae9f2b3a6f60f14cf (patch)
tree094dd4135fc438a3d1221d239fbe3590526c1c15
parent3813490f0ac20b5fe5f4017deff77224f34ede66 (diff)
libav decoder plugin: improve timestamps handling
Make sure the timestamps start at zero.
-rw-r--r--src/decoder/libav_decoder_plugin.c34
1 files 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);
}