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 | AVIAMFParamDefinition *param; | 501 | AVIAMFParamDefinition *param; |
| 502 | unsigned int parameter_id, parameter_rate, mode; | 502 | unsigned int parameter_id, parameter_rate, mode; |
| 503 | unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0; | 503 | unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0; |
| 504 | unsigned int total_duration = 0; | ||
| 504 | size_t param_size; | 505 | size_t param_size; |
| 505 | 506 | ||
| 506 | parameter_id = ffio_read_leb(pb); | 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 | constant_subblock_duration = ffio_read_leb(pb); | 522 | constant_subblock_duration = ffio_read_leb(pb); |
| 522 | if (constant_subblock_duration == 0) | 523 | if (constant_subblock_duration == 0) |
| 523 | nb_subblocks = ffio_read_leb(pb); | 524 | nb_subblocks = ffio_read_leb(pb); |
| 524 | else | 525 | else { |
| 525 | nb_subblocks = duration / constant_subblock_duration; | 526 | nb_subblocks = duration / constant_subblock_duration; |
| 527 | total_duration = duration; | ||
| 528 | } | ||
| 526 | } | 529 | } |
| 527 | 530 | ||
| 528 | param = av_iamf_param_definition_alloc(type, nb_subblocks, ¶m_size); | 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 | void *subblock = av_iamf_param_definition_get_subblock(param, i); | 536 | void *subblock = av_iamf_param_definition_get_subblock(param, i); |
| 534 | unsigned int subblock_duration = constant_subblock_duration; | 537 | unsigned int subblock_duration = constant_subblock_duration; |
| 535 | 538 | ||
| 536 | if (constant_subblock_duration == 0) | 539 | if (constant_subblock_duration == 0) { |
| 537 | subblock_duration = ffio_read_leb(pb); | 540 | subblock_duration = ffio_read_leb(pb); |
| 541 | total_duration += subblock_duration; | ||
| 542 | } | ||
| 538 | 543 | ||
| 539 | switch (type) { | 544 | switch (type) { |
| 540 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { | 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 | param->parameter_id = parameter_id; | 575 | param->parameter_id = parameter_id; |
| 566 | param->parameter_rate = parameter_rate; | 576 | param->parameter_rate = parameter_rate; |
| 567 | param->duration = duration; | 577 | param->duration = duration; |
| @@ -109,6 +109,7 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, · 108 unmodified lines | |||
| 109 | AVIOContext *pb; | 109 | AVIOContext *pb; |
| 110 | uint8_t *buf; | 110 | uint8_t *buf; |
| 111 | unsigned int duration, constant_subblock_duration; | 111 | unsigned int duration, constant_subblock_duration; |
| 112 | unsigned int total_duration = 0; | ||
| 112 | unsigned int nb_subblocks; | 113 | unsigned int nb_subblocks; |
| 113 | unsigned int parameter_id; | 114 | unsigned int parameter_id; |
| 114 | size_t out_param_size; | 115 | size_t out_param_size; |
| @@ -147,8 +148,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c, · 32 unmodified lines | |||
| 147 | constant_subblock_duration = ffio_read_leb(pb); | 148 | constant_subblock_duration = ffio_read_leb(pb); |
| 148 | if (constant_subblock_duration == 0) | 149 | if (constant_subblock_duration == 0) |
| 149 | nb_subblocks = ffio_read_leb(pb); | 150 | nb_subblocks = ffio_read_leb(pb); |
| 150 | else | 151 | else { |
| 151 | nb_subblocks = duration / constant_subblock_duration; | 152 | nb_subblocks = duration / constant_subblock_duration; |
| 153 | total_duration = duration; | ||
| 154 | } | ||
| 152 | } else { | 155 | } else { |
| 153 | duration = param->duration; | 156 | duration = param->duration; |
| 154 | constant_subblock_duration = param->constant_subblock_duration; | 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 | void *subblock = av_iamf_param_definition_get_subblock(out_param, i); | 175 | void *subblock = av_iamf_param_definition_get_subblock(out_param, i); |
| 173 | unsigned int subblock_duration = constant_subblock_duration; | 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 | subblock_duration = ffio_read_leb(pb); | 179 | subblock_duration = ffio_read_leb(pb); |
| 180 | total_duration += subblock_duration; | ||
| 181 | } | ||
| 177 | 182 | ||
| 178 | switch (param->type) { | 183 | switch (param->type) { |
| 179 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: { | 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 | av_log(s, level, "Underread in parameter_block_obu. %d bytes left at the end\n", len); | 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 | switch (param->type) { | 249 | switch (param->type) { |
| 239 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: | 250 | case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: |
| 240 | av_free(c->mix); | 251 | av_free(c->mix); |