From 86d3d11a68510764504a2a3c5987ab8e059d6df5 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Tue, 25 Mar 2014 18:45:08 +0100 Subject: video: Add BT.2020-NCL colorspace and transfer function Source: http://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-0-201208-I!!PDF-E.pdf --- DOCS/man/options.rst | 1 + DOCS/man/vo.rst | 4 ++-- old-configure | 6 ++++++ options/options.c | 1 + video/csputils.c | 24 +++++++++++++++++------- video/csputils.h | 1 + video/mp_image.c | 1 + video/out/gl_video_shaders.glsl | 23 ++++++++++++++--------- wscript | 6 ++++++ 9 files changed, 49 insertions(+), 18 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index d67d93c592..6e96c9c541 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -537,6 +537,7 @@ OPTIONS :auto: automatic selection (default) :BT.601: ITU-R BT.601 (SD) :BT.709: ITU-R BT.709 (HD) + :BT.2020-NC: ITU-R BT.2020 non-constant luminance system :SMPTE-240M: SMPTE-240M ``--colormatrix-input-range=`` diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 57fe41f5b7..35df26e245 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -509,14 +509,14 @@ Available video output drivers are: absolute colorimetric ``approx-gamma`` - Approximate the actual BT.709 gamma function as a pure power curve of + Approximate the actual gamma function as a pure power curve of 1.95. A number of video editing programs and studios apparently use this for mastering instead of the true curve. Most notably, anything in the Apple ecosystem uses this approximation - including all programs compatible with it. It's a sound idea to try enabling this flag first when watching movies and shows to see if things look better that way. - This only affects the output when using either ``icc-profile`` or``srgb``. + This only affects the output when using either ``icc-profile`` or ``srgb``. ``3dlut-size=xx`` Size of the 3D LUT generated from the ICC profile in each dimension. diff --git a/old-configure b/old-configure index 686cbcfd62..3280dcb563 100755 --- a/old-configure +++ b/old-configure @@ -797,6 +797,12 @@ api_statement_check \ libavcodec/avcodec.h \ 'int x, y; avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)' +api_statement_check \ + "libavcodec avcol_spc_bt2020 available" \ + HAVE_AVCOL_SPC_BT2020 \ + libavcodec/avcodec.h \ + 'int x = AVCOL_SPC_BT2020_NCL' + api_statement_check \ "libavcodec metadata update side data" \ HAVE_AVCODEC_METADATA_UPDATE_SIDE_DATA \ diff --git a/options/options.c b/options/options.c index 45accce0de..ea79a7d609 100644 --- a/options/options.c +++ b/options/options.c @@ -389,6 +389,7 @@ const m_option_t mp_opts[] = { {"BT.601", MP_CSP_BT_601}, {"BT.709", MP_CSP_BT_709}, {"SMPTE-240M", MP_CSP_SMPTE_240M}, + {"BT.2020-NC", MP_CSP_BT_2020_NC}, {"YCgCo", MP_CSP_YCGCO})), OPT_CHOICE("colormatrix-input-range", requested_input_range, 0, ({"auto", MP_CSP_LEVELS_AUTO}, diff --git a/video/csputils.c b/video/csputils.c index 9c1b04c928..13398d6d10 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -27,6 +27,8 @@ * version 2.1 of the License, or (at your option) any later version. */ +#include "config.h" + #include #include #include @@ -40,6 +42,7 @@ const char *const mp_csp_names[MP_CSP_COUNT] = { "BT.601 (SD)", "BT.709 (HD)", "SMPTE-240M", + "BT.2020 (NC)", "RGB", "XYZ", "YCgCo", @@ -68,13 +71,16 @@ const char *const mp_chroma_names[MP_CHROMA_COUNT] = { enum mp_csp avcol_spc_to_mp_csp(int avcolorspace) { switch (avcolorspace) { - case AVCOL_SPC_BT709: return MP_CSP_BT_709; - case AVCOL_SPC_BT470BG: return MP_CSP_BT_601; - case AVCOL_SPC_SMPTE170M: return MP_CSP_BT_601; - case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M; - case AVCOL_SPC_RGB: return MP_CSP_RGB; - case AVCOL_SPC_YCOCG: return MP_CSP_YCGCO; - default: return MP_CSP_AUTO; + case AVCOL_SPC_BT709: return MP_CSP_BT_709; + case AVCOL_SPC_BT470BG: return MP_CSP_BT_601; +#if HAVE_AVCOL_SPC_BT2020 + case AVCOL_SPC_BT2020_NCL: return MP_CSP_BT_2020_NC; +#endif + case AVCOL_SPC_SMPTE170M: return MP_CSP_BT_601; + case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M; + case AVCOL_SPC_RGB: return MP_CSP_RGB; + case AVCOL_SPC_YCOCG: return MP_CSP_YCGCO; + default: return MP_CSP_AUTO; } } @@ -92,6 +98,9 @@ int mp_csp_to_avcol_spc(enum mp_csp colorspace) switch (colorspace) { case MP_CSP_BT_709: return AVCOL_SPC_BT709; case MP_CSP_BT_601: return AVCOL_SPC_BT470BG; +#if HAVE_AVCOL_SPC_BT2020 + case MP_CSP_BT_2020_NC: return AVCOL_SPC_BT2020_NCL; +#endif case MP_CSP_SMPTE_240M: return AVCOL_SPC_SMPTE240M; case MP_CSP_RGB: return AVCOL_SPC_RGB; case MP_CSP_YCGCO: return AVCOL_SPC_YCOCG; @@ -218,6 +227,7 @@ void mp_get_yuv2rgb_coeffs(struct mp_csp_params *params, float m[3][4]) case MP_CSP_BT_601: luma_coeffs(m, 0.299, 0.587, 0.114 ); break; case MP_CSP_BT_709: luma_coeffs(m, 0.2126, 0.7152, 0.0722); break; case MP_CSP_SMPTE_240M: luma_coeffs(m, 0.2122, 0.7013, 0.0865); break; + case MP_CSP_BT_2020_NC: luma_coeffs(m, 0.2627, 0.6780, 0.0593); break; case MP_CSP_RGB: { static const float ident[3][4] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; memcpy(m, ident, sizeof(ident)); diff --git a/video/csputils.h b/video/csputils.h index c11c3506a6..57e10b3c27 100644 --- a/video/csputils.h +++ b/video/csputils.h @@ -37,6 +37,7 @@ enum mp_csp { MP_CSP_BT_601, MP_CSP_BT_709, MP_CSP_SMPTE_240M, + MP_CSP_BT_2020_NC, MP_CSP_RGB, MP_CSP_XYZ, MP_CSP_YCGCO, diff --git a/video/mp_image.c b/video/mp_image.c index 85638e9fd1..64c310aaed 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -521,6 +521,7 @@ void mp_image_params_guess_csp(struct mp_image_params *params) if (fmt.flags & MP_IMGFLAG_YUV) { if (params->colorspace != MP_CSP_BT_601 && params->colorspace != MP_CSP_BT_709 && + params->colorspace != MP_CSP_BT_2020_NC && params->colorspace != MP_CSP_SMPTE_240M && params->colorspace != MP_CSP_YCGCO) { diff --git a/video/out/gl_video_shaders.glsl b/video/out/gl_video_shaders.glsl index 15bb600e61..b0058f8ca6 100644 --- a/video/out/gl_video_shaders.glsl +++ b/video/out/gl_video_shaders.glsl @@ -49,10 +49,10 @@ vec3 srgb_compand(vec3 v) lessThanEqual(vec3(0.0031308), v)); } -vec3 bt709_expand(vec3 v) +vec3 bt2020_expand(vec3 v) { - return mix(v / 4.5, pow((v + vec3(0.099))/1.099, vec3(1/0.45)), - lessThanEqual(vec3(0.0812), v)); + return mix(v / 4.5, pow((v + vec3(0.0993))/1.0993, vec3(1/0.45)), + lessThanEqual(vec3(0.08145), v)); } #endif @@ -85,8 +85,8 @@ void main() { // Although we are not scaling in linear light, both 3DLUT and SRGB still // operate on linear light inputs so we have to convert to it before // either step can be applied. - color.rgb = bt709_expand(color.rgb); - // NOTE: This always applies the true BT709, maybe we need to use + color.rgb = bt2020_expand(color.rgb); + // NOTE: This always applies the true BT2020, maybe we need to use // approx-gamma here too? #endif #ifdef USE_OSD_3DLUT @@ -387,13 +387,18 @@ void main() { #endif #ifdef USE_LINEAR_LIGHT // If we are scaling in linear light (SRGB or 3DLUT option enabled), we - // expand our source colors before scaling + // expand our source colors before scaling. This shader currently just + // assumes everything uses the BT.2020 12-bit gamma function, since the + // difference between this and BT.601, BT.709 and BT.2020 10-bit is well + // below the rounding error threshold for both 8-bit and even 10-bit + // content. It only makes a difference for 12-bit sources, so it should be + // fine to use here. #ifdef USE_APPROX_GAMMA - // We differentiate between approximate BT.709 (gamma 1.95) ... + // We differentiate between approximate BT.2020 (gamma 1.95) ... color = pow(color, vec3(1.95)); #else - // ... and actual BT709 (two-part function) - color = bt709_expand(color); + // ... and actual BT.2020 (two-part function) + color = bt2020_expand(color); #endif #endif // Image upscaling happens roughly here diff --git a/wscript b/wscript index 18d9b5c242..b4550a88ec 100644 --- a/wscript +++ b/wscript @@ -364,6 +364,12 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks)) 'func': check_statement('libavcodec/avcodec.h', """int x, y; avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)""", use='libav') + }, { + 'name': 'avcol-spc-bt2020', + 'desc': 'libavcodec avcol_spc_bt2020 available', + 'func': check_statement('libavcodec/avcodec.h', + 'int x = AVCOL_SPC_BT2020_NCL', + use='libav') }, { 'name': 'avutil-qp-api', 'desc': 'libavutil QP API', -- cgit v1.2.3