mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec/dovi_rpu: fix dm_metadata_id handling
Despite the suggestive size limits, this metadata ID has nothing to do with the VDR metadata ID used for the data mappings. Actually, the specification leaves them wholly unexplained, other than acknowleding their existence. Must be some secret dolby sauce. They're not even involved in DM metadata compression, which is handled using an entirely separate ID. That leaves us with a lack of anything sensible to do with these IDs. Since we unfortunately only expose one `dm_metadata_id` field to the user, just ensure that they match; which appears to always be the case in practice. If somebody ever hits this error, I would really much rather like to see the triggering file.
This commit is contained in:
parent
68a22ac936
commit
7ee64631f6
|
@ -28,6 +28,7 @@
|
|||
|
||||
void ff_dovi_ctx_unref(DOVIContext *s)
|
||||
{
|
||||
ff_refstruct_unref(&s->dm);
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr); i++)
|
||||
ff_refstruct_unref(&s->vdr[i]);
|
||||
ff_refstruct_unref(&s->ext_blocks);
|
||||
|
@ -40,6 +41,7 @@ void ff_dovi_ctx_unref(DOVIContext *s)
|
|||
|
||||
void ff_dovi_ctx_flush(DOVIContext *s)
|
||||
{
|
||||
ff_refstruct_unref(&s->dm);
|
||||
for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr); i++)
|
||||
ff_refstruct_unref(&s->vdr[i]);
|
||||
ff_refstruct_unref(&s->ext_blocks);
|
||||
|
@ -60,6 +62,7 @@ void ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0)
|
|||
s->header = s0->header;
|
||||
s->mapping = s0->mapping;
|
||||
s->color = s0->color;
|
||||
ff_refstruct_replace(&s->dm, s0->dm);
|
||||
for (int i = 0; i <= DOVI_MAX_DM_ID; i++)
|
||||
ff_refstruct_replace(&s->vdr[i], s0->vdr[i]);
|
||||
ff_refstruct_replace(&s->ext_blocks, s0->ext_blocks);
|
||||
|
|
|
@ -74,6 +74,7 @@ typedef struct DOVIContext {
|
|||
/**
|
||||
* Private fields internal to dovi_rpu.c
|
||||
*/
|
||||
AVDOVIColorMetadata *dm; ///< RefStruct
|
||||
struct DOVIVdr *vdr[DOVI_MAX_DM_ID+1]; ///< RefStruct references
|
||||
uint8_t *rpu_buf; ///< temporary buffer
|
||||
unsigned rpu_buf_sz;
|
||||
|
|
|
@ -580,25 +580,25 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
|
|||
int current_dm_id = get_ue_golomb_31(gb);
|
||||
VALIDATE(affected_dm_id, 0, DOVI_MAX_DM_ID);
|
||||
VALIDATE(current_dm_id, 0, DOVI_MAX_DM_ID);
|
||||
if (!s->vdr[affected_dm_id]) {
|
||||
s->vdr[affected_dm_id] = ff_refstruct_allocz(sizeof(DOVIVdr));
|
||||
if (!s->vdr[affected_dm_id])
|
||||
if (affected_dm_id != current_dm_id) {
|
||||
/* The spec does not explain these fields at all, and there is
|
||||
* a lack of samples to understand how they're supposed to work,
|
||||
* so just assert them being equal for now */
|
||||
avpriv_request_sample(s->logctx, "affected/current_dm_metadata_id "
|
||||
"mismatch? %u != %u\n", affected_dm_id, current_dm_id);
|
||||
ff_dovi_ctx_unref(s);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
if (!s->dm) {
|
||||
s->dm = ff_refstruct_allocz(sizeof(AVDOVIColorMetadata));
|
||||
if (!s->dm) {
|
||||
ff_dovi_ctx_unref(s);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->vdr[current_dm_id]) {
|
||||
av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU DM ID: %u\n",
|
||||
current_dm_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Update current pointer based on current_dm_id */
|
||||
vdr = s->vdr[current_dm_id];
|
||||
s->color = &vdr->color;
|
||||
|
||||
/* Update values of affected_dm_id */
|
||||
vdr = s->vdr[affected_dm_id];
|
||||
color = &vdr->color;
|
||||
s->color = color = s->dm;
|
||||
color->dm_metadata_id = affected_dm_id;
|
||||
color->scene_refresh_flag = get_ue_golomb_31(gb);
|
||||
for (int i = 0; i < 9; i++)
|
||||
|
|
|
@ -479,12 +479,6 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
|
|||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
if (!s->vdr[color->dm_metadata_id]) {
|
||||
s->vdr[color->dm_metadata_id] = ff_refstruct_allocz(sizeof(DOVIVdr));
|
||||
if (!s->vdr[color->dm_metadata_id])
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
num_ext_blocks_v1 = num_ext_blocks_v2 = 0;
|
||||
for (int i = 0; i < metadata->num_ext_blocks; i++) {
|
||||
const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
|
||||
|
@ -515,6 +509,12 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
|
|||
vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
|
||||
use_prev_vdr_rpu = !memcmp(&s->vdr[vdr_rpu_id]->mapping, mapping, sizeof(*mapping));
|
||||
|
||||
if (vdr_dm_metadata_present && !s->dm) {
|
||||
s->dm = ff_refstruct_allocz(sizeof(AVDOVIColorMetadata));
|
||||
if (!s->dm)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
buffer_size = 12 /* vdr seq info */ + 5 /* CRC32 + terminator */;
|
||||
buffer_size += num_ext_blocks_v1 * 13;
|
||||
buffer_size += num_ext_blocks_v2 * 28;
|
||||
|
@ -655,8 +655,8 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
|
|||
put_bits(pb, 12, color->source_max_pq);
|
||||
put_bits(pb, 10, color->source_diagonal);
|
||||
|
||||
memcpy(&s->vdr[color->dm_metadata_id]->color, color, sizeof(*color));
|
||||
s->color = &s->vdr[color->dm_metadata_id]->color;
|
||||
memcpy(s->dm, color, sizeof(*color));
|
||||
s->color = s->dm;
|
||||
} else {
|
||||
s->color = &ff_dovi_color_default;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue