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.".
Unified · Split
| @@ -501,6 +501,7 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, · 500 unmodified lines | ||
| 501 | 501 | AVIAMFParamDefinition *param; |
| 502 | 502 | unsigned int parameter_id, parameter_rate, mode; |
| 503 | 503 | unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0; |
| 504 | + unsigned int total_duration = 0; | |
| 504 | 505 | size_t param_size; |
| 505 | 506 | |
| 506 | 507 | parameter_id = ffio_read_leb(pb); |
| @@ -521,8 +522,10 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, · 14 unmodified lines | ||
| 521 | 522 | constant_subblock_duration = ffio_read_leb(pb); |
| 522 | 523 | if (constant_subblock_duration == 0) |
| 523 | 524 | nb_subblocks = ffio_read_leb(pb); |
| 524 | − else | |
| 525 | + else { | |
| 525 | 526 | nb_subblocks = duration / constant_subblock_duration; |
| 527 | + total_duration = duration; | |
| 528 | + } | |
| 526 | 529 | } |
| 527 | 530 | |
| 528 | 531 | 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, · 4 unmodified lines | ||
| 533 | 536 | void *subblock = av_iamf_param_definition_get_subblock(param, i); |
| 534 | 537 | unsigned int subblock_duration = constant_subblock_duration; |
| 535 | 538 | |
| 536 | − if (constant_subblock_duration == 0) | |
| 539 | + if (constant_subblock_duration == 0) { | |
| 537 | 540 | subblock_duration = ffio_read_leb(pb); |
| 541 | + total_duration += subblock_duration; | |
| 542 | + } | |
| 538 | 543 | |
| 539 | 544 | switch (type) { |
| 540 | 545 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { |
| @@ -562,6 +567,11 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, · 21 unmodified lines | ||
| 562 | 567 | } |
| 563 | 568 | } |
| 564 | 569 | |
| 570 | + if (!mode && !constant_subblock_duration && total_duration != duration) { | |
| 571 | + av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id); | |
| 572 | + return AVERROR_INVALIDDATA; | |
| 573 | + } | |
| 574 | + | |
| 565 | 575 | param->parameter_id = parameter_id; |
| 566 | 576 | param->parameter_rate = parameter_rate; |
| 567 | 577 | param->duration = duration; |
| @@ -109,6 +109,7 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, · 108 unmodified lines | ||
| 109 | 109 | AVIOContext *pb; |
| 110 | 110 | uint8_t *buf; |
| 111 | 111 | unsigned int duration, constant_subblock_duration; |
| 112 | + unsigned int total_duration = 0; | |
| 112 | 113 | unsigned int nb_subblocks; |
| 113 | 114 | unsigned int parameter_id; |
| 114 | 115 | size_t out_param_size; |
| @@ -147,8 +148,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, · 32 unmodified lines | ||
| 147 | 148 | constant_subblock_duration = ffio_read_leb(pb); |
| 148 | 149 | if (constant_subblock_duration == 0) |
| 149 | 150 | nb_subblocks = ffio_read_leb(pb); |
| 150 | − else | |
| 151 | + else { | |
| 151 | 152 | nb_subblocks = duration / constant_subblock_duration; |
| 153 | + total_duration = duration; | |
| 154 | + } | |
| 152 | 155 | } else { |
| 153 | 156 | duration = param->duration; |
| 154 | 157 | constant_subblock_duration = param->constant_subblock_duration; |
| @@ -172,8 +175,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, · 17 unmodified lines | ||
| 172 | 175 | void *subblock = av_iamf_param_definition_get_subblock(out_param, i); |
| 173 | 176 | unsigned int subblock_duration = constant_subblock_duration; |
| 174 | 177 | |
| 175 | − if (!param_definition->mode && !constant_subblock_duration) | |
| 178 | + if (!param_definition->mode && !constant_subblock_duration) { | |
| 176 | 179 | subblock_duration = ffio_read_leb(pb); |
| 180 | + total_duration += subblock_duration; | |
| 181 | + } | |
| 177 | 182 | |
| 178 | 183 | switch (param->type) { |
| 179 | 184 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { |
| @@ -235,6 +240,12 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, · 55 unmodified lines | ||
| 235 | 240 | av_log(s, level, "Underread in parameter_block_obu. %d bytes left at the end\n", len); |
| 236 | 241 | } |
| 237 | 242 | |
| 243 | + if (!param_definition->mode && !constant_subblock_duration && total_duration != duration) { | |
| 244 | + av_log(s, AV_LOG_ERROR, "Invalid duration in parameter block\n"); | |
| 245 | + ret = AVERROR_INVALIDDATA; | |
| 246 | + goto fail; | |
| 247 | + } | |
| 248 | + | |
| 238 | 249 | switch (param->type) { |
| 239 | 250 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: |
| 240 | 251 | av_free(c->mix); |