From 4205bbf243227bf151f2439ecb7772c41ecbfd12 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 25 Nov 2013 23:08:29 +0100 Subject: video: pass PTS as part of demux_packet/AVPacket and mp_image/AVFrame Instead of passing the PTS as separate field, pass it as part of the usual data structures. Basically, this removes strange artifacts from the API. (It's not finished, though: the final decoded PTS goes through strange paths, and filter_video() finally overwrites the decoded mp_image's pts field with it.) We also stop using libavcodec's reordered_opaque fields, and use AVPacket.pts and AVFrame.pkt_pts. This is slightly unorthodox, because these pts fields are not "really" opaque anymore, yet we treat them as such. But the end result should be the same, and reordered_opaque is marked as partially deprecated (it's not clear whether it's really deprecated). --- mpvcore/player/video.c | 21 ++++++++------------- video/decode/dec_video.c | 7 +++++-- video/decode/dec_video.h | 8 +++++--- video/decode/vd.h | 2 +- video/decode/vd_lavc.c | 22 +++++++++++----------- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/mpvcore/player/video.c b/mpvcore/player/video.c index 9ff6c8ec3d..f858106750 100644 --- a/mpvcore/player/video.c +++ b/mpvcore/player/video.c @@ -323,8 +323,8 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx) update_fps(mpctx); int framedrop_type = check_framedrop(mpctx, frame_time); - void *decoded_frame = video_decode(d_video, pkt, framedrop_type, - d_video->pts); + pkt->pts = d_video->pts; + void *decoded_frame = video_decode(d_video, pkt, framedrop_type); talloc_free(pkt); if (decoded_frame) { filter_video(mpctx, decoded_frame); @@ -343,7 +343,7 @@ static double update_video_attached_pic(struct MPContext *mpctx) return -1; struct mp_image *decoded_frame = - video_decode(d_video, d_video->header->attached_picture, 0, 0); + video_decode(d_video, d_video->header->attached_picture, 0); if (decoded_frame) filter_video(mpctx, decoded_frame); load_next_vo_frame(mpctx, true); @@ -393,12 +393,9 @@ double update_video(struct MPContext *mpctx, double endpts) if (d_video->header->attached_picture) return update_video_attached_pic(mpctx); - double pts; - while (1) { if (load_next_vo_frame(mpctx, false)) break; - pts = MP_NOPTS_VALUE; struct demux_packet *pkt = NULL; while (1) { pkt = demux_read_packet(d_video->header); @@ -409,16 +406,14 @@ double update_video(struct MPContext *mpctx, double endpts) * that must have packets at fixed timecode intervals. */ talloc_free(pkt); } - if (pkt) - pts = pkt->pts; - if (pts != MP_NOPTS_VALUE) - pts += mpctx->video_offset; - if (pts >= mpctx->hrseek_pts - .005) + if (pkt && pkt->pts != MP_NOPTS_VALUE) + pkt->pts += mpctx->video_offset; + if (pkt && pkt->pts >= mpctx->hrseek_pts - .005) mpctx->hrseek_framedrop = false; int framedrop_type = mpctx->hrseek_active && mpctx->hrseek_framedrop ? 1 : check_framedrop(mpctx, -1); struct mp_image *decoded_frame = - video_decode(d_video, pkt, framedrop_type, pts); + video_decode(d_video, pkt, framedrop_type); talloc_free(pkt); if (decoded_frame) { determine_frame_pts(mpctx); @@ -433,7 +428,7 @@ double update_video(struct MPContext *mpctx, double endpts) if (!video_out->frame_loaded) return 0; - pts = video_out->next_pts; + double pts = video_out->next_pts; if (pts == MP_NOPTS_VALUE) { MP_ERR(mpctx, "Video pts after filters MISSING\n"); // Try to use decoder pts from before filters diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 34dc9bd073..e9a59da255 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -206,10 +206,11 @@ bool video_init_best_codec(struct dec_video *d_video, char* video_decoders) } void *video_decode(struct dec_video *d_video, struct demux_packet *packet, - int drop_frame, double pts) + int drop_frame) { mp_image_t *mpi = NULL; struct MPOpts *opts = d_video->opts; + double pts = packet ? packet->pts : MP_NOPTS_VALUE; if (opts->correct_pts && pts != MP_NOPTS_VALUE) { int delay = -1; @@ -242,7 +243,7 @@ void *video_decode(struct dec_video *d_video, struct demux_packet *packet, } } - mpi = d_video->vd_driver->decode(d_video, packet, drop_frame, &pts); + mpi = d_video->vd_driver->decode(d_video, packet, drop_frame); //------------------------ frame decoded. -------------------- @@ -256,6 +257,8 @@ void *video_decode(struct dec_video *d_video, struct demux_packet *packet, else if (opts->field_dominance == 1) mpi->fields &= ~MP_IMGFIELD_TOP_FIRST; + pts = mpi->pts; + double prevpts = d_video->codec_reordered_pts; d_video->prev_codec_reordered_pts = prevpts; d_video->codec_reordered_pts = pts; diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 9f01d32947..7d8928eb58 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -42,8 +42,6 @@ struct dec_video { void *priv; - float next_frame_time; - double last_pts; double buffered_pts[32]; int num_buffered_pts; double codec_reordered_pts; @@ -59,6 +57,10 @@ struct dec_video { int i_bps; // == bitrate (compressed bytes/sec) float fps; // FPS from demuxer or from user override float initial_decoder_aspect; + + // State used only by player/video.c + float next_frame_time; + double last_pts; }; struct mp_decoder_list *video_decoder_list(void); @@ -68,7 +70,7 @@ void video_uninit(struct dec_video *d_video); struct demux_packet; void *video_decode(struct dec_video *d_video, struct demux_packet *packet, - int drop_frame, double pts); + int drop_frame); int video_get_colors(struct dec_video *d_video, const char *item, int *value); int video_set_colors(struct dec_video *d_video, const char *item, int value); diff --git a/video/decode/vd.h b/video/decode/vd.h index dd2536ab2a..045914f502 100644 --- a/video/decode/vd.h +++ b/video/decode/vd.h @@ -35,7 +35,7 @@ typedef struct vd_functions void (*uninit)(struct dec_video *vd); int (*control)(struct dec_video *vd, int cmd, void *arg); struct mp_image *(*decode)(struct dec_video *vd, struct demux_packet *pkt, - int flags, double *reordered_pts); + int flags); } vd_functions_t; // NULL terminated array of all drivers diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 864da74741..03d77e1c2b 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -729,12 +729,11 @@ static struct mp_image *image_from_decoder(struct dec_video *vd) #endif /* HAVE_AVUTIL_REFCOUNTING */ static int decode(struct dec_video *vd, struct demux_packet *packet, - int flags, double *reordered_pts, struct mp_image **out_image) + int flags, struct mp_image **out_image) { int got_picture = 0; int ret; vd_ffmpeg_ctx *ctx = vd->priv; - AVFrame *pic = ctx->pic; AVCodecContext *avctx = ctx->avctx; AVPacket pkt; @@ -747,22 +746,23 @@ static int decode(struct dec_video *vd, struct demux_packet *packet, mp_set_av_packet(&pkt, packet); - // The avcodec opaque field stupidly supports only int64_t type + // We merely pass-through our PTS as an int64_t; libavcodec won't use it. union pts { int64_t i; double d; }; - avctx->reordered_opaque = (union pts){.d = *reordered_pts}.i; - ret = avcodec_decode_video2(avctx, pic, &got_picture, &pkt); + pkt.pts = (union pts){.d = packet ? packet->pts : MP_NOPTS_VALUE}.i; + ret = avcodec_decode_video2(avctx, ctx->pic, &got_picture, &pkt); if (ret < 0) { mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Error while decoding frame!\n"); return -1; } - *reordered_pts = (union pts){.i = pic->reordered_opaque}.d; // Skipped frame, or delayed output due to multithreaded decoding. if (!got_picture) return 0; - update_image_params(vd, pic); + update_image_params(vd, ctx->pic); + double out_pts = (union pts){.i = ctx->pic->pkt_pts}.d; + // Note: potentially resets ctx->pic as it is transferred to mpi struct mp_image *mpi = image_from_decoder(vd); assert(mpi->planes[0]); mp_image_set_params(mpi, &ctx->image_params); @@ -772,6 +772,7 @@ static int decode(struct dec_video *vd, struct demux_packet *packet, struct mp_image_params vo_params; mp_image_params_from_image(&vo_params, mpi); + mpi->pts = out_pts; if (!mp_image_params_equals(&vo_params, &ctx->vo_image_params)) { mp_image_pool_clear(ctx->non_dr1_pool); @@ -787,15 +788,14 @@ static int decode(struct dec_video *vd, struct demux_packet *packet, } static struct mp_image *decode_with_fallback(struct dec_video *vd, - struct demux_packet *packet, - int flags, double *reordered_pts) + struct demux_packet *packet, int flags) { vd_ffmpeg_ctx *ctx = vd->priv; if (!ctx->avctx) return NULL; struct mp_image *mpi = NULL; - int res = decode(vd, packet, flags, reordered_pts, &mpi); + int res = decode(vd, packet, flags, &mpi); if (res >= 0) return mpi; @@ -811,7 +811,7 @@ static struct mp_image *decode_with_fallback(struct dec_video *vd, mpi = NULL; if (vd->vf_initialized < 0) vd->vf_initialized = 0; - decode(vd, packet, flags, reordered_pts, &mpi); + decode(vd, packet, flags, &mpi); return mpi; } } -- cgit v1.2.3