avcodec/dovi_rpu: separate static ext blocks

Static and dynamic extension blocks are handled differently by metadata
compression, so we need to separate the extension block array into two.
This commit is contained in:
Niklas Haas 2024-07-10 14:47:40 +02:00
parent f5d6eb4017
commit a1f96ae157
3 changed files with 47 additions and 15 deletions

View File

@ -33,8 +33,10 @@
#define DOVI_MAX_DM_ID 15
typedef struct DOVIExt {
AVDOVIDmData dm[AV_DOVI_MAX_EXT_BLOCKS];
int num_dm;
AVDOVIDmData dm_static[7]; ///< static extension blocks
AVDOVIDmData dm_dynamic[25]; ///< dynamic extension blocks
int num_static;
int num_dynamic;
} DOVIExt;
typedef struct DOVIContext {
@ -191,4 +193,18 @@ int ff_dovi_guess_profile_hevc(const AVDOVIRpuDataHeader *hdr);
/* Default values for AVDOVIColorMetadata */
extern const AVDOVIColorMetadata ff_dovi_color_default;
static inline int ff_dovi_rpu_extension_is_static(int level)
{
switch (level) {
case 6:
case 10:
case 32: /* reserved as static by spec */
case 254:
case 255:
return 1;
default:
return 0;
}
}
#endif /* AVCODEC_DOVI_RPU_H */

View File

@ -51,9 +51,10 @@ int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
if (s->ext_blocks) {
const DOVIExt *ext = s->ext_blocks;
size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
for (int i = 0; i < ext->num_dm; i++)
memcpy(av_dovi_get_ext(dovi, i), &ext->dm[i], ext_sz);
dovi->num_ext_blocks = ext->num_dm;
for (int i = 0; i < ext->num_static; i++)
memcpy(av_dovi_get_ext(dovi, dovi->num_ext_blocks++), &ext->dm_static[i], ext_sz);
for (int i = 0; i < ext->num_dynamic; i++)
memcpy(av_dovi_get_ext(dovi, dovi->num_ext_blocks++), &ext->dm_dynamic[i], ext_sz);
}
*out_metadata = dovi;
@ -296,15 +297,23 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
while (num_ext_blocks--) {
AVDOVIDmData *dm;
if (ext->num_dm >= FF_ARRAY_ELEMS(ext->dm))
return AVERROR_INVALIDDATA;
dm = &ext->dm[ext->num_dm++];
uint8_t level;
ext_block_length = get_ue_golomb_31(gb);
dm->level = get_bits(gb, 8);
level = get_bits(gb, 8);
start_pos = get_bits_count(gb);
if (ff_dovi_rpu_extension_is_static(level)) {
if (ext->num_static >= FF_ARRAY_ELEMS(ext->dm_static))
return AVERROR_INVALIDDATA;
dm = &ext->dm_static[ext->num_static++];
} else {
if (ext->num_dynamic >= FF_ARRAY_ELEMS(ext->dm_dynamic))
return AVERROR_INVALIDDATA;
dm = &ext->dm_dynamic[ext->num_dynamic++];
}
dm->level = level;
switch (ver) {
case 1: ret = parse_ext_v1(s, gb, dm); break;
case 2: ret = parse_ext_v2(s, gb, dm, ext_block_length); break;
@ -674,8 +683,10 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
color->source_diagonal = get_bits(gb, 10);
/* Parse extension blocks */
if (s->ext_blocks)
s->ext_blocks->num_dm = 0;
if (s->ext_blocks) {
DOVIExt *ext = s->ext_blocks;
ext->num_static = ext->num_dynamic = 0;
}
if ((ret = parse_ext_blocks(s, gb, 1)) < 0) {
ff_dovi_ctx_unref(s);
return ret;

View File

@ -758,9 +758,14 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
if (ext) {
size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
for (int i = 0; i < metadata->num_ext_blocks; i++)
memcpy(&ext->dm[i], av_dovi_get_ext(metadata, i), ext_sz);
ext->num_dm = metadata->num_ext_blocks;
ext->num_static = ext->num_dynamic = 0;
for (int i = 0; i < metadata->num_ext_blocks; i++) {
const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
if (ff_dovi_rpu_extension_is_static(dm->level))
memcpy(&ext->dm_static[ext->num_static++], dm, ext_sz);
else
memcpy(&ext->dm_dynamic[ext->num_dynamic++], dm, ext_sz);
}
}
} else {
s->color = &ff_dovi_color_default;