summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/command.c145
-rw-r--r--core/mplayer.c1
-rw-r--r--video/decode/dec_video.c51
-rw-r--r--video/decode/dec_video.h2
-rw-r--r--video/decode/vd.c10
-rw-r--r--video/filter/vf.c17
-rw-r--r--video/filter/vf_scale.c69
-rw-r--r--video/filter/vf_sub.c12
-rw-r--r--video/mp_image.c2
-rw-r--r--video/out/vo.c9
10 files changed, 150 insertions, 168 deletions
diff --git a/core/command.c b/core/command.c
index af5e24d494..a5504438de 100644
--- a/core/command.c
+++ b/core/command.c
@@ -1093,13 +1093,16 @@ static int mp_property_deinterlace(m_option_t *prop, int action,
return M_PROPERTY_NOT_IMPLEMENTED;
}
-static int colormatrix_property_helper(m_option_t *prop, int action,
- void *arg, MPContext *mpctx)
+// Generic option + requires hard refresh to make changes take effect.
+static int video_refresh_property_helper(m_option_t *prop, int action,
+ void *arg, MPContext *mpctx)
{
int r = mp_property_generic_option(prop, action, arg, mpctx);
if (action == M_PROPERTY_SET) {
- if (mpctx->sh_video)
- set_video_colorspace(mpctx->sh_video);
+ if (mpctx->sh_video) {
+ reinit_video_filters(mpctx);
+ mp_force_video_refresh(mpctx);
+ }
}
return r;
}
@@ -1108,88 +1111,98 @@ static int mp_property_colormatrix(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
if (action != M_PROPERTY_PRINT)
- return colormatrix_property_helper(prop, action, arg, mpctx);
+ return video_refresh_property_helper(prop, action, arg, mpctx);
struct MPOpts *opts = &mpctx->opts;
- struct mp_csp_details actual = { .format = -1 };
- char *req_csp = mp_csp_names[opts->requested_colorspace];
- char *real_csp = NULL;
- if (mpctx->sh_video) {
- struct vf_instance *vf = mpctx->sh_video->vfilter;
- if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &actual) == true) {
- real_csp = mp_csp_names[actual.format];
- } else {
- real_csp = "Unknown";
- }
+
+ struct mp_csp_details vo_csp = {0};
+ if (mpctx->sh_video && mpctx->sh_video->vfilter)
+ vf_control(mpctx->sh_video->vfilter, VFCTRL_GET_YUV_COLORSPACE, &vo_csp);
+
+ struct mp_image_params vd_csp = {0};
+ if (mpctx->sh_video)
+ vd_control(mpctx->sh_video, VDCTRL_GET_PARAMS, &vd_csp);
+
+ char *res = talloc_asprintf(NULL, "%s",
+ mp_csp_names[opts->requested_colorspace]);
+ if (!vo_csp.format) {
+ res = talloc_asprintf_append(res, " (VO: unknown)");
+ } else if (vo_csp.format != opts->requested_colorspace) {
+ res = talloc_asprintf_append(res, " (VO: %s)",
+ mp_csp_names[vo_csp.format]);
+ }
+ if (!vd_csp.colorspace) {
+ res = talloc_asprintf_append(res, " (VD: unknown)");
+ } else if (!vo_csp.format || vd_csp.colorspace != vo_csp.format) {
+ res = talloc_asprintf_append(res, " (VD: %s)",
+ mp_csp_names[vd_csp.colorspace]);
}
- char *res;
- if (opts->requested_colorspace == MP_CSP_AUTO && real_csp) {
- // Caveat: doesn't handle the case when the autodetected colorspace
- // is different from the actual colorspace as used by the
- // VO - the OSD will display the VO colorspace without
- // indication that it doesn't match the requested colorspace.
- res = talloc_asprintf(NULL, "Auto (%s)", real_csp);
- } else if (opts->requested_colorspace == actual.format || !real_csp) {
- res = talloc_strdup(NULL, req_csp);
- } else
- res = talloc_asprintf(NULL, mp_gtext("%s, but %s used"),
- req_csp, real_csp);
*(char **)arg = res;
return M_PROPERTY_OK;
}
-static int levels_property_helper(int offset, m_option_t *prop, int action,
- void *arg, MPContext *mpctx)
+static int mp_property_colormatrix_input_range(m_option_t *prop, int action,
+ void *arg, MPContext *mpctx)
{
if (action != M_PROPERTY_PRINT)
- return colormatrix_property_helper(prop, action, arg, mpctx);
+ return video_refresh_property_helper(prop, action, arg, mpctx);
- struct m_option opt = {0};
- mp_property_generic_option(prop, M_PROPERTY_GET_TYPE, &opt, mpctx);
- assert(opt.type);
+ struct MPOpts *opts = &mpctx->opts;
- int requested = 0;
- mp_property_generic_option(prop, M_PROPERTY_GET, &requested, mpctx);
+ struct mp_csp_details vo_csp = {0};
+ if (mpctx->sh_video && mpctx->sh_video->vfilter)
+ vf_control(mpctx->sh_video->vfilter, VFCTRL_GET_YUV_COLORSPACE, &vo_csp );
- struct mp_csp_details actual = {0};
- int actual_level = -1;
- char *req_level = m_option_print(&opt, &requested);
- char *real_level = NULL;
- if (mpctx->sh_video) {
- struct vf_instance *vf = mpctx->sh_video->vfilter;
- if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &actual) == true) {
- actual_level = *(enum mp_csp_levels *)(((char *)&actual) + offset);
- real_level = m_option_print(&opt, &actual_level);
- } else {
- real_level = talloc_strdup(NULL, "Unknown");
- }
+ struct mp_image_params vd_csp = {0};
+ if (mpctx->sh_video)
+ vd_control(mpctx->sh_video, VDCTRL_GET_PARAMS, &vd_csp);
+
+ char *res = talloc_asprintf(NULL, "%s",
+ mp_csp_levels_names[opts->requested_input_range]);
+ if (!vo_csp.levels_in) {
+ res = talloc_asprintf_append(res, " (VO: unknown)");
+ } else if (vo_csp.levels_in != opts->requested_input_range) {
+ res = talloc_asprintf_append(res, " (VO: %s)",
+ mp_csp_levels_names[vo_csp.levels_in]);
+ }
+ if (!vd_csp.colorlevels) {
+ res = talloc_asprintf_append(res, " (VD: unknown)");
+ } else if (!vo_csp.levels_in || vd_csp.colorlevels != vo_csp.levels_in) {
+ res = talloc_asprintf_append(res, " (VD: %s)",
+ mp_csp_levels_names[vd_csp.colorlevels]);
}
- char *res;
- if (requested == MP_CSP_LEVELS_AUTO && real_level) {
- res = talloc_asprintf(NULL, "Auto (%s)", real_level);
- } else if (requested == actual_level || !real_level) {
- res = talloc_strdup(NULL, real_level);
- } else
- res = talloc_asprintf(NULL, mp_gtext("%s, but %s used"),
- req_level, real_level);
- talloc_free(req_level);
- talloc_free(real_level);
*(char **)arg = res;
return M_PROPERTY_OK;
}
-static int mp_property_colormatrix_input_range(m_option_t *prop, int action,
- void *arg, MPContext *mpctx)
-{
- return levels_property_helper(offsetof(struct mp_csp_details, levels_in),
- prop, action, arg, mpctx);
-}
-
static int mp_property_colormatrix_output_range(m_option_t *prop, int action,
void *arg, MPContext *mpctx)
{
- return levels_property_helper(offsetof(struct mp_csp_details, levels_out),
- prop, action, arg, mpctx);
+ if (action != M_PROPERTY_PRINT) {
+ int r = mp_property_generic_option(prop, action, arg, mpctx);
+ if (action == M_PROPERTY_SET) {
+ if (mpctx->sh_video)
+ set_video_output_levels(mpctx->sh_video);
+ }
+ return r;
+ }
+
+ struct MPOpts *opts = &mpctx->opts;
+
+ int req = opts->requested_output_range;
+ struct mp_csp_details actual = {0};
+ if (mpctx->sh_video && mpctx->sh_video->vfilter)
+ vf_control(mpctx->sh_video->vfilter, VFCTRL_GET_YUV_COLORSPACE, &actual);
+
+ char *res = talloc_asprintf(NULL, "%s", mp_csp_levels_names[req]);
+ if (!actual.levels_out) {
+ res = talloc_asprintf_append(res, " (Actual: unknown)");
+ } else if (actual.levels_out != req) {
+ res = talloc_asprintf_append(res, " (Actual: %s)",
+ mp_csp_levels_names[actual.levels_out]);
+ }
+ *(char **)arg = res;
+ return M_PROPERTY_OK;
}
/// Panscan (RW)
diff --git a/core/mplayer.c b/core/mplayer.c
index 363d89cc53..c2efe82f13 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -2385,6 +2385,7 @@ void mp_force_video_refresh(struct MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
+ // If not paused, the next frame should come soon enough.
if (opts->pause && mpctx->last_vo_pts != MP_NOPTS_VALUE)
queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->last_vo_pts, 1);
}
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c
index cd9e8be1e5..595ffb0e16 100644
--- a/video/decode/dec_video.c
+++ b/video/decode/dec_video.c
@@ -106,62 +106,27 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value)
// This is affected by user-specified overrides (aspect, colorspace...).
bool get_video_params(struct sh_video *sh, struct mp_image_params *p)
{
- struct MPOpts *opts = sh->opts;
-
if (!sh->vf_input)
return false;
*p = *sh->vf_input;
-
- // Apply user overrides
- if (opts->requested_colorspace != MP_CSP_AUTO)
- p->colorspace = opts->requested_colorspace;
- if (opts->requested_input_range != MP_CSP_LEVELS_AUTO)
- p->colorlevels = opts->requested_input_range;
-
- // Make sure the user-overrides are consistent (no RGB csp for YUV, etc.)
- mp_image_params_guess_csp(p);
-
return true;
}
-void set_video_colorspace(struct sh_video *sh)
+void set_video_output_levels(struct sh_video *sh)
{
struct MPOpts *opts = sh->opts;
- struct vf_instance *vf = sh->vfilter;
- struct mp_image_params params;
- if (!get_video_params(sh, &params))
+ if (!sh->vfilter)
return;
- struct mp_csp_details requested = {
- .format = params.colorspace,
- .levels_in = params.colorlevels,
- .levels_out = opts->requested_output_range,
- };
- if (requested.levels_out == MP_CSP_LEVELS_AUTO)
- requested.levels_out = MP_CSP_LEVELS_PC;
-
- vf_control(vf, VFCTRL_SET_YUV_COLORSPACE, &requested);
-
- struct mp_csp_details actual = MP_CSP_DETAILS_DEFAULTS;
- vf_control(vf, VFCTRL_GET_YUV_COLORSPACE, &actual);
-
- int success = actual.format == requested.format
- && actual.levels_in == requested.levels_in
- && actual.levels_out == requested.levels_out;
-
- if (!success)
- mp_tmsg(MSGT_DECVIDEO, MSGL_WARN,
- "Colorspace details not fully supported by selected vo.\n");
-
- if (actual.format != requested.format
- && requested.format == MP_CSP_SMPTE_240M) {
- // BT.709 is pretty close, much better than BT.601
- requested.format = MP_CSP_BT_709;
- vf_control(vf, VFCTRL_SET_YUV_COLORSPACE, &requested);
+ struct mp_csp_details csp;
+ if (vf_control(sh->vfilter, VFCTRL_GET_YUV_COLORSPACE, &csp) > 0) {
+ csp.levels_out = opts->requested_output_range;
+ if (csp.levels_out == MP_CSP_LEVELS_AUTO)
+ csp.levels_out = MP_CSP_LEVELS_PC;
+ vf_control(sh->vfilter, VFCTRL_SET_YUV_COLORSPACE, &csp);
}
-
}
void resync_video_stream(sh_video_t *sh_video)
diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h
index 88161ee54f..141442fa19 100644
--- a/video/decode/dec_video.h
+++ b/video/decode/dec_video.h
@@ -39,7 +39,7 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value);
int set_video_colors(sh_video_t *sh_video, const char *item, int value);
struct mp_image_params;
bool get_video_params(struct sh_video *sh, struct mp_image_params *p);
-void set_video_colorspace(struct sh_video *sh);
+void set_video_output_levels(struct sh_video *sh);
void resync_video_stream(sh_video_t *sh_video);
void video_reinit_vo(struct sh_video *sh_video);
int get_current_video_decoder_lag(sh_video_t *sh_video);
diff --git a/video/decode/vd.c b/video/decode/vd.c
index b344491c6b..98b9b155df 100644
--- a/video/decode/vd.c
+++ b/video/decode/vd.c
@@ -152,6 +152,14 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params)
p.d_w = d_w;
p.d_h = d_h;
+ // Apply user overrides
+ if (opts->requested_colorspace != MP_CSP_AUTO)
+ p.colorspace = opts->requested_colorspace;
+ if (opts->requested_input_range != MP_CSP_LEVELS_AUTO)
+ p.colorlevels = opts->requested_input_range;
+
+ // Detect colorspace from resolution.
+ // Make sure the user-overrides are consistent (no RGB csp for YUV, etc.).
mp_image_params_guess_csp(&p);
vocfg_flags = (opts->fullscreen ? VOFLAG_FULLSCREEN : 0) |
@@ -177,7 +185,7 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params)
sh->vf_input = talloc(sh, struct mp_image_params);
*sh->vf_input = p;
- set_video_colorspace(sh);
+ set_video_output_levels(sh);
if (opts->gamma_gamma != 1000)
set_video_colors(sh, "gamma", opts->gamma_gamma);
diff --git a/video/filter/vf.c b/video/filter/vf.c
index 1570e8402c..8946aeb801 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -170,6 +170,8 @@ static void print_fmt(int msglevel, struct vf_format *fmt)
mp_msg(MSGT_VFILTER, msglevel, "->%dx%d", p->d_w, p->d_h);
mp_msg(MSGT_VFILTER, msglevel, " %s %#x", mp_imgfmt_to_name(p->imgfmt),
fmt->flags);
+ mp_msg(MSGT_VFILTER, msglevel, " %s/%s", mp_csp_names[p->colorspace],
+ mp_csp_levels_names[p->colorlevels]);
} else {
mp_msg(MSGT_VFILTER, msglevel, "???");
}
@@ -357,8 +359,19 @@ unsigned int vf_match_csp(vf_instance_t **vfp, const unsigned int *list,
// Ownership of img is transferred from caller to the filter chain.
void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img)
{
- if (img)
+ if (img) {
+ struct mp_image_params *p = &vf->fmt_out.params;
+ // vf_vo doesn't have output config
+ if (vf->fmt_out.configured) {
+ assert(p->imgfmt == img->imgfmt);
+ assert(p->w == img->w && p->h == img->h);
+ // Too many filters which don't set these correctly
+ img->colorspace = p->colorspace;
+ img->levels = p->colorlevels;
+ img->chroma_location = p->chroma_location;
+ }
MP_TARRAY_APPEND(vf, vf->out_queued, vf->num_out_queued, img);
+ }
}
static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf)
@@ -486,6 +499,8 @@ int vf_next_config(struct vf_instance *vf,
.colorlevels = vf->fmt_in.params.colorlevels,
.chroma_location = vf->fmt_in.params.chroma_location,
};
+ // Fix csp in case of pixel format change
+ mp_image_params_guess_csp(&p);
int r = vf_reconfig_wrapper(vf->next, &p, voflags);
return r < 0 ? 0 : 1;
}
diff --git a/video/filter/vf_scale.c b/video/filter/vf_scale.c
index f357581bb3..2a1c397807 100644
--- a/video/filter/vf_scale.c
+++ b/video/filter/vf_scale.c
@@ -50,7 +50,6 @@ static struct vf_priv_s {
int interlaced;
int noup;
int accurate_rnd;
- struct mp_csp_details colorspace;
} const vf_priv_dflt = {
0, 0,
-1,-1,
@@ -59,7 +58,7 @@ static struct vf_priv_s {
};
static int mp_sws_set_colorspace(struct SwsContext *sws,
- struct mp_csp_details *csp);
+ struct mp_image_params *p);
//===========================================================================//
@@ -197,20 +196,19 @@ static unsigned int find_best_out(vf_instance_t *vf, int in_format){
return best;
}
-static int config(struct vf_instance *vf,
- int width, int height, int d_width, int d_height,
- unsigned int flags, unsigned int outfmt){
+static int reconfig(struct vf_instance *vf, struct mp_image_params *p, int flags)
+{
+ int width = p->w, height = p->h, d_width = p->d_w, d_height = p->d_h;
+ unsigned int outfmt = p->imgfmt;
unsigned int best=find_best_out(vf, outfmt);
int int_sws_flags=0;
int round_w=0, round_h=0;
SwsFilter *srcFilter, *dstFilter;
enum PixelFormat dfmt, sfmt;
- vf->priv->colorspace = (struct mp_csp_details) {0};
-
if(!best){
mp_msg(MSGT_VFILTER,MSGL_WARN,"SwScale: no supported outfmt found :(\n");
- return 0;
+ return -1;
}
sfmt = imgfmt2pixfmt(outfmt);
dfmt = imgfmt2pixfmt(best);
@@ -235,7 +233,7 @@ static int config(struct vf_instance *vf,
// and find out what the heck he thinks MPlayer should do
// with this nonsense.
mp_msg(MSGT_VFILTER, MSGL_ERR, "SwScale: EUSERBROKEN Check your parameters, they make no sense!\n");
- return 0;
+ return -1;
}
if (vf->priv->w == -1)
@@ -301,7 +299,7 @@ static int config(struct vf_instance *vf,
if(!vf->priv->ctx){
// error...
mp_msg(MSGT_VFILTER,MSGL_WARN,"Couldn't init SwScaler for this setup\n");
- return 0;
+ return -1;
}
vf->priv->fmt=best;
// Compute new d_width and d_height, preserving aspect
@@ -315,7 +313,17 @@ static int config(struct vf_instance *vf,
}
//d_width=d_width*vf->priv->w/width;
//d_height=d_height*vf->priv->h/height;
- return vf_next_config(vf,vf->priv->w,vf->priv->h,d_width,d_height,flags,best);
+ p->w = vf->priv->w;
+ p->h = vf->priv->h;
+ p->d_w = d_width;
+ p->d_h = d_height;
+ p->imgfmt = best;
+ mp_sws_set_colorspace(vf->priv->ctx, p);
+ // In particular, fix up colorspace/levels if YUV<->RGB conversion is
+ // performed.
+ p->colorlevels = MP_CSP_LEVELS_TV; // in case output is YUV
+ mp_image_params_guess_csp(p);
+ return vf_next_reconfig(vf, p, flags);
}
static void scale(struct SwsContext *sws1, struct SwsContext *sws2, uint8_t *src[MP_MAX_PLANES], int src_stride[MP_MAX_PLANES],
@@ -407,30 +415,6 @@ static int control(struct vf_instance *vf, int request, void* data){
if(r<0) break;
return CONTROL_TRUE;
- case VFCTRL_SET_YUV_COLORSPACE: {
- struct mp_csp_details colorspace = *(struct mp_csp_details *)data;
- if (mp_sws_set_colorspace(vf->priv->ctx, &colorspace) >= 0) {
- vf->priv->colorspace = colorspace;
- return 1;
- }
- break;
- }
- case VFCTRL_GET_YUV_COLORSPACE: {
- /* This scale filter should never react to colorspace commands if it
- * doesn't do YUV->RGB conversion. But because finding out whether this
- * is really YUV->RGB (and not YUV->YUV or anything else) is hard,
- * react only if the colorspace has been set explicitly before. The
- * trick is that mp_sws_set_colorspace does not succeed for YUV->YUV
- * and RGB->YUV conversions, which makes this code correct in "most"
- * cases. (This would be trivial to do correctly if libswscale exposed
- * functionality like isYUV()).
- */
- if (vf->priv->colorspace.format) {
- *(struct mp_csp_details *)data = vf->priv->colorspace;
- return CONTROL_TRUE;
- }
- break;
- }
default:
break;
}
@@ -446,26 +430,22 @@ static const int mp_csp_to_swscale[MP_CSP_COUNT] = {
// Adjust the colorspace used for YUV->RGB conversion. On other conversions,
// do nothing or return an error.
-// The csp argument is set to the supported values.
// Return 0 on success and -1 on error.
static int mp_sws_set_colorspace(struct SwsContext *sws,
- struct mp_csp_details *csp)
+ struct mp_image_params *p)
{
int *table, *inv_table;
int brightness, contrast, saturation, srcRange, dstRange;
- csp->levels_out = MP_CSP_LEVELS_PC;
-
// NOTE: returns an error if the destination format is YUV
if (sws_getColorspaceDetails(sws, &inv_table, &srcRange, &table, &dstRange,
&brightness, &contrast, &saturation) == -1)
goto error_out;
- int sws_csp = mp_csp_to_swscale[csp->format];
+ int sws_csp = mp_csp_to_swscale[p->colorspace];
if (sws_csp == 0) {
// colorspace not supported, go with a reasonable default
- csp->format = SWS_CS_ITU601;
- sws_csp = MP_CSP_BT_601;
+ sws_csp = SWS_CS_ITU601;
}
/* The swscale API for these is hardly documented.
@@ -473,7 +453,7 @@ static int mp_sws_set_colorspace(struct SwsContext *sws,
* for YUV->RGB conversions, and conversions to limited-range RGB are
* not supported.
*/
- srcRange = csp->levels_in == MP_CSP_LEVELS_PC;
+ srcRange = p->colorlevels == MP_CSP_LEVELS_PC;
const int *new_inv_table = sws_getCoefficients(sws_csp);
if (sws_setColorspaceDetails(sws, new_inv_table, srcRange, table, dstRange,
@@ -483,7 +463,6 @@ static int mp_sws_set_colorspace(struct SwsContext *sws,
return 0;
error_out:
- *csp = (struct mp_csp_details){0};
return -1;
}
@@ -509,7 +488,7 @@ static void uninit(struct vf_instance *vf){
}
static int vf_open(vf_instance_t *vf, char *args){
- vf->config=config;
+ vf->reconfig=reconfig;
vf->filter=filter;
vf->query_format=query_format;
vf->control= control;
diff --git a/video/filter/vf_sub.c b/video/filter/vf_sub.c
index e918574c30..e85a58afb7 100644
--- a/video/filter/vf_sub.c
+++ b/video/filter/vf_sub.c
@@ -39,7 +39,6 @@
#include "video/sws_utils.h"
#include "video/memcpy_pic.h"
-#include "video/csputils.h"
#include "core/m_option.h"
#include "core/m_struct.h"
@@ -49,12 +48,10 @@ static const struct vf_priv_s {
int outh, outw;
- struct mp_csp_details csp;
-
struct osd_state *osd;
struct mp_osd_res dim;
} vf_priv_dflt = {
- .csp = MP_CSP_DETAILS_DEFAULTS,
+ 0
};
static int config(struct vf_instance *vf,
@@ -109,8 +106,6 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
mpi = dmpi;
}
- mp_image_set_colorspace_details(mpi, &priv->csp);
-
osd_draw_on_image_p(osd, priv->dim, mpi->pts, OSD_DRAW_SUB_FILTER,
vf->out_pool, mpi);
@@ -132,11 +127,6 @@ static int control(vf_instance_t *vf, int request, void *data)
break;
case VFCTRL_INIT_OSD:
return CONTROL_TRUE;
- case VFCTRL_SET_YUV_COLORSPACE: {
- struct mp_csp_details colorspace = *(struct mp_csp_details *)data;
- vf->priv->csp = colorspace;
- break;
- }
}
return vf_next_control(vf, request, data);
}
diff --git a/video/mp_image.c b/video/mp_image.c
index c1e4ba18e7..029c5fa91b 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -439,6 +439,8 @@ void mp_image_set_colorspace_details(struct mp_image *image,
{
struct mp_image_params params;
mp_image_params_from_image(&params, image);
+ params.colorspace = csp->format;
+ params.colorlevels = csp->levels_in;
mp_image_params_guess_csp(&params);
image->colorspace = params.colorspace;
image->levels = params.colorlevels;
diff --git a/video/out/vo.c b/video/out/vo.c
index e05b1ae8a6..425c49aab8 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -441,6 +441,15 @@ int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags)
vo->waiting_mpi = NULL;
vo->redrawing = false;
vo->hasframe = false;
+ if (vo->config_ok) {
+ // Legacy
+ struct mp_csp_details csp;
+ if (vo_control(vo, VOCTRL_GET_YUV_COLORSPACE, &csp) > 0) {
+ csp.levels_in = params->colorlevels;
+ csp.format = params->colorspace;
+ vo_control(vo, VOCTRL_SET_YUV_COLORSPACE, &csp);
+ }
+ }
return ret;
}