diff options
author | James Almer <jamrial@gmail.com> | 2024-12-11 23:27:00 -0300 |
---|---|---|
committer | James Almer <jamrial@gmail.com> | 2024-12-15 20:37:39 -0300 |
commit | d38fc25519cf12a9212dadcba1258fc176ffbade (patch) | |
tree | a66ff6832666b691c74f9d306389372b134b88e6 | |
parent | 8ad34e97b62c0e4afdacda58d5e02a6dee16fac5 (diff) | |
download | ffmpeg-d38fc25519cf12a9212dadcba1258fc176ffbade.tar.gz |
avformat/iamf_parse: add checks to parameter definition durations
Section 3.6.1 of the IAMF spec states "When constant_subblock_duration is equal to 0, the summation of all
subblock_duration in this parameter block SHALL be equal to duration.".
Signed-off-by: James Almer <jamrial@gmail.com>
-rw-r--r-- | libavformat/iamf_parse.c | 14 | ||||
-rw-r--r-- | libavformat/iamf_reader.c | 15 |
2 files changed, 25 insertions, 4 deletions
diff --git a/libavformat/iamf_parse.c b/libavformat/iamf_parse.c index 6c2efc0a6c..00190d87a4 100644 --- a/libavformat/iamf_parse.c +++ b/libavformat/iamf_parse.c @@ -501,6 +501,7 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, AVIAMFParamDefinition *param; unsigned int parameter_id, parameter_rate, mode; unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0; + unsigned int total_duration = 0; size_t param_size; parameter_id = ffio_read_leb(pb); @@ -521,8 +522,10 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, constant_subblock_duration = ffio_read_leb(pb); if (constant_subblock_duration == 0) nb_subblocks = ffio_read_leb(pb); - else + else { nb_subblocks = duration / constant_subblock_duration; + total_duration = duration; + } } param = av_iamf_param_definition_alloc(type, nb_subblocks, ¶m_size); @@ -533,8 +536,10 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, void *subblock = av_iamf_param_definition_get_subblock(param, i); unsigned int subblock_duration = constant_subblock_duration; - if (constant_subblock_duration == 0) + if (constant_subblock_duration == 0) { subblock_duration = ffio_read_leb(pb); + total_duration += subblock_duration; + } switch (type) { case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { @@ -562,6 +567,11 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, } } + if (!mode && !constant_subblock_duration && total_duration != duration) { + av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id); + return AVERROR_INVALIDDATA; + } + param->parameter_id = parameter_id; param->parameter_rate = parameter_rate; param->duration = duration; diff --git a/libavformat/iamf_reader.c b/libavformat/iamf_reader.c index b00bb997ca..7ad61cb246 100644 --- a/libavformat/iamf_reader.c +++ b/libavformat/iamf_reader.c @@ -109,6 +109,7 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, AVIOContext *pb; uint8_t *buf; unsigned int duration, constant_subblock_duration; + unsigned int total_duration = 0; unsigned int nb_subblocks; unsigned int parameter_id; size_t out_param_size; @@ -147,8 +148,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, constant_subblock_duration = ffio_read_leb(pb); if (constant_subblock_duration == 0) nb_subblocks = ffio_read_leb(pb); - else + else { nb_subblocks = duration / constant_subblock_duration; + total_duration = duration; + } } else { duration = param->duration; constant_subblock_duration = param->constant_subblock_duration; @@ -172,8 +175,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, void *subblock = av_iamf_param_definition_get_subblock(out_param, i); unsigned int subblock_duration = constant_subblock_duration; - if (!param_definition->mode && !constant_subblock_duration) + if (!param_definition->mode && !constant_subblock_duration) { subblock_duration = ffio_read_leb(pb); + total_duration += subblock_duration; + } switch (param->type) { case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { @@ -235,6 +240,12 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, av_log(s, level, "Underread in parameter_block_obu. %d bytes left at the end\n", len); } + if (!param_definition->mode && !constant_subblock_duration && total_duration != duration) { + av_log(s, AV_LOG_ERROR, "Invalid duration in parameter block\n"); + ret = AVERROR_INVALIDDATA; + goto fail; + } + switch (param->type) { case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: av_free(c->mix); |