summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTorsten Jager <t.jager@gmx.de>2012-06-29 21:25:56 +0300
committerTorsten Jager <t.jager@gmx.de>2012-06-29 21:25:56 +0300
commit65da909ff4684e5feb53c39ee43a5a9dd3dc0ffe (patch)
treeb9921d332f340e7630c2c6be9ba4196367b66c94 /src
parent94010a9d0e5cddcbb4973ec3c654826c91094b24 (diff)
downloadxine-lib-65da909ff4684e5feb53c39ee43a5a9dd3dc0ffe.tar.gz
xine-lib-65da909ff4684e5feb53c39ee43a5a9dd3dc0ffe.tar.bz2
Add color matrix support to video out interface
Diffstat (limited to 'src')
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c19
-rw-r--r--src/video_out/color_matrix.c173
2 files changed, 189 insertions, 3 deletions
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index 4de2aeae8..54ddfd2ad 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -140,8 +140,11 @@ struct ff_video_decoder_s {
#endif
};
+/* import color matrix names */
+#include "../../video_out/color_matrix.c"
+
static void ff_check_colorspace (ff_video_decoder_t *this) {
- int i, cm;
+ int i, cm, caps;
#ifdef AVCODEC_HAS_COLORSPACE
cm = this->context->colorspace << 1;
@@ -162,17 +165,27 @@ static void ff_check_colorspace (ff_video_decoder_t *this) {
if (cm != this->color_matrix) {
this->color_matrix = cm;
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
- "ffmpeg_video_dec: color matrix #%d\n", cm >> 1);
+ "ffmpeg_video_dec: color matrix #%d [%s]\n", cm >> 1, cm_names[cm & 15]);
+
+ caps = this->stream->video_out->get_capabilities (this->stream->video_out);
+
+ if (!(caps & VO_CAP_COLOR_MATRIX)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "ffmpeg_video_dec: video out plugin does not support color matrix switching\n");
+ cm &= 1;
+ }
this->full2mpeg = 0;
- if (cm & 1) {
+ if ((cm & 1) && !(caps & VO_CAP_FULLRANGE)) {
/* sigh. fall back to manual conversion */
+ cm &= ~1;
this->full2mpeg = 1;
for (i = 0; i < 256; i++) {
this->ytab[i] = (219 * i + 127) / 255 + 16;
this->ctab[i] = 112 * (i - 128) / 127 + 128;
}
}
+ VO_SET_FLAGS_CM (cm, this->frame_flags);
}
}
diff --git a/src/video_out/color_matrix.c b/src/video_out/color_matrix.c
new file mode 100644
index 000000000..22b62ef02
--- /dev/null
+++ b/src/video_out/color_matrix.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2012 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ */
+
+
+/*
+ TJ. the output color matrix selection feature.
+
+ This file must be included after declaration of xxxx_driver_t,
+ and #define'ing CM_DRIVER_T to it.
+ That struct must contain the integer values cm_state and cm_new.
+
+ In theory, HD video uses a different YUV->RGB matrix than the rest.
+ It shall come closer to the human eye's brightness feel, and give
+ more shades of green even without higher bit depth.
+
+ I discussed this topic with local TV engineers earlier.
+ They say their studio equipment throws around uncompressed YUV with no
+ extra info attached to it. Anything smaller than 720p is assumed to be
+ ITU-R 601, otherwise ITU-R 709. A rematrix filter applies whenever
+ video is scaled across the above mentioned HD threshold.
+
+ However, the weak point of their argumentation is potentially non-standard
+ input material. Those machines obviously dont verify input data, and
+ ocasionally they dont even respect stream info (tested by comparing TV
+ against retail DVD version of same movie).
+
+ Consumer TV sets handle this fairly inconsistent - stream info, video size,
+ hard-wired matrix, user choice or so-called intelligent picture enhancers
+ that effectively go way off standards.
+ So I decided to provide functionality, and let the user decide if and how
+ to actually use it.
+
+ BTW. VDPAU already has its own matrix switch based on stream info.
+ Rumour has it that proprietory ATI drivers auto switch their xv ports
+ based on video size. Both not user configurable, and both not tested...
+*/
+
+#ifdef CM_DRIVER_T
+
+/* cm_update () modes */
+#define CM_UPDATE_INIT 0
+#define CM_UPDATE_CONFIG 1
+#define CM_UPDATE_STREAM 2
+#define CM_UPDATE_HEIGHT 3
+#define CM_UPDATE_CLOSE 4
+
+/* user configuration settings */
+#define CM_CONFIG_SIGNAL 0
+#define CM_CONFIG_SIZE 1
+#define CM_CONFIG_SD 2
+#define CM_CONFIG_HD 3
+
+static void cm_update (CM_DRIVER_T *this, int mode, int value);
+
+/* the names thereof */
+static const char * const cm_conf_labels[] = {
+ "Signal", "Signal+Size", "SD", "HD", NULL
+};
+
+#endif /* defined CM_DRIVER_T */
+
+static const char * const cm_names[] = {
+ "ITU-R 470 BG / SDTV",
+ "ITU-R 709 / HDTV",
+ "ITU-R 470 BG / SDTV",
+ "ITU-R 470 BG / SDTV",
+ "FCC",
+ "ITU-R 470 BG / SDTV",
+ "SMPTE 170M",
+ "SMPTE 240M"
+};
+
+#ifdef CM_DRIVER_T
+
+/* callback when user changes them */
+static void cm_cb_config (void *this_gen, xine_cfg_entry_t *entry) {
+ CM_DRIVER_T *this = (CM_DRIVER_T *)this_gen;
+ cm_update (this, CM_UPDATE_CONFIG, entry->num_value);
+}
+
+/* handle generic changes */
+static void cm_update (CM_DRIVER_T *this, int mode, int value) {
+ /* get state */
+ int conf = this->cm_state & 7;
+ int stream = (this->cm_state >> 3) & 7;
+ int hd = (this->cm_state >> 6) & 1;
+ /* update it */
+ switch (mode) {
+ case CM_UPDATE_INIT:
+ /* register configuration */
+ conf = this->xine->config->register_enum (
+ this->xine->config,
+ "video.output.color_matrix",
+ CM_CONFIG_SD,
+ (char **)cm_conf_labels,
+ _("Output color matrix to use"),
+ _("Tell how output colors should be calculated.\n\n"
+ "Signal: Do as current stream suggests.\n"
+ " This may be wrong sometimes.\n\n"
+ "Signal+Size: Same as above,\n"
+ " but assume HD color for unmarked HD streams.\n\n"
+ "SD: Force SD video standard ITU-R 470/601.\n"
+ " Try this if you get too little green.\n\n"
+ "HD: Force HD video standard ITU-R 709.\n"
+ " Try when there is too much green coming out.\n\n"),
+ 10,
+ cm_cb_config,
+ this
+ );
+ /* lock to legacy matrix until someone sends CM_UPDATE_STREAM.
+ This way still images and audio visualisation stay correct */
+ stream = 0;
+ hd = 0;
+ break;
+ case CM_UPDATE_CONFIG:
+ conf = value;
+ break;
+ case CM_UPDATE_STREAM:
+ stream = value;
+ if ((stream < 1) || (stream > 7)) stream = 2; /* undefined */
+ break;
+ case CM_UPDATE_HEIGHT:
+ hd = value >= 720 ? 1 : 0;
+ break;
+ case CM_UPDATE_CLOSE:
+ /* dont know whether this is really necessary */
+ this->xine->config->unregister_callback (this->xine->config,
+ "video.output.color_matrix");
+ break;
+ }
+ /* check user configuration */
+ switch (conf) {
+ case CM_CONFIG_SIZE:
+ if (stream == 2) {
+ /* no stream info, decide based on video size */
+ this->yuv2rgb_cm = hd ? 1 : 2;
+ break;
+ }
+ /* fall through */
+ case CM_CONFIG_SIGNAL:
+ /* follow stream info */
+ this->yuv2rgb_cm = stream ? stream : 2;
+ break;
+ case CM_CONFIG_SD:
+ this->yuv2rgb_cm = 5; /* ITU-R 601/SDTV */
+ break;
+ case CM_CONFIG_HD:
+ this->yuv2rgb_cm = 1; /* ITU-R 709/HDTV */
+ break;
+ }
+ /* save state */
+ this->cm_state = (hd << 6) | (stream << 3) | conf;
+}
+
+#endif /* defined CM_DRIVER_T */