| 607 | } |
| 608 | |
| 609 | static int param_parse(void *s, IAMFContext *c, AVIOContext *pb, |
| 610 | unsigned int type, |
| 611 | const IAMFAudioElement *audio_element, |
| 612 | AVIAMFParamDefinition **out_param_definition) |
| 613 | { |
| 614 | IAMFParamDefinition *param_definition = NULL; |
| 615 | AVIAMFParamDefinition *param; |
| 616 | unsigned int parameter_id, parameter_rate, mode; |
| 617 | unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0; |
| 618 | unsigned int total_duration = 0; |
| 619 | size_t param_size; |
| 620 | |
| 621 | parameter_id = ffio_read_leb(pb); |
| 622 | |
| 623 | for (int i = 0; i < c->nb_param_definitions; i++) |
| 624 | if (c->param_definitions[i]->param->parameter_id == parameter_id) { |
| 625 | param_definition = c->param_definitions[i]; |
| 626 | break; |
| 627 | } |
| 628 | |
| 629 | parameter_rate = ffio_read_leb(pb); |
| 630 | mode = avio_r8(pb) >> 7; |
| 631 | |
| 632 | if (mode == 0) { |
| 633 | duration = ffio_read_leb(pb); |
| 634 | if (!duration) |
| 635 | return AVERROR_INVALIDDATA; |
| 636 | if (audio_element) { |
| 637 | const IAMFCodecConfig *codec_config = ff_iamf_get_codec_config(c, audio_element->codec_config_id); |
| 638 | if (duration > av_rescale(codec_config->nb_samples, codec_config->sample_rate, parameter_rate)) { |
| 639 | av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id); |
| 640 | return AVERROR_INVALIDDATA; |
| 641 | } |
| 642 | } |
| 643 | constant_subblock_duration = ffio_read_leb(pb); |
| 644 | if (constant_subblock_duration == 0) |
| 645 | nb_subblocks = ffio_read_leb(pb); |
| 646 | else { |
| 647 | if (constant_subblock_duration > duration) { |
| 648 | av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id); |
| 649 | return AVERROR_INVALIDDATA; |
| 650 | } |
| 651 | nb_subblocks = duration / constant_subblock_duration; |
| 652 | total_duration = duration; |
| 653 | } |
| 654 | } |
| 655 | |
| 656 | if (nb_subblocks > duration) { |
| 657 | av_log(s, AV_LOG_ERROR, "Invalid duration or subblock count in parameter_id %u\n", parameter_id); |
| 658 | return AVERROR_INVALIDDATA; |
| 659 | } |
| 660 | |
| 661 | param = av_iamf_param_definition_alloc(type, nb_subblocks, ¶m_size); |
| 662 | if (!param) |
| 663 | return AVERROR(ENOMEM); |
| 664 | |
| 665 | for (int i = 0; i < nb_subblocks; i++) { |
| 666 | void *subblock = av_iamf_param_definition_get_subblock(param, i); |
no test coverage detected