From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 76D654DFD4 for ; Fri, 9 Jan 2026 11:11:41 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'7QpvAZ4torotoPX7xVribLPkIgW6dms5+UsOQnEVog8=', expected b'KR073fZJY5QqV6DT3Nn3pomx6i99qbE4Az0pJLZBftQ=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1767957083; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=7QpvAZ4torotoPX7xVribLPkIgW6dms5+UsOQnEVog8=; b=Wzi8Sy8c5pkszr/02rqU9pWAZGkzCPkfjcIZbSDB2rhwfY7aqn5KHrXnrEc/BkVV1b2Xu ovvPW3HA0KrL2iUYusicylennSSdd+mn9nOuBs/SrwXyH//DMpbNYE7HOqyIfS36MJTImJ+ +LZu1C+Hx1s5LCadKx2man+N+fOKgsqAdoManh6ktaW3wbnd2C2AZuLg82U+snnro0lNIth do8slQsf9rP416eQdqqa2W30Nj6oaU5gKihPEsCQLeTqVK8j5mIRnHpr4VLcY0cBz0XcGbK npHt/u9DbkBlcPpHJXV1ThCDYZfZtRNTJfOzFbF8aKBcSzYS0wPXhpzLcHJA== Received: from [172.20.0.4] (unknown [172.20.0.4]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 697B3690DE0; Fri, 9 Jan 2026 13:11:23 +0200 (EET) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1767957058; b=HajVQbqNV8hJvXWI1jG4UmqYd5sXuecdYFFLKzec/S7yF3j9lgoWwx1thrQErNJ6hCDqf hbIHGKQnVqJecSwQjOoxpAqcKbWNdxrdFG4UFB09zI0ahGv26BfN4JxYa0iPCB/bPzT62a5 8JF2iOcU+eDyQXIBfIbVcGtMJv74gaT5GYS9asr0nASGFK4y1MyIJ2v7mfUFQt9pjgl+glx bm3Ze8u4GBLqhrIGtIIVM+WWWBE1zMFzircxRXC99Of7+T/JvS1HHO3uzoTfedx564lN+2u Qvk8MreBbU93DON54OElRQpWwIntE5DotYfdR82GFS4VxWLDHG3jGNQt41Cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1767957058; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=7wZ1N5iPUZmo6EoIFMsRrwLHYj3jlwkIMZ6uxv9P4WY=; b=o25rwcKXuMDaGbQIk2IvuIPVM4gOCRw9FSdS43DKKNNXiGNkcrKtQzooYR12YWTzQWYeb PhJVcfRLDkj6reVkwRlEaDb+phABTLL5llnI/tBqbg7fs8XSH8uIre0KQBxOCxwwvhoccmR EsaZFPWWgNef8CKfH5Q5SmLinuwTeewj9pe2gLgdg8V3uc4APvdQJy7Y7EGHnO9paMQ2gwX BL358SK0ZmnOX6hyaqbU6wI3EonkMrC03f/yvUjcDJ7GfzC7ij72FkHyHCGcxZyGTvDFdea pe7jounjj5W/z+G8aLykk9vGeuYOMj7blLyfeS4vTjlrAxEREmweJT2I0y0g== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1767957051; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=KR073fZJY5QqV6DT3Nn3pomx6i99qbE4Az0pJLZBftQ=; b=OImcWBfgdlr8zWY4Wx6/HzLtp+nEj3o93SCnWEOsyf8UprpJTQweYhYCFDrD0YLHqA5pi PAs2PgrBOT3gm0HhhcS119kT9bN39n/1iblRLTrep8zMEl2fxovSFCG2Mdax7gE71V6w5KO L+epI465kvULCVEWyoPMMFAqeFQMRalLbm3IaAUGxUTg1krX/LkpeL02tBugm9tCEvmXyRc WD1WQFgSxwm/f7eXPIhpI11kPhsIdED27IHYFGncLGEnAGSE33VLfQ6/rKTEIncTZ1SvOF7 klsOal5cayD86GRCA+4kGJnZlsXRBXyKV6ebZaWGqBXJ/XRVudawAYI9yCFw== Received: from f7c34508609e (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 09163690CEC for ; Fri, 9 Jan 2026 13:10:51 +0200 (EET) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Fri, 09 Jan 2026 11:10:50 -0000 Message-ID: <176795705119.25.6337134388074307826@4457048688e7> Message-ID-Hash: 5M75BLKGJYVPAZUYNC4BRYZIXZVG6DXS X-Message-ID-Hash: 5M75BLKGJYVPAZUYNC4BRYZIXZVG6DXS X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PR] avcodec/liboapvenc: Added support for mastering display color volume and content light level metadata (PR #21418) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: dkozinski via ffmpeg-devel Cc: dkozinski Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #21418 opened by dkozinski URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21418 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21418.patch >>From 40c5d21cfd53b2520b5203eec5b1398c2efe9bea Mon Sep 17 00:00:00 2001 From: Dawid Kozinski Date: Fri, 9 Jan 2026 11:58:58 +0100 Subject: [PATCH] avcodec/liboapvenc: Added support for mastering display color volume and content light level metadata --- libavcodec/liboapvenc.c | 323 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 317 insertions(+), 6 deletions(-) diff --git a/libavcodec/liboapvenc.c b/libavcodec/liboapvenc.c index 84bd175ef6..3b0c3bab1a 100644 --- a/libavcodec/liboapvenc.c +++ b/libavcodec/liboapvenc.c @@ -33,6 +33,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" +#include "libavutil/mastering_display_metadata.h" #include "avcodec.h" #include "apv.h" @@ -45,6 +46,23 @@ #define FRM_IDX (0) // supports only 1-frame in an access unit #define MAX_NUM_CC (OAPV_MAX_CC) // Max number of color components (upto 4:4:4:4) +#define MAX_METADATA_PAYLOADS (8) + +// ne2be ... native-endian to big-endian +#if AV_HAVE_BIGENDIAN +#define oapv_ne2be16(x) (x) +#define oapv_ne2be32(x) (x) +#else +#define oapv_ne2be16(x) av_bswap16(x) +#define oapv_ne2be32(x) av_bswap32(x) +#endif + +typedef struct apv_metadata apv_metadata_t; +struct apv_metadata { + uint32_t num_plds; + oapvm_payload_t payloads[MAX_METADATA_PAYLOADS]; +}; + /** * The structure stores all the states associated with the instance of APV encoder */ @@ -65,6 +83,14 @@ typedef struct ApvEncContext { int qp; // quantization parameter (QP) [0,63] + oapvm_payload_mdcv_t mdcv; + oapvm_payload_cll_t cll; + + apv_metadata_t* metadata; + + char *mastering_display_string; + char *content_light_string; + AVDictionary *oapv_params; } ApvEncContext; @@ -179,6 +205,205 @@ fail: return NULL; } +/** + * Parses the SMPTE ST 2086 mastering display color volume metadata string. + * The expected format is "G(x,y)B(x,y)R(x,y)WP(x,y)L(max,min)", + * where x,y are CIE 1931 coordinates (floats) and max,min are luminance + * values (floats in cd/m^2). + * + * @param m The oapvm_payload_mdcv_t structure to fill. + * @param str The input string containing the metadata. + * @return 0 on success, AVERROR_INVALIDDATA on parsing error or invalid values. + */ +static int parse_mdcv_string_metadata(oapvm_payload_mdcv_t *mdcv, const char *str) { + if (!str || !mdcv) { + return AVERROR_INVALIDDATA; + } + + uint16_t gx, gy, bx, by, rx, ry, wpx, wpy; + uint32_t max_l, min_l; + int ret; + + // Use sscanf to extract the 10 floating-point values from the specific format string. + ret = sscanf(str, "G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)", + &gx, &gy, &bx, &by, &rx, &ry, &wpx, &wpy, &max_l, &min_l); + + // Check if sscanf successfully assigned all expected fields (10 numerical values). + const int expected_fields = 10; + if (ret != expected_fields) { + // Parsing failed, incorrect format provided. + return AVERROR_INVALIDDATA; + } + + // According to APV specification, i = 0, 1, 2 specifies Red, Green, Blue respectively + // Store the parsed values in the correct order for APV + mdcv->primary_chromaticity_x[0] = rx; // Red X + mdcv->primary_chromaticity_y[0] = ry; // Red Y + mdcv->primary_chromaticity_x[1] = gx; // Green X + mdcv->primary_chromaticity_y[1] = gy; // Green Y + mdcv->primary_chromaticity_x[2] = bx; // Blue X + mdcv->primary_chromaticity_y[2] = by; // Blue Y + + mdcv->white_point_chromaticity_x = wpx; + mdcv->white_point_chromaticity_y = wpy; + + // Luminance values (max/min nits) are also stored in the same 10000 denominator format. + mdcv->max_mastering_luminance = max_l; + mdcv->min_mastering_luminance = min_l; + + return 0; // Success +} + +/** + * Parses the CTA-861.3 content light level metadata string into an AVContentLightMetadata structure. + * The expected format is "," (e.g., "1000,400"). + * + * @param cl The oapvm_payload_cll_t structure to fill. + * @param str The input string containing the metadata. + * @return 0 on success, AVERROR_INVALIDDATA on parsing error. + */ + +static int parse_cll_string_metadata(oapvm_payload_cll_t *cll, const char *str) { + if (!str || !cll) { + return AVERROR_INVALIDDATA; + } + + // Use sscanf to extract the two integer values separated by a comma. + // MaxCLL and MaxFALL values in the standard are represented as unsigned 16-bit integers (cd/m^2). + // sscanf is a simple way to parse this fixed format. + uint16_t max_cll_val, max_fall_val; + int ret = sscanf(str, "%hu,%hu", &max_cll_val, &max_fall_val); + + // Check if both values were successfully parsed. + const int expected_fields = 2; + if (ret != expected_fields) { + // Parsing failed, incorrect format provided. + return AVERROR_INVALIDDATA; + } + + // Assign the parsed values to the structure fields. + // The fields in AVContentLightMetadata are already in cd/m^2 (nits), + // so no AVRational conversion is needed, unlike with mastering display metadata. + cll->max_cll = max_cll_val; + cll->max_fall = max_fall_val; + + return 0; // Success +} + +static int serialize_metadata_mdcv(const oapvm_payload_mdcv_t* mdcv, uint8_t** buffer, size_t *size) { + int i; + uint8_t* current_ptr = NULL; + uint16_t beu16_val; + uint32_t beu32_val; + + *size = 6*sizeof(uint16_t) + 2*sizeof(uint16_t) + 2*sizeof(uint32_t); + *buffer = (uint8_t*)av_mallocz(*size); + if(*buffer == NULL) { + return -1; + } + + current_ptr = *buffer; + + // OAPV structure uses primary_chromaticity_x[0-2] and primary_chromaticity_y[0-2] + // where 0=Red, 1=Green, 2=Blue according to APV specification + for (i = 0; i < 3; i++) { + beu16_val = oapv_ne2be16(mdcv->primary_chromaticity_x[i]); + memcpy(current_ptr, &beu16_val, sizeof(uint16_t)); + current_ptr += sizeof(uint16_t); + + beu16_val = oapv_ne2be16(mdcv->primary_chromaticity_y[i]); + memcpy(current_ptr, &beu16_val, sizeof(uint16_t)); + current_ptr += sizeof(uint16_t); + } + + beu16_val = oapv_ne2be16(mdcv->white_point_chromaticity_x); + memcpy(current_ptr, &beu16_val, sizeof(uint16_t)); + current_ptr += sizeof(uint16_t); + + beu16_val = oapv_ne2be16(mdcv->white_point_chromaticity_y); + memcpy(current_ptr, &beu16_val, sizeof(uint16_t)); + current_ptr += sizeof(uint16_t); + + beu32_val = oapv_ne2be32(mdcv->max_mastering_luminance); + memcpy(current_ptr, &beu32_val, sizeof(uint32_t)); + current_ptr += sizeof(uint32_t); + + beu32_val = oapv_ne2be32(mdcv->min_mastering_luminance); + memcpy(current_ptr, &beu32_val, sizeof(uint32_t)); + current_ptr += sizeof(uint32_t); + + return 0; +} + +static int serialize_metadata_cll(const oapvm_payload_cll_t* cll, uint8_t** buffer, size_t* size) { + uint8_t* current_ptr = NULL; + uint16_t beu16_val; + + *size = 2*sizeof(uint16_t); + *buffer = (uint8_t*)av_mallocz(*size); + if(*buffer == NULL) { + return -1; + } + + current_ptr = *buffer; + + beu16_val = oapv_ne2be16(cll->max_cll); + memcpy(current_ptr, &beu16_val, sizeof(uint16_t)); + current_ptr += sizeof(uint16_t); + + beu16_val = oapv_ne2be16(cll->max_fall); + memcpy(current_ptr, &beu16_val, sizeof(uint16_t)); + current_ptr += sizeof(uint16_t); + + return 0; +} + +static apv_metadata_t* apv_metadata_create(void) { + apv_metadata_t* metadata = (apv_metadata_t*)av_malloc(sizeof(apv_metadata_t)); + if (metadata) { + metadata->num_plds = 0; + + for (int i = 0; i < MAX_METADATA_PAYLOADS; i++) { + metadata->payloads[i].data = NULL; + } + } + return metadata; +} + +static void apv_metadata_destroy(apv_metadata_t* metadata) { + if (metadata) { + for (int i = 0; i < metadata->num_plds; i++) { + if (metadata->payloads[i].data) { + av_free(metadata->payloads[i].data); + metadata->payloads[i].data = NULL; + } + } + av_free(metadata); + } +} + +static int apv_metadata_add_payload(apv_metadata_t* metadata, uint32_t group_id, uint32_t type, uint32_t size, void* data) { + if (!metadata || metadata->num_plds >= MAX_METADATA_PAYLOADS || !data || size == 0) { + return AVERROR_INVALIDDATA; + } + + // Copying data into internal buffer + void* new_data = av_malloc(size); + if (!new_data) { + return AVERROR_INVALIDDATA; + } + memcpy(new_data, data, size); + + metadata->payloads[metadata->num_plds].group_id = group_id; + metadata->payloads[metadata->num_plds].type = type; + metadata->payloads[metadata->num_plds].size = size; + metadata->payloads[metadata->num_plds].data = new_data; + metadata->num_plds++; + + return 0; // Success +} + + /** * The function returns a pointer to the object of the oapve_cdesc_t type. * oapve_cdesc_t contains all encoder parameters that should be initialized before the encoder is used. @@ -292,6 +517,8 @@ static av_cold int liboapve_init(AVCodecContext *avctx) unsigned char *bs_buf; int ret; + apv->metadata = apv_metadata_create(); + /* allocate bitstream buffer */ bs_buf = (unsigned char *)av_malloc(MAX_BS_BUF); if (bs_buf == NULL) { @@ -324,6 +551,64 @@ static av_cold int liboapve_init(AVCodecContext *avctx) return AVERROR_EXTERNAL; } + if(apv->mastering_display_string) { + oapvm_payload_mdcv_t* mastering = av_mallocz(sizeof(oapvm_payload_mdcv_t)); + if (!mastering) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate memory for mastering display metadata\n"); + return AVERROR(ENOMEM); + } + + ret = parse_mdcv_string_metadata(mastering, apv->mastering_display_string); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "Error parsing master-display %s'.\n", apv->mastering_display_string); + av_free(mastering); + } else { + size_t mdcv_buffer_size = 0; + uint8_t* mdcv_buffer = NULL; + + if(!serialize_metadata_mdcv(mastering, &mdcv_buffer, &mdcv_buffer_size)) { + ret = apv_metadata_add_payload(apv->metadata, 1, OAPV_METADATA_MDCV, mdcv_buffer_size, mdcv_buffer); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "Error adding mastering display metadata\n"); + } + } + av_free(mdcv_buffer); + av_free(mastering); + } + } + + if(apv->content_light_string) { + oapvm_payload_cll_t* content_light = av_mallocz(sizeof(oapvm_payload_cll_t)); + if (!content_light) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate memory for content light metadata\n"); + return AVERROR(ENOMEM); + } + + ret = parse_cll_string_metadata(content_light, apv->content_light_string); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "Error parsing content-light %s'.\n", apv->content_light_string); + av_free(content_light); + } else { + size_t cll_buffer_size = 0; + uint8_t* cll_buffer = NULL; + + if(!serialize_metadata_cll(content_light, &cll_buffer, &cll_buffer_size)) { + ret = apv_metadata_add_payload(apv->metadata, 1, OAPV_METADATA_CLL, cll_buffer_size, cll_buffer); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "Error adding content light metadata\n"); + } + } + av_free(cll_buffer); + av_free(content_light); + } + } + + ret = oapvm_set_all(apv->mid, apv->metadata->payloads, apv->metadata->num_plds); + if(OAPV_FAILED(ret)) { + av_log(avctx, AV_LOG_ERROR, "cannot set metadata\n"); + return AVERROR_EXTERNAL; + } + int value = OAPV_CFG_VAL_AU_BS_FMT_NONE; int size = 4; ret = oapve_config(apv->id, OAPV_CFG_SET_AU_BS_FMT, &value, &size); @@ -426,6 +711,8 @@ static av_cold int liboapve_close(AVCodecContext *avctx) { ApvEncContext *apv = avctx->priv_data; + apv_metadata_destroy(apv->metadata); + for (int i = 0; i < apv->num_frames; i++) { if (apv->ifrms.frm[i].imgb != NULL) apv->ifrms.frm[i].imgb->release(apv->ifrms.frm[i].imgb); @@ -467,15 +754,39 @@ static const enum AVPixelFormat supported_pixel_formats[] = { static const AVOption liboapv_options[] = { { "preset", "Encoding preset for setting encoding speed (optimization level control)", OFFSET(preset_id), AV_OPT_TYPE_INT, { .i64 = OAPV_PRESET_DEFAULT }, OAPV_PRESET_FASTEST, OAPV_PRESET_PLACEBO, VE, .unit = "preset" }, - { "fastest", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_FASTEST }, INT_MIN, INT_MAX, VE, .unit = "preset" }, - { "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_FAST }, INT_MIN, INT_MAX, VE, .unit = "preset" }, - { "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_MEDIUM }, INT_MIN, INT_MAX, VE, .unit = "preset" }, - { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_SLOW }, INT_MIN, INT_MAX, VE, .unit = "preset" }, - { "placebo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_PLACEBO }, INT_MIN, INT_MAX, VE, .unit = "preset" }, - { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_DEFAULT }, INT_MIN, INT_MAX, VE, .unit = "preset" }, + { "fastest", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_FASTEST }, 0, 0, VE, .unit = "preset" }, + { "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_FAST }, 0, 0, VE, .unit = "preset" }, + { "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_MEDIUM }, 0, 0, VE, .unit = "preset" }, + { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_SLOW }, 0, 0, VE, .unit = "preset" }, + { "placebo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_PLACEBO }, 0, 0, VE, .unit = "preset" }, + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_DEFAULT }, 0, 0, VE, .unit = "preset" }, { "qp", "Quantization parameter value for CQP rate control mode", OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 63, VE }, { "oapv-params", "Override the apv configuration using a :-separated list of key=value parameters", OFFSET(oapv_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, + + { "master-display", + "Mastering display color volume metadata (SMPTE 2086)" + "Format: G(x,y)B(x,y)R(x,y)WP(x,y)L(max,min)", + OFFSET(mastering_display_string), + AV_OPT_TYPE_STRING, + {.str = NULL}, + 0, + 0, + AV_OPT_FLAG_ENCODING_PARAM + }, + + { + "max-cll", + "Maximum Content Light Level (MaxCLL) and Maximum Frame-Average Light Level (MaxFALL) metadata (CTA-861.3). " + "Format: , (e.g., 1000,400)", + OFFSET(content_light_string), + AV_OPT_TYPE_STRING, + {.str = NULL}, + 0, + 0, + AV_OPT_FLAG_ENCODING_PARAM + }, + { NULL } }; -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org