From b1c0bbe8b8b9d25c2682f29af66ad243e0072897 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 21 Dec 2016 18:18:24 +0100 Subject: [PATCH] video: use demuxer-signaled duration for last video frame Helps with gif, probably does unwanted things with other formats. This doesn't handle --end quite correctly, but this could be added later. Fixes #3924. --- player/core.h | 3 +++ player/video.c | 6 ++++++ video/decode/vd_lavc.c | 5 +++++ video/mp_image.c | 1 + video/mp_image.h | 2 +- 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/player/core.h b/player/core.h index 9a71ce33de..5d055482a5 100644 --- a/player/core.h +++ b/player/core.h @@ -353,6 +353,9 @@ typedef struct MPContext { // As video_pts, but is not reset when seeking away. (For the very short // period of time until a new frame is decoded and shown.) double last_vo_pts; + // Frame duration field from demuxer. Only used for duration of the last + // video frame. + double last_frame_duration; // Video PTS, or audio PTS if video has ended. double playback_pts; // audio stats only diff --git a/player/video.c b/player/video.c index 03dd5aeabe..4621d19cb4 100644 --- a/player/video.c +++ b/player/video.c @@ -343,6 +343,7 @@ void reset_video_state(struct MPContext *mpctx) mpctx->delay = 0; mpctx->time_frame = 0; mpctx->video_pts = MP_NOPTS_VALUE; + mpctx->last_frame_duration = 0; mpctx->num_past_frames = 0; mpctx->total_avsync_change = 0; mpctx->last_av_difference = 0; @@ -1369,6 +1370,9 @@ void write_video(struct MPContext *mpctx) { MP_VERBOSE(mpctx, "assuming this is an image\n"); mpctx->time_frame += opts->image_display_duration; + } else if (mpctx->last_frame_duration > 0) { + MP_VERBOSE(mpctx, "using demuxer frame duration for last frame\n"); + mpctx->time_frame += mpctx->last_frame_duration; } else { mpctx->time_frame = 0; } @@ -1482,6 +1486,8 @@ void write_video(struct MPContext *mpctx) mpctx->video_pts = mpctx->next_frames[0]->pts; mpctx->last_vo_pts = mpctx->video_pts; + mpctx->last_frame_duration = + mpctx->next_frames[0]->pkt_duration / mpctx->video_speed; shift_frames(mpctx); diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index cd3c611ebd..78d34bbb47 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -859,6 +859,11 @@ static void decode(struct dec_video *vd, struct demux_packet *packet, mpi->pts = mp_pts_from_av(ctx->pic->pts, &ctx->codec_timebase); mpi->dts = mp_pts_from_av(ctx->pic->pkt_dts, &ctx->codec_timebase); +#if LIBAVCODEC_VERSION_MICRO >= 100 + mpi->pkt_duration = + mp_pts_from_av(av_frame_get_pkt_duration(ctx->pic), &ctx->codec_timebase); +#endif + struct mp_image_params params; update_image_params(vd, ctx->pic, ¶ms); mp_image_set_params(mpi, ¶ms); diff --git a/video/mp_image.c b/video/mp_image.c index ee1ab4104e..2c4627c33e 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -386,6 +386,7 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) dst->fields = src->fields; dst->pts = src->pts; dst->dts = src->dts; + dst->pkt_duration = src->pkt_duration; dst->params.rotate = src->params.rotate; dst->params.stereo_in = src->params.stereo_in; dst->params.stereo_out = src->params.stereo_out; diff --git a/video/mp_image.h b/video/mp_image.h index 7c0f7bad7e..6606f19c90 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -85,7 +85,7 @@ typedef struct mp_image { /* only inside filter chain */ double pts; /* only after decoder */ - double dts; + double dts, pkt_duration; /* for private use */ void* priv;