mirror of
https://github.com/mpv-player/mpv
synced 2024-12-25 16:33:02 +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:
parent
a1ad64a1c8
commit
400a7c409f
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user