Skip to content

Commit 7e9d0f7

Browse files
committed
feat(encoder): Added support for mastering display color volume and content light level metadata
Signed-off-by: Dawid Kozinski <[email protected]>
1 parent 8d2e357 commit 7e9d0f7

File tree

3 files changed

+164
-4
lines changed

3 files changed

+164
-4
lines changed

app/oapv_app_enc.c

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "oapv_app_util.h"
3434
#include "oapv_app_args.h"
3535
#include "oapv_app_y4m.h"
36+
#include "oapv_port.h"
3637

3738
#define MAX_BS_BUF (128 * 1024 * 1024)
3839
#define MAX_NUM_FRMS (1) // supports only 1-frame in an access unit
@@ -45,6 +46,24 @@ typedef enum _STATES {
4546
STATE_STOP
4647
} STATES;
4748

49+
/* Mastering display colour volume metadata*/
50+
typedef struct md_mdcv md_mdcv_t;
51+
struct md_mdcv {
52+
u16 primary_chromaticity_x[3];
53+
u16 primary_chromaticity_y[3];
54+
u16 white_point_chromaticity_x;
55+
u16 white_point_chromaticity_y;
56+
u32 max_mastering_luminance;
57+
u32 min_mastering_luminance;
58+
};
59+
60+
/* Content light level information*/
61+
typedef struct md_cll md_cll_t;
62+
struct md_cll {
63+
u16 max_cll;
64+
u16 max_fall;
65+
};
66+
4867
// clang-format off
4968

5069
/* define various command line options as a table */
@@ -275,6 +294,14 @@ static const args_opt_t enc_args_opts[] = {
275294
ARGS_NO_KEY, "hash", ARGS_VAL_TYPE_NONE, 0, NULL,
276295
"embed frame hash value for conformance checking in decoding"
277296
},
297+
{
298+
ARGS_NO_KEY, "master-display", ARGS_VAL_TYPE_STRING, 0, NULL,
299+
"mastering display color volume metadata"
300+
},
301+
{
302+
ARGS_NO_KEY, "max-cll", ARGS_VAL_TYPE_STRING, 0, NULL,
303+
"content light level information metadata"
304+
},
278305
{ARGS_END_KEY, "", ARGS_VAL_TYPE_NONE, 0, NULL, ""} /* termination */
279306
};
280307

@@ -318,11 +345,14 @@ typedef struct args_var {
318345
char tile_w[16];
319346
char tile_h[16];
320347

321-
int color_primaries;
322-
int color_transfer;
323-
int color_matrix;
324-
int color_range;
348+
int color_primaries;
349+
int color_transfer;
350+
int color_matrix;
351+
int color_range;
325352

353+
char master_display[512];
354+
char max_cll[64];
355+
326356
oapve_param_t *param;
327357
} args_var_t;
328358

@@ -393,6 +423,10 @@ static args_var_t *args_init_vars(args_parser_t *args, oapve_param_t *param)
393423
args_set_variable_by_key_long(opts, "color-range", &vars->color_range);
394424
vars->color_range = -1; /* unset */
395425

426+
args_set_variable_by_key_long(opts, "master-display", vars->master_display);
427+
args_set_variable_by_key_long(opts, "max-cll", vars->max_cll);
428+
429+
396430
return vars;
397431
}
398432

@@ -750,6 +784,13 @@ static int update_param(args_var_t *vars, oapve_param_t *param)
750784

751785
UPDATE_A_PARAM_W_KEY_VAL(param, "tile-w", vars->tile_w);
752786
UPDATE_A_PARAM_W_KEY_VAL(param, "tile-h", vars->tile_h);
787+
788+
UPDATE_A_PARAM_W_KEY_VAL(param, "tile-w", vars->tile_w);
789+
UPDATE_A_PARAM_W_KEY_VAL(param, "tile-h", vars->tile_h);
790+
791+
UPDATE_A_PARAM_W_KEY_VAL(param, "master-display", vars->master_display);
792+
UPDATE_A_PARAM_W_KEY_VAL(param, "max-cll", vars->max_cll);
793+
753794
return 0;
754795
}
755796

@@ -962,6 +1003,46 @@ int main(int argc, const char **argv)
9621003
ret = -1;
9631004
goto ERR;
9641005
}
1006+
1007+
if(param->mdcv_flag) {
1008+
md_mdcv_t mdcv;
1009+
1010+
mdcv.primary_chromaticity_x[0] = param->mdcv_primary_chromaticity_x[0];
1011+
mdcv.primary_chromaticity_x[1] = param->mdcv_primary_chromaticity_x[1];
1012+
mdcv.primary_chromaticity_x[2] = param->mdcv_primary_chromaticity_x[2];
1013+
1014+
mdcv.primary_chromaticity_y[0] = param->mdcv_primary_chromaticity_y[0];
1015+
mdcv.primary_chromaticity_y[1] = param->mdcv_primary_chromaticity_y[1];
1016+
mdcv.primary_chromaticity_y[2] = param->mdcv_primary_chromaticity_y[2];
1017+
1018+
mdcv.white_point_chromaticity_x = param->mdcv_white_point_chromaticity_x;
1019+
mdcv.white_point_chromaticity_y = param->mdcv_white_point_chromaticity_y;
1020+
1021+
mdcv.min_mastering_luminance = param->mdcv_min_mastering_luminance;
1022+
mdcv.max_mastering_luminance = param->mdcv_max_mastering_luminance;
1023+
1024+
void *data = &mdcv;
1025+
size_t size = sizeof(md_mdcv_t);
1026+
if(oapvm_set(mid, 1, OAPV_METADATA_MDCV, data, size)) {
1027+
logerr("ERR: cannot set mastering display color metadata\n");
1028+
ret = -1;
1029+
goto ERR;
1030+
}
1031+
}
1032+
1033+
if(param->cll_flag) {
1034+
md_cll_t cll;
1035+
cll.max_cll = param->cll_max_cll;
1036+
cll.max_fall = param->cll_max_fall;
1037+
1038+
void *data = &cll;
1039+
size_t size = sizeof(md_cll_t);
1040+
if(oapvm_set(mid, 1, OAPV_METADATA_CLL, data, size)) {
1041+
logerr("ERR: cannot set content light level metadata\n");
1042+
ret = -1;
1043+
goto ERR;
1044+
}
1045+
}
9651046

9661047
if(set_extra_config(id, args_var, param)) {
9671048
logerr("ERR: cannot set extra configurations\n");

inc/oapv.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,20 @@ struct oapve_param {
586586
unsigned char transfer_characteristics;
587587
unsigned char matrix_coefficients;
588588
int full_range_flag;
589+
590+
/* mastering display color volume metadata metadata */
591+
int mdcv_flag;
592+
short unsigned int mdcv_primary_chromaticity_x[3];
593+
short unsigned int mdcv_primary_chromaticity_y[3];
594+
short unsigned int mdcv_white_point_chromaticity_x;
595+
short unsigned int mdcv_white_point_chromaticity_y;
596+
unsigned int mdcv_max_mastering_luminance;
597+
unsigned int mdcv_min_mastering_luminance;
598+
599+
/* content light level information metadata */
600+
int cll_flag;
601+
short unsigned int cll_max_cll;
602+
short unsigned int cll_max_fall;
589603
};
590604

591605
/*****************************************************************************

src/oapv_param.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ int oapve_param_default(oapve_param_t *param)
6262
param->transfer_characteristics = 2; // unspecified transfer characteristics
6363
param->matrix_coefficients = 2; // unspecified matrix coefficients
6464
param->full_range_flag = 0; // limited range
65+
66+
// mastering display color volume metadata not set by the user
67+
param->mdcv_flag = 0;
68+
69+
// content light level information not set by the user
70+
param->cll_flag = 0;
71+
6572
return OAPV_OK;
6673
}
6774

@@ -147,6 +154,52 @@ static int get_q_matrix(const char *str, u8 q_matrix[OAPV_BLK_D])
147154
if(strlen(left)>0) return (ERR); \
148155
}
149156

157+
static int parse_master_display(const char* data_string, oapve_param_t *param) {
158+
if (data_string == NULL || param == NULL) {
159+
fprintf(stderr, "Error: Input pointer is NULL.\n");
160+
return -1;
161+
}
162+
163+
int assigned_fields = sscanf(data_string,
164+
"G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)",
165+
&param->mdcv_primary_chromaticity_x[2], &param->mdcv_primary_chromaticity_y[2], // G
166+
&param->mdcv_primary_chromaticity_x[1], &param->mdcv_primary_chromaticity_y[1], // B
167+
&param->mdcv_primary_chromaticity_x[0], &param->mdcv_primary_chromaticity_y[0], // R
168+
&param->mdcv_white_point_chromaticity_x, &param->mdcv_white_point_chromaticity_y, // White Point
169+
&param->mdcv_max_mastering_luminance, &param->mdcv_min_mastering_luminance // Luminance
170+
);
171+
172+
// Check if sscanf successfully assigned all expected fields (10 numerical values).
173+
const int expected_fields = 10;
174+
if (assigned_fields != expected_fields) {
175+
fprintf(stderr, "Parsing error: Expected %d fields, found %d.\n", expected_fields, assigned_fields);
176+
return OAPV_ERR_INVALID_ARGUMENT;
177+
}
178+
179+
return 0; // Success
180+
}
181+
182+
static int parse_max_cll(const char* data_string, oapve_param_t *param) {
183+
if (data_string == NULL || param == NULL) {
184+
fprintf(stderr, "Error: Input pointer is NULL.\n");
185+
return -1;
186+
}
187+
188+
int assigned_fields = sscanf(data_string,
189+
"%hu,%hu",
190+
&param->cll_max_cll, &param->cll_max_fall
191+
);
192+
193+
// Check if sscanf successfully assigned all expected fields (10 numerical values).
194+
const int expected_fields = 2;
195+
if (assigned_fields != expected_fields) {
196+
fprintf(stderr, "Parsing error: Expected %d fields, found %d.\n", expected_fields, assigned_fields);
197+
return OAPV_ERR_INVALID_ARGUMENT;
198+
}
199+
200+
return 0; // Success
201+
}
202+
150203
int oapve_param_parse(oapve_param_t *param, const char *name, const char *value)
151204
{
152205
u8 q_matrix[OAPV_BLK_D];
@@ -339,6 +392,18 @@ int oapve_param_parse(oapve_param_t *param, const char *name, const char *value
339392
param->full_range_flag = ti0;
340393
param->color_description_present_flag = 1;
341394
}
395+
NAME_CMP("master-display") { // mastering display color volume metadata
396+
if(parse_master_display(value, param)) {
397+
return OAPV_ERR_INVALID_ARGUMENT;
398+
}
399+
param->mdcv_flag = 1;
400+
}
401+
NAME_CMP("max-cll") { // maximum content light level
402+
if(parse_max_cll(value, param)) {
403+
return OAPV_ERR_INVALID_ARGUMENT;
404+
}
405+
param->cll_flag = 1;
406+
}
342407
else {
343408
return OAPV_ERR_INVALID_ARGUMENT;
344409
}

0 commit comments

Comments
 (0)