diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/csputils.c | 19 | ||||
-rw-r--r-- | video/csputils.h | 10 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 3 | ||||
-rw-r--r-- | video/filter/vf.c | 1 | ||||
-rw-r--r-- | video/mp_image.c | 1 | ||||
-rw-r--r-- | video/mp_image.h | 3 | ||||
-rw-r--r-- | video/out/gl_video.c | 27 | ||||
-rw-r--r-- | video/out/gl_video.h | 1 | ||||
-rw-r--r-- | video/out/gl_video_shaders.glsl | 8 |
9 files changed, 70 insertions, 3 deletions
diff --git a/video/csputils.c b/video/csputils.c index 240c7a3259..91b7d88ec6 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -100,6 +100,25 @@ enum mp_csp mp_csp_guess_colorspace(int width, int height) return width >= 1280 || height > 576 ? MP_CSP_BT_709 : MP_CSP_BT_601; } +enum mp_chroma_location avchroma_location_to_mp(enum AVChromaLocation loc) +{ + switch (loc) { + case AVCHROMA_LOC_LEFT: return MP_CHROMA_LEFT; + case AVCHROMA_LOC_CENTER: return MP_CHROMA_CENTER; + default: return MP_CHROMA_AUTO; + } +} + +// Return location of chroma samples relative to luma samples. 0/0 means +// centered. Other possible values are -1 (top/left) and +1 (right/bottom). +void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y) +{ + *x = 0; + *y = 0; + if (loc == MP_CHROMA_LEFT) + *x = -1; +} + /** * \brief little helper function to create a lookup table for gamma * \param map buffer to create map into diff --git a/video/csputils.h b/video/csputils.h index d11e85e38b..af510299cf 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -87,6 +87,12 @@ struct mp_csp_params { .rgamma = 1, .ggamma = 1, .bgamma = 1, \ .texture_bits = 8, .input_bits = 8} +enum mp_chroma_location { + MP_CHROMA_AUTO, + MP_CHROMA_LEFT, // mpeg2/4, h264 + MP_CHROMA_CENTER, // mpeg1, jpeg +}; + enum mp_csp_equalizer_param { MP_CSP_EQ_BRIGHTNESS, MP_CSP_EQ_CONTRAST, @@ -136,6 +142,10 @@ enum AVColorRange mp_csp_levels_to_avcol_range(enum mp_csp_levels range); enum mp_csp mp_csp_guess_colorspace(int width, int height); +enum mp_chroma_location avchroma_location_to_mp(enum AVChromaLocation loc); + +void mp_get_chroma_location(enum mp_chroma_location loc, int *x, int *y); + void mp_gen_gamma_map(unsigned char *map, int size, float gamma); #define ROW_R 0 #define ROW_G 1 diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index f67e6dfbe6..ff1565f38f 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -446,6 +446,8 @@ static int init_vo(sh_video_t *sh, AVFrame *frame) .d_h = height, .colorspace = avcol_spc_to_mp_csp(ctx->avctx->colorspace), .colorlevels = avcol_range_to_mp_csp_levels(ctx->avctx->color_range), + .chroma_location = + avchroma_location_to_mp(ctx->avctx->chroma_sample_location), }; if (mpcodecs_reconfig_vo(sh, &ctx->image_params) < 0) @@ -701,6 +703,7 @@ static int decode(struct sh_video *sh, struct demux_packet *packet, mpi->colorspace = ctx->image_params.colorspace; mpi->levels = ctx->image_params.colorlevels; + mpi->chroma_location = ctx->image_params.chroma_location; *out_image = mpi; return 1; diff --git a/video/filter/vf.c b/video/filter/vf.c index 26841f380f..0f7cc58ee5 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -477,6 +477,7 @@ int vf_next_config(struct vf_instance *vf, .d_h = d_height, .colorspace = vf->fmt_in.params.colorspace, .colorlevels = vf->fmt_in.params.colorlevels, + .chroma_location = vf->fmt_in.params.chroma_location, }; int r = vf_reconfig_wrapper(vf->next, &p, voflags); return r < 0 ? 0 : 1; diff --git a/video/mp_image.c b/video/mp_image.c index 85c174dfaa..95b59eae28 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -324,6 +324,7 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) if ((dst->flags & MP_IMGFLAG_YUV) == (src->flags & MP_IMGFLAG_YUV)) { dst->colorspace = src->colorspace; dst->levels = src->levels; + dst->chroma_location = src->chroma_location; } if (dst->imgfmt == IMGFMT_PAL8 && src->imgfmt == IMGFMT_PAL8) { if (dst->planes[1] && src->planes[1]) diff --git a/video/mp_image.h b/video/mp_image.h index 643b70b949..96b980039d 100644 --- a/video/mp_image.h +++ b/video/mp_image.h @@ -43,6 +43,7 @@ struct mp_image_params { int d_w, d_h; // define display aspect ratio (never 0/0) enum mp_csp colorspace; enum mp_csp_levels colorlevels; + enum mp_chroma_location chroma_location; }; /* Memory management: @@ -90,6 +91,8 @@ typedef struct mp_image { enum mp_csp colorspace; enum mp_csp_levels levels; + enum mp_chroma_location chroma_location; + /* only inside filter chain */ double pts; /* memory management */ 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); |