diff options
author | Torsten Jager <t.jager@gmx.de> | 2012-07-06 21:59:08 +0300 |
---|---|---|
committer | Torsten Jager <t.jager@gmx.de> | 2012-07-06 21:59:08 +0300 |
commit | 9fa49e23cc5341d17b246996da26915ab5b1db15 (patch) | |
tree | 8e46eb76e7ca84681cf0dc6aecf854dd249fefd1 /src | |
parent | b31054e542aaacc2c4c83a5e6d398121793d1a37 (diff) | |
download | xine-lib-9fa49e23cc5341d17b246996da26915ab5b1db15.tar.gz xine-lib-9fa49e23cc5341d17b246996da26915ab5b1db15.tar.bz2 |
opengl/(xcb)xv/x(cb)shm: added color matrix and fullrange support
Diffstat (limited to 'src')
-rw-r--r-- | src/video_out/video_out_opengl.c | 156 | ||||
-rw-r--r-- | src/video_out/video_out_xcbshm.c | 78 | ||||
-rw-r--r-- | src/video_out/video_out_xcbxv.c | 62 | ||||
-rw-r--r-- | src/video_out/video_out_xshm.c | 79 | ||||
-rw-r--r-- | src/video_out/video_out_xv.c | 36 |
5 files changed, 288 insertions, 123 deletions
diff --git a/src/video_out/video_out_opengl.c b/src/video_out/video_out_opengl.c index e6108f0db..0d54dff1f 100644 --- a/src/video_out/video_out_opengl.c +++ b/src/video_out/video_out_opengl.c @@ -204,12 +204,15 @@ typedef struct { PFNMYGLGENTEXTURESEXTPROC glGenTexturesEXT; PFNMYGLBINDTEXTUREEXTPROC glBindTextureEXT; - int yuv2rgb_brightness; - int yuv2rgb_contrast; - int yuv2rgb_saturation; + int brightness; + int contrast; + int saturation; uint8_t *yuv2rgb_cmap; yuv2rgb_factory_t *yuv2rgb_factory; + /* color matrix switching */ + int cm_yuv2rgb, cm_fragprog, cm_state; + /* Frame state */ opengl_frame_t *frame[NUM_FRAMES_BACKLOG]; x11osd *xoverlay; @@ -246,6 +249,12 @@ typedef struct { } opengl_render_t; +/* import common color matrix stuff */ +#define CM_DRIVER_T opengl_driver_t +#include "color_matrix.c" + +extern const int32_t Inverse_Table_6_9[8][4]; /* from yuv2rgb.c */ + /* * Render functions */ @@ -929,7 +938,48 @@ static int render_setup_torus (opengl_driver_t *this) { static int render_setup_fp_yuv (opengl_driver_t *this) { GLint errorpos; int ret; - static const char *fragprog_yuv = + + int i = (this->cm_fragprog >> 1) & 7; + int vr = Inverse_Table_6_9[i][0]; + int ug = Inverse_Table_6_9[i][2]; + int vg = Inverse_Table_6_9[i][3]; + int ub = Inverse_Table_6_9[i][1]; + int ygain, yoffset; + /* TV set behaviour: contrast affects colour difference as well */ + int saturation = (this->saturation * this->contrast + 64) / 128; + + static char fragprog_yuv[512]; + const char *s = ""; + + /* full range mode */ + if (this->cm_fragprog & 1) { + ygain = (1000 * this->contrast + 64) / 128; + yoffset = this->brightness * ygain / 255; + /* be careful to stay within 32 bit */ + vr = (saturation * (112 / 4) * vr + 127 * 16) / (127 * 128 / 4); + ug = (saturation * (112 / 4) * ug + 127 * 16) / (127 * 128 / 4); + vg = (saturation * (112 / 4) * vg + 127 * 16) / (127 * 128 / 4); + ub = (saturation * (112 / 4) * ub + 127 * 16) / (127 * 128 / 4); + } else { + ygain = (1000 * 255 * this->contrast + 219 * 64) / (219 * 128); + yoffset = (this->brightness - 16) * ygain / 255; + vr = (saturation * vr + 64) / 128; + ug = (saturation * ug + 64) / 128; + vg = (saturation * vg + 64) / 128; + ub = (saturation * ub + 64) / 128; + } + + vr = 1000 * vr / 65536; + ug = 1000 * ug / 65536; + vg = 1000 * vg / 65536; + ub = 1000 * ub / 65536; + + if (yoffset < 0) { + s = "-"; + yoffset = -yoffset; + } + + sprintf (fragprog_yuv, "!!ARBfp1.0\n" "ATTRIB tex = fragment.texcoord[0];" "PARAM off = program.env[0];" @@ -941,16 +991,28 @@ static int render_setup_fp_yuv (opengl_driver_t *this) { "ADD u, v, off.xyww;" "ADD v, v, off.zyww;" "TEX tmp.x, u, texture[0], 2D;" - "MAD res, res, 1.164, -0.073;" /* -1.164*16/255 */ + "MAD res, res, %d.%03d, %s%d.%03d;" "TEX tmp.y, v, texture[0], 2D;" "SUB tmp, tmp, { .5, .5 };" - "MAD res, { 0, -.391, 2.018 }, tmp.xxxw, res;" - "MAD result.color, { 1.596, -.813, 0 }, tmp.yyyw, res;" - "END"; + "MAD res, { 0, -%d.%03d, %d.%03d }, tmp.xxxw, res;" + "MAD result.color, { %d.%03d, -%d.%03d, 0 }, tmp.yyyw, res;" + "END", + /* nasty: "%.3f" may use comma as decimal point... */ + ygain / 1000, ygain % 1000, + s, yoffset / 1000, yoffset % 1000, + ug / 1000, ug % 1000, + ub / 1000, ub % 1000, + vr / 1000, vr % 1000, + vg / 1000, vg % 1000); ret = render_setup_tex2d (this); if (! this->has_fragprog) return 0; + + xprintf (this->xine, XINE_VERBOSITY_LOG, + "video_out_open_opengl_fragprog: b %d c %d s %d [%s]\n", + this->brightness, this->contrast, this->saturation, cm_names[this->cm_fragprog]); + if (this->fprog == (GLuint)-1) this->glGenProgramsARB (1, &this->fprog); this->glBindProgramARB (MYGL_FRAGMENT_PROGRAM_ARB, this->fprog); @@ -1058,6 +1120,15 @@ static void *render_run (opengl_driver_t *this) { this->render_frame_changed = 0; pthread_mutex_unlock (&this->render_action_mutex); if (this->context && frame) { + /* update fragprog if color matrix changed */ + if (this->render_fun_id == 0) { + int cm = cm_from_frame ((vo_frame_t *)frame); + if (cm != this->cm_fragprog) { + this->cm_fragprog = cm; + this->render_action = RENDER_SETUP; + break; + } + } XLockDisplay (this->display); CHECKERR ("pre-render"); ret = 1; @@ -1209,7 +1280,8 @@ static void *render_run (opengl_driver_t *this) { static uint32_t opengl_get_capabilities (vo_driver_t *this_gen) { /* opengl_driver_t *this = (opengl_driver_t *) this_gen; */ - uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_BRIGHTNESS | VO_CAP_CONTRAST | VO_CAP_SATURATION; + uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_BRIGHTNESS + | VO_CAP_CONTRAST | VO_CAP_SATURATION | VO_CAP_COLOR_MATRIX | VO_CAP_FULLRANGE; /* TODO: somehow performance goes down during the first few frames */ /* if (this->xoverlay) */ @@ -1220,7 +1292,8 @@ static uint32_t opengl_get_capabilities (vo_driver_t *this_gen) { static void opengl_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { opengl_frame_t *frame = (opengl_frame_t *) vo_img ; -/* opengl_driver_t *this = (opengl_driver_t *) vo_img->driver; */ + opengl_driver_t *this = (opengl_driver_t *) vo_img->driver; + int cm; vo_img->proc_called = 1; if (! frame->rgb_dst) @@ -1236,6 +1309,16 @@ static void opengl_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { return; } + cm = cm_from_frame (vo_img); + if (cm != this->cm_yuv2rgb) { + this->cm_yuv2rgb = cm; + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, + this->brightness, this->contrast, this->saturation, cm); + xprintf (this->xine, XINE_VERBOSITY_LOG, + "video_out_opengl: b %d c %d s %d [%s]\n", + this->brightness, this->contrast, this->saturation, cm_names[cm]); + } + if (frame->format == XINE_IMGFMT_YV12) frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0], src[1], src[2]); @@ -1603,11 +1686,11 @@ static int opengl_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_MAX_NUM_FRAMES: return 15; case VO_PROP_BRIGHTNESS: - return this->yuv2rgb_brightness; + return this->brightness; case VO_PROP_CONTRAST: - return this->yuv2rgb_contrast; + return this->contrast; case VO_PROP_SATURATION: - return this->yuv2rgb_saturation; + return this->saturation; case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; case VO_PROP_WINDOW_HEIGHT: @@ -1636,30 +1719,21 @@ static int opengl_set_property (vo_driver_t *this_gen, "video_out_opengl: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name_table[value]); break; case VO_PROP_BRIGHTNESS: - this->yuv2rgb_brightness = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->brightness = value; + this->cm_yuv2rgb = 0; + this->cm_fragprog = 0; this->sc.force_redraw = 1; break; case VO_PROP_CONTRAST: - this->yuv2rgb_contrast = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->contrast = value; + this->cm_yuv2rgb = 0; + this->cm_fragprog = 0; this->sc.force_redraw = 1; break; case VO_PROP_SATURATION: - this->yuv2rgb_saturation = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->saturation = value; + this->cm_yuv2rgb = 0; + this->cm_fragprog = 0; this->sc.force_redraw = 1; break; default: @@ -1808,6 +1882,8 @@ static void opengl_dispose (vo_driver_t *this_gen) { this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + cm_close (this); + if (this->xoverlay) { XLockDisplay (this->display); x11osd_destroy (this->xoverlay); @@ -1883,17 +1959,13 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v this->vo_driver.dispose = opengl_dispose; this->vo_driver.redraw_needed = opengl_redraw_needed; - this->yuv2rgb_brightness = 0; - this->yuv2rgb_contrast = 128; - this->yuv2rgb_saturation = 128; - - this->yuv2rgb_factory = yuv2rgb_factory_init (YUV_FORMAT, YUV_SWAP_MODE, - NULL); - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->brightness = 0; + this->contrast = 128; + this->saturation = 128; + + cm_init (this); + + this->yuv2rgb_factory = yuv2rgb_factory_init (YUV_FORMAT, YUV_SWAP_MODE, NULL); XLockDisplay (this->display); this->xoverlay = x11osd_create (this->xine, this->display, this->screen, diff --git a/src/video_out/video_out_xcbshm.c b/src/video_out/video_out_xcbshm.c index 76e4a79e3..05e5ad731 100644 --- a/src/video_out/video_out_xcbshm.c +++ b/src/video_out/video_out_xcbshm.c @@ -26,7 +26,7 @@ * * ported to xcb by Christoph Pfister - Feb 2007 * - * crop support added by Torsten Jager <t.jager@gmx.de> + * fullrange/HD color and crop support added by Torsten Jager <t.jager@gmx.de> */ #define LOG_MODULE "video_out_xcbshm" @@ -113,12 +113,15 @@ typedef struct { int scanline_pad; int use_shm; - int yuv2rgb_brightness; - int yuv2rgb_contrast; - int yuv2rgb_saturation; + int brightness; + int contrast; + int saturation; uint8_t *yuv2rgb_cmap; yuv2rgb_factory_t *yuv2rgb_factory; + /* color matrix switching */ + int cm_active, cm_state; + vo_scale_t sc; xshm_frame_t *cur_frame; @@ -141,6 +144,10 @@ typedef struct { } xshm_class_t; +/* import common color matrix stuff */ +#define CM_DRIVER_T xshm_driver_t +#include "color_matrix.c" + /* * allocate an XImage, try XShm first but fall back to * plain X11 if XShm should fail @@ -238,7 +245,7 @@ static void dispose_ximage(xshm_driver_t *this, xshm_frame_t *frame) static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { xshm_driver_t *this = (xshm_driver_t *) this_gen; uint32_t capabilities = VO_CAP_CROP | VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_BRIGHTNESS - | VO_CAP_CONTRAST | VO_CAP_SATURATION; + | VO_CAP_CONTRAST | VO_CAP_SATURATION | VO_CAP_COLOR_MATRIX | VO_CAP_FULLRANGE; if( this->xoverlay ) capabilities |= VO_CAP_UNSCALED_OVERLAY; @@ -418,6 +425,17 @@ static void xshm_frame_proc_setup (vo_frame_t *vo_img) { + (frame->sc.delivered_height - frame->sc.crop_bottom) * vo_img->pitches[0]; if (i + frame->sc.crop_bottom < 0) frame->crop_flush -= 16 * vo_img->pitches[0]; + + /* switch color matrix/range */ + i = cm_from_frame (vo_img); + if (i != this->cm_active) { + this->cm_active = i; + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, + this->brightness, this->contrast, this->saturation, i); + xprintf (this->xine, XINE_VERBOSITY_LOG, + "video_out_xcbshm: b %d c %d s %d [%s]\n", + this->brightness, this->contrast, this->saturation, cm_names[i]); + } } static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { @@ -820,11 +838,11 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_MAX_NUM_FRAMES: return 15; case VO_PROP_BRIGHTNESS: - return this->yuv2rgb_brightness; + return this->brightness; case VO_PROP_CONTRAST: - return this->yuv2rgb_contrast; + return this->contrast; case VO_PROP_SATURATION: - return this->yuv2rgb_saturation; + return this->saturation; case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; case VO_PROP_WINDOW_HEIGHT: @@ -859,32 +877,20 @@ static int xshm_set_property (vo_driver_t *this_gen, break; case VO_PROP_BRIGHTNESS: - this->yuv2rgb_brightness = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->brightness = value; + this->cm_active = 0; this->sc.force_redraw = 1; break; case VO_PROP_CONTRAST: - this->yuv2rgb_contrast = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->contrast = value; + this->cm_active = 0; this->sc.force_redraw = 1; break; case VO_PROP_SATURATION: - this->yuv2rgb_saturation = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->saturation = value; + this->cm_active = 0; this->sc.force_redraw = 1; break; @@ -1019,6 +1025,8 @@ static void xshm_dispose (vo_driver_t *this_gen) { this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + cm_close (this); + pthread_mutex_lock(&this->main_mutex); xcb_free_gc(this->connection, this->gc); pthread_mutex_unlock(&this->main_mutex); @@ -1317,17 +1325,13 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void return NULL; } - this->yuv2rgb_brightness = 0; - this->yuv2rgb_contrast = 128; - this->yuv2rgb_saturation = 128; - - this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, - this->yuv2rgb_cmap); - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + cm_init (this); + + this->brightness = 0; + this->contrast = 128; + this->saturation = 128; + + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, this->yuv2rgb_cmap); this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen, this->window, XCBOSD_SHAPED); diff --git a/src/video_out/video_out_xcbxv.c b/src/video_out/video_out_xcbxv.c index f24141db7..ad3b4b552 100644 --- a/src/video_out/video_out_xcbxv.c +++ b/src/video_out/video_out_xcbxv.c @@ -31,6 +31,12 @@ * ported to xcb by Christoph Pfister - Feb 2007 */ +#define LOG_MODULE "video_out_xcbxv" +#define LOG_VERBOSE +/* +#define LOG +*/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -51,12 +57,6 @@ #include <xcb/xv.h> -#define LOG_MODULE "video_out_xcbxv" -#define LOG_VERBOSE -/* -#define LOG -*/ - #include "xine.h" #include <xine/video_out.h> #include <xine/xine_internal.h> @@ -145,6 +145,9 @@ struct xv_driver_s { pthread_mutex_t main_mutex; + /* color matrix switching */ + int cm_active, cm_state; + xcb_atom_t cm_atom; }; typedef struct { @@ -154,6 +157,10 @@ typedef struct { xine_t *xine; } xv_class_t; +/* import common color matrix stuff */ +#define CM_DRIVER_T xv_driver_t +#include "color_matrix.c" + VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; VIDEO_DEVICE_XV_DECL_PREFER_TYPES; VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; @@ -581,10 +588,24 @@ static int xv_redraw_needed (vo_driver_t *this_gen) { static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; + int cm; /* printf (LOG_MODULE ": xv_display_frame...\n"); */ + cm = cm_from_frame (frame_gen); + if (cm != this->cm_active) { + this->cm_active = cm; + cm = (0xc00c >> cm) & 1; + if (this->cm_atom != XCB_NONE) { + pthread_mutex_lock(&this->main_mutex); + xcb_xv_set_port_attribute (this->connection, this->xv_port, this->cm_atom, cm); + pthread_mutex_unlock(&this->main_mutex); + xprintf (this->xine, XINE_VERBOSITY_LOG, "video_out_xcbxv: color_matrix %s\n", + cm_names[cm ? 2 : 10]); + } + } + /* * queue frames (deinterlacing) * free old frames @@ -962,6 +983,8 @@ static void xv_dispose (vo_driver_t *this_gen) { _x_alphablend_free(&this->alphablend_extra_data); + cm_close (this); + free (this); } @@ -1288,6 +1311,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis this->xoverlay = NULL; this->ovl_changed = 0; this->xine = class->xine; + this->cm_atom = XCB_NONE; this->vo_driver.get_capabilities = xv_get_capabilities; this->vo_driver.alloc_frame = xv_alloc_frame; @@ -1321,6 +1345,8 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis this->props[VO_PROP_ZOOM_X].value = 100; this->props[VO_PROP_ZOOM_Y].value = 100; + cm_init (this); + /* * check this adaptor's capabilities */ @@ -1367,6 +1393,30 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis xv_check_capability (this, VO_PROP_GAMMA, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); + } else if(!strcmp(name, "XV_ITURBT_709")) { + xcb_xv_get_port_attribute_cookie_t get_attribute_cookie; + xcb_xv_get_port_attribute_reply_t *get_attribute_reply; + xcb_intern_atom_cookie_t atom_cookie; + xcb_intern_atom_reply_t *atom_reply; + pthread_mutex_lock(&this->main_mutex); + atom_cookie = xcb_intern_atom (this->connection, 0, 13, name); + atom_reply = xcb_intern_atom_reply (this->connection, atom_cookie, NULL); + if (atom_reply) { + this->cm_atom = atom_reply->atom; + free (atom_reply); + } + if (this->cm_atom != XCB_NONE) { + get_attribute_cookie = xcb_xv_get_port_attribute (this->connection, + this->xv_port, this->cm_atom); + get_attribute_reply = xcb_xv_get_port_attribute_reply (this->connection, + get_attribute_cookie, NULL); + if (get_attribute_reply) { + this->cm_active = get_attribute_reply->value ? 2 : 10; + free(get_attribute_reply); + this->capabilities |= VO_CAP_COLOR_MATRIX; + } + } + pthread_mutex_unlock(&this->main_mutex); } else if(!strcmp(name, "XV_COLORKEY")) { this->capabilities |= VO_CAP_COLORKEY; xv_check_capability (this, VO_PROP_COLORKEY, attribute_it.data, diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 2c443bb7d..6b52acccd 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -24,7 +24,7 @@ * * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de> * - * crop support added by Torsten Jager <t.jager@gmx.de> + * fullrange/HD color and crop support added by Torsten Jager <t.jager@gmx.de> */ #ifdef HAVE_CONFIG_H @@ -114,12 +114,15 @@ typedef struct { int use_shm; XColor black; - int yuv2rgb_brightness; - int yuv2rgb_contrast; - int yuv2rgb_saturation; + int brightness; + int contrast; + int saturation; uint8_t *yuv2rgb_cmap; yuv2rgb_factory_t *yuv2rgb_factory; + /* color matrix switching */ + int cm_active, cm_state; + vo_scale_t sc; xshm_frame_t *cur_frame; @@ -148,11 +151,16 @@ typedef struct { } xshm_class_t; +/* import common color matrix stuff */ +#define CM_DRIVER_T xshm_driver_t +#include "color_matrix.c" + static int gX11Fail; /* * first, some utility functions */ + /* called xlocked */ static int HandleXError (Display *display, XErrorEvent *xevent) { char str [1024]; @@ -328,7 +336,7 @@ static void dispose_ximage (xshm_driver_t *this, static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { xshm_driver_t *this = (xshm_driver_t *) this_gen; uint32_t capabilities = VO_CAP_CROP | VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_BRIGHTNESS - | VO_CAP_CONTRAST | VO_CAP_SATURATION; + | VO_CAP_CONTRAST | VO_CAP_SATURATION | VO_CAP_COLOR_MATRIX | VO_CAP_FULLRANGE; if( this->xoverlay ) capabilities |= VO_CAP_UNSCALED_OVERLAY; @@ -513,12 +521,21 @@ static void xshm_frame_proc_setup (vo_frame_t *vo_img) { if (i + frame->sc.crop_bottom < 0) frame->crop_flush -= 16 * vo_img->pitches[0]; + /* switch color matrix/range */ + i = cm_from_frame (vo_img); + if (i != this->cm_active) { + this->cm_active = i; + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, + this->brightness, this->contrast, this->saturation, i); + xprintf (this->xine, XINE_VERBOSITY_LOG, + "video_out_xshm: b %d c %d s %d [%s]\n", + this->brightness, this->contrast, this->saturation, cm_names[i]); + } } static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; uint8_t *src0; - /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */ /* delayed setup */ if (!vo_img->proc_called) { @@ -908,11 +925,11 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_MAX_NUM_FRAMES: return 15; case VO_PROP_BRIGHTNESS: - return this->yuv2rgb_brightness; + return this->brightness; case VO_PROP_CONTRAST: - return this->yuv2rgb_contrast; + return this->contrast; case VO_PROP_SATURATION: - return this->yuv2rgb_saturation; + return this->saturation; case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; case VO_PROP_WINDOW_HEIGHT: @@ -947,32 +964,20 @@ static int xshm_set_property (vo_driver_t *this_gen, break; case VO_PROP_BRIGHTNESS: - this->yuv2rgb_brightness = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->brightness = value; + this->cm_active = 0; this->sc.force_redraw = 1; break; case VO_PROP_CONTRAST: - this->yuv2rgb_contrast = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->contrast = value; + this->cm_active = 0; this->sc.force_redraw = 1; break; case VO_PROP_SATURATION: - this->yuv2rgb_saturation = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + this->saturation = value; + this->cm_active = 0; this->sc.force_redraw = 1; break; @@ -1102,6 +1107,8 @@ static void xshm_dispose (vo_driver_t *this_gen) { this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + cm_close (this); + LOCK_DISPLAY(this); XFreeGC(this->display, this->gc); UNLOCK_DISPLAY(this); @@ -1358,17 +1365,13 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v return NULL; } - this->yuv2rgb_brightness = 0; - this->yuv2rgb_contrast = 128; - this->yuv2rgb_saturation = 128; - - this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, - this->yuv2rgb_cmap); - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation, - CM_DEFAULT); + cm_init (this); + + this->brightness = 0; + this->contrast = 128; + this->saturation = 128; + + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, this->yuv2rgb_cmap); LOCK_DISPLAY(this); this->xoverlay = x11osd_create (this->xine, this->display, this->screen, diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index a17017b7f..1a546d2b5 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -156,6 +156,9 @@ struct xv_driver_s { void *user_data; + /* color matrix switching */ + int cm_active, cm_state; + Atom cm_atom; }; typedef struct { @@ -165,6 +168,10 @@ typedef struct { xine_t *xine; } xv_class_t; +/* import common color matrix stuff */ +#define CM_DRIVER_T xv_driver_t +#include "color_matrix.c" + static int gX11Fail; VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; @@ -669,10 +676,24 @@ static double timeOfDay() static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; + int cm; /* printf (LOG_MODULE ": xv_display_frame...\n"); */ + cm = cm_from_frame (frame_gen); + if (cm != this->cm_active) { + this->cm_active = cm; + cm = (0xc00c >> cm) & 1; + if (this->cm_atom != None) { + LOCK_DISPLAY(this); + XvSetPortAttribute (this->display, this->xv_port, this->cm_atom, cm); + UNLOCK_DISPLAY(this); + xprintf (this->xine, XINE_VERBOSITY_LOG, "video_out_xv: color_matrix %s\n", + cm_names[cm ? 2 : 10]); + } + } + /* * queue frames (deinterlacing) * free old frames @@ -1035,6 +1056,8 @@ static void xv_dispose (vo_driver_t *this_gen) { _x_alphablend_free(&this->alphablend_extra_data); + cm_close (this); + free (this); } @@ -1336,6 +1359,8 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * this->x11_old_error_handler = NULL; this->xine = class->xine; + this->cm_atom = None; + LOCK_DISPLAY(this); XAllocNamedColor (this->display, DefaultColormap(this->display, this->screen), @@ -1374,6 +1399,8 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * this->props[VO_PROP_ZOOM_X].value = 100; this->props[VO_PROP_ZOOM_Y].value = 100; + cm_init (this); + /* * check this adaptor's capabilities */ @@ -1419,6 +1446,15 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * xv_check_capability (this, VO_PROP_GAMMA, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); + } else if(!strcmp(name, "XV_ITURBT_709")) { + LOCK_DISPLAY(this); + this->cm_atom = XInternAtom (this->display, name, False); + if (this->cm_atom != None) { + XvGetPortAttribute (this->display, this->xv_port, this->cm_atom, &this->cm_active); + this->cm_active = this->cm_active ? 2 : 10; + this->capabilities |= VO_CAP_COLOR_MATRIX; + } + UNLOCK_DISPLAY(this); } else if(!strcmp(name, "XV_COLORKEY")) { this->capabilities |= VO_CAP_COLORKEY; xv_check_capability (this, VO_PROP_COLORKEY, attr[k], |