summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-04-05 11:06:25 +0200
committerwm4 <wm4@nowhere>2017-04-05 11:06:25 +0200
commit400a7c409fa15252055e5747d7bff9acf593dd25 (patch)
tree742cee0476e8d088f5313493f2a4f4687adb439d
parenta1ad64a1c80bbeca1d9943e4a7ea86ff0bdcdb57 (diff)
downloadmpv-400a7c409fa15252055e5747d7bff9acf593dd25.tar.bz2
mpv-400a7c409fa15252055e5747d7bff9acf593dd25.tar.xz
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.
-rw-r--r--video/filter/vf.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/video/filter/vf.c b/video/filter/vf.c
index b5383732e3..004df75c2b 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -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,