From bb6165342db0ba60fefa97afe770b393fd6cb463 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 7 Dec 2013 19:32:44 +0100 Subject: video: create a separate context for video filter chain This adds vf_chain, which unlike vf_instance refers to the filter chain as a whole. This makes the filter API less awkward, and will allow handling format negotiation better. --- mpvcore/player/command.c | 12 +-- mpvcore/player/playloop.c | 3 +- mpvcore/player/screenshot.c | 6 +- mpvcore/player/video.c | 24 +++--- video/decode/dec_video.c | 56 ++----------- video/decode/dec_video.h | 3 +- video/decode/vd_lavc.c | 4 +- video/filter/vf.c | 189 +++++++++++++++++++++++++++++++------------- video/filter/vf.h | 52 ++++++------ video/filter/vf_vavpp.c | 6 +- video/filter/vf_vo.c | 2 - 11 files changed, 197 insertions(+), 160 deletions(-) diff --git a/mpvcore/player/command.c b/mpvcore/player/command.c index 05742e0da6..728e01c636 100644 --- a/mpvcore/player/command.c +++ b/mpvcore/player/command.c @@ -1189,13 +1189,13 @@ static int probe_deint_filters(struct MPContext *mpctx, const char *cmd) static int get_deinterlacing(struct MPContext *mpctx) { - vf_instance_t *vf = mpctx->d_video->vfilter; + struct vf_chain *c = mpctx->d_video->vfilter; int enabled = 0; - if (vf->control(vf, VFCTRL_GET_DEINTERLACE, &enabled) != CONTROL_OK) + if (vf_control_any(c, VFCTRL_GET_DEINTERLACE, &enabled) != CONTROL_OK) enabled = -1; if (enabled < 0) { // vf_lavfi doesn't support VFCTRL_GET_DEINTERLACE - if (vf_find_by_label(vf, VF_DEINTERLACE_LABEL)) + if (vf_find_by_label(c, VF_DEINTERLACE_LABEL)) enabled = 1; } return enabled; @@ -1203,14 +1203,14 @@ static int get_deinterlacing(struct MPContext *mpctx) static void set_deinterlacing(struct MPContext *mpctx, bool enable) { - vf_instance_t *vf = mpctx->d_video->vfilter; - if (vf_find_by_label(vf, VF_DEINTERLACE_LABEL)) { + struct vf_chain *c = mpctx->d_video->vfilter; + if (vf_find_by_label(c, VF_DEINTERLACE_LABEL)) { if (!enable) edit_filters(mpctx, STREAM_VIDEO, "del", "@" VF_DEINTERLACE_LABEL); } else { if ((get_deinterlacing(mpctx) > 0) != enable) { int arg = enable; - if (vf->control(vf, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK) + if (vf_control_any(c, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK) probe_deint_filters(mpctx, "pre"); } } diff --git a/mpvcore/player/playloop.c b/mpvcore/player/playloop.c index b069e5c3f7..b87231c709 100644 --- a/mpvcore/player/playloop.c +++ b/mpvcore/player/playloop.c @@ -994,7 +994,8 @@ void run_playloop(struct MPContext *mpctx) if (!vo->frame_loaded && (!mpctx->paused || mpctx->restart_playback)) { double frame_time = update_video(mpctx, endpts); mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time); - if (mpctx->d_video->vf_initialized < 0) { + if (mpctx->d_video->vfilter && mpctx->d_video->vfilter->initialized < 0) + { MP_FATAL(mpctx, "\nFATAL: Could not initialize video filters " "(-vf) or video output (-vo).\n"); int uninit = INITIALIZED_VCODEC; diff --git a/mpvcore/player/screenshot.c b/mpvcore/player/screenshot.c index 6a3c258094..bf7a0ce9ee 100644 --- a/mpvcore/player/screenshot.c +++ b/mpvcore/player/screenshot.c @@ -314,10 +314,8 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode) struct voctrl_screenshot_args args = { .full_window = (mode == MODE_FULL_WINDOW) }; - if (mpctx->d_video && mpctx->d_video->vfilter) { - struct vf_instance *vfilter = mpctx->d_video->vfilter; - vfilter->control(vfilter, VFCTRL_SCREENSHOT, &args); - } + if (mpctx->d_video && mpctx->d_video->vfilter) + vf_control_any(mpctx->d_video->vfilter, VFCTRL_SCREENSHOT, &args); if (!args.out_image) vo_control(mpctx->video_out, VOCTRL_SCREENSHOT, &args); diff --git a/mpvcore/player/video.c b/mpvcore/player/video.c index 6560192fb4..1b88422593 100644 --- a/mpvcore/player/video.c +++ b/mpvcore/player/video.c @@ -58,18 +58,19 @@ static void recreate_video_filters(struct MPContext *mpctx) struct dec_video *d_video = mpctx->d_video; assert(d_video); - vf_uninit_filter_chain(d_video->vfilter); + vf_destroy(d_video->vfilter); + d_video->vfilter = vf_new(opts); + d_video->vfilter->hwdec = &d_video->hwdec_info; - d_video->vfilter = vf_open_filter(opts, NULL, "vo", NULL); - if (!d_video->vfilter) - abort(); - d_video->vfilter->control(d_video->vfilter, VFCTRL_SET_VO, mpctx->video_out); + vf_append_filter(d_video->vfilter, "vo", NULL); + vf_control_any(d_video->vfilter, VFCTRL_SET_VO, mpctx->video_out); - d_video->vfilter = append_filters(d_video->vfilter, opts->vf_settings); + vf_append_filter_list(d_video->vfilter, opts->vf_settings); - struct vf_instance *vf = d_video->vfilter; + // for vf_sub + vf_control_any(d_video->vfilter, VFCTRL_SET_OSD_OBJ, mpctx->osd); mpctx->osd->render_subs_in_filter - = vf->control(vf, VFCTRL_INIT_OSD, NULL) == VO_TRUE; + = vf_control_any(d_video->vfilter, VFCTRL_INIT_OSD, NULL) == CONTROL_OK; } int reinit_video_filters(struct MPContext *mpctx) @@ -82,7 +83,7 @@ int reinit_video_filters(struct MPContext *mpctx) recreate_video_filters(mpctx); video_reinit_vo(d_video); - return d_video->vf_initialized > 0 ? 0 : -1; + return d_video->vfilter && d_video->vfilter->initialized > 0 ? 0 : -1; } int reinit_video_chain(struct MPContext *mpctx) @@ -189,7 +190,7 @@ static bool filter_output_queued_frame(struct MPContext *mpctx) struct dec_video *d_video = mpctx->d_video; struct vo *video_out = mpctx->video_out; - struct mp_image *img = vf_chain_output_queued_frame(d_video->vfilter); + struct mp_image *img = vf_output_queued_frame(d_video->vfilter); if (img) vo_queue_image(video_out, img); talloc_free(img); @@ -215,7 +216,7 @@ static void init_filter_params(struct MPContext *mpctx) // might recreate the chain a second time, which is not very elegant, but // allows us to test whether enabling deinterlacing works with the current // video format and other filters. - if (d_video->vf_initialized != 1) + if (!d_video->vfilter || d_video->vfilter->initialized != 1) return; if (d_video->vf_reconfig_count <= mpctx->last_vf_reconfig_count) { @@ -286,7 +287,6 @@ double update_video(struct MPContext *mpctx, double endpts) { struct dec_video *d_video = mpctx->d_video; struct vo *video_out = mpctx->video_out; - vf_control(d_video->vfilter, VFCTRL_SET_OSD_OBJ, mpctx->osd); // for vf_sub if (d_video->header->attached_picture) return update_video_attached_pic(mpctx); diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 7b7f7f73fc..9a43ada4c4 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -59,8 +59,8 @@ const vd_functions_t * const mpcodecs_vd_drivers[] = { void video_reset_decoding(struct dec_video *d_video) { video_vd_control(d_video, VDCTRL_RESET, NULL); - if (d_video->vf_initialized == 1) - vf_chain_seek_reset(d_video->vfilter); + if (d_video->vfilter && d_video->vfilter->initialized == 1) + vf_seek_reset(d_video->vfilter); d_video->num_buffered_pts = 0; d_video->last_pts = MP_NOPTS_VALUE; d_video->last_packet_pdts = MP_NOPTS_VALUE; @@ -81,15 +81,14 @@ int video_vd_control(struct dec_video *d_video, int cmd, void *arg) int video_set_colors(struct dec_video *d_video, const char *item, int value) { - vf_instance_t *vf = d_video->vfilter; vf_equalizer_t data; data.item = item; data.value = value; mp_dbg(MSGT_DECVIDEO, MSGL_V, "set video colors %s=%d \n", item, value); - if (vf) { - int ret = vf_control(vf, VFCTRL_SET_EQUALIZER, &data); + if (d_video->vfilter) { + int ret = vf_control_any(d_video->vfilter, VFCTRL_SET_EQUALIZER, &data); if (ret == CONTROL_TRUE) return 1; } @@ -100,14 +99,13 @@ int video_set_colors(struct dec_video *d_video, const char *item, int value) int video_get_colors(struct dec_video *d_video, const char *item, int *value) { - vf_instance_t *vf = d_video->vfilter; vf_equalizer_t data; data.item = item; mp_dbg(MSGT_DECVIDEO, MSGL_V, "get video colors %s \n", item); - if (vf) { - int ret = vf_control(vf, VFCTRL_GET_EQUALIZER, &data); + if (d_video->vfilter) { + int ret = vf_control_any(d_video->vfilter, VFCTRL_GET_EQUALIZER, &data); if (ret == CONTROL_TRUE) { *value = data.value; return 1; @@ -128,7 +126,7 @@ void video_uninit(struct dec_video *d_video) d_video->vd_driver->uninit(d_video); } talloc_free(d_video->priv); - vf_uninit_filter_chain(d_video->vfilter); + vf_destroy(d_video->vfilter); talloc_free(d_video); } @@ -383,7 +381,6 @@ int mpcodecs_reconfig_vo(struct dec_video *d_video, const struct mp_image_params *params) { struct MPOpts *opts = d_video->opts; - vf_instance_t *vf = d_video->vfilter; struct mp_image_params p = *params; struct sh_video *sh = d_video->header->video; @@ -397,37 +394,6 @@ int mpcodecs_reconfig_vo(struct dec_video *d_video, mp_msg(MSGT_DECVIDEO, MSGL_V, "VDec: vo config request - %d x %d (%s)\n", p.w, p.h, vo_format_name(p.imgfmt)); - // check if libvo and codec has common outfmt (no conversion): - int flags = 0; - for (;;) { - mp_msg(MSGT_VFILTER, MSGL_V, "Trying filter chain:\n"); - vf_print_filter_chain(MSGL_V, vf); - - flags = vf->query_format(vf, p.imgfmt); - mp_msg(MSGT_CPLAYER, MSGL_DBG2, "vo_debug: query(%s) returned 0x%X \n", - vo_format_name(p.imgfmt), flags); - if ((flags & VFCAP_CSP_SUPPORTED_BY_HW) - || (flags & VFCAP_CSP_SUPPORTED)) - { - break; - } - // TODO: no match - we should use conversion... - if (strcmp(vf->info->name, "scale")) { - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Could not find matching colorspace - retrying with -vf scale...\n"); - vf = vf_open_filter(opts, vf, "scale", NULL); - continue; - } - mp_tmsg(MSGT_CPLAYER, MSGL_WARN, - "The selected video_out device is incompatible with this codec.\n"\ - "Try appending the scale filter to your filter list,\n"\ - "e.g. -vf filter,scale instead of -vf filter.\n"); - mp_tmsg(MSGT_VFILTER, MSGL_WARN, "Attempted filter chain:\n"); - vf_print_filter_chain(MSGL_WARN, vf); - d_video->vf_initialized = -1; - return -1; // failed - } - d_video->vfilter = vf; - float decoder_aspect = p.d_w / (float)p.d_h; if (d_video->initial_decoder_aspect == 0) d_video->initial_decoder_aspect = decoder_aspect; @@ -473,17 +439,11 @@ int mpcodecs_reconfig_vo(struct dec_video *d_video, mp_msg(MSGT_CPLAYER, MSGL_V, "VO Config (%dx%d->%dx%d,0x%X)\n", p.w, p.h, p.d_w, p.d_h, p.imgfmt); - if (vf_reconfig_wrapper(vf, &p, 0) < 0) { + if (vf_reconfig(d_video->vfilter, &p) < 0) { mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "FATAL: Cannot initialize video driver.\n"); - d_video->vf_initialized = -1; return -1; } - mp_tmsg(MSGT_VFILTER, MSGL_V, "Video filter chain:\n"); - vf_print_filter_chain(MSGL_V, vf); - - d_video->vf_initialized = 1; - d_video->vf_input = p; if (opts->gamma_gamma != 1000) diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 090b60bc1c..29e23ff322 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -30,9 +30,8 @@ struct mp_decoder_list; struct dec_video { struct MPOpts *opts; - struct vf_instance *vfilter; // video filter chain + struct vf_chain *vfilter; // video filter chain const struct vd_functions *vd_driver; - int vf_initialized; // -1 failed, 0 not done, 1 done long vf_reconfig_count; // incremented each mpcodecs_reconfig_vo() call struct mp_image_params vf_input; // video filter input params struct mp_hwdec_info hwdec_info; // video output hwdec handles diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 10e46b78b1..7683f6c6de 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -791,8 +791,8 @@ static struct mp_image *decode_with_fallback(struct dec_video *vd, init_avctx(vd, decoder, NULL); if (ctx->avctx) { mpi = NULL; - if (vd->vf_initialized < 0) - vd->vf_initialized = 0; + if (vd->vfilter && vd->vfilter->initialized < 0) + vd->vfilter->initialized = 0; decode(vd, packet, flags, &mpi); return mpi; } diff --git a/video/filter/vf.c b/video/filter/vf.c index 03044906f9..21f89e5386 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -116,6 +116,10 @@ static const vf_info_t *const filter_list[] = { NULL }; +static void vf_uninit_filter(vf_instance_t *vf); +static int vf_reconfig_wrapper(struct vf_instance *vf, + const struct mp_image_params *params, int flags); + static bool get_desc(struct m_obj_desc *dst, int index) { if (index >= MP_ARRAY_SIZE(filter_list) - 1) @@ -139,9 +143,11 @@ const struct m_obj_list vf_obj_list = { .description = "video filters", }; -int vf_control(struct vf_instance *vf, int cmd, void *arg) +int vf_control_any(struct vf_chain *c, int cmd, void *arg) { - return vf->control(vf, cmd, arg); + if (c->first) + return c->first->control(c->first, cmd, arg); + return CONTROL_UNKNOWN; } static void vf_fix_img_params(struct mp_image *img, struct mp_image_params *p) @@ -210,12 +216,12 @@ static void print_fmt(int msglevel, struct vf_format *fmt) } } -void vf_print_filter_chain(int msglevel, struct vf_instance *vf) +void vf_print_filter_chain(struct vf_chain *c, int msglevel) { if (!mp_msg_test(MSGT_VFILTER, msglevel)) return; - for (vf_instance_t *f = vf; f; f = f->next) { + for (vf_instance_t *f = c->first; f; f = f->next) { mp_msg(MSGT_VFILTER, msglevel, " [%s] ", f->info->name); print_fmt(msglevel, &f->fmt_in); if (f->next) { @@ -226,8 +232,8 @@ void vf_print_filter_chain(int msglevel, struct vf_instance *vf) } } -static struct vf_instance *vf_open(struct MPOpts *opts, vf_instance_t *next, - const char *name, char **args) +static struct vf_instance *vf_open(struct vf_chain *c, const char *name, + char **args) { struct m_obj_desc desc; if (!m_obj_list_find(&desc, &vf_obj_list, bstr0(name))) { @@ -238,16 +244,17 @@ static struct vf_instance *vf_open(struct MPOpts *opts, vf_instance_t *next, vf_instance_t *vf = talloc_zero(NULL, struct vf_instance); *vf = (vf_instance_t) { .info = desc.p, - .opts = opts, - .next = next, + .opts = c->opts, + .hwdec = c->hwdec, .config = vf_next_config, .control = vf_next_control, .query_format = vf_default_query_format, .filter = vf_default_filter, .out_pool = talloc_steal(vf, mp_image_pool_new(16)), + .chain = c, }; struct m_config *config = m_config_from_obj_desc(vf, &desc); - if (m_config_apply_defaults(config, name, opts->vf_defs) < 0) + if (m_config_apply_defaults(config, name, c->opts->vf_defs) < 0) goto error; if (m_config_set_obj_params(config, args) < 0) goto error; @@ -263,8 +270,8 @@ error: return NULL; } -vf_instance_t *vf_open_filter(struct MPOpts *opts, vf_instance_t *next, - const char *name, char **args) +static vf_instance_t *vf_open_filter(struct vf_chain *c, const char *name, + char **args) { if (strcmp(name, "vo") != 0) { int i, l = 0; @@ -279,7 +286,35 @@ vf_instance_t *vf_open_filter(struct MPOpts *opts, vf_instance_t *next, mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n", "Opening video filter: ", str); } - return vf_open(opts, next, name, args); + return vf_open(c, name, args); +} + +struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name, + char **args) +{ + struct vf_instance *vf = vf_open_filter(c, name, args); + if (vf) { + // Insert it before the last filter, which is the "vo" filter + struct vf_instance **pprev = &c->first; + while (*pprev && (*pprev)->next) + pprev = &(*pprev)->next; + vf->next = *pprev ? *pprev : NULL; + *pprev = vf; + } + return vf; +} + +int vf_append_filter_list(struct vf_chain *c, struct m_obj_settings *list) +{ + for (int n = 0; list && list[n].name; n++) { + struct vf_instance *vf = + vf_append_filter(c, list[n].name, list[n].attribs); + if (vf) { + if (list[n].label) + vf->label = talloc_strdup(vf, list[n].label); + } + } + return 0; } // Used by filters to add a filtered frame to the output queue. @@ -304,9 +339,7 @@ static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf) return res; } -// Input a frame into the filter chain. -// Return >= 0 on success, < 0 on failure (even if output frames were produced) -int vf_filter_frame(struct vf_instance *vf, struct mp_image *img) +static int vf_do_filter(struct vf_instance *vf, struct mp_image *img) { assert(vf->fmt_in.configured); vf_fix_img_params(img, &vf->fmt_in.params); @@ -319,12 +352,24 @@ int vf_filter_frame(struct vf_instance *vf, struct mp_image *img) } } +// Input a frame into the filter chain. Ownership of img is transferred. +// Return >= 0 on success, < 0 on failure (even if output frames were produced) +int vf_filter_frame(struct vf_chain *c, struct mp_image *img) +{ + if (c->first) { + return vf_do_filter(c->first, img); + } else { + talloc_free(img); + return 0; + } +} + // Output the next queued image (if any) from the full filter chain. -struct mp_image *vf_chain_output_queued_frame(struct vf_instance *vf) +struct mp_image *vf_output_queued_frame(struct vf_chain *c) { while (1) { struct vf_instance *last = NULL; - for (struct vf_instance * cur = vf; cur; cur = cur->next) { + for (struct vf_instance * cur = c->first; cur; cur = cur->next) { if (cur->num_out_queued) last = cur; } @@ -333,7 +378,7 @@ struct mp_image *vf_chain_output_queued_frame(struct vf_instance *vf) struct mp_image *img = vf_dequeue_output_frame(last); if (!last->next) return img; - vf_filter_frame(last->next, img); + vf_do_filter(last->next, img); } } @@ -344,15 +389,17 @@ static void vf_forget_frames(struct vf_instance *vf) vf->num_out_queued = 0; } -void vf_chain_seek_reset(struct vf_instance *vf) +void vf_seek_reset(struct vf_chain *c) { - vf->control(vf, VFCTRL_SEEK_RESET, NULL); - for (struct vf_instance *cur = vf; cur; cur = cur->next) + if (!c->first) + return; + c->first->control(c->first, VFCTRL_SEEK_RESET, NULL); + for (struct vf_instance *cur = c->first; cur; cur = cur->next) vf_forget_frames(cur); } -int vf_reconfig_wrapper(struct vf_instance *vf, const struct mp_image_params *p, - int flags) +static int vf_reconfig_wrapper(struct vf_instance *vf, const struct mp_image_params *p, + int flags) { vf_forget_frames(vf); mp_image_pool_clear(vf->out_pool); @@ -382,7 +429,6 @@ int vf_reconfig_wrapper(struct vf_instance *vf, const struct mp_image_params *p, int vf_next_reconfig(struct vf_instance *vf, struct mp_image_params *p, int outflags) { - struct MPOpts *opts = vf->opts; int flags = vf->next->query_format(vf->next, p->imgfmt); if (!flags) { // hmm. colorspace mismatch!!! @@ -390,9 +436,10 @@ int vf_next_reconfig(struct vf_instance *vf, struct mp_image_params *p, vf_instance_t *vf2; if (vf->next->info == &vf_info_scale) return -1; // scale->scale - vf2 = vf_open_filter(opts, vf->next, "scale", NULL); + vf2 = vf_open_filter(vf->chain, "scale", NULL); if (!vf2) return -1; // shouldn't happen! + vf2->next = vf->next; vf->next = vf2; flags = vf->next->query_format(vf->next, p->imgfmt); if (!flags) { @@ -437,43 +484,59 @@ int vf_next_query_format(struct vf_instance *vf, unsigned int fmt) //============================================================================ -vf_instance_t *append_filters(vf_instance_t *last, - struct m_obj_settings *vf_settings) -{ - struct MPOpts *opts = last->opts; - vf_instance_t *vf; - int i; - - if (vf_settings) { - // We want to add them in the 'right order' - for (i = 0; vf_settings[i].name; i++) - /* NOP */; - for (i--; i >= 0; i--) { - //printf("Open filter %s\n",vf_settings[i].name); - vf = vf_open_filter(opts, last, vf_settings[i].name, - vf_settings[i].attribs); - if (vf) { - if (vf_settings[i].label) - vf->label = talloc_strdup(vf, vf_settings[i].label); - last = vf; - } +int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params) +{ + // check if libvo and codec has common outfmt (no conversion): + struct vf_instance *vf = c->first; + int flags = 0; + for (;;) { + mp_msg(MSGT_VFILTER, MSGL_V, "Trying filter chain:\n"); + vf_print_filter_chain(c, MSGL_V); + + flags = vf->query_format(vf, params->imgfmt); + mp_msg(MSGT_CPLAYER, MSGL_DBG2, "vo_debug: query(%s) returned 0x%X \n", + vo_format_name(params->imgfmt), flags); + if ((flags & VFCAP_CSP_SUPPORTED_BY_HW) + || (flags & VFCAP_CSP_SUPPORTED)) + { + break; + } + // TODO: no match - we should use conversion... + if (strcmp(vf->info->name, "scale")) { + mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Could not find matching colorspace - retrying with -vf scale...\n"); + vf = vf_open_filter(c, "scale", NULL); + vf->next = c->first; + c->first = vf; + continue; } + mp_tmsg(MSGT_CPLAYER, MSGL_WARN, + "The selected video_out device is incompatible with this codec.\n"\ + "Try appending the scale filter to your filter list,\n"\ + "e.g. -vf filter,scale instead of -vf filter.\n"); + mp_tmsg(MSGT_VFILTER, MSGL_WARN, "Attempted filter chain:\n"); + vf_print_filter_chain(c, MSGL_WARN); + c->initialized = -1; + return -1; // failed } - return last; + + int r = vf_reconfig_wrapper(c->first, params, 0); + c->initialized = r >= 0 ? 1 : -1; + mp_tmsg(MSGT_VFILTER, MSGL_V, "Video filter chain:\n"); + vf_print_filter_chain(c, MSGL_V); + return r; } -vf_instance_t *vf_find_by_label(vf_instance_t *chain, const char *label) +struct vf_instance *vf_find_by_label(struct vf_chain *c, const char *label) { - while (chain) { - if (chain->label && label && strcmp(chain->label, label) == 0) - return chain; - chain = chain->next; + struct vf_instance *vf = c->first; + while (vf) { + if (vf->label && label && strcmp(vf->label, label) == 0) + return vf; + vf = vf->next; } return NULL; } -//============================================================================ - void vf_uninit_filter(vf_instance_t *vf) { if (vf->uninit) @@ -482,13 +545,25 @@ void vf_uninit_filter(vf_instance_t *vf) talloc_free(vf); } -void vf_uninit_filter_chain(vf_instance_t *vf) +struct vf_chain *vf_new(struct MPOpts *opts) { - while (vf) { - vf_instance_t *next = vf->next; + struct vf_chain *c = talloc_ptrtype(NULL, c); + *c = (struct vf_chain){ + .opts = opts, + }; + return c; +} + +void vf_destroy(struct vf_chain *c) +{ + if (!c) + return; + while (c->first) { + vf_instance_t *vf = c->first; + c->first = vf->next; vf_uninit_filter(vf); - vf = next; } + talloc_free(c); } // When changing the size of an image that had old_w/old_h with diff --git a/video/filter/vf.h b/video/filter/vf.h index d47ac2beb8..21031de3ac 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -29,6 +29,7 @@ struct MPOpts; struct vf_instance; struct vf_priv_s; +struct m_obj_settings; typedef struct vf_info { const char *description; @@ -82,11 +83,25 @@ typedef struct vf_instance { struct mp_image_pool *out_pool; struct vf_priv_s *priv; struct MPOpts *opts; + struct mp_hwdec_info *hwdec; struct mp_image **out_queued; int num_out_queued; + + // Temporary + struct vf_chain *chain; } vf_instance_t; +// A chain of video filters +struct vf_chain { + int initialized; // 0: no, 1: yes, -1: attempted to, but failed + + struct vf_instance *first; + + struct MPOpts *opts; + struct mp_hwdec_info *hwdec; +}; + typedef struct vf_seteq { const char *item; int value; @@ -104,22 +119,26 @@ enum vf_ctrl { * access OSD/subtitle state outside of normal OSD draw time. */ VFCTRL_SET_OSD_OBJ, VFCTRL_SET_VO, - VFCTRL_GET_HWDEC_INFO, // for hwdec filters }; -int vf_control(struct vf_instance *vf, int cmd, void *arg); - +struct vf_chain *vf_new(struct MPOpts *opts); +void vf_destroy(struct vf_chain *c); +int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params); +int vf_control_any(struct vf_chain *c, int cmd, void *arg); +int vf_filter_frame(struct vf_chain *c, struct mp_image *img); +struct mp_image *vf_output_queued_frame(struct vf_chain *c); +void vf_seek_reset(struct vf_chain *c); +struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name, + char **args); +int vf_append_filter_list(struct vf_chain *c, struct m_obj_settings *list); +struct vf_instance *vf_find_by_label(struct vf_chain *c, const char *label); +void vf_print_filter_chain(struct vf_chain *c, int msglevel); + +// Filter internal API struct mp_image *vf_alloc_out_image(struct vf_instance *vf); void vf_make_out_image_writeable(struct vf_instance *vf, struct mp_image *img); void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img); -int vf_filter_frame(struct vf_instance *vf, struct mp_image *img); -struct mp_image *vf_chain_output_queued_frame(struct vf_instance *vf); -void vf_chain_seek_reset(struct vf_instance *vf); - -vf_instance_t *vf_open_filter(struct MPOpts *opts, vf_instance_t *next, - const char *name, char **args); - // default wrappers: int vf_next_config(struct vf_instance *vf, int width, int height, int d_width, int d_height, @@ -130,18 +149,7 @@ int vf_next_query_format(struct vf_instance *vf, unsigned int fmt); int vf_next_reconfig(struct vf_instance *vf, struct mp_image_params *params, int flags); -struct m_obj_settings; -vf_instance_t *append_filters(vf_instance_t *last, - struct m_obj_settings *vf_settings); - -vf_instance_t *vf_find_by_label(vf_instance_t *chain, const char *label); - -void vf_uninit_filter(vf_instance_t *vf); -void vf_uninit_filter_chain(vf_instance_t *vf); - -int vf_reconfig_wrapper(struct vf_instance *vf, - const struct mp_image_params *params, int flags); -void vf_print_filter_chain(int msglevel, struct vf_instance *vf); +// Helpers void vf_rescale_dsize(int *d_width, int *d_height, int old_w, int old_h, int new_w, int new_h); diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c index 352f2a586c..1a8a974e11 100644 --- a/video/filter/vf_vavpp.c +++ b/video/filter/vf_vavpp.c @@ -372,10 +372,8 @@ static int vf_open(vf_instance_t *vf) vf->control = control; struct vf_priv_s *p = vf->priv; - struct mp_hwdec_info hwdec = {0}; - vf_control(vf->next, VFCTRL_GET_HWDEC_INFO, &hwdec); - hwdec_request_api(&hwdec, "vaapi"); - p->va = hwdec.vaapi_ctx; + hwdec_request_api(vf->hwdec, "vaapi"); + p->va = vf->hwdec ? vf->hwdec->vaapi_ctx : NULL; if (!p->va || !p->va->display) return false; p->display = p->va->display; diff --git a/video/filter/vf_vo.c b/video/filter/vf_vo.c index 3ba0a60fe8..87cdb781f7 100644 --- a/video/filter/vf_vo.c +++ b/video/filter/vf_vo.c @@ -88,8 +88,6 @@ static int control(struct vf_instance *vf, int request, void *data) }; return vo_control(video_out, VOCTRL_GET_EQUALIZER, ¶m) == VO_TRUE; } - case VFCTRL_GET_HWDEC_INFO: - return vo_control(video_out, VOCTRL_GET_HWDEC_INFO, data) == VO_TRUE; } return CONTROL_UNKNOWN; } -- cgit v1.2.3