summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-16 23:22:55 +0200
committerwm4 <wm4@nowhere>2013-07-16 23:22:55 +0200
commit18b6c01d921c1dea0986bba4bcd867da5605a3d8 (patch)
tree3489728f82c0270a72005f64590781118b02540f /core
parenta98aad61f854d9a216675dc54096aa39767c4a35 (diff)
downloadmpv-18b6c01d921c1dea0986bba4bcd867da5605a3d8.tar.bz2
mpv-18b6c01d921c1dea0986bba4bcd867da5605a3d8.tar.xz
video: redo how colorspaces are handled
Instead of handling colorspaces with VFCTRLs/VOCTRLs, make them part of the normal video format negotiation. The colorspace is passed down like other video params with config/reconfig calls. Forcing colorspaces (via the --colormatrix options and properties) is handled differently too: if it's changed, completely reinit the video chain. This is slower and requires a precise seek to the same position to perform an update, but it's simpler and less bug-prone. Considering switching the colorspace at runtime by user-interaction is a rather obscure feature, this is a good change. The colorspace VFCTRLs and VOCTRLs are still kept. The VOs rely on it, and would have to be changed to get rid of them. We'll do that later, and convert them incrementally instead of in one go. Note that controlling the output range now always works on VO level. Basically, this means you can't get vf_scale to output full-range YUV for whatever reason. If that is really wanted, it should be a vf_scale option. the previous behavior didn't make too much sense anyway. This commit fixes a few bugs (such as playing RGB video and converting that to YUV with vf_scale - a recent commit broke this and forced the VO to display YUV as RGB if possible), and might introduce some new ones.
Diffstat (limited to 'core')
-rw-r--r--core/command.c145
-rw-r--r--core/mplayer.c1
2 files changed, 80 insertions, 66 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);
}