[x264-devel] [Git][videolan/x264][master] 2 commits: Support writing the mastering display color volume SEI message
Anton Mitrofanov
gitlab at videolan.org
Wed May 5 07:23:23 UTC 2021
Anton Mitrofanov pushed to branch master at VideoLAN / x264
Commits:
8719ef8a by Phillip Blucas at 2021-05-05T07:11:57+00:00
Support writing the mastering display color volume SEI message
Use --mastering-display to specify the properties of the reference display.
A formatted string with all 10 values is required: G,B,R primaries and
white point coordinates, plus max/min brightness. Coordinates are in
0.00002 increments. Brightness units are 0.0001 cd/m^2.
For example, a 1000 nit BT.2020 display with a 0.0001 nit black level:
--mastering-display G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)
- - - - -
fa770fd5 by Phillip Blucas at 2021-05-05T07:11:57+00:00
Support writing the content light level information SEI message
Use --cll to specify the maximum content light level (MaxCLL)
and the maximum frame average light level (MaxFALL) as described
by the CTA 861.3 specification.
- - - - -
8 changed files:
- autocomplete.c
- common/base.c
- common/base.h
- encoder/encoder.c
- encoder/set.c
- encoder/set.h
- x264.c
- x264.h
Changes:
=====================================
autocomplete.c
=====================================
@@ -115,6 +115,8 @@ static const char * const opts_nosuggest[] =
"--ipratio",
"--keyint", "-I",
"--lookahead-threads",
+ "--mastering-display",
+ "--cll",
"--merange",
"--min-keyint", "-i",
"--mvrange",
=====================================
common/base.c
=====================================
@@ -1013,6 +1013,32 @@ REALIGN_STACK int x264_param_parse( x264_param_t *p, const char *name, const cha
p->vui.i_chroma_loc = atoi(value);
b_error = ( p->vui.i_chroma_loc < 0 || p->vui.i_chroma_loc > 5 );
}
+ OPT("mastering-display")
+ {
+ if( strcasecmp( value, "undef" ) )
+ {
+ b_error |= sscanf( value, "G(%d,%d)B(%d,%d)R(%d,%d)WP(%d,%d)L(%"SCNd64",%"SCNd64")",
+ &p->mastering_display.i_green_x, &p->mastering_display.i_green_y,
+ &p->mastering_display.i_blue_x, &p->mastering_display.i_blue_y,
+ &p->mastering_display.i_red_x, &p->mastering_display.i_red_y,
+ &p->mastering_display.i_white_x, &p->mastering_display.i_white_y,
+ &p->mastering_display.i_display_max, &p->mastering_display.i_display_min ) != 10;
+ p->mastering_display.b_mastering_display = !b_error;
+ }
+ else
+ p->mastering_display.b_mastering_display = 0;
+ }
+ OPT("cll")
+ {
+ if( strcasecmp( value, "undef" ) )
+ {
+ b_error |= sscanf( value, "%d,%d",
+ &p->content_light_level.i_max_cll, &p->content_light_level.i_max_fall ) != 2;
+ p->content_light_level.b_cll = !b_error;
+ }
+ else
+ p->content_light_level.b_cll = 0;
+ }
OPT("alternative-transfer")
b_error |= parse_enum( value, x264_transfer_names, &p->i_alternative_transfer );
OPT("fps")
@@ -1389,7 +1415,7 @@ REALIGN_STACK int x264_param_parse( x264_param_t *p, const char *name, const cha
****************************************************************************/
char *x264_param2string( x264_param_t *p, int b_res )
{
- int len = 1000;
+ int len = 2000;
char *buf, *s;
if( p->rc.psz_zones )
len += strlen(p->rc.psz_zones);
@@ -1498,6 +1524,16 @@ char *x264_param2string( x264_param_t *p, int b_res )
if( p->crop_rect.i_left | p->crop_rect.i_top | p->crop_rect.i_right | p->crop_rect.i_bottom )
s += sprintf( s, " crop_rect=%d,%d,%d,%d", p->crop_rect.i_left, p->crop_rect.i_top,
p->crop_rect.i_right, p->crop_rect.i_bottom );
+ if( p->mastering_display.b_mastering_display )
+ s += sprintf( s, " mastering-display=G(%d,%d)B(%d,%d)R(%d,%d)WP(%d,%d)L(%"PRId64",%"PRId64")",
+ p->mastering_display.i_green_x, p->mastering_display.i_green_y,
+ p->mastering_display.i_blue_x, p->mastering_display.i_blue_y,
+ p->mastering_display.i_red_x, p->mastering_display.i_red_y,
+ p->mastering_display.i_white_x, p->mastering_display.i_white_y,
+ p->mastering_display.i_display_max, p->mastering_display.i_display_min );
+ if( p->content_light_level.b_cll )
+ s += sprintf( s, " cll=%d,%d",
+ p->content_light_level.i_max_cll, p->content_light_level.i_max_fall );
if( p->i_frame_packing >= 0 )
s += sprintf( s, " frame-packing=%d", p->i_frame_packing );
=====================================
common/base.h
=====================================
@@ -128,6 +128,8 @@ enum sei_payload_type_e
SEI_RECOVERY_POINT = 6,
SEI_DEC_REF_PIC_MARKING = 7,
SEI_FRAME_PACKING = 45,
+ SEI_MASTERING_DISPLAY = 137,
+ SEI_CONTENT_LIGHT_LEVEL = 144,
SEI_ALTERNATIVE_TRANSFER = 147,
};
=====================================
encoder/encoder.c
=====================================
@@ -640,6 +640,41 @@ static int validate_parameters( x264_t *h, int b_open )
return -1;
}
+ if( h->param.mastering_display.b_mastering_display )
+ {
+ if( h->param.mastering_display.i_green_x > UINT16_MAX || h->param.mastering_display.i_green_x < 0 ||
+ h->param.mastering_display.i_green_y > UINT16_MAX || h->param.mastering_display.i_green_y < 0 ||
+ h->param.mastering_display.i_blue_x > UINT16_MAX || h->param.mastering_display.i_blue_x < 0 ||
+ h->param.mastering_display.i_blue_y > UINT16_MAX || h->param.mastering_display.i_blue_y < 0 ||
+ h->param.mastering_display.i_red_x > UINT16_MAX || h->param.mastering_display.i_red_x < 0 ||
+ h->param.mastering_display.i_red_y > UINT16_MAX || h->param.mastering_display.i_red_y < 0 ||
+ h->param.mastering_display.i_white_x > UINT16_MAX || h->param.mastering_display.i_white_x < 0 ||
+ h->param.mastering_display.i_white_y > UINT16_MAX || h->param.mastering_display.i_white_y < 0 )
+ {
+ x264_log( h, X264_LOG_ERROR, "mastering display xy coordinates out of range [0,%u]\n", UINT16_MAX );
+ return -1;
+ }
+ if( h->param.mastering_display.i_display_max > UINT32_MAX || h->param.mastering_display.i_display_max < 0 ||
+ h->param.mastering_display.i_display_min > UINT32_MAX || h->param.mastering_display.i_display_min < 0 )
+ {
+ x264_log( h, X264_LOG_ERROR, "mastering display brightness out of range [0,%u]\n", UINT32_MAX );
+ return -1;
+ }
+ if( h->param.mastering_display.i_display_min == 50000 && h->param.mastering_display.i_display_max == 50000 )
+ {
+ x264_log( h, X264_LOG_ERROR, "mastering display min and max brightness cannot both be 50000\n" );
+ return -1;
+ }
+ }
+
+ if( h->param.content_light_level.b_cll &&
+ (h->param.content_light_level.i_max_cll > UINT16_MAX || h->param.content_light_level.i_max_cll < 0 ||
+ h->param.content_light_level.i_max_fall > UINT16_MAX || h->param.content_light_level.i_max_fall < 0) )
+ {
+ x264_log( h, X264_LOG_ERROR, "content light levels out of range [0,%u]\n", UINT16_MAX );
+ return -1;
+ }
+
/* Detect default ffmpeg settings and terminate with an error. */
if( b_open )
{
@@ -1818,6 +1853,9 @@ static int encoder_try_reconfig( x264_t *h, x264_param_t *param, int *rc_reconfi
COPY( i_deblocking_filter_alphac0 );
COPY( i_deblocking_filter_beta );
COPY( i_frame_packing );
+ COPY( mastering_display );
+ COPY( content_light_level );
+ COPY( i_alternative_transfer );
COPY( analyse.inter );
COPY( analyse.intra );
COPY( analyse.i_direct_mv_pred );
@@ -3691,6 +3729,33 @@ int x264_encoder_encode( x264_t *h,
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
+
+ if( h->param.mastering_display.b_mastering_display )
+ {
+ nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ x264_sei_mastering_display_write( h, &h->out.bs );
+ if( nal_end( h ) )
+ return -1;
+ overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
+ }
+
+ if( h->param.content_light_level.b_cll )
+ {
+ nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ x264_sei_content_light_level_write( h, &h->out.bs );
+ if( nal_end( h ) )
+ return -1;
+ overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
+ }
+
+ if( h->param.i_alternative_transfer != 2 )
+ {
+ nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ x264_sei_alternative_transfer_write( h, &h->out.bs );
+ if( nal_end( h ) )
+ return -1;
+ overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
+ }
}
if( h->param.i_frame_packing >= 0 && (h->fenc->b_keyframe || h->param.i_frame_packing == 5) )
@@ -3702,15 +3767,6 @@ int x264_encoder_encode( x264_t *h,
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
- if( h->param.i_alternative_transfer != 2 )
- {
- nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- x264_sei_alternative_transfer_write( h, &h->out.bs );
- if( nal_end( h ) )
- return -1;
- overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
- }
-
/* generate sei pic timing */
if( h->sps->vui.b_pic_struct_present || h->sps->vui.b_nal_hrd_parameters_present )
{
=====================================
encoder/set.c
=====================================
@@ -703,6 +703,48 @@ void x264_sei_frame_packing_write( x264_t *h, bs_t *s )
x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_FRAME_PACKING );
}
+void x264_sei_mastering_display_write( x264_t *h, bs_t *s )
+{
+ bs_t q;
+ ALIGNED_4( uint8_t tmp_buf[100] );
+ M32( tmp_buf ) = 0; // shut up gcc
+ bs_init( &q, tmp_buf, 100 );
+
+ bs_realign( &q );
+
+ bs_write( &q, 16, h->param.mastering_display.i_green_x );
+ bs_write( &q, 16, h->param.mastering_display.i_green_y );
+ bs_write( &q, 16, h->param.mastering_display.i_blue_x );
+ bs_write( &q, 16, h->param.mastering_display.i_blue_y );
+ bs_write( &q, 16, h->param.mastering_display.i_red_x );
+ bs_write( &q, 16, h->param.mastering_display.i_red_y );
+ bs_write( &q, 16, h->param.mastering_display.i_white_x );
+ bs_write( &q, 16, h->param.mastering_display.i_white_y );
+ bs_write32( &q, h->param.mastering_display.i_display_max );
+ bs_write32( &q, h->param.mastering_display.i_display_min );
+
+ bs_align_10( &q );
+
+ x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_MASTERING_DISPLAY );
+}
+
+void x264_sei_content_light_level_write( x264_t *h, bs_t *s )
+{
+ bs_t q;
+ ALIGNED_4( uint8_t tmp_buf[100] );
+ M32( tmp_buf ) = 0; // shut up gcc
+ bs_init( &q, tmp_buf, 100 );
+
+ bs_realign( &q );
+
+ bs_write( &q, 16, h->param.content_light_level.i_max_cll );
+ bs_write( &q, 16, h->param.content_light_level.i_max_fall );
+
+ bs_align_10( &q );
+
+ x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_CONTENT_LIGHT_LEVEL );
+}
+
void x264_sei_alternative_transfer_write( x264_t *h, bs_t *s )
{
bs_t q;
=====================================
encoder/set.h
=====================================
@@ -53,6 +53,10 @@ void x264_sei_pic_timing_write( x264_t *h, bs_t *s );
void x264_sei_dec_ref_pic_marking_write( x264_t *h, bs_t *s );
#define x264_sei_frame_packing_write x264_template(sei_frame_packing_write)
void x264_sei_frame_packing_write( x264_t *h, bs_t *s );
+#define x264_sei_mastering_display_write x264_template(sei_mastering_display_write)
+void x264_sei_mastering_display_write( x264_t *h, bs_t *s );
+#define x264_sei_content_light_level_write x264_template(sei_content_light_level_write)
+void x264_sei_content_light_level_write( x264_t *h, bs_t *s );
#define x264_sei_alternative_transfer_write x264_template(sei_alternative_transfer_write)
void x264_sei_alternative_transfer_write( x264_t *h, bs_t *s );
#define x264_sei_avcintra_umid_write x264_template(sei_avcintra_umid_write)
=====================================
x264.c
=====================================
@@ -874,6 +874,10 @@ static void help( x264_param_t *defaults, int longhelp )
strtable_lookup( x264_colmatrix_names, defaults->vui.i_colmatrix ) );
H2( " --chromaloc <integer> Specify chroma sample location (0 to 5) [%d]\n",
defaults->vui.i_chroma_loc );
+ H2( " --mastering-display <string> Specify 'G(x,y)B(x,y)R(x,y)WP(x,y)L(max,min)'\n"
+ " for primaries, white point, and display brightness\n" );
+ H2( " --cll <string> Specify 'max_content,max_frame_average' content\n"
+ " light levels\n" );
H2( " --alternative-transfer <string> Specify an alternative transfer\n"
" characteristics [\"%s\"]\n"
" - same values as --transfer\n",
@@ -1160,6 +1164,8 @@ static struct option long_options[] =
{ "pulldown", required_argument, NULL, OPT_PULLDOWN },
{ "fake-interlaced", no_argument, NULL, 0 },
{ "frame-packing", required_argument, NULL, 0 },
+ { "mastering-display", required_argument, NULL, 0 },
+ { "cll", required_argument, NULL, 0 },
{ "alternative-transfer", required_argument, NULL, 0 },
{ "vf", required_argument, NULL, OPT_VIDEO_FILTER },
{ "video-filter", required_argument, NULL, OPT_VIDEO_FILTER },
=====================================
x264.h
=====================================
@@ -45,7 +45,7 @@ extern "C" {
#include "x264_config.h"
-#define X264_BUILD 161
+#define X264_BUILD 163
#ifdef _WIN32
# define X264_DLL_IMPORT __declspec(dllimport)
@@ -485,6 +485,31 @@ typedef struct x264_param_t
/* frame packing arrangement flag */
int i_frame_packing;
+ /* mastering display SEI: Primary and white point chromaticity coordinates
+ in 0.00002 increments. Brightness units are 0.0001 cd/m^2. */
+ struct
+ {
+ int b_mastering_display; /* enable writing this SEI */
+ int i_green_x;
+ int i_green_y;
+ int i_blue_x;
+ int i_blue_y;
+ int i_red_x;
+ int i_red_y;
+ int i_white_x;
+ int i_white_y;
+ int64_t i_display_max;
+ int64_t i_display_min;
+ } mastering_display;
+
+ /* content light level SEI */
+ struct
+ {
+ int b_cll; /* enable writing this SEI */
+ int i_max_cll;
+ int i_max_fall;
+ } content_light_level;
+
/* alternative transfer SEI */
int i_alternative_transfer;
View it on GitLab: https://code.videolan.org/videolan/x264/-/compare/4459373fd7d3eac92507372b55e4af93c04d4be9...fa770fd537f776beb2bd3f1080503b3797b66b88
--
View it on GitLab: https://code.videolan.org/videolan/x264/-/compare/4459373fd7d3eac92507372b55e4af93c04d4be9...fa770fd537f776beb2bd3f1080503b3797b66b88
You're receiving this email because of your account on code.videolan.org.
More information about the x264-devel
mailing list