On Wed, 2020-12-02 at 13:18 +0000, Fredrick Odhiambo wrote: > This patch allows passing of HDR10 metadata through qsv_params for encoding > with hevc_qsv similar to how HDR10 parameters are passed to x265-params in > libx265 encoding. The HDR10 metadata parameters passed are master-display, > max-cll, color primary, color matrix, transfer characteristics and color > range. > > -qsv_params master- > display=R(35399,14599)G(8500,39850)B(6550,2300)WP(15634,16450)L(10000000,50):m > ax- > cll=1000,400:colorprim=bt2020:colormatrix=bt2020c:transfer=smpte2084:range=ful > l -y hdr_vid_output.mp4
May we get the HDR parameters from input frame via AV_FRAME_DATA_MASTERING_DISPLAY_METADATA ? avcodec has already provided options color_primaries / color_trc / colorspace / color_range to set the corresponding parameters in avctx. > > Signed-off-by: Fredrick Odhiambo <fredrick.odhia...@intel.com> > --- > libavcodec/qsvenc.c | 425 ++++++++++++++++++++++++++++++++++++++++++++ > libavcodec/qsvenc.h | 110 +++++++++++- > 2 files changed, 534 insertions(+), 1 deletion(-) > > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c > index 2bd2a56227..29faa59497 100644 > --- a/libavcodec/qsvenc.c > +++ b/libavcodec/qsvenc.c > @@ -1102,6 +1102,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext > *q) > int iopattern = 0; > int opaque_alloc = 0; > int ret; > + AVContentLightMetadata light_meta; > > q->param.AsyncDepth = q->async_depth; > > @@ -1203,6 +1204,92 @@ int ff_qsv_enc_init(AVCodecContext *avctx, > QSVEncContext *q) > return ret; > } > > + if (q->qsv_opts) { > + AVDictionaryEntry *en = NULL; > + AVMasteringDisplayMetadata hdr_meta; > + memset(&hdr_meta, 0, sizeof(AVMasteringDisplayMetadata)); > + memset(&light_meta, 0, sizeof(AVContentLightMetadata)); > + if (!avctx) { > + return ff_qsv_print_error(avctx, MFX_ERR_INVALID_VIDEO_PARAM, > + "AVCodecContext no set"); > + } Don't check avctx against NULL after the pointer has been dereferenced. > + > + while ((en = av_dict_get(q->qsv_opts, "", en, > AV_DICT_IGNORE_SUFFIX))) { > + int parse_ret = ff_qsv_validate_params(en->key, en->value); > + switch (parse_ret) { > + case QSV_PARAM_VALID: > + if (!strcmp(en->key, "master-display")) { Please use the same indentation style. > + ff_qsv_extract_display_values(en->value, &hdr_meta); > + break; > + } > + if (!strcmp(en->key, "range")) { > + avctx->color_range = ff_qsv_extract_range_value(en- > >value); > + break; > + } > + if (!strcmp(en->key, "max-cll")) { > + ff_qsv_get_content_light_level(en->value, > &light_meta); > + break; > + } > + if (!strcmp(en->key, "colorprim")) { > + avctx->color_primaries = > av_color_primaries_from_name(en->value); > + break; > + } > + if (!strcmp(en->key, "colormatrix")) { > + avctx->colorspace = av_color_space_from_name(en- > >value); > + break; > + } > + if (!strcmp(en->key, "transfer")) { > + avctx->color_trc = av_color_transfer_from_name(en- > >value); > + break; > + } > + case QSV_PARAM_BAD_VALUE: > + av_log(q, AV_LOG_ERROR, > + "Invalid value for %s: %s.\n", en->key, en->value); > + return ff_qsv_print_error(avctx, > MFX_ERR_INVALID_VIDEO_PARAM, > + "Invalid value"); > + case QSV_PARAM_BAD_NAME: > + av_log(q, AV_LOG_ERROR, > + "Invalid value for %s: %s.\n", en->key, en->value); > + return ff_qsv_print_error(avctx, > MFX_ERR_INVALID_VIDEO_PARAM, > + "Invalid parameter name"); > + } > + } > +#if QSV_HAVE_HDR_METADATA > + if (hdr_meta.has_primaries) { > + q->master_display_volume_data.Header.BufferId = > MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME; > + q->master_display_volume_data.Header.BufferSz = sizeof(q- > >master_display_volume_data); > + q->master_display_volume_data.InsertPayloadToggle = > MFX_PAYLOAD_IDR; > + q->master_display_volume_data.DisplayPrimariesX[0] = > (int)av_q2d(hdr_meta.display_primaries[0][0]); > + q->master_display_volume_data.DisplayPrimariesX[1] = > (int)av_q2d(hdr_meta.display_primaries[0][1]); > + q->master_display_volume_data.DisplayPrimariesX[2] = > (int)av_q2d(hdr_meta.display_primaries[1][0]); > + q->master_display_volume_data.DisplayPrimariesY[0] = > (int)av_q2d(hdr_meta.display_primaries[1][1]); > + q->master_display_volume_data.DisplayPrimariesY[1] = > (int)av_q2d(hdr_meta.display_primaries[2][0]); > + q->master_display_volume_data.DisplayPrimariesY[2] = > (int)av_q2d(hdr_meta.display_primaries[2][1]); DisplayPrimariesX[0] and DisplayPrimariesY[0] in MSDK is R however display_primaries[0][0] and display_primaries[0][1] is R in FFmpeg, so the above assignments are wrong. > + q->master_display_volume_data.WhitePointX = > (int)av_q2d(hdr_meta.white_point[0]); > + q->master_display_volume_data.WhitePointY = > (int)av_q2d(hdr_meta.white_point[1]); > + q->master_display_volume_data.MaxDisplayMasteringLuminance = > (int)av_q2d(hdr_meta.max_luminance); > + q->master_display_volume_data.MinDisplayMasteringLuminance = > (int)av_q2d(hdr_meta.min_luminance); > + > + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer > *)&q->master_display_volume_data; > + q->param.ExtParam[q->param.NumExtParam++] = (mfxExtBuffer*)&q- > >master_display_volume_data; > + > +#if QSV_HAVE_VIDEO_SIGNAL_INFO > + q->video_signal_data.Header.BufferId = > MFX_EXTBUFF_VIDEO_SIGNAL_INFO; > + q->video_signal_data.Header.BufferSz = sizeof(q- > >video_signal_data); > + q->video_signal_data.VideoFormat = > VIDEO_SIGNAL_FORMAT_UNSPECIFIED; > + q->video_signal_data.VideoFullRange = > ff_avcol_range_to_mfx_col_range(avctx->color_range); > + q->video_signal_data.ColourDescriptionPresent = > VIDEO_SIGNAL_COLOR_DESCRIPTION_PRESENT; > + q->video_signal_data.ColourPrimaries = avctx->color_primaries; > + q->video_signal_data.TransferCharacteristics = avctx->color_trc; > + q->video_signal_data.MatrixCoefficients = avctx->colorspace; > + > + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer > *)&q->video_signal_data; > + q->param.ExtParam[q->param.NumExtParam++] = (mfxExtBuffer*)&q- > >video_signal_data; > +#endif > + } > +#endif > + } > + > ret = MFXVideoENCODE_Init(q->session, &q->param); > if (ret < 0) > return ff_qsv_print_error(avctx, ret, > @@ -1661,3 +1748,341 @@ const AVCodecHWConfigInternal *const > ff_qsv_enc_hw_configs[] = { > HW_CONFIG_ENCODER_DEVICE(P010, QSV), > NULL, > }; > + > +int ff_qsv_extract_values(char *input_value, int *output_values) > +{ > + char *p; > + int i; > + int res[2]; > + char input_array[QSV_PARAMS_BUFFER_LENGTH]; > + strcpy(input_array, input_value); > + for (i = 1, p = strtok(input_array, ","); p != NULL; p = strtok(NULL, > ","), i++) { > + for (int j = 0; j < strlen(p); j++) { > + if (!isdigit(p[j])) { > + return AVERROR(EINVAL); > + } > + } > + res[i-1] = (int) strtol(p, (char **)NULL, 10); > + } > + output_values[0] = res[0]; > + output_values[1] = res[1]; > + > + return 0; > +} > + > +int ff_qsv_validate_cll(char * value) > +{ > + int n = strlen(value); > + int res[LIGHT_LEVEL_DATA_LENGTH]; > + const int maximum_cll = 1000; > + const int minimum_cll = 400; > + if (!ff_qsv_extract_values(value, res)) { > + if (n > QSV_PARAMS_BUFFER_LENGTH) { > + return AVERROR(EINVAL); > + } > + } > + if (res[1] >= minimum_cll && res[0] <= maximum_cll) { > + return 0; > + } > + > + return AVERROR(EINVAL); > +} > + > +void ff_build_sub_string(char *input_string, char *output, int start_index) > +{ > + int n = strlen(input_string); > + for (int i = start_index; i < n; i++) { > + if (input_string[i] != '(' && input_string[i] != ')' && > input_string[i] != ' ' && > + input_string[i] != 'P') { > + strncat(output, &input_string[i], 1); > + } > + if (input_string[i] ==')') { > + break; > + } > + } > +} > + > +int ff_qsv_validate_display(char *value) > +{ > + int n = strlen(value); > + int ret = 0; > + char *red_values = NULL; > + char *blue_values = NULL; > + char *green_values = NULL; > + char *white_point_values = NULL; > + char *light_info_values = NULL; > + int xy_red_values[RGB_CHANNEL_LENGTH] ; > + int xy_green_values[RGB_CHANNEL_LENGTH]; > + int xy_blue_values[RGB_CHANNEL_LENGTH]; > + int xy_white_point_values[WHITE_POINT_DATA_LENGTH]; > + int luminousity_values[LIGHT_LEVEL_DATA_LENGTH]; > + > + if (!(red_values = (char*)av_calloc(n + 1, sizeof(red_values)))) > + return AVERROR(ENOMEM); > + if (!(green_values = (char*)av_calloc(n + 1, sizeof(green_values)))) > + return AVERROR(ENOMEM); > + if (!(blue_values = (char*)av_calloc(n + 1, sizeof(blue_values)))) > + return AVERROR(ENOMEM); > + if (!(white_point_values = (char*)av_calloc(n + 1, > sizeof(white_point_values)))) > + return AVERROR(ENOMEM); > + if (!(light_info_values = (char*)av_calloc(n + 1, > sizeof(light_info_values)))) > + return AVERROR(ENOMEM); > + > + for (int i = 0; i < n; i++) { > + char current_char = value[i]; > + switch (current_char) { > + case 'R': > + ff_build_sub_string(value, red_values, i+1); > + break; > + case 'G': > + ff_build_sub_string(value, green_values, i+1); > + break; > + case 'B': > + ff_build_sub_string(value, blue_values, i+1); > + break; > + case 'W': > + ff_build_sub_string(value, white_point_values, i+1); > + break; > + case 'L': > + ff_build_sub_string(value, light_info_values, i+1); > + break; > + default: > + break; > + } > + } > + > + if (!ff_qsv_extract_values(red_values, xy_red_values) && > + !ff_qsv_validate_display_color_range(xy_red_values) && > + !ff_qsv_extract_values(green_values, xy_green_values) && > + !ff_qsv_validate_display_color_range(xy_green_values) && > + !ff_qsv_extract_values(blue_values, xy_blue_values) && > + !ff_qsv_validate_display_color_range(xy_blue_values) && > + !ff_qsv_extract_values(white_point_values, xy_white_point_values) && > + !ff_qsv_validate_display_color_range(xy_white_point_values) && > + !ff_qsv_extract_values(light_info_values, luminousity_values) && > + !ff_qsv_validate_display_luminousity_range(luminousity_values)) { > + goto end; > + } else { > + ret = AVERROR(EINVAL); > + } > + > +end: > + av_free(red_values); > + av_free(green_values); > + av_free(blue_values); > + av_free(white_point_values); > + av_free(light_info_values); > + > + return ret; > +} > + > +int ff_qsv_validate_params(char *key, char *value) > +{ > + int key_is_valid = 0; > + int value_is_valid = 0; > + int key_index; > + int n = sizeof(qsv_key_names)/sizeof(qsv_key_names[0]); > + for (int i = 0;i < n; i++) { > + if (!strcmp(key, qsv_key_names[i])) { > + key_is_valid = 1; > + key_index = i; > + } > + } > + if (key_is_valid) { > + switch (key_index) { > + case 0: > + for (int i = 0; i < > (sizeof(qsv_color_range_names)/sizeof(qsv_color_range_names[0])); i++) { > + if (!strcasecmp(value, qsv_color_range_names[i])) { strcasecmp is defined in strings.h which is not included in this file, so it will break the compiling. > + value_is_valid = 1; > + break; > + } > + } > + break; > + case 1: > + for(int i = 0; i < > (sizeof(qsv_colorprim_names)/sizeof(qsv_colorprim_names[0])); i++) { > + if (!strcmp(value, qsv_colorprim_names[i])) { > + value_is_valid = 1; > + break; > + } > + } > + break; > + case 2: > + for(int i = 0; i < > (sizeof(qsv_transfer_names)/sizeof(qsv_transfer_names[0])); i++) { > + if (!strcmp(value, qsv_transfer_names[i])) { > + value_is_valid = 1; > + break; > + } > + } > + break; > + case 3: > + for(int i = 0; i < > (sizeof(qsv_colmatrix_names)/sizeof(qsv_colmatrix_names[0])); i++) { > + if (!strcmp(value, qsv_colmatrix_names[i])) { > + value_is_valid = 1; > + break; > + } > + } > + break; > + case 4: > + value_is_valid = (!ff_qsv_validate_display(value)) ? 1 : 0; > + break; > + case 5: > + value_is_valid = (!ff_qsv_validate_cll(value)) ? 1 : 0; > + break; > + default: > + break; > + } > + } > + if (!key_is_valid) { > + return QSV_PARAM_BAD_NAME; > + } > + if (!value_is_valid) { > + return QSV_PARAM_BAD_VALUE; > + } > + return QSV_PARAM_VALID; > +} > + > +int ff_qsv_validate_display_color_range(int *input_colors) > +{ > + const int display_color_minimum = 0; > + const int display_color_maximum = 50000; > + if (( input_colors[0] >= display_color_minimum && input_colors[0] <= > display_color_maximum) && > + input_colors[1] >= display_color_minimum && input_colors[1] <= > display_color_maximum) { > + return 0; > + } > + > + return AVERROR(EINVAL); > +} > + > +int ff_qsv_validate_display_luminousity_range(int *input_luminousity) > +{ > + const int display_primary_luminous_minimum = 50; > + const int display_primary_luminous_maximum = 10000000; > + if (input_luminousity[0] >= display_primary_luminous_minimum && > + input_luminousity[1] <= display_primary_luminous_maximum) { > + return 0; > + } > + > + return AVERROR(EINVAL); > +} > + > +int ff_qsv_extract_range_value(char *value) > +{ > + if (!strcmp(value, "limited")) { > + return AVCOL_RANGE_MPEG; > + } > + if (!strcmp(value, "full")) { > + return AVCOL_RANGE_JPEG; > + } > + > + return AVCOL_PRI_UNSPECIFIED; > +} > + > +int ff_qsv_extract_display_values(char *value, AVMasteringDisplayMetadata > *hdr_meta) > +{ > + int n = strlen(value); > + int ret = 0; > + char *red_values = NULL; > + char *blue_values = NULL; > + char *green_values = NULL; > + char *light_info_values = NULL; > + char *white_point_values = NULL; > + int hdr_data_red[RGB_CHANNEL_LENGTH]; > + int hdr_data_green[RGB_CHANNEL_LENGTH]; > + int hdr_data_blue[RGB_CHANNEL_LENGTH]; > + int hdr_data_light_level[LIGHT_LEVEL_DATA_LENGTH]; > + int hdr_data_white_point[WHITE_POINT_DATA_LENGTH]; > + if (!(red_values = (char*)av_calloc(n + 1, sizeof(red_values)))) > + return AVERROR(ENOMEM); > + if (!(green_values = (char*)av_calloc(n + 1, sizeof(green_values)))) > + return AVERROR(ENOMEM); > + if (!(blue_values = (char*)av_calloc(n + 1, sizeof(blue_values)))) > + return AVERROR(ENOMEM); > + if (!(white_point_values = (char*)av_calloc(n + 1, > sizeof(white_point_values)))) > + return AVERROR(ENOMEM); > + if (!(light_info_values = (char*)av_calloc(n + 1, > sizeof(light_info_values)))) > + return AVERROR(ENOMEM); > + > + for (int i = 0; i < n; i++) { > + char current_char = value[i]; > + switch (current_char) { > + case 'R': > + ff_build_sub_string(value, red_values, i+1); > + break; > + case 'G': > + ff_build_sub_string(value, green_values, i+1); > + break; > + case 'B': > + ff_build_sub_string(value, blue_values, i+1); > + break; > + case 'W': > + ff_build_sub_string(value, white_point_values, i+1); > + break; > + case 'L': > + ff_build_sub_string(value, light_info_values, i+1); > + break; > + default: > + break; > + } > + } > + > + if (!ff_qsv_extract_values(red_values, hdr_data_red) && > + !ff_qsv_extract_values(green_values, hdr_data_green) && > + !ff_qsv_extract_values(blue_values, hdr_data_blue) && > + !ff_qsv_extract_values(white_point_values, hdr_data_white_point) && > + !ff_qsv_extract_values(light_info_values, hdr_data_light_level)) { > + hdr_meta->display_primaries[0][0] = (AVRational) { > hdr_data_red[0], 1 }; > + hdr_meta->display_primaries[0][1] = (AVRational) { > hdr_data_red[1], 1 }; > + hdr_meta->display_primaries[1][0] = (AVRational) { > hdr_data_green[0], 1 }; > + hdr_meta->display_primaries[1][1] = (AVRational) { > hdr_data_green[1], 1 }; > + hdr_meta->display_primaries[2][0] = (AVRational) { > hdr_data_blue[0], 1 }; > + hdr_meta->display_primaries[2][1] = (AVRational) { > hdr_data_blue[1], 1 }; > + hdr_meta->white_point[0] = (AVRational) { > hdr_data_white_point[0], 1 }; > + hdr_meta->white_point[1] = (AVRational) { > hdr_data_white_point[1], 1 }; > + hdr_meta->min_luminance = (AVRational) { hdr_data_light_level[0], > 1 }; > + hdr_meta->max_luminance =(AVRational) { hdr_data_light_level[1], > 1 }; > + hdr_meta->has_primaries = 1; > + hdr_meta->has_luminance = 1; > + > + goto end; > + }else { > + ret = AVERROR(EINVAL); > + } > + > +end: > + av_free(red_values); > + av_free(green_values); > + av_free(blue_values); > + av_free(white_point_values); > + av_free(light_info_values); > + > + return ret; > +} > + > +int ff_qsv_get_content_light_level(char *value, AVContentLightMetadata > *light_meta) > +{ > + int n = strlen(value); > + int results[2]; > + if (!ff_qsv_extract_values(value, results)) { > + if (n > QSV_PARAMS_BUFFER_LENGTH) { > + return AVERROR(EINVAL); > + } > + } > + light_meta->MaxCLL = results[0]; > + light_meta->MaxFALL = results[1]; > + > + return 0; > +} > + > +int ff_avcol_range_to_mfx_col_range(int color_range) > +{ > + switch (color_range) { > + case AVCOL_RANGE_JPEG: > + return MFX_NOMINALRANGE_0_255; > + break; > + case AVCOL_RANGE_MPEG: > + return MFX_NOMINALRANGE_16_235; > + break; > + default: > + return MFX_NOMINALRANGE_UNKNOWN; > + } > +} > diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h > index 6d305f87dd..b663e2fa05 100644 > --- a/libavcodec/qsvenc.h > +++ b/libavcodec/qsvenc.h > @@ -25,11 +25,18 @@ > > #include <stdint.h> > #include <sys/types.h> > +#include <string.h> > +#include <stdlib.h> > +#include <ctype.h> > > #include <mfx/mfxvideo.h> > > #include "libavutil/avutil.h" > #include "libavutil/fifo.h" > +#include "libavutil/mastering_display_metadata.h" > +#include "libavutil/rational.h" > +#include "libavutil/parseutils.h" > +#include "libavutil/pixdesc.h" > > #include "avcodec.h" > #include "hwconfig.h" > @@ -38,6 +45,8 @@ > #define QSV_HAVE_CO2 QSV_VERSION_ATLEAST(1, 6) > #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11) > #define QSV_HAVE_CO_VPS QSV_VERSION_ATLEAST(1, 17) > +#define QSV_HAVE_HDR_METADATA QSV_VERSION_ATLEAST(1, 26) > +#define QSV_HAVE_VIDEO_SIGNAL_INFO QSV_VERSION_ATLEAST(1, 3 lack of ')' ? It will break the compiling. > > #define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13) > #define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26) > @@ -74,6 +83,16 @@ > #define MFX_LOOKAHEAD_DS_4x 0 > #endif > > +#define QSV_PARAM_BAD_NAME (-1) > +#define QSV_PARAM_BAD_VALUE (-2) > +#define QSV_PARAMS_BUFFER_LENGTH 100 > +#define QSV_PARAM_VALID (0) > +#define VIDEO_SIGNAL_COLOR_DESCRIPTION_PRESENT (1) > +#define VIDEO_SIGNAL_FORMAT_UNSPECIFIED (5) > +#define RGB_CHANNEL_LENGTH (2) > +#define LIGHT_LEVEL_DATA_LENGTH (2) > +#define WHITE_POINT_DATA_LENGTH (2) > + > #define QSV_COMMON_OPTS \ > { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), > AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VE > }, \ > { "avbr_accuracy", "Accuracy of the AVBR > ratecontrol", OFFSET(qsv.avbr_accuracy), AV_OPT_TYPE_INT, { .i64 = 0 }, > 0, INT_MAX, VE }, \ > @@ -97,6 +116,19 @@ > { "b_strategy", "Strategy to choose between I/P/B-frames", > OFFSET(qsv.b_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE > }, \ > { "forced_idr", "Forcing I frames as IDR > frames", OFFSET(qsv.forced_idr), AV_OPT_TYPE_BOOL,{ .i64 = > 0 }, 0, 1, VE }, \ > { "low_power", "enable low power mode(experimental: many limitations by mfx > version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = > 0}, 0, 1, VE},\ > +{ "qsv_params", "set the qsv configuration using a :-separated list of > key=value parameters", OFFSET(qsv.qsv_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE > },\ > + > +/* String keys and values accepted by qsv_param_keys*/ > +static const char * const qsv_color_range_names[] = { "limited", "full", 0 }; > +static const char * const qsv_colorprim_names[] = { "reserved", "bt709", > "unknown", > + "reserved", "bt470m", > "bt470bg", "smpte170m", "smpte240m", "film", "bt2020", "smpte428", "smpte431", > "smpte432", 0 }; > +static const char * const qsv_transfer_names[] = { "reserved", "bt709", > "unknown", "reserved", "bt470m", "bt470bg", "smpte170m", "smpte240m", > "linear", "log100", > + "log316", > "iec61966-2-4", > "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", > + "smpte2084", "smpte428", > "arib-std-b67", 0 }; > +static const char * const qsv_colmatrix_names[] = { "gbr", "bt709", > "unknown", "", "fcc", "bt470bg", "smpte170m", "smpte240m", > + "ycgco", "bt2020nc", > "bt2020c", "smpte2085", "chroma-derived-nc", "chroma-derived-c", "ictcp", 0 }; > +static const char * const qsv_key_names[] = { "range", "colorprim", > "transfer", "colormatrix", "master-display", "max-cll" }; > +extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; > > extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; > > @@ -131,6 +163,12 @@ typedef struct QSVEncContext { > #if QSV_HAVE_EXT_HEVC_TILES > mfxExtHEVCTiles exthevctiles; > #endif > +#if QSV_HAVE_HDR_METADATA > + mfxExtMasteringDisplayColourVolume master_display_volume_data; > +#endif > +#if QSV_HAVE_VIDEO_SIGNAL_INFO > + mfxExtVideoSignalInfo video_signal_data; > +#endif > #if QSV_HAVE_EXT_VP9_PARAM > mfxExtVP9Param extvp9param; > #endif > @@ -139,7 +177,7 @@ typedef struct QSVEncContext { > mfxFrameSurface1 **opaque_surfaces; > AVBufferRef *opaque_alloc_buf; > > - mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + > (QSV_HAVE_MF * 2)]; > + mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + > (QSV_HAVE_MF * 2) + QSV_HAVE_HDR_METADATA + QSV_HAVE_VIDEO_SIGNAL_INFO]; > int nb_extparam_internal; > > mfxExtBuffer **extparam; > @@ -194,6 +232,7 @@ typedef struct QSVEncContext { > int gpb; > > int a53_cc; > + AVDictionary *qsv_opts; > > #if QSV_HAVE_MF > int mfmode; > @@ -210,4 +249,73 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext > *q, > > int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q); > > +/** > + * Verify a key that specifies a specific qsv parameter exists and its value > + * is valid > + */ > +int ff_qsv_validate_params(char *key, char *value); > + > +/** > + * validate master display values provided as input and check if they are > within HDR > + * range > + */ > +int ff_qsv_validate_display(char *value); > + > +/** > + * Extract the display_color values once verified and store in an > AVMasteringDisplayMetadata > + * struct > + */ > +int ff_qsv_extract_display_values(char *value, AVMasteringDisplayMetadata > *aVMasteringDisplayMetadata); > + > +/** > + * Verify content light level is within acceptable HDR range > + */ > +int ff_qsv_validate_cll(char *value); > + > +/** > + * Parse and extract values from a string and store them in an array as > integers > + */ > +int ff_qsv_extract_values(char *input_value, int *output_values); > + > +/** > + * validate display's RGB and white point color levels > + * @param input_colors an array representation of the X and Y values of the > color. > + */ > +int ff_qsv_validate_display_color_range(int *input_colors); > + > +/** > + * validate display's luminousity > + * @param input_luminousity an array representation of the min and max values > of the display luminousity. > + */ > + > +int ff_qsv_validate_display_luminousity_range(int *input_luminousity); > + > +/** > + * Obtain video range value from the acceptable strings > + * @param value a predefined string defining the video color range as per > ISO/IEC TR 23091-4. > + */ > + > +int ff_qsv_extract_range_value(char *value); > + > +/** > + * Obtain source video light level and assign these values to > AVContentLightMetadata reference > + * @param value a predefined string defining the light level. > + * @param light_meta AVContentLightMetadata reference. > + */ > + int ff_qsv_get_content_light_level(char *value, AVContentLightMetadata > *light_meta); > + > +/** > + * convert AVCodecContext color range value to equivalent mfx color range > + * @param AVCodecContext color range > + */ > +int ff_avcol_range_to_mfx_col_range(int color_range); > + > +/** > +* Extract a substring from a string from a specified index > + * @param start_index, where the target substring offset begins > + * @param input_string, pointer to the first character of the original long > string > + * @param ouput_string, pointer to the first character of the string > variable that will hold the result substring > + */ > +void ff_build_sub_string(char *input_string, char *ouput_string, int > start_index); > + > #endif /* AVCODEC_QSVENC_H */ _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".