aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Uoti Urpala <uau@glyph.nonexistent.invalid>2009-11-15 15:21:40 +0200
committerGravatar Uoti Urpala <uau@glyph.nonexistent.invalid>2009-11-15 17:03:41 +0200
commit98ee8dd15976501157c894ec385c4c551c6614ad (patch)
tree0ca98500193f1e76da5ecc15d2076abec9caee59
parent201bef7ee150f9d852996b379c926ba0c47320d5 (diff)
Add yuv_colorspace property, implemented in vo_vdpau and vo_xv
Add a property to select YUV colorspace. Currently implemented only in vo_vdpau and vo_xv. Allows switching between BT.601, BT.709 and SMPTE-240M (vdpau only). The xv support uses the "XV_ITURBT_709" attribute. At least my NVIDIA card supports that; I don't know whether other xv implementations do. Bind the colorspace switch to the 'c' key by default. 'c' is currently used by vo_sdl for some fullscreen mode change thing, but at the moment that does not conflict and if it will in the future then vo_sdl can change. VDPAU part based on a patch from Lauri Mylläri <lauri.myllari@gmail.com>
-rw-r--r--DOCS/man/en/mplayer.122
-rw-r--r--command.c45
-rw-r--r--input/input.c1
-rw-r--r--libmpcodecs/vf.h2
-rw-r--r--libmpcodecs/vf_vo.c4
-rw-r--r--libvo/video_out.h3
-rw-r--r--libvo/vo_vdpau.c59
-rw-r--r--libvo/vo_xv.c9
-rw-r--r--libvo/x11_common.c8
9 files changed, 137 insertions, 16 deletions
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1
index 6c832c0217..b48f653892 100644
--- a/DOCS/man/en/mplayer.1
+++ b/DOCS/man/en/mplayer.1
@@ -282,8 +282,10 @@ Show filename on the OSD.
Seek to the beginning of the previous/next chapter.
.IPs "D (\-vo xvmc, \-vo vdpau, \-vf yadif, \-vf kerndeint only)"
Activate/deactivate deinterlacer.
-.IPs "A"
+.IPs "A\ \ \ \ "
Cycle through the available DVD angles.
+.IPs "c (currently -vo vdpau and -vo xv only)"
+Change YUV colorspace.
.RE
.PD 1
.PP
@@ -3442,6 +3444,24 @@ Use nochroma\-deint to solely use luma and speed up advanced deinterlacing.
Useful with slow video memory.
.IPs pullup
Try to apply inverse telecine, needs motion adaptive temporal deinterlacing.
+.IPs colorspace
+Select the color space for YUV to RGB conversion (default: 1, BT.601).
+In general BT.601 should be used for standard definition (SD) content and
+BT.709 for high definition (HD) content.
+Using incorrect color space results in slightly under or over saturated and
+shifted colors.
+.RSss
+.IPs 0
+Guess the color space based on video resolution.
+Video with width >= 1280 or height > 576 is assumed to be HD and BT.709 color
+space will be used.
+.IPs 1
+Use ITU-R BT.601 color space (default).
+.IPs 2
+Use ITU-R BT.709 color space.
+.IPs 3
+Use SMPTE-240M color space.
+.RE
.IPs fps=<number>
Override autodetected display refresh rate value (the value is needed for framedrop to allow video playback rates higher than display refresh rate, and for vsync-aware frame timing adjustments).
Default 0 means use autodetected value.
diff --git a/command.c b/command.c
index 9738377dd3..b52cfaf07d 100644
--- a/command.c
+++ b/command.c
@@ -1051,6 +1051,48 @@ static int mp_property_deinterlace(m_option_t *prop, int action,
return m_property_flag_ro(prop, action, arg, value);
}
+static int mp_property_yuv_colorspace(m_option_t *prop, int action,
+ void *arg, MPContext *mpctx)
+{
+ if (!mpctx->sh_video || !mpctx->sh_video->vfilter)
+ return M_PROPERTY_UNAVAILABLE;
+
+ struct vf_instance *vf = mpctx->sh_video->vfilter;
+ int colorspace;
+ switch (action) {
+ case M_PROPERTY_GET:
+ if (!arg)
+ return M_PROPERTY_ERROR;
+ if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, arg) != true)
+ return M_PROPERTY_UNAVAILABLE;
+ return M_PROPERTY_OK;
+ case M_PROPERTY_PRINT:
+ if (!arg)
+ return M_PROPERTY_ERROR;
+ if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &colorspace) != true)
+ return M_PROPERTY_UNAVAILABLE;
+ char * const names[] = {"BT.601 (SD)", "BT.709 (HD)", "SMPTE-240M"};
+ if (colorspace < 0 || colorspace >= sizeof(names) / sizeof(names[0]))
+ *(char **)arg = strdup("Unknown");
+ else
+ *(char**)arg = strdup(names[colorspace]);
+ return M_PROPERTY_OK;
+ case M_PROPERTY_SET:
+ if (!arg)
+ return M_PROPERTY_ERROR;
+ M_PROPERTY_CLAMP(prop, *(int *) arg);
+ vf->control(vf, VFCTRL_SET_YUV_COLORSPACE, arg);
+ return M_PROPERTY_OK;
+ case M_PROPERTY_STEP_UP:;
+ if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &colorspace) != true)
+ return M_PROPERTY_UNAVAILABLE;
+ colorspace += 1;
+ vf->control(vf, VFCTRL_SET_YUV_COLORSPACE, &colorspace);
+ return M_PROPERTY_OK;
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
/// Panscan (RW)
static int mp_property_panscan(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
@@ -2058,6 +2100,8 @@ static const m_option_t mp_properties[] = {
M_OPT_RANGE, 0, 1, NULL },
{ "deinterlace", mp_property_deinterlace, CONF_TYPE_FLAG,
M_OPT_RANGE, 0, 1, NULL },
+ { "yuv_colorspace", mp_property_yuv_colorspace, CONF_TYPE_INT,
+ M_OPT_RANGE, 0, 2, NULL },
{ "ontop", mp_property_ontop, CONF_TYPE_FLAG,
M_OPT_RANGE, 0, 1, NULL },
{ "rootwin", mp_property_rootwin, CONF_TYPE_FLAG,
@@ -2217,6 +2261,7 @@ static struct property_osd_display {
{ "border", 0, -1, _("Border: %s") },
{ "framedropping", 0, -1, _("Framedropping: %s") },
{ "deinterlace", 0, -1, _("Deinterlace: %s") },
+ { "yuv_colorspace", 0, -1, _("YUV colorspace: %s") },
{ "gamma", OSD_BRIGHTNESS, -1, _("Gamma") },
{ "brightness", OSD_BRIGHTNESS, -1, _("Brightness") },
{ "contrast", OSD_CONTRAST, -1, _("Contrast") },
diff --git a/input/input.c b/input/input.c
index 71dfb38155..7738da8bcf 100644
--- a/input/input.c
+++ b/input/input.c
@@ -426,6 +426,7 @@ static const mp_cmd_bind_t def_cmd_binds[] = {
{ { '8', 0 }, "saturation 1" },
{ { 'd', 0 }, "frame_drop" },
{ { 'D', 0 }, "step_property_osd deinterlace" },
+ { { 'c', 0 }, "step_property_osd yuv_colorspace" },
{ { 'r', 0 }, "sub_pos -1" },
{ { 't', 0 }, "sub_pos +1" },
{ { 'a', 0 }, "sub_alignment" },
diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h
index d0e3c1cba4..f9dbb8b4fb 100644
--- a/libmpcodecs/vf.h
+++ b/libmpcodecs/vf.h
@@ -93,6 +93,8 @@ typedef struct vf_seteq_s
* the OSD state outside of normal OSD draw time. */
#define VFCTRL_SET_OSD_OBJ 20
#define VFCTRL_REDRAW_OSD 21 /* Change user-visible OSD immediately */
+#define VFCTRL_SET_YUV_COLORSPACE 22
+#define VFCTRL_GET_YUV_COLORSPACE 23
#include "vfcap.h"
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index 7416e5f1d4..7026ac93fc 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -88,6 +88,10 @@ static int control(struct vf_instance* vf, int request, void* data)
if(!video_out) return CONTROL_FALSE; // vo not configured?
return vo_control(video_out, VOCTRL_SET_DEINTERLACE, data) == VO_TRUE;
}
+ case VFCTRL_GET_YUV_COLORSPACE:
+ return vo_control(video_out, VOCTRL_GET_YUV_COLORSPACE, data) == true;
+ case VFCTRL_SET_YUV_COLORSPACE:
+ return vo_control(video_out, VOCTRL_SET_YUV_COLORSPACE, data) == true;
case VFCTRL_DRAW_OSD:
if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured?
vo_draw_osd(video_out, data);
diff --git a/libvo/video_out.h b/libvo/video_out.h
index 50602e83a4..17c387a320 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -88,6 +88,9 @@ typedef struct {
#define VOCTRL_UPDATE_SCREENINFO 32
+#define VOCTRL_SET_YUV_COLORSPACE 33
+#define VOCTRL_GET_YUV_COLORSPACE 34
+
// Vo can be used by xover
#define VOCTRL_XOVERLAY_SUPPORT 22
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
index 6eef93842f..a228b00787 100644
--- a/libvo/vo_vdpau.c
+++ b/libvo/vo_vdpau.c
@@ -124,6 +124,8 @@ struct vdpctx {
int output_surface_width, output_surface_height;
VdpVideoMixer video_mixer;
+ int user_colorspace;
+ int colorspace;
int deint;
int deint_type;
int deint_counter;
@@ -541,6 +543,33 @@ static int win_x11_init_vdpau_flip_queue(struct vo *vo)
return 0;
}
+static void update_csc_matrix(struct vo *vo)
+{
+ struct vdpctx *vc = vo->priv;
+ struct vdp_functions *vdp = vc->vdp;
+ VdpStatus vdp_st;
+
+ const VdpColorStandard vdp_colors[] = {VDP_COLOR_STANDARD_ITUR_BT_601,
+ VDP_COLOR_STANDARD_ITUR_BT_709,
+ VDP_COLOR_STANDARD_SMPTE_240M};
+ char * const vdp_names[] = {"BT.601", "BT.709", "SMPTE-240M"};
+ int csp = vc->colorspace;
+ mp_msg(MSGT_VO, MSGL_V, "[vdpau] Updating CSC matrix for %s\n",
+ vdp_names[csp]);
+
+ VdpCSCMatrix matrix;
+ vdp_st = vdp->generate_csc_matrix(&vc->procamp, vdp_colors[csp], &matrix);
+ CHECK_ST_WARNING("Error when generating CSC matrix");
+
+ const VdpVideoMixerAttribute attributes[] =
+ {VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX};
+ const void *attribute_values[] = {&matrix};
+ vdp_st = vdp->video_mixer_set_attribute_values(vc->video_mixer, 1,
+ attributes,
+ attribute_values);
+ CHECK_ST_WARNING("Error when setting CSC matrix");
+}
+
static int create_vdp_mixer(struct vo *vo, VdpChromaType vdp_chroma_type)
{
struct vdpctx *vc = vo->priv;
@@ -611,6 +640,7 @@ static int create_vdp_mixer(struct vo *vo, VdpChromaType vdp_chroma_type)
skip_chroma_attrib,
skip_chroma_value_ptr);
+ update_csc_matrix(vo);
return 0;
}
@@ -803,6 +833,10 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
vc->image_format = format;
vc->vid_width = width;
vc->vid_height = height;
+ if (vc->user_colorspace == 0)
+ vc->colorspace = width >= 1280 || height > 576 ? 1 : 0;
+ else
+ vc->colorspace = vc->user_colorspace - 1;
free_video_specific(vo);
if (IMGFMT_IS_VDPAU(vc->image_format) && !create_vdp_decoder(vo, 2))
return -1;
@@ -1543,12 +1577,14 @@ static int preinit(struct vo *vo, const char *arg)
vc->deint_type = 3;
vc->chroma_deint = 1;
+ vc->user_colorspace = 1;
const opt_t subopts[] = {
{"deint", OPT_ARG_INT, &vc->deint, (opt_test_f)int_non_neg},
{"chroma-deint", OPT_ARG_BOOL, &vc->chroma_deint, NULL},
{"pullup", OPT_ARG_BOOL, &vc->pullup, NULL},
{"denoise", OPT_ARG_FLOAT, &vc->denoise, NULL},
{"sharpen", OPT_ARG_FLOAT, &vc->sharpen, NULL},
+ {"colorspace", OPT_ARG_INT, &vc->user_colorspace, NULL},
{"fps", OPT_ARG_FLOAT, &vc->user_fps, NULL},
{NULL}
};
@@ -1623,11 +1659,6 @@ static int set_equalizer(struct vo *vo, const char *name, int value)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
- VdpStatus vdp_st;
- VdpCSCMatrix matrix;
- static const VdpVideoMixerAttribute attributes[] =
- {VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX};
- const void *attribute_values[] = {&matrix};
if (!strcasecmp(name, "brightness"))
vc->procamp.brightness = value / 100.0;
@@ -1640,15 +1671,8 @@ static int set_equalizer(struct vo *vo, const char *name, int value)
else
return VO_NOTIMPL;
- vdp_st = vdp->generate_csc_matrix(&vc->procamp,
- VDP_COLOR_STANDARD_ITUR_BT_601,
- &matrix);
- CHECK_ST_WARNING("Error when generating CSC matrix");
- vdp_st = vdp->video_mixer_set_attribute_values(vc->video_mixer, 1,
- attributes,
- attribute_values);
- CHECK_ST_WARNING("Error when setting CSC matrix");
- return VO_TRUE;
+ update_csc_matrix(vo);
+ return true;
}
static int control(struct vo *vo, uint32_t request, void *data)
@@ -1712,6 +1736,13 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct voctrl_get_equalizer_args *args = data;
return get_equalizer(vo, args->name, args->valueptr);
}
+ case VOCTRL_SET_YUV_COLORSPACE:
+ vc->colorspace = *(int *)data % 3;
+ update_csc_matrix(vo);
+ return true;
+ case VOCTRL_GET_YUV_COLORSPACE:
+ *(int *)data = vc->colorspace;
+ return true;
case VOCTRL_ONTOP:
vo_x11_ontop(vo);
return VO_TRUE;
diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c
index 886fd0a0d7..9a030ac71c 100644
--- a/libvo/vo_xv.c
+++ b/libvo/vo_xv.c
@@ -817,6 +817,15 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct voctrl_get_equalizer_args *args = data;
return vo_xv_get_eq(vo, x11->xv_port, args->name, args->valueptr);
}
+ case VOCTRL_SET_YUV_COLORSPACE:;
+ int given_cspc = *(int *)data % 2;
+ return vo_xv_set_eq(vo, x11->xv_port, "bt_709", given_cspc * 200 - 100);
+ case VOCTRL_GET_YUV_COLORSPACE:;
+ int bt709_enabled;
+ if (!vo_xv_get_eq(vo, x11->xv_port, "bt_709", &bt709_enabled))
+ return false;
+ *(int *)data = bt709_enabled == 100;
+ return true;
case VOCTRL_ONTOP:
vo_x11_ontop(vo);
return VO_TRUE;
diff --git a/libvo/x11_common.c b/libvo/x11_common.c
index 621880e137..e617aad082 100644
--- a/libvo/x11_common.c
+++ b/libvo/x11_common.c
@@ -1651,7 +1651,7 @@ double vo_vm_get_fps(struct vo *vo)
if (!XF86VidModeGetModeLine(x11->display, x11->screen, &clock, &modeline))
return 0;
if (modeline.privsize)
- Xfree(modeline.private);
+ XFree(modeline.private);
return 1e3 * clock / modeline.htotal / modeline.vtotal;
}
#endif
@@ -1906,6 +1906,9 @@ int vo_xv_set_eq(struct vo *vo, uint32_t xv_port, char *name, int value)
else if (!strcmp(attributes[i].name, "XV_BLUE_INTENSITY")
&& (!strcasecmp(name, "blue_intensity")))
port_value = value;
+ else if (!strcmp(attributes[i].name, "XV_ITURBT_709")
+ && (!strcasecmp(name, "bt_709")))
+ port_value = value;
else
continue;
@@ -1987,6 +1990,9 @@ int vo_xv_get_eq(struct vo *vo, uint32_t xv_port, char *name, int *value)
else if (!strcmp(attributes[i].name, "XV_BLUE_INTENSITY")
&& (!strcasecmp(name, "blue_intensity")))
*value = val;
+ else if (!strcmp(attributes[i].name, "XV_ITURBT_709")
+ && (!strcasecmp(name, "bt_709")))
+ *value = val;
else
continue;