From ff24285eb15676dc7519b858be01a1def155e847 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 19 Apr 2018 17:42:14 +0200 Subject: video: pass through container fps to filters This means vf_vapoursynth doesn't need a hack to work around the filter code, and libavfilter filters now actually get the frame_rate field on input pads set. The libavfilter doxygen says the frame_rate field is only to be set if the frame rate is known to be constant, and uses the word "must" (which probably means they really mean it?) - but ffmpeg.c sets the field to mere guesses anyway, and it looks like this normally won't lead to problems. --- filters/f_decoder_wrapper.c | 1 + filters/f_lavfi.c | 9 ++++++++- filters/f_output_chain.c | 7 ------- filters/filter.h | 1 - video/filter/vf_vapoursynth.c | 10 ++++------ video/mp_image.c | 1 + video/mp_image.h | 2 ++ 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c index 16b9cd06df..2ad145b5cb 100644 --- a/filters/f_decoder_wrapper.c +++ b/filters/f_decoder_wrapper.c @@ -358,6 +358,7 @@ static void process_video_frame(struct priv *p, struct mp_image *mpi) fix_image_params(p, &mpi->params); mpi->params = p->fixed_format; + mpi->nominal_fps = p->public.fps; mpi->pts = pts; p->pts = pts; diff --git a/filters/f_lavfi.c b/filters/f_lavfi.c index 1b41c93aac..2c01eaf59c 100644 --- a/filters/f_lavfi.c +++ b/filters/f_lavfi.c @@ -340,7 +340,8 @@ static bool is_vformat_ok(struct mp_image *a, struct mp_image *b) { return a->imgfmt == b->imgfmt && a->w == b->w && a->h && b->h && - a->params.p_w == b->params.p_w && a->params.p_h == b->params.p_h; + a->params.p_w == b->params.p_w && a->params.p_h == b->params.p_h && + a->nominal_fps == b->nominal_fps; } static bool is_format_ok(struct mp_frame a, struct mp_frame b) { @@ -483,6 +484,7 @@ static bool init_pads(struct lavfi *c) params->sample_aspect_ratio.num = fmt->params.p_w; params->sample_aspect_ratio.den = fmt->params.p_h; params->hw_frames_ctx = fmt->hwctx; + params->frame_rate = av_d2q(fmt->nominal_fps, 1000000); filter_name = "buffer"; } else { assert(0); @@ -680,6 +682,11 @@ static bool read_output_pads(struct lavfi *c) mp_aframe_set_pts(aframe, c->in_pts + (c->in_pts != MP_NOPTS_VALUE ? (out_time - in_time) : 0)); } + if (frame.type == MP_FRAME_VIDEO) { + struct mp_image *vframe = frame.data; + vframe->nominal_fps = + av_q2d(av_buffersink_get_frame_rate(pad->buffer)); + } av_frame_unref(c->tmp_frame); if (frame.type) { mp_pin_in_write(pad->pin, frame); diff --git a/filters/f_output_chain.c b/filters/f_output_chain.c index e986614e9d..cd577a6ca2 100644 --- a/filters/f_output_chain.c +++ b/filters/f_output_chain.c @@ -357,12 +357,6 @@ static double get_display_fps(struct mp_stream_info *i) return res; } -static double get_container_fps(struct mp_stream_info *i) -{ - struct chain *p = i->priv; - return p->public.container_fps; -} - void mp_output_chain_set_vo(struct mp_output_chain *c, struct vo *vo) { struct chain *p = c->f->priv; @@ -650,7 +644,6 @@ static void create_video_things(struct chain *p) p->stream_info.priv = p; p->stream_info.get_display_fps = get_display_fps; - p->stream_info.get_container_fps = get_container_fps; p->f->stream_info = &p->stream_info; diff --git a/filters/filter.h b/filters/filter.h index e63b812a79..33177444c2 100644 --- a/filters/filter.h +++ b/filters/filter.h @@ -382,7 +382,6 @@ struct mp_stream_info { void *priv; // for use by whoever implements the callbacks double (*get_display_fps)(struct mp_stream_info *i); - double (*get_container_fps)(struct mp_stream_info *i); struct mp_hwdec_devices *hwdec_devs; struct osd_state *osd; diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c index 5077f4cf19..d9a222db83 100644 --- a/video/filter/vf_vapoursynth.c +++ b/video/filter/vf_vapoursynth.c @@ -103,7 +103,7 @@ static const struct mp_image dummy_img; static const struct mp_image dummy_img_eof; static void destroy_vs(struct priv *p); -static int reinit_vs(struct priv *p); +static int reinit_vs(struct priv *p, struct mp_image *input); struct script_driver { int (*init)(struct priv *p); // first time init @@ -368,7 +368,7 @@ static void vf_vapoursynth_process(struct mp_filter *f) if (p->out_node) destroy_vs(p); p->fmt_in = mpi->params; - if (reinit_vs(p) < 0) { + if (reinit_vs(p, mpi) < 0) { MP_ERR(p, "could not init VS\n"); mp_frame_unref(&frame); return; @@ -617,7 +617,7 @@ static void destroy_vs(struct priv *p) MP_DBG(p, "uninitialized.\n"); } -static int reinit_vs(struct priv *p) +static int reinit_vs(struct priv *p, struct mp_image *input) { VSMap *vars = NULL, *in = NULL, *out = NULL; int res = -1; @@ -665,11 +665,9 @@ static int reinit_vs(struct priv *p) p->vsapi->propSetInt(vars, "video_in_dh", d_h, 0); struct mp_stream_info *info = mp_filter_find_stream_info(p->f); - double container_fps = 0; + double container_fps = input->nominal_fps; double display_fps = 0; if (info) { - if (info->get_container_fps) - container_fps = info->get_container_fps(info); if (info->get_display_fps) display_fps = info->get_display_fps(info); } diff --git a/video/mp_image.c b/video/mp_image.c index 6ab3b87150..8aa3aa025c 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -508,6 +508,7 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) dst->params.color = src->params.color; dst->params.chroma_location = src->params.chroma_location; dst->params.spherical = src->params.spherical; + dst->nominal_fps = src->nominal_fps; // ensure colorspace consistency if (mp_image_params_get_forced_csp(&dst->params) != mp_image_params_get_forced_csp(&src->params)) diff --git a/video/mp_image.h b/video/mp_image.h index 88e261306f..70e9b9e138 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -105,6 +105,8 @@ typedef struct mp_image { double pts; /* only after decoder */ double dts, pkt_duration; + /* container reported FPS; can be incorrect, or 0 if unknown */ + double nominal_fps; /* for private use */ void* priv; -- cgit v1.2.3