summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-06-08 02:15:24 +0200
committerwm4 <wm4@nowhere>2013-06-28 21:20:41 +0200
commitac266da6588f25a449a739f7a6a3d2c69ca80e19 (patch)
tree6fc863452bec6fd07b05d057d093946772ba96c7 /video/out
parent3382a6f6e48c7e093c2b7e0e4a0e28b60a084358 (diff)
downloadmpv-ac266da6588f25a449a739f7a6a3d2c69ca80e19.tar.bz2
mpv-ac266da6588f25a449a739f7a6a3d2c69ca80e19.tar.xz
vo_opengl: handle chroma location
Use the video decoder chroma location flags and render chroma locations other than centered. Until now, we've always used the intuitive and obvious centered chroma location, but H.264 uses something else. FFmpeg provides a small overview in libavcodec/avcodec.h: ----------- /** * X X 3 4 X X are luma samples, * 1 2 1-6 are possible chroma positions * X X 5 6 X 0 is undefined/unknown position */ enum AVChromaLocation{ AVCHROMA_LOC_UNSPECIFIED = 0, AVCHROMA_LOC_LEFT = 1, ///< mpeg2/4, h264 default AVCHROMA_LOC_CENTER = 2, ///< mpeg1, jpeg, h263 AVCHROMA_LOC_TOPLEFT = 3, ///< DV AVCHROMA_LOC_TOP = 4, AVCHROMA_LOC_BOTTOMLEFT = 5, AVCHROMA_LOC_BOTTOM = 6, AVCHROMA_LOC_NB , ///< Not part of ABI }; ----------- The visual difference is literally minimal, but since videophiles apparently consider this detail as quality mark of a video renderer, support it anyway. We don't bother with chroma locations other than centered and left, though. Not sure about correctness, but it's probably ok.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/gl_video.c27
-rw-r--r--video/out/gl_video.h1
-rw-r--r--video/out/gl_video_shaders.glsl8
3 files changed, 33 insertions, 3 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 658c531546..bdca0a1ff4 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -185,6 +185,7 @@ struct gl_video {
struct mp_csp_details colorspace;
struct mp_csp_equalizer video_eq;
+ enum mp_chroma_location chroma_loc;
struct mp_rect src_rect; // displayed part of the source video
struct mp_rect dst_rect; // video rectangle on output window
@@ -279,6 +280,10 @@ const struct m_sub_options gl_video_conf = {
({"fruit", 0}, {"ordered", 1}, {"no", -1})),
OPT_INTRANGE("dither-size-fruit", dither_size, 0, 2, 8),
OPT_FLAG("temporal-dither", temporal_dither, 0),
+ OPT_CHOICE("chroma-location", chroma_location, 0,
+ ({"auto", MP_CHROMA_AUTO},
+ {"center", MP_CHROMA_CENTER},
+ {"left", MP_CHROMA_LEFT})),
OPT_FLAG("alpha", enable_alpha, 0),
{0}
},
@@ -510,6 +515,27 @@ static void update_uniforms(struct gl_video *p, GLuint program)
p->image.planes[n].tex_w, p->image.planes[n].tex_h);
}
+ loc = gl->GetUniformLocation(program, "chroma_center_offset");
+ if (loc >= 0) {
+ int chr = p->opts.chroma_location;
+ if (!chr)
+ chr = p->chroma_loc;
+ int cx, cy;
+ mp_get_chroma_location(chr, &cx, &cy);
+ // By default texture coordinates are such that chroma is centered with
+ // any chroma subsampling. If a specific direction is given, make it
+ // so that the luma and chroma sample line up exactly.
+ // For 4:4:4, setting chroma location should have no effect at all.
+ // luma sample size (in chroma coord. space)
+ float ls_w = 1.0 / (1 << p->image_desc.chroma_xs);
+ float ls_h = 1.0 / (1 << p->image_desc.chroma_ys);
+ // move chroma center to luma center (in chroma coord. space)
+ float o_x = ls_w < 1 ? ls_w * -cx / 2 : 0;
+ float o_y = ls_h < 1 ? ls_h * -cy / 2 : 0;
+ gl->Uniform2f(loc, o_x / FFMAX(p->image.planes[1].w, 1),
+ o_y / FFMAX(p->image.planes[1].h, 1));
+ }
+
gl->Uniform2f(gl->GetUniformLocation(program, "dither_size"),
p->dither_size, p->dither_size);
@@ -1861,6 +1887,7 @@ void gl_video_config(struct gl_video *p, struct mp_image_params *params)
}
p->image_dw = params->d_w;
p->image_dh = params->d_h;
+ p->chroma_loc = params->chroma_location;
}
void gl_video_set_output_depth(struct gl_video *p, int r, int g, int b)
diff --git a/video/out/gl_video.h b/video/out/gl_video.h
index 289ccddf52..ca0cb5468a 100644
--- a/video/out/gl_video.h
+++ b/video/out/gl_video.h
@@ -45,6 +45,7 @@ struct gl_video_opts {
int fbo_format;
int stereo_mode;
int enable_alpha;
+ int chroma_location;
};
extern const struct m_sub_options gl_video_conf;
diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl
index 47be240571..6337822c02 100644
--- a/video/out/gl_video_shaders.glsl
+++ b/video/out/gl_video_shaders.glsl
@@ -114,6 +114,7 @@ void main() {
#!section frag_video
uniform sampler2D textures[4];
uniform vec2 textures_size[4];
+uniform vec2 chroma_center_offset;
uniform sampler1D lut_c_1d;
uniform sampler1D lut_l_1d;
uniform sampler2D lut_c_2d;
@@ -321,17 +322,18 @@ vec4 sample_sharpen5(sampler2D tex, vec2 texsize, vec2 texcoord) {
}
void main() {
+ vec2 chr_texcoord = texcoord + chroma_center_offset;
#ifndef USE_CONV
#define USE_CONV 0
#endif
#if USE_CONV == CONV_PLANAR
vec3 color = vec3(SAMPLE_L(textures[0], textures_size[0], texcoord).r,
- SAMPLE_C(textures[1], textures_size[1], texcoord).r,
- SAMPLE_C(textures[2], textures_size[2], texcoord).r);
+ SAMPLE_C(textures[1], textures_size[1], chr_texcoord).r,
+ SAMPLE_C(textures[2], textures_size[2], chr_texcoord).r);
float alpha = 1.0;
#elif USE_CONV == CONV_NV12
vec3 color = vec3(SAMPLE_L(textures[0], textures_size[0], texcoord).r,
- SAMPLE_C(textures[1], textures_size[1], texcoord).rg);
+ SAMPLE_C(textures[1], textures_size[1], chr_texcoord).rg);
float alpha = 1.0;
#else
vec4 acolor = SAMPLE_L(textures[0], textures_size[0], texcoord);