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.
This commit is contained in:
wm4 2013-12-07 19:32:44 +01:00
parent 75d3bf4711
commit bb6165342d
11 changed files with 194 additions and 157 deletions

View File

@ -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");
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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)
int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params)
{
struct MPOpts *opts = last->opts;
vf_instance_t *vf;
int i;
// 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);
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;
}
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

View File

@ -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);

View File

@ -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;

View File

@ -88,8 +88,6 @@ static int control(struct vf_instance *vf, int request, void *data)
};
return vo_control(video_out, VOCTRL_GET_EQUALIZER, &param) == VO_TRUE;
}
case VFCTRL_GET_HWDEC_INFO:
return vo_control(video_out, VOCTRL_GET_HWDEC_INFO, data) == VO_TRUE;
}
return CONTROL_UNKNOWN;
}