1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-22 03:08:33 +00:00

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
This commit is contained in:
Niklas Haas 2014-03-25 18:45:08 +01:00 committed by wm4
parent 082fbe39e8
commit 86d3d11a68
9 changed files with 49 additions and 18 deletions

View File

@ -537,6 +537,7 @@ OPTIONS
:auto: automatic selection (default) :auto: automatic selection (default)
:BT.601: ITU-R BT.601 (SD) :BT.601: ITU-R BT.601 (SD)
:BT.709: ITU-R BT.709 (HD) :BT.709: ITU-R BT.709 (HD)
:BT.2020-NC: ITU-R BT.2020 non-constant luminance system
:SMPTE-240M: SMPTE-240M :SMPTE-240M: SMPTE-240M
``--colormatrix-input-range=<color-range>`` ``--colormatrix-input-range=<color-range>``

View File

@ -509,7 +509,7 @@ Available video output drivers are:
absolute colorimetric absolute colorimetric
``approx-gamma`` ``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 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 for mastering instead of the true curve. Most notably, anything in the
Apple ecosystem uses this approximation - including all programs Apple ecosystem uses this approximation - including all programs

View File

@ -797,6 +797,12 @@ api_statement_check \
libavcodec/avcodec.h \ libavcodec/avcodec.h \
'int x, y; avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)' '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 \ api_statement_check \
"libavcodec metadata update side data" \ "libavcodec metadata update side data" \
HAVE_AVCODEC_METADATA_UPDATE_SIDE_DATA \ HAVE_AVCODEC_METADATA_UPDATE_SIDE_DATA \

View File

@ -389,6 +389,7 @@ const m_option_t mp_opts[] = {
{"BT.601", MP_CSP_BT_601}, {"BT.601", MP_CSP_BT_601},
{"BT.709", MP_CSP_BT_709}, {"BT.709", MP_CSP_BT_709},
{"SMPTE-240M", MP_CSP_SMPTE_240M}, {"SMPTE-240M", MP_CSP_SMPTE_240M},
{"BT.2020-NC", MP_CSP_BT_2020_NC},
{"YCgCo", MP_CSP_YCGCO})), {"YCgCo", MP_CSP_YCGCO})),
OPT_CHOICE("colormatrix-input-range", requested_input_range, 0, OPT_CHOICE("colormatrix-input-range", requested_input_range, 0,
({"auto", MP_CSP_LEVELS_AUTO}, ({"auto", MP_CSP_LEVELS_AUTO},

View File

@ -27,6 +27,8 @@
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
*/ */
#include "config.h"
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
@ -40,6 +42,7 @@ const char *const mp_csp_names[MP_CSP_COUNT] = {
"BT.601 (SD)", "BT.601 (SD)",
"BT.709 (HD)", "BT.709 (HD)",
"SMPTE-240M", "SMPTE-240M",
"BT.2020 (NC)",
"RGB", "RGB",
"XYZ", "XYZ",
"YCgCo", "YCgCo",
@ -70,6 +73,9 @@ enum mp_csp avcol_spc_to_mp_csp(int avcolorspace)
switch (avcolorspace) { switch (avcolorspace) {
case AVCOL_SPC_BT709: return MP_CSP_BT_709; case AVCOL_SPC_BT709: return MP_CSP_BT_709;
case AVCOL_SPC_BT470BG: return MP_CSP_BT_601; 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_SMPTE170M: return MP_CSP_BT_601;
case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M; case AVCOL_SPC_SMPTE240M: return MP_CSP_SMPTE_240M;
case AVCOL_SPC_RGB: return MP_CSP_RGB; case AVCOL_SPC_RGB: return MP_CSP_RGB;
@ -92,6 +98,9 @@ int mp_csp_to_avcol_spc(enum mp_csp colorspace)
switch (colorspace) { switch (colorspace) {
case MP_CSP_BT_709: return AVCOL_SPC_BT709; case MP_CSP_BT_709: return AVCOL_SPC_BT709;
case MP_CSP_BT_601: return AVCOL_SPC_BT470BG; 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_SMPTE_240M: return AVCOL_SPC_SMPTE240M;
case MP_CSP_RGB: return AVCOL_SPC_RGB; case MP_CSP_RGB: return AVCOL_SPC_RGB;
case MP_CSP_YCGCO: return AVCOL_SPC_YCOCG; 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_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_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_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: { case MP_CSP_RGB: {
static const float ident[3][4] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; static const float ident[3][4] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
memcpy(m, ident, sizeof(ident)); memcpy(m, ident, sizeof(ident));

View File

@ -37,6 +37,7 @@ enum mp_csp {
MP_CSP_BT_601, MP_CSP_BT_601,
MP_CSP_BT_709, MP_CSP_BT_709,
MP_CSP_SMPTE_240M, MP_CSP_SMPTE_240M,
MP_CSP_BT_2020_NC,
MP_CSP_RGB, MP_CSP_RGB,
MP_CSP_XYZ, MP_CSP_XYZ,
MP_CSP_YCGCO, MP_CSP_YCGCO,

View File

@ -521,6 +521,7 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
if (fmt.flags & MP_IMGFLAG_YUV) { if (fmt.flags & MP_IMGFLAG_YUV) {
if (params->colorspace != MP_CSP_BT_601 && if (params->colorspace != MP_CSP_BT_601 &&
params->colorspace != MP_CSP_BT_709 && params->colorspace != MP_CSP_BT_709 &&
params->colorspace != MP_CSP_BT_2020_NC &&
params->colorspace != MP_CSP_SMPTE_240M && params->colorspace != MP_CSP_SMPTE_240M &&
params->colorspace != MP_CSP_YCGCO) params->colorspace != MP_CSP_YCGCO)
{ {

View File

@ -49,10 +49,10 @@ vec3 srgb_compand(vec3 v)
lessThanEqual(vec3(0.0031308), 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)), return mix(v / 4.5, pow((v + vec3(0.0993))/1.0993, vec3(1/0.45)),
lessThanEqual(vec3(0.0812), v)); lessThanEqual(vec3(0.08145), v));
} }
#endif #endif
@ -85,8 +85,8 @@ void main() {
// Although we are not scaling in linear light, both 3DLUT and SRGB still // 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 // operate on linear light inputs so we have to convert to it before
// either step can be applied. // either step can be applied.
color.rgb = bt709_expand(color.rgb); color.rgb = bt2020_expand(color.rgb);
// NOTE: This always applies the true BT709, maybe we need to use // NOTE: This always applies the true BT2020, maybe we need to use
// approx-gamma here too? // approx-gamma here too?
#endif #endif
#ifdef USE_OSD_3DLUT #ifdef USE_OSD_3DLUT
@ -387,13 +387,18 @@ void main() {
#endif #endif
#ifdef USE_LINEAR_LIGHT #ifdef USE_LINEAR_LIGHT
// If we are scaling in linear light (SRGB or 3DLUT option enabled), we // 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 #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)); color = pow(color, vec3(1.95));
#else #else
// ... and actual BT709 (two-part function) // ... and actual BT.2020 (two-part function)
color = bt709_expand(color); color = bt2020_expand(color);
#endif #endif
#endif #endif
// Image upscaling happens roughly here // Image upscaling happens roughly here

View File

@ -364,6 +364,12 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
'func': check_statement('libavcodec/avcodec.h', """int x, y; 'func': check_statement('libavcodec/avcodec.h', """int x, y;
avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)""", avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)""",
use='libav') 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', 'name': 'avutil-qp-api',
'desc': 'libavutil QP API', 'desc': 'libavutil QP API',