summaryrefslogtreecommitdiffstats
path: root/filters
diff options
context:
space:
mode:
Diffstat (limited to 'filters')
-rw-r--r--filters/f_autoconvert.c45
-rw-r--r--filters/f_autoconvert.h9
-rw-r--r--filters/f_swscale.c13
-rw-r--r--filters/f_swscale.h5
4 files changed, 69 insertions, 3 deletions
diff --git a/filters/f_autoconvert.c b/filters/f_autoconvert.c
index 065092ac64..20c083de54 100644
--- a/filters/f_autoconvert.c
+++ b/filters/f_autoconvert.c
@@ -27,6 +27,8 @@ struct priv {
int *imgfmts;
int *subfmts;
int num_imgfmts;
+ struct mp_image_params imgparams;
+ bool imgparams_set;
// Enable special conversion for the final stage before the VO.
bool vo_convert;
@@ -73,6 +75,7 @@ void mp_autoconvert_clear(struct mp_autoconvert *c)
struct priv *p = c->f->priv;
p->num_imgfmts = 0;
+ p->imgparams_set = false;
p->num_afmts = 0;
p->num_srates = 0;
p->chmaps = (struct mp_chmap_sel){0};
@@ -93,6 +96,23 @@ void mp_autoconvert_add_imgfmt(struct mp_autoconvert *c, int imgfmt, int subfmt)
p->force_update = true;
}
+void mp_autoconvert_set_target_image_params(struct mp_autoconvert *c,
+ struct mp_image_params *par)
+{
+ struct priv *p = c->f->priv;
+
+ if (p->imgparams_set && mp_image_params_equal(&p->imgparams, par) &&
+ p->num_imgfmts == 1 && p->imgfmts[0] == par->imgfmt &&
+ p->subfmts[0] == par->hw_subfmt)
+ return;
+
+ p->imgparams = *par;
+ p->imgparams_set = true;
+
+ p->num_imgfmts = 0;
+ mp_autoconvert_add_imgfmt(c, par->imgfmt, par->hw_subfmt);
+}
+
void mp_autoconvert_add_all_sw_imgfmts(struct mp_autoconvert *c)
{
for (int n = IMGFMT_START; n < IMGFMT_END; n++) {
@@ -185,8 +205,13 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
bool samesubffmt = img->params.hw_subfmt == p->subfmts[n];
if (samefmt && !samesubffmt)
different_subfmt = true;
- if (samefmt && (samesubffmt || !p->subfmts[n]))
+ if (samefmt && (samesubffmt || !p->subfmts[n])) {
+ if (p->imgparams_set) {
+ if (!mp_image_params_equal(&p->imgparams, &img->params))
+ break;
+ }
return true;
+ }
}
struct mp_stream_info *info = mp_filter_find_stream_info(f);
@@ -200,6 +225,8 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
// 2: sw->hw upload
struct mp_filter *filters[3] = {0};
bool need_sws = true;
+ bool force_sws_params = false;
+ struct mp_image_params imgpar = img->params;
int *fmts = p->imgfmts;
int num_fmts = p->num_imgfmts;
@@ -259,9 +286,21 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
if (hwd) {
filters[0] = hwd->f;
src_fmt = res_fmt;
+ // Downloading from hw will obviously change the parameters. We
+ // stupidly don't know the result parameters, but if it's
+ // sufficiently sane, it will only do the following.
+ imgpar.imgfmt = src_fmt;
+ imgpar.hw_subfmt = 0;
+ // Try to compensate for in-sane cases.
+ mp_image_params_guess_csp(&imgpar);
}
}
+ if (p->imgparams_set) {
+ force_sws_params |= !mp_image_params_equal(&imgpar, &p->imgparams);
+ need_sws |= force_sws_params;
+ }
+
if (need_sws) {
// Create a new conversion filter.
struct mp_sws_filter *sws = mp_sws_filter_create(conv);
@@ -277,11 +316,13 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
goto fail;
}
- if (out == src_fmt) {
+ if (out == src_fmt && !force_sws_params) {
// Can happen if hwupload goes to same format.
talloc_free(sws->f);
} else {
sws->out_format = out;
+ sws->out_params = p->imgparams;
+ sws->use_out_params = force_sws_params;
mp_info(log, "Converting %s -> %s\n", mp_imgfmt_to_name(src_fmt),
mp_imgfmt_to_name(sws->out_format));
filters[1] = sws->f;
diff --git a/filters/f_autoconvert.h b/filters/f_autoconvert.h
index e8c5a44134..ae08fd4e51 100644
--- a/filters/f_autoconvert.h
+++ b/filters/f_autoconvert.h
@@ -3,6 +3,7 @@
#include "filter.h"
struct mp_image;
+struct mp_image_params;
// A filter which automatically creates and uses a conversion filter based on
// the filter settings, or passes through data unchanged if no conversion is
@@ -22,6 +23,14 @@ struct mp_autoconvert {
// (to free this, free the filter itself, mp_autoconvert.f)
struct mp_autoconvert *mp_autoconvert_create(struct mp_filter *parent);
+// Require that output frames have the following params set.
+// This implicitly clears the image format list, and calls
+// mp_autoconvert_add_imgfmt() with the values in *p.
+// Idempotent on subsequent calls (no reinit forced if parameters don't change).
+// Mixing this with other format-altering calls has undefined effects.
+void mp_autoconvert_set_target_image_params(struct mp_autoconvert *c,
+ struct mp_image_params *p);
+
// Add the imgfmt as allowed video image format, and error on non-video frames.
// Each call adds to the list of allowed formats. Before the first call, all
// formats are allowed (even non-video).
diff --git a/filters/f_swscale.c b/filters/f_swscale.c
index 07198b1377..1ff25ab909 100644
--- a/filters/f_swscale.c
+++ b/filters/f_swscale.c
@@ -88,9 +88,18 @@ static void process(struct mp_filter *f)
}
struct mp_image *src = frame.data;
+
int dstfmt = s->out_format ? s->out_format : src->imgfmt;
+ int w = src->w;
+ int h = src->h;
+
+ if (s->use_out_params) {
+ w = s->out_params.w;
+ h = s->out_params.h;
+ dstfmt = s->out_params.imgfmt;
+ }
- struct mp_image *dst = mp_image_pool_get(s->pool, dstfmt, src->w, src->h);
+ struct mp_image *dst = mp_image_pool_get(s->pool, dstfmt, w, h);
if (!dst)
goto error;
@@ -102,6 +111,8 @@ static void process(struct mp_filter *f)
{
dst->params.color.levels = MP_CSP_LEVELS_TV;
}
+ if (s->use_out_params)
+ dst->params = s->out_params;
mp_image_params_guess_csp(&dst->params);
bool ok = mp_sws_scale(s->sws, dst, src) >= 0;
diff --git a/filters/f_swscale.h b/filters/f_swscale.h
index fd5aa11f5e..6e26aef1ac 100644
--- a/filters/f_swscale.h
+++ b/filters/f_swscale.h
@@ -2,10 +2,15 @@
#include <stdbool.h>
+#include "video/mp_image.h"
+
struct mp_sws_filter {
struct mp_filter *f;
// Desired output imgfmt. If 0, uses the input format.
int out_format;
+ // If set, force all image params; ignores out_format.
+ bool use_out_params;
+ struct mp_image_params out_params;
// private state
struct mp_sws_context *sws;
struct mp_image_pool *pool;