summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-10-21 01:29:48 +0200
committerwm4 <wm4@nowhere>2019-10-21 01:38:25 +0200
commit5dba244c226383f9f3b15b07dfa5133ad08b6497 (patch)
tree3b6e46e9ef3350670f32a56140322980e3b37954 /video
parent8a4e9d5c180157684546db4c1235d8c958172ca9 (diff)
downloadmpv-5dba244c226383f9f3b15b07dfa5133ad08b6497.tar.bz2
mpv-5dba244c226383f9f3b15b07dfa5133ad08b6497.tar.xz
filters: extend vf_format so that it can convert color parameters
Form some reason (and because of my fault), vf_format converts image formats, but nothing else. For example, setting the "colormatrix" sub-parameter would not convert it to the new value, but instead overwrite the metadata (basically "reinterpreting" the image data without changing it). Make the historical mistake worse, and go all the way and extend it such that it can perform a conversion. For compatibility reasons, this needs to be requested explicitly. (Maybe this would deserve a separate filter to begin with, but things are messed up anyway. Feel free to suggest an elegant and simple solution.) This demonstrates how zimg can properly perform some conversions which swscale cannot (see examples added to vf.rst). Stupidly this requires 2 code paths, one for conversion, and one for overriding the parameters. Due to the filter bullshit (what was I thinking), this requires quite some acrobatics that would not be necessary without these abstractions. On the other hand, it'd definitely be more of a mess without it. Oh whatever.
Diffstat (limited to 'video')
-rw-r--r--video/filter/vf_format.c88
1 files changed, 52 insertions, 36 deletions
diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c
index 1700f002ab..942fa27a52 100644
--- a/video/filter/vf_format.c
+++ b/video/filter/vf_format.c
@@ -36,12 +36,11 @@
struct priv {
struct vf_format_opts *opts;
- struct mp_pin *in_pin;
+ struct mp_autoconvert *conv;
};
struct vf_format_opts {
int fmt;
- int outfmt;
int colormatrix;
int colorlevels;
int primaries;
@@ -53,34 +52,11 @@ struct vf_format_opts {
int rotate;
int dw, dh;
double dar;
+ int convert;
};
-static void vf_format_process(struct mp_filter *f)
+static void set_params(struct vf_format_opts *p, struct mp_image_params *out)
{
- struct priv *priv = f->priv;
- struct vf_format_opts *p = priv->opts;
-
- if (!mp_pin_can_transfer_data(f->ppins[1], priv->in_pin))
- return;
-
- struct mp_frame frame = mp_pin_out_read(priv->in_pin);
-
- if (mp_frame_is_signaling(frame)) {
- mp_pin_in_write(f->ppins[1], frame);
- return;
- }
- if (frame.type != MP_FRAME_VIDEO) {
- MP_ERR(f, "unsupported frame type\n");
- mp_frame_unref(&frame);
- mp_filter_internal_mark_failed(f);
- return;
- }
-
- struct mp_image *img = frame.data;
- struct mp_image_params *out = &img->params;
-
- if (p->outfmt)
- out->imgfmt = p->outfmt;
if (p->colormatrix)
out->color.space = p->colormatrix;
if (p->colorlevels)
@@ -118,11 +94,53 @@ static void vf_format_process(struct mp_filter *f)
if (p->dar > 0)
dsize = av_d2q(p->dar, INT_MAX);
mp_image_params_set_dsize(out, dsize.num, dsize.den);
+}
+
+static void vf_format_process(struct mp_filter *f)
+{
+ struct priv *priv = f->priv;
- // Make sure the user-overrides are consistent (no RGB csp for YUV, etc.).
- mp_image_params_guess_csp(out);
+ if (mp_pin_can_transfer_data(priv->conv->f->pins[0], f->ppins[0])) {
+ struct mp_frame frame = mp_pin_out_read(f->ppins[0]);
- mp_pin_in_write(f->ppins[1], frame);
+ if (priv->opts->convert && frame.type == MP_FRAME_VIDEO) {
+ struct mp_image *img = frame.data;
+ struct mp_image_params par = img->params;
+ int outfmt = priv->opts->fmt;
+
+ // If we convert from RGB to YUV, default to limited range.
+ if (mp_imgfmt_get_forced_csp(img->imgfmt) == MP_CSP_RGB &&
+ outfmt && mp_imgfmt_get_forced_csp(outfmt) == MP_CSP_AUTO)
+ {
+ par.color.levels = MP_CSP_LEVELS_TV;
+ }
+
+ set_params(priv->opts, &par);
+
+ if (par.imgfmt != outfmt) {
+ par.imgfmt = outfmt;
+ par.hw_subfmt = 0;
+ }
+ mp_image_params_guess_csp(&par);
+
+ mp_autoconvert_set_target_image_params(priv->conv, &par);
+ }
+
+ mp_pin_in_write(priv->conv->f->pins[0], frame);
+ }
+
+ if (mp_pin_can_transfer_data(f->ppins[1], priv->conv->f->pins[1])) {
+ struct mp_frame frame = mp_pin_out_read(priv->conv->f->pins[1]);
+
+ if (!priv->opts->convert && frame.type == MP_FRAME_VIDEO) {
+ struct mp_image *img = frame.data;
+
+ set_params(priv->opts, &img->params);
+ mp_image_params_guess_csp(&img->params);
+ }
+
+ mp_pin_in_write(f->ppins[1], frame);
+ }
}
static const struct mp_filter_info vf_format_filter = {
@@ -145,17 +163,14 @@ static struct mp_filter *vf_format_create(struct mp_filter *parent, void *option
mp_filter_add_pin(f, MP_PIN_IN, "in");
mp_filter_add_pin(f, MP_PIN_OUT, "out");
- struct mp_autoconvert *conv = mp_autoconvert_create(f);
- if (!conv) {
+ priv->conv = mp_autoconvert_create(f);
+ if (!priv->conv) {
talloc_free(f);
return NULL;
}
if (priv->opts->fmt)
- mp_autoconvert_add_imgfmt(conv, priv->opts->fmt, 0);
-
- priv->in_pin = conv->f->pins[1];
- mp_pin_connect(conv->f->pins[0], f->ppins[0]);
+ mp_autoconvert_add_imgfmt(priv->conv, priv->opts->fmt, 0);
return f;
}
@@ -175,6 +190,7 @@ static const m_option_t vf_opts_fields[] = {
OPT_INT("dw", dw, 0),
OPT_INT("dh", dh, 0),
OPT_DOUBLE("dar", dar, 0),
+ OPT_FLAG("convert", convert, 0),
OPT_REMOVED("outputlevels", "use the --video-output-levels global option"),
OPT_REMOVED("peak", "use sig-peak instead (changed value scale!)"),
{0}