Permalink
Browse files

Clarify YUV <-> non-linear RGB conversions, and add some comments.

  • Loading branch information...
1 parent bd47c64 commit 708d34719b31d4ab7f433844ede36294ed38cd50 @marlam marlam committed Dec 11, 2010
Showing with 39 additions and 10 deletions.
  1. +11 −0 src/video_output_opengl.cpp
  2. +28 −10 src/video_output_opengl_color.fs.glsl
View
11 src/video_output_opengl.cpp
@@ -69,6 +69,17 @@
* values for output. We do not use the GL_ARB_framebuffer_sRGB extension for
* this purpose because 1) we need computations on non-linear values for the
* anaglyph methods and 2) sRGB framebuffers are not yet widely supported.
+ *
+ * Open issues / TODO:
+ * 1. The conversion from YUV to non-linear RGB assumes ITU.BT-601 input.
+ * This is wrong in case of HDTV, where ITU.BT-709 would be correct.
+ * This is also wrong in case FFmpeg gives us input which uses the full
+ * value range 0-255 for each component (should not happen for video data).
+ * We should get the information which conversion to use from FFmpeg,
+ * but I currently don't know how.
+ * 2. I *think* that the matrices used for the Dubois method in the rendering
+ * shader should be applied to non-linear RGB values, but I'm not 100%
+ * sure.
*/
View
38 src/video_output_opengl_color.fs.glsl
@@ -40,21 +40,39 @@ uniform float sin_hue;
#if defined(input_bgra32)
vec3 srgb_to_yuv(vec3 srgb)
{
- // Values taken from http://www.fourcc.org/fccyvrgb.php
- float y = dot(srgb, vec3(0.299, 0.587, 0.114));
- float u = 0.564 * (srgb.b - y) + 0.5;
- float v = 0.713 * (srgb.r - y) + 0.5;
- return vec3(y, u, v);
+ // According to ITU.BT-601
+ mat3 m = mat3(
+ 0.299, -0.169, 0.5,
+ 0.587, -0.331, -0.419,
+ 0.114, 0.500, -0.081);
+ return m * srgb + vec3(0.0, 0.5, 0.5);
+# if 0
+ // According to ITU.BT-709
+ mat3 m = mat3(
+ 0.2215, -0.1145, 0.5016,
+ 0.7154, -0.3855, -0.4556,
+ 0.0721, 0.5, -0.0459);
+ return m * srgb + vec3(0.0, 0.5, 0.5);
+#endif
}
#endif
vec3 yuv_to_srgb(vec3 yuv)
{
- // Values taken from http://www.fourcc.org/fccyvrgb.php
- float r = yuv.x + 1.403 * (yuv.z - 0.5);
- float g = yuv.x - 0.344 * (yuv.y - 0.5) - 0.714 * (yuv.z - 0.5);
- float b = yuv.x + 1.770 * (yuv.y - 0.5);
- return vec3(r, g, b);
+ // According to ITU.BT-601
+ mat3 m = mat3(
+ 1.0, 1.0, 1.0,
+ 0.0, -0.344, 1.773,
+ 1.403, -0.714, 0.0);
+ return m * (yuv - vec3(0.0, 0.5, 0.5));
+# if 0
+ // According to ITU.BT-709
+ mat3 m = mat3(
+ 1.0, 1.0, 1.0,
+ 0.0, -0.187, -1.8556,
+ 1.5701, -0.4664, 0.0);
+ return m * (yuv - vec3(0.0, 0.5, 0.5));
+#endif
}
vec3 adjust_yuv(vec3 yuv)

0 comments on commit 708d347

Please sign in to comment.