1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-25 08:12:17 +00:00

vf: fix another broken case of conversion filter auto-insertion

If the VO doesn't support a format output by vf_lavfi, no conversion
filter was inserted, and filter chain creation failed.

This is because vf_lavfi doesn't properly follow the format negotiation
model, which means the format negotiation pass does not catch all cases
where conversion is needed. Specifically, vf_lavfi supports that all
output formats are supported for any given input format, but then does
not actually call vf_next_query_format() in reconfig() to check which
format it uses, but outputs whatever it gets from libavfilter.

I think this is ok to avoid excessive complexity in vf_lavfi.c, but it
also means adding more kludges to vf.c. I justify this (and the code
duplication) with the idea that the current filter chain code will die
anyway at some point.

The .log field additions for c->first/c->last are strictly speaking not
needed, but useful for debugging.
This commit is contained in:
wm4 2017-04-05 11:06:25 +02:00
parent a1ad64a1c8
commit 400a7c409f

View File

@ -627,6 +627,39 @@ static void update_formats(struct vf_chain *c, struct vf_instance *vf,
}
}
// Insert a conversion filter _after_ vf.
// vf needs to have been successfully configured, vf->next unconfigured but
// with formats negotiated.
static void auto_insert_conversion_filter_if_needed(struct vf_chain *c,
struct vf_instance *vf)
{
if (!vf->next || vf->next->query_format(vf->next, vf->fmt_out.imgfmt) ||
is_conv_filter(vf) || is_conv_filter(vf->next))
return;
MP_INFO(c, "Using conversion filter.\n");
uint8_t fmts[IMGFMT_END - IMGFMT_START];
query_formats(fmts, vf->next);
uint8_t out_formats[IMGFMT_END - IMGFMT_START];
for (int n = IMGFMT_START; n < IMGFMT_END; n++)
out_formats[n - IMGFMT_START] = n == vf->fmt_out.imgfmt;
const char *filter = find_conv_filter(out_formats, fmts);
char **args = NULL;
char *args_no_warn[] = {"warn", "no", NULL};
if (strcmp(filter, "scale") == 0)
args = args_no_warn;
struct vf_instance *conv = vf_open(c, filter, args);
if (conv) {
conv->autoinserted = true;
conv->next = vf->next;
vf->next = conv;
update_formats(c, conv, vf->last_outfmts);
}
}
static int vf_reconfig_wrapper(struct vf_instance *vf,
const struct mp_image_params *p)
{
@ -689,6 +722,8 @@ int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params)
}
cur = vf->fmt_out;
hwfctx = vf->out_hwframes_ref;
// Recheck if the new output format works with the following filters.
auto_insert_conversion_filter_if_needed(c, vf);
}
c->output_params = cur;
c->initialized = r < 0 ? -1 : 1;
@ -757,12 +792,14 @@ struct vf_chain *vf_new(struct mpv_global *global)
static const struct vf_info in = { .name = "in" };
c->first = talloc(c, struct vf_instance);
*c->first = (struct vf_instance) {
.log = c->log,
.info = &in,
.query_format = input_query_format,
};
static const struct vf_info out = { .name = "out" };
c->last = talloc(c, struct vf_instance);
*c->last = (struct vf_instance) {
.log = c->log,
.info = &out,
.query_format = output_query_format,
.priv = (void *)c,