FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/iamf_parse.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 486 694 70.0%
Functions: 13 14 92.9%
Branches: 205 367 55.9%

Line Branch Exec Source
1 /*
2 * Immersive Audio Model and Formats parsing
3 * Copyright (c) 2023 James Almer <jamrial@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "libavutil/avassert.h"
23 #include "libavutil/iamf.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/log.h"
26 #include "libavutil/mem.h"
27 #include "libavcodec/get_bits.h"
28 #include "libavcodec/flac.h"
29 #include "libavcodec/leb.h"
30 #include "libavcodec/mpeg4audio.h"
31 #include "libavcodec/put_bits.h"
32 #include "avio_internal.h"
33 #include "iamf_parse.h"
34 #include "isom.h"
35
36 5 static int opus_decoder_config(IAMFCodecConfig *codec_config,
37 AVIOContext *pb, int len)
38 {
39 5 int ret, left = len - avio_tell(pb);
40
41
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (left < 11 || codec_config->audio_roll_distance >= 0)
42 return AVERROR_INVALIDDATA;
43
44 5 codec_config->extradata = av_malloc(left + 8);
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!codec_config->extradata)
46 return AVERROR(ENOMEM);
47
48 5 AV_WB32A(codec_config->extradata, MKBETAG('O','p','u','s'));
49 5 AV_WB32A(codec_config->extradata + 4, MKBETAG('H','e','a','d'));
50 5 ret = ffio_read_size(pb, codec_config->extradata + 8, left);
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
52 return ret;
53
54 5 codec_config->extradata_size = left + 8;
55 5 codec_config->sample_rate = 48000;
56
57 5 return 0;
58 }
59
60 2 static int aac_decoder_config(IAMFCodecConfig *codec_config,
61 AVIOContext *pb, int len, void *logctx)
62 {
63 2 MPEG4AudioConfig cfg = { 0 };
64 int object_type_id, codec_id, stream_type;
65 int ret, tag, left;
66
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (codec_config->audio_roll_distance >= 0)
68 return AVERROR_INVALIDDATA;
69
70 2 ff_mp4_read_descr(logctx, pb, &tag);
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tag != MP4DecConfigDescrTag)
72 return AVERROR_INVALIDDATA;
73
74 2 object_type_id = avio_r8(pb);
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (object_type_id != 0x40)
76 return AVERROR_INVALIDDATA;
77
78 2 stream_type = avio_r8(pb);
79
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (((stream_type >> 2) != 5) || ((stream_type >> 1) & 1))
80 return AVERROR_INVALIDDATA;
81
82 2 avio_skip(pb, 3); // buffer size db
83 2 avio_skip(pb, 4); // rc_max_rate
84 2 avio_skip(pb, 4); // avg bitrate
85
86 2 codec_id = ff_codec_get_id(ff_mp4_obj_type, object_type_id);
87
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (codec_id && codec_id != codec_config->codec_id)
88 return AVERROR_INVALIDDATA;
89
90 2 left = ff_mp4_read_descr(logctx, pb, &tag);
91
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (tag != MP4DecSpecificDescrTag ||
92
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 !left || left > (len - avio_tell(pb)))
93 return AVERROR_INVALIDDATA;
94
95 // We pad extradata here because avpriv_mpeg4audio_get_config2() needs it.
96 2 codec_config->extradata = av_malloc((size_t)left + AV_INPUT_BUFFER_PADDING_SIZE);
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!codec_config->extradata)
98 return AVERROR(ENOMEM);
99
100 2 ret = ffio_read_size(pb, codec_config->extradata, left);
101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
102 return ret;
103 2 codec_config->extradata_size = left;
104 2 memset(codec_config->extradata + codec_config->extradata_size, 0,
105 AV_INPUT_BUFFER_PADDING_SIZE);
106
107 2 ret = avpriv_mpeg4audio_get_config2(&cfg, codec_config->extradata,
108 codec_config->extradata_size, 1, logctx);
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
110 return ret;
111
112 2 codec_config->sample_rate = cfg.sample_rate;
113
114 2 return 0;
115 }
116
117 18 static int flac_decoder_config(IAMFCodecConfig *codec_config,
118 AVIOContext *pb, int len)
119 {
120 int ret, left;
121
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (codec_config->audio_roll_distance)
123 return AVERROR_INVALIDDATA;
124
125 18 avio_skip(pb, 4); // METADATA_BLOCK_HEADER
126
127 18 left = len - avio_tell(pb);
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (left < FLAC_STREAMINFO_SIZE)
129 return AVERROR_INVALIDDATA;
130
131 18 codec_config->extradata = av_malloc(left);
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (!codec_config->extradata)
133 return AVERROR(ENOMEM);
134
135 18 ret = ffio_read_size(pb, codec_config->extradata, left);
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (ret < 0)
137 return ret;
138
139 18 codec_config->extradata_size = left;
140 18 codec_config->sample_rate = AV_RB24(codec_config->extradata + 10) >> 4;
141
142 18 return 0;
143 }
144
145 static int ipcm_decoder_config(IAMFCodecConfig *codec_config,
146 AVIOContext *pb, int len)
147 {
148 static const enum AVCodecID sample_fmt[2][3] = {
149 { AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S24BE, AV_CODEC_ID_PCM_S32BE },
150 { AV_CODEC_ID_PCM_S16LE, AV_CODEC_ID_PCM_S24LE, AV_CODEC_ID_PCM_S32LE },
151 };
152 int sample_format = avio_r8(pb); // 0 = BE, 1 = LE
153 int sample_size = (avio_r8(pb) / 8 - 2); // 16, 24, 32
154 if (sample_format > 1 || sample_size > 2U || codec_config->audio_roll_distance)
155 return AVERROR_INVALIDDATA;
156
157 codec_config->codec_id = sample_fmt[sample_format][sample_size];
158 codec_config->sample_rate = avio_rb32(pb);
159
160 if (len - avio_tell(pb))
161 return AVERROR_INVALIDDATA;
162
163 return 0;
164 }
165
166 25 static int codec_config_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
167 {
168 25 IAMFCodecConfig **tmp, *codec_config = NULL;
169 FFIOContext b;
170 AVIOContext *pbc;
171 uint8_t *buf;
172 enum AVCodecID avcodec_id;
173 unsigned codec_config_id, nb_samples, codec_id;
174 int16_t audio_roll_distance;
175 int ret;
176
177 25 buf = av_malloc(len);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!buf)
179 return AVERROR(ENOMEM);
180
181 25 ret = ffio_read_size(pb, buf, len);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
183 goto fail;
184
185 25 ffio_init_context(&b, buf, len, 0, NULL, NULL, NULL, NULL);
186 25 pbc = &b.pub;
187
188 25 codec_config_id = ffio_read_leb(pbc);
189 25 codec_id = avio_rb32(pbc);
190 25 nb_samples = ffio_read_leb(pbc);
191 25 audio_roll_distance = avio_rb16(pbc);
192
193
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
25 switch(codec_id) {
194 5 case MKBETAG('O','p','u','s'):
195 5 avcodec_id = AV_CODEC_ID_OPUS;
196 5 break;
197 2 case MKBETAG('m','p','4','a'):
198 2 avcodec_id = AV_CODEC_ID_AAC;
199 2 break;
200 18 case MKBETAG('f','L','a','C'):
201 18 avcodec_id = AV_CODEC_ID_FLAC;
202 18 break;
203 default:
204 avcodec_id = AV_CODEC_ID_NONE;
205 break;
206 }
207
208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 for (int i = 0; i < c->nb_codec_configs; i++)
209 if (c->codec_configs[i]->codec_config_id == codec_config_id) {
210 ret = AVERROR_INVALIDDATA;
211 goto fail;
212 }
213
214 25 tmp = av_realloc_array(c->codec_configs, c->nb_codec_configs + 1, sizeof(*c->codec_configs));
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!tmp) {
216 ret = AVERROR(ENOMEM);
217 goto fail;
218 }
219 25 c->codec_configs = tmp;
220
221 25 codec_config = av_mallocz(sizeof(*codec_config));
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!codec_config) {
223 ret = AVERROR(ENOMEM);
224 goto fail;
225 }
226
227 25 codec_config->codec_config_id = codec_config_id;
228 25 codec_config->codec_id = avcodec_id;
229 25 codec_config->nb_samples = nb_samples;
230 25 codec_config->audio_roll_distance = audio_roll_distance;
231
232
3/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
25 switch(codec_id) {
233 5 case MKBETAG('O','p','u','s'):
234 5 ret = opus_decoder_config(codec_config, pbc, len);
235 5 break;
236 2 case MKBETAG('m','p','4','a'):
237 2 ret = aac_decoder_config(codec_config, pbc, len, s);
238 2 break;
239 18 case MKBETAG('f','L','a','C'):
240 18 ret = flac_decoder_config(codec_config, pbc, len);
241 18 break;
242 case MKBETAG('i','p','c','m'):
243 ret = ipcm_decoder_config(codec_config, pbc, len);
244 break;
245 default:
246 break;
247 }
248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
249 goto fail;
250
251
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 if ((codec_config->nb_samples > INT_MAX) || codec_config->nb_samples <= 0 ||
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 (-codec_config->audio_roll_distance > INT_MAX / codec_config->nb_samples)) {
253 ret = AVERROR_INVALIDDATA;
254 goto fail;
255 }
256
257 25 c->codec_configs[c->nb_codec_configs++] = codec_config;
258
259 25 len -= avio_tell(pbc);
260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (len)
261 av_log(s, AV_LOG_WARNING, "Underread in codec_config_obu. %d bytes left at the end\n", len);
262
263 25 ret = 0;
264 25 fail:
265 25 av_free(buf);
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0) {
267 if (codec_config)
268 av_free(codec_config->extradata);
269 av_free(codec_config);
270 }
271 25 return ret;
272 }
273
274 108 static int update_extradata(AVCodecParameters *codecpar)
275 {
276 GetBitContext gb;
277 PutBitContext pb;
278 int ret;
279
280
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
108 switch(codecpar->codec_id) {
281 20 case AV_CODEC_ID_OPUS:
282 20 AV_WB8(codecpar->extradata + 9, codecpar->ch_layout.nb_channels);
283 20 AV_WL16A(codecpar->extradata + 10, AV_RB16A(codecpar->extradata + 10)); // Byte swap pre-skip
284 20 AV_WL32A(codecpar->extradata + 12, AV_RB32A(codecpar->extradata + 12)); // Byte swap sample rate
285 20 AV_WL16A(codecpar->extradata + 16, AV_RB16A(codecpar->extradata + 16)); // Byte swap Output Gain
286 20 break;
287 2 case AV_CODEC_ID_AAC: {
288 uint8_t buf[5];
289
290 2 init_put_bits(&pb, buf, sizeof(buf));
291 2 ret = init_get_bits8(&gb, codecpar->extradata, codecpar->extradata_size);
292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
293 return ret;
294
295 2 ret = get_bits(&gb, 5);
296 2 put_bits(&pb, 5, ret);
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret == AOT_ESCAPE) // violates section 3.11.2, but better check for it
298 put_bits(&pb, 6, get_bits(&gb, 6));
299 2 ret = get_bits(&gb, 4);
300 2 put_bits(&pb, 4, ret);
301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret == 0x0f)
302 put_bits(&pb, 24, get_bits(&gb, 24));
303
304 2 skip_bits(&gb, 4);
305 2 put_bits(&pb, 4, codecpar->ch_layout.nb_channels); // set channel config
306 2 ret = put_bits_left(&pb);
307 2 put_bits(&pb, ret, get_bits_long(&gb, ret));
308 2 flush_put_bits(&pb);
309
310 2 memcpy(codecpar->extradata, buf, put_bytes_output(&pb));
311 2 break;
312 }
313 86 case AV_CODEC_ID_FLAC: {
314 uint8_t buf[13];
315
316 86 init_put_bits(&pb, buf, sizeof(buf));
317 86 ret = init_get_bits8(&gb, codecpar->extradata, codecpar->extradata_size);
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 if (ret < 0)
319 return ret;
320
321 86 put_bits32(&pb, get_bits_long(&gb, 32)); // min/max blocksize
322 86 put_bits64(&pb, 48, get_bits64(&gb, 48)); // min/max framesize
323 86 put_bits(&pb, 20, get_bits(&gb, 20)); // samplerate
324 86 skip_bits(&gb, 3);
325 86 put_bits(&pb, 3, codecpar->ch_layout.nb_channels - 1);
326 86 ret = put_bits_left(&pb);
327 86 put_bits(&pb, ret, get_bits(&gb, ret));
328 86 flush_put_bits(&pb);
329
330 86 memcpy(codecpar->extradata, buf, sizeof(buf));
331 86 break;
332 }
333 }
334
335 108 return 0;
336 }
337
338 21 static int scalable_channel_layout_config(void *s, AVIOContext *pb,
339 IAMFAudioElement *audio_element,
340 const IAMFCodecConfig *codec_config)
341 {
342 21 int nb_layers, k = 0;
343
344 21 nb_layers = avio_r8(pb) >> 5; // get_bits(&gb, 3);
345 // skip_bits(&gb, 5); //reserved
346
347
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
21 if (nb_layers > 6 || nb_layers == 0)
348 return AVERROR_INVALIDDATA;
349
350 21 audio_element->layers = av_calloc(nb_layers, sizeof(*audio_element->layers));
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!audio_element->layers)
352 return AVERROR(ENOMEM);
353
354 21 audio_element->nb_layers = nb_layers;
355
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 21 times.
77 for (int i = 0; i < nb_layers; i++) {
356 AVIAMFLayer *layer;
357 int loudspeaker_layout, output_gain_is_present_flag;
358 int substream_count, coupled_substream_count;
359 56 int ret, byte = avio_r8(pb);
360
361 56 layer = av_iamf_audio_element_add_layer(audio_element->element);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (!layer)
363 return AVERROR(ENOMEM);
364
365 56 loudspeaker_layout = byte >> 4; // get_bits(&gb, 4);
366 56 output_gain_is_present_flag = (byte >> 3) & 1; //get_bits1(&gb);
367
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 51 times.
56 if ((byte >> 2) & 1)
368 5 layer->flags |= AV_IAMF_LAYER_FLAG_RECON_GAIN;
369 56 substream_count = avio_r8(pb);
370 56 coupled_substream_count = avio_r8(pb);
371
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (substream_count + k > audio_element->nb_substreams)
373 return AVERROR_INVALIDDATA;
374
375 56 audio_element->layers[i].substream_count = substream_count;
376 56 audio_element->layers[i].coupled_substream_count = coupled_substream_count;
377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (output_gain_is_present_flag) {
378 layer->output_gain_flags = avio_r8(pb) >> 2; // get_bits(&gb, 6);
379 layer->output_gain = av_make_q(sign_extend(avio_rb16(pb), 16), 1 << 8);
380 }
381
382
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (loudspeaker_layout < 10)
383 56 av_channel_layout_copy(&layer->ch_layout, &ff_iamf_scalable_ch_layouts[loudspeaker_layout]);
384 else
385 layer->ch_layout = (AVChannelLayout){ .order = AV_CHANNEL_ORDER_UNSPEC,
386 .nb_channels = substream_count +
387 coupled_substream_count };
388
389
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 56 times.
148 for (int j = 0; j < substream_count; j++) {
390 92 IAMFSubStream *substream = &audio_element->substreams[k++];
391
392
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 30 times.
92 substream->codecpar->ch_layout = coupled_substream_count-- > 0 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO :
393 (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
394
395 92 ret = update_extradata(substream->codecpar);
396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 if (ret < 0)
397 return ret;
398 }
399
400 }
401
402 21 return 0;
403 }
404
405 4 static int ambisonics_config(void *s, AVIOContext *pb,
406 IAMFAudioElement *audio_element,
407 const IAMFCodecConfig *codec_config)
408 {
409 AVIAMFLayer *layer;
410 unsigned ambisonics_mode;
411 int output_channel_count, substream_count, order;
412 int ret;
413
414 4 ambisonics_mode = ffio_read_leb(pb);
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ambisonics_mode > 1)
416 return 0;
417
418 4 output_channel_count = avio_r8(pb); // C
419 4 substream_count = avio_r8(pb); // N
420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (audio_element->nb_substreams != substream_count)
421 return AVERROR_INVALIDDATA;
422
423 4 order = floor(sqrt(output_channel_count - 1));
424 /* incomplete order - some harmonics are missing */
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if ((order + 1) * (order + 1) != output_channel_count)
426 return AVERROR_INVALIDDATA;
427
428 4 audio_element->layers = av_mallocz(sizeof(*audio_element->layers));
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!audio_element->layers)
430 return AVERROR(ENOMEM);
431
432 4 audio_element->nb_layers = 1;
433 4 audio_element->layers->substream_count = substream_count;
434
435 4 layer = av_iamf_audio_element_add_layer(audio_element->element);
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!layer)
437 return AVERROR(ENOMEM);
438
439 4 layer->ambisonics_mode = ambisonics_mode;
440
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ambisonics_mode == 0) {
441
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < substream_count; i++) {
442 16 IAMFSubStream *substream = &audio_element->substreams[i];
443
444 16 substream->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
445
446 16 ret = update_extradata(substream->codecpar);
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
448 return ret;
449 }
450
451 4 layer->ch_layout.order = AV_CHANNEL_ORDER_CUSTOM;
452 4 layer->ch_layout.nb_channels = output_channel_count;
453 4 layer->ch_layout.u.map = av_calloc(output_channel_count, sizeof(*layer->ch_layout.u.map));
454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!layer->ch_layout.u.map)
455 return AVERROR(ENOMEM);
456
457
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < output_channel_count; i++)
458 16 layer->ch_layout.u.map[i].id = avio_r8(pb) + AV_CHAN_AMBISONIC_BASE;
459 } else {
460 int coupled_substream_count = avio_r8(pb); // M
461 int nb_demixing_matrix = substream_count + coupled_substream_count;
462 int demixing_matrix_size = nb_demixing_matrix * output_channel_count;
463
464 audio_element->layers->coupled_substream_count = coupled_substream_count;
465
466 layer->ch_layout = (AVChannelLayout){ .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = output_channel_count };
467 layer->demixing_matrix = av_malloc_array(demixing_matrix_size, sizeof(*layer->demixing_matrix));
468 if (!layer->demixing_matrix)
469 return AVERROR(ENOMEM);
470
471 for (int i = 0; i < demixing_matrix_size; i++)
472 layer->demixing_matrix[i] = av_make_q(sign_extend(avio_rb16(pb), 16), 1 << 8);
473
474 for (int i = 0; i < substream_count; i++) {
475 IAMFSubStream *substream = &audio_element->substreams[i];
476
477 substream->codecpar->ch_layout = coupled_substream_count-- > 0 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO :
478 (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
479
480
481 ret = update_extradata(substream->codecpar);
482 if (ret < 0)
483 return ret;
484 }
485 }
486
487 4 return 0;
488 }
489
490 78 static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
491 unsigned int type,
492 const IAMFAudioElement *audio_element,
493 AVIAMFParamDefinition **out_param_definition)
494 {
495 78 IAMFParamDefinition *param_definition = NULL;
496 AVIAMFParamDefinition *param;
497 unsigned int parameter_id, parameter_rate, mode;
498 78 unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0;
499 size_t param_size;
500
501 78 parameter_id = ffio_read_leb(pb);
502
503
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 for (int i = 0; i < c->nb_param_definitions; i++)
504
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 45 times.
78 if (c->param_definitions[i]->param->parameter_id == parameter_id) {
505 33 param_definition = c->param_definitions[i];
506 33 break;
507 }
508
509 78 parameter_rate = ffio_read_leb(pb);
510 78 mode = avio_r8(pb) >> 7;
511
512
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 58 times.
78 if (mode == 0) {
513 20 duration = ffio_read_leb(pb);
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!duration)
515 return AVERROR_INVALIDDATA;
516 20 constant_subblock_duration = ffio_read_leb(pb);
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (constant_subblock_duration == 0)
518 nb_subblocks = ffio_read_leb(pb);
519 else
520 20 nb_subblocks = duration / constant_subblock_duration;
521 }
522
523 78 param = av_iamf_param_definition_alloc(type, nb_subblocks, &param_size);
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (!param)
525 return AVERROR(ENOMEM);
526
527
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 78 times.
98 for (int i = 0; i < nb_subblocks; i++) {
528 20 void *subblock = av_iamf_param_definition_get_subblock(param, i);
529 20 unsigned int subblock_duration = constant_subblock_duration;
530
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (constant_subblock_duration == 0)
532 subblock_duration = ffio_read_leb(pb);
533
534
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
20 switch (type) {
535 case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
536 AVIAMFMixGain *mix = subblock;
537 mix->subblock_duration = subblock_duration;
538 break;
539 }
540 15 case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
541 15 AVIAMFDemixingInfo *demix = subblock;
542 15 demix->subblock_duration = subblock_duration;
543 // DefaultDemixingInfoParameterData
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 av_assert0(audio_element);
545 15 demix->dmixp_mode = avio_r8(pb) >> 5;
546 15 audio_element->element->default_w = avio_r8(pb) >> 4;
547 15 break;
548 }
549 5 case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
550 5 AVIAMFReconGain *recon = subblock;
551 5 recon->subblock_duration = subblock_duration;
552 5 break;
553 }
554 default:
555 av_free(param);
556 return AVERROR_INVALIDDATA;
557 }
558 }
559
560 78 param->parameter_id = parameter_id;
561 78 param->parameter_rate = parameter_rate;
562 78 param->duration = duration;
563 78 param->constant_subblock_duration = constant_subblock_duration;
564 78 param->nb_subblocks = nb_subblocks;
565
566
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 45 times.
78 if (param_definition) {
567
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 if (param_definition->param_size != param_size || memcmp(param_definition->param, param, param_size)) {
568 av_log(s, AV_LOG_ERROR, "Incosistent parameters for parameter_id %u\n", parameter_id);
569 av_free(param);
570 return AVERROR_INVALIDDATA;
571 }
572 } else {
573 45 IAMFParamDefinition **tmp = av_realloc_array(c->param_definitions, c->nb_param_definitions + 1,
574 sizeof(*c->param_definitions));
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!tmp) {
576 av_free(param);
577 return AVERROR(ENOMEM);
578 }
579 45 c->param_definitions = tmp;
580
581 45 param_definition = av_mallocz(sizeof(*param_definition));
582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!param_definition) {
583 av_free(param);
584 return AVERROR(ENOMEM);
585 }
586 45 param_definition->param = param;
587 45 param_definition->mode = !mode;
588 45 param_definition->param_size = param_size;
589 45 param_definition->audio_element = audio_element;
590
591 45 c->param_definitions[c->nb_param_definitions++] = param_definition;
592 }
593
594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 av_assert0(out_param_definition);
595 78 *out_param_definition = param;
596
597 78 return 0;
598 }
599
600 25 static int audio_element_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
601 {
602 const IAMFCodecConfig *codec_config;
603 AVIAMFAudioElement *element;
604 25 IAMFAudioElement **tmp, *audio_element = NULL;
605 FFIOContext b;
606 AVIOContext *pbc;
607 uint8_t *buf;
608 unsigned audio_element_id, nb_substreams, codec_config_id, num_parameters;
609 int audio_element_type, ret;
610
611 25 buf = av_malloc(len);
612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!buf)
613 return AVERROR(ENOMEM);
614
615 25 ret = ffio_read_size(pb, buf, len);
616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
617 goto fail;
618
619 25 ffio_init_context(&b, buf, len, 0, NULL, NULL, NULL, NULL);
620 25 pbc = &b.pub;
621
622 25 audio_element_id = ffio_read_leb(pbc);
623
624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 for (int i = 0; i < c->nb_audio_elements; i++)
625 if (c->audio_elements[i]->audio_element_id == audio_element_id) {
626 av_log(s, AV_LOG_ERROR, "Duplicate audio_element_id %d\n", audio_element_id);
627 ret = AVERROR_INVALIDDATA;
628 goto fail;
629 }
630
631 25 audio_element_type = avio_r8(pbc) >> 5;
632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (audio_element_type > AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
633 av_log(s, AV_LOG_DEBUG, "Unknown audio_element_type referenced in an audio element. Ignoring\n");
634 ret = 0;
635 goto fail;
636 }
637
638 25 codec_config_id = ffio_read_leb(pbc);
639
640 25 codec_config = ff_iamf_get_codec_config(c, codec_config_id);
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!codec_config) {
642 av_log(s, AV_LOG_ERROR, "Non existant codec config id %d referenced in an audio element\n", codec_config_id);
643 ret = AVERROR_INVALIDDATA;
644 goto fail;
645 }
646
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (codec_config->codec_id == AV_CODEC_ID_NONE) {
648 av_log(s, AV_LOG_DEBUG, "Unknown codec id referenced in an audio element. Ignoring\n");
649 ret = 0;
650 goto fail;
651 }
652
653 25 tmp = av_realloc_array(c->audio_elements, c->nb_audio_elements + 1, sizeof(*c->audio_elements));
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!tmp) {
655 ret = AVERROR(ENOMEM);
656 goto fail;
657 }
658 25 c->audio_elements = tmp;
659
660 25 audio_element = av_mallocz(sizeof(*audio_element));
661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!audio_element) {
662 ret = AVERROR(ENOMEM);
663 goto fail;
664 }
665
666 25 nb_substreams = ffio_read_leb(pbc);
667 25 audio_element->codec_config_id = codec_config_id;
668 25 audio_element->audio_element_id = audio_element_id;
669 25 audio_element->substreams = av_calloc(nb_substreams, sizeof(*audio_element->substreams));
670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!audio_element->substreams) {
671 ret = AVERROR(ENOMEM);
672 goto fail;
673 }
674 25 audio_element->nb_substreams = nb_substreams;
675
676 25 element = audio_element->element = av_iamf_audio_element_alloc();
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!element) {
678 ret = AVERROR(ENOMEM);
679 goto fail;
680 }
681 25 audio_element->celement = element;
682
683 25 element->audio_element_type = audio_element_type;
684
685
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 25 times.
133 for (int i = 0; i < audio_element->nb_substreams; i++) {
686 108 IAMFSubStream *substream = &audio_element->substreams[i];
687
688 108 substream->codecpar = avcodec_parameters_alloc();
689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!substream->codecpar) {
690 ret = AVERROR(ENOMEM);
691 goto fail;
692 }
693
694 108 substream->audio_substream_id = ffio_read_leb(pbc);
695
696 108 substream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
697 108 substream->codecpar->codec_id = codec_config->codec_id;
698 108 substream->codecpar->frame_size = codec_config->nb_samples;
699 108 substream->codecpar->sample_rate = codec_config->sample_rate;
700 108 substream->codecpar->seek_preroll = -codec_config->audio_roll_distance * codec_config->nb_samples;
701
702
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 switch(substream->codecpar->codec_id) {
703 108 case AV_CODEC_ID_AAC:
704 case AV_CODEC_ID_FLAC:
705 case AV_CODEC_ID_OPUS:
706 108 substream->codecpar->extradata = av_malloc(codec_config->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!substream->codecpar->extradata) {
708 ret = AVERROR(ENOMEM);
709 goto fail;
710 }
711 108 memcpy(substream->codecpar->extradata, codec_config->extradata, codec_config->extradata_size);
712 108 memset(substream->codecpar->extradata + codec_config->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
713 108 substream->codecpar->extradata_size = codec_config->extradata_size;
714 108 break;
715 }
716 }
717
718 25 num_parameters = ffio_read_leb(pbc);
719
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
25 if (num_parameters && audio_element_type != 0) {
720 av_log(s, AV_LOG_ERROR, "Audio Element parameter count %u is invalid"
721 " for Scene representations\n", num_parameters);
722 ret = AVERROR_INVALIDDATA;
723 goto fail;
724 }
725
726
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 25 times.
45 for (int i = 0; i < num_parameters; i++) {
727 unsigned type;
728
729 20 type = ffio_read_leb(pbc);
730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (type == AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN)
731 ret = AVERROR_INVALIDDATA;
732
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
20 else if (type == AV_IAMF_PARAMETER_DEFINITION_DEMIXING)
733 15 ret = param_parse(s, c, pbc, type, audio_element, &element->demixing_info);
734
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 else if (type == AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN)
735 5 ret = param_parse(s, c, pbc, type, audio_element, &element->recon_gain_info);
736 else {
737 unsigned param_definition_size = ffio_read_leb(pbc);
738 avio_skip(pbc, param_definition_size);
739 }
740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (ret < 0)
741 goto fail;
742 }
743
744
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 4 times.
25 if (audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
745 21 ret = scalable_channel_layout_config(s, pbc, audio_element, codec_config);
746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret < 0)
747 goto fail;
748
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if (audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
749 4 ret = ambisonics_config(s, pbc, audio_element, codec_config);
750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
751 goto fail;
752 } else {
753 av_assert0(0);
754 }
755
756 25 c->audio_elements[c->nb_audio_elements++] = audio_element;
757
758 25 len -= avio_tell(pbc);
759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (len)
760 av_log(s, AV_LOG_WARNING, "Underread in audio_element_obu. %d bytes left at the end\n", len);
761
762 25 ret = 0;
763 25 fail:
764 25 av_free(buf);
765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
766 ff_iamf_free_audio_element(&audio_element);
767 25 return ret;
768 }
769
770 79 static int label_string(AVIOContext *pb, char **label)
771 {
772 uint8_t buf[128];
773
774 79 avio_get_str(pb, sizeof(buf), buf, sizeof(buf));
775
776
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (pb->error)
777 return pb->error;
778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (pb->eof_reached)
779 return AVERROR_INVALIDDATA;
780 79 *label = av_strdup(buf);
781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!*label)
782 return AVERROR(ENOMEM);
783
784 79 return 0;
785 }
786
787 25 static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
788 {
789 AVIAMFMixPresentation *mix;
790 25 IAMFMixPresentation **tmp, *mix_presentation = NULL;
791 FFIOContext b;
792 AVIOContext *pbc;
793 uint8_t *buf;
794 unsigned nb_submixes, mix_presentation_id;
795 int ret;
796
797 25 buf = av_malloc(len);
798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!buf)
799 return AVERROR(ENOMEM);
800
801 25 ret = ffio_read_size(pb, buf, len);
802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
803 goto fail;
804
805 25 ffio_init_context(&b, buf, len, 0, NULL, NULL, NULL, NULL);
806 25 pbc = &b.pub;
807
808 25 mix_presentation_id = ffio_read_leb(pbc);
809
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 for (int i = 0; i < c->nb_mix_presentations; i++)
811 if (c->mix_presentations[i]->mix_presentation_id == mix_presentation_id) {
812 av_log(s, AV_LOG_ERROR, "Duplicate mix_presentation_id %d\n", mix_presentation_id);
813 ret = AVERROR_INVALIDDATA;
814 goto fail;
815 }
816
817 25 tmp = av_realloc_array(c->mix_presentations, c->nb_mix_presentations + 1, sizeof(*c->mix_presentations));
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!tmp) {
819 ret = AVERROR(ENOMEM);
820 goto fail;
821 }
822 25 c->mix_presentations = tmp;
823
824 25 mix_presentation = av_mallocz(sizeof(*mix_presentation));
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!mix_presentation) {
826 ret = AVERROR(ENOMEM);
827 goto fail;
828 }
829
830 25 mix_presentation->mix_presentation_id = mix_presentation_id;
831 25 mix = mix_presentation->mix = av_iamf_mix_presentation_alloc();
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!mix) {
833 ret = AVERROR(ENOMEM);
834 goto fail;
835 }
836 25 mix_presentation->cmix = mix;
837
838 25 mix_presentation->count_label = ffio_read_leb(pbc);
839 25 mix_presentation->language_label = av_calloc(mix_presentation->count_label,
840 sizeof(*mix_presentation->language_label));
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (!mix_presentation->language_label) {
842 mix_presentation->count_label = 0;
843 ret = AVERROR(ENOMEM);
844 goto fail;
845 }
846
847
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 25 times.
50 for (int i = 0; i < mix_presentation->count_label; i++) {
848 25 ret = label_string(pbc, &mix_presentation->language_label[i]);
849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
850 goto fail;
851 }
852
853
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 25 times.
50 for (int i = 0; i < mix_presentation->count_label; i++) {
854 25 char *annotation = NULL;
855 25 ret = label_string(pbc, &annotation);
856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
857 goto fail;
858 25 ret = av_dict_set(&mix->annotations, mix_presentation->language_label[i], annotation,
859 AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
861 goto fail;
862 }
863
864 25 nb_submixes = ffio_read_leb(pbc);
865
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 25 times.
54 for (int i = 0; i < nb_submixes; i++) {
866 AVIAMFSubmix *sub_mix;
867 unsigned nb_elements, nb_layouts;
868
869 29 sub_mix = av_iamf_mix_presentation_add_submix(mix);
870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!sub_mix) {
871 ret = AVERROR(ENOMEM);
872 goto fail;
873 }
874
875 29 nb_elements = ffio_read_leb(pbc);
876
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 29 times.
58 for (int j = 0; j < nb_elements; j++) {
877 AVIAMFSubmixElement *submix_element;
878 29 IAMFAudioElement *audio_element = NULL;
879 unsigned int rendering_config_extension_size;
880
881 29 submix_element = av_iamf_submix_add_element(sub_mix);
882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!submix_element) {
883 ret = AVERROR(ENOMEM);
884 goto fail;
885 }
886
887 29 submix_element->audio_element_id = ffio_read_leb(pbc);
888
889
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 for (int k = 0; k < c->nb_audio_elements; k++)
890
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (c->audio_elements[k]->audio_element_id == submix_element->audio_element_id) {
891 29 audio_element = c->audio_elements[k];
892 29 break;
893 }
894
895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!audio_element) {
896 av_log(s, AV_LOG_ERROR, "Invalid Audio Element with id %u referenced by Mix Parameters %u\n",
897 submix_element->audio_element_id, mix_presentation_id);
898 ret = AVERROR_INVALIDDATA;
899 goto fail;
900 }
901
902
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 29 times.
58 for (int k = 0; k < mix_presentation->count_label; k++) {
903 29 char *annotation = NULL;
904 29 ret = label_string(pbc, &annotation);
905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
906 goto fail;
907 29 ret = av_dict_set(&submix_element->annotations, mix_presentation->language_label[k], annotation,
908 AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
910 goto fail;
911 }
912
913 29 submix_element->headphones_rendering_mode = avio_r8(pbc) >> 6;
914
915 29 rendering_config_extension_size = ffio_read_leb(pbc);
916 29 avio_skip(pbc, rendering_config_extension_size);
917
918 29 ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
919 NULL,
920 &submix_element->element_mix_config);
921
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
922 goto fail;
923 29 submix_element->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
924 }
925
926 29 ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, NULL, &sub_mix->output_mix_config);
927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
928 goto fail;
929 29 sub_mix->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
930
931 29 nb_layouts = ffio_read_leb(pbc);
932
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 29 times.
93 for (int j = 0; j < nb_layouts; j++) {
933 AVIAMFSubmixLayout *submix_layout;
934 int info_type;
935 64 int byte = avio_r8(pbc);
936
937 64 submix_layout = av_iamf_submix_add_layout(sub_mix);
938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (!submix_layout) {
939 ret = AVERROR(ENOMEM);
940 goto fail;
941 }
942
943 64 submix_layout->layout_type = byte >> 6;
944
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if (submix_layout->layout_type < AV_IAMF_SUBMIX_LAYOUT_TYPE_LOUDSPEAKERS ||
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 submix_layout->layout_type > AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL) {
946 av_log(s, AV_LOG_ERROR, "Invalid Layout type %u in a submix from Mix Presentation %u\n",
947 submix_layout->layout_type, mix_presentation_id);
948 ret = AVERROR_INVALIDDATA;
949 goto fail;
950 }
951
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
64 if (submix_layout->layout_type == 2) {
952 int sound_system;
953 60 sound_system = (byte >> 2) & 0xF;
954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (sound_system >= FF_ARRAY_ELEMS(ff_iamf_sound_system_map)) {
955 ret = AVERROR_INVALIDDATA;
956 goto fail;
957 }
958 60 av_channel_layout_copy(&submix_layout->sound_system, &ff_iamf_sound_system_map[sound_system].layout);
959 } else
960 4 submix_layout->sound_system = (AVChannelLayout)AV_CHANNEL_LAYOUT_BINAURAL;
961
962 64 info_type = avio_r8(pbc);
963 64 submix_layout->integrated_loudness = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
964 64 submix_layout->digital_peak = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
965
966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (info_type & 1)
967 submix_layout->true_peak = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (info_type & 2) {
969 unsigned int num_anchored_loudness = avio_r8(pbc);
970
971 for (int k = 0; k < num_anchored_loudness; k++) {
972 unsigned int anchor_element = avio_r8(pbc);
973 AVRational anchored_loudness = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
974 if (anchor_element == IAMF_ANCHOR_ELEMENT_DIALOGUE)
975 submix_layout->dialogue_anchored_loudness = anchored_loudness;
976 else if (anchor_element <= IAMF_ANCHOR_ELEMENT_ALBUM)
977 submix_layout->album_anchored_loudness = anchored_loudness;
978 else
979 av_log(s, AV_LOG_DEBUG, "Unknown anchor_element. Ignoring\n");
980 }
981 }
982
983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 if (info_type & 0xFC) {
984 unsigned int info_type_size = ffio_read_leb(pbc);
985 avio_skip(pbc, info_type_size);
986 }
987 }
988 }
989
990 25 c->mix_presentations[c->nb_mix_presentations++] = mix_presentation;
991
992 25 len -= avio_tell(pbc);
993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (len)
994 av_log(s, AV_LOG_WARNING, "Underread in mix_presentation_obu. %d bytes left at the end\n", len);
995
996 25 ret = 0;
997 25 fail:
998 25 av_free(buf);
999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (ret < 0)
1000 ff_iamf_free_mix_presentation(&mix_presentation);
1001 25 return ret;
1002 }
1003
1004 7991 int ff_iamf_parse_obu_header(const uint8_t *buf, int buf_size,
1005 unsigned *obu_size, int *start_pos, enum IAMF_OBU_Type *type,
1006 unsigned *skip_samples, unsigned *discard_padding)
1007 {
1008 GetBitContext gb;
1009 int ret, extension_flag, trimming, start;
1010 7991 unsigned skip = 0, discard = 0;
1011 unsigned size;
1012
1013 7991 ret = init_get_bits8(&gb, buf, FFMIN(buf_size, MAX_IAMF_OBU_HEADER_SIZE));
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7991 times.
7991 if (ret < 0)
1015 return ret;
1016
1017 7991 *type = get_bits(&gb, 5);
1018 7991 /*redundant =*/ get_bits1(&gb);
1019 7991 trimming = get_bits1(&gb);
1020 7991 extension_flag = get_bits1(&gb);
1021
1022 7991 *obu_size = get_leb(&gb);
1023
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 7982 times.
7991 if (*obu_size > INT_MAX)
1024 9 return AVERROR_INVALIDDATA;
1025
1026 7982 start = get_bits_count(&gb) / 8;
1027
1028
2/2
✓ Branch 0 taken 2331 times.
✓ Branch 1 taken 5651 times.
7982 if (trimming) {
1029 2331 discard = get_leb(&gb); // num_samples_to_trim_at_end
1030 2331 skip = get_leb(&gb); // num_samples_to_trim_at_start
1031 }
1032
1033
2/2
✓ Branch 0 taken 635 times.
✓ Branch 1 taken 7347 times.
7982 if (skip_samples)
1034 635 *skip_samples = skip;
1035
2/2
✓ Branch 0 taken 635 times.
✓ Branch 1 taken 7347 times.
7982 if (discard_padding)
1036 635 *discard_padding = discard;
1037
1038
2/2
✓ Branch 0 taken 728 times.
✓ Branch 1 taken 7254 times.
7982 if (extension_flag) {
1039 unsigned int extension_bytes;
1040 728 extension_bytes = get_leb(&gb);
1041
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 710 times.
728 if (extension_bytes > INT_MAX / 8)
1042 18 return AVERROR_INVALIDDATA;
1043 710 skip_bits_long(&gb, extension_bytes * 8);
1044 }
1045
1046
2/2
✓ Branch 1 taken 530 times.
✓ Branch 2 taken 7434 times.
7964 if (get_bits_left(&gb) < 0)
1047 530 return AVERROR_INVALIDDATA;
1048
1049 7434 size = *obu_size + start;
1050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7434 times.
7434 if (size > INT_MAX)
1051 return AVERROR_INVALIDDATA;
1052
1053 7434 *obu_size -= get_bits_count(&gb) / 8 - start;
1054 7434 *start_pos = size - *obu_size;
1055
1056 7434 return size;
1057 }
1058
1059 25 int ff_iamfdec_read_descriptors(IAMFContext *c, AVIOContext *pb,
1060 int max_size, void *log_ctx)
1061 {
1062 uint8_t header[MAX_IAMF_OBU_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1063 int ret;
1064
1065 90 while (1) {
1066 unsigned obu_size;
1067 enum IAMF_OBU_Type type;
1068 int start_pos, len, size;
1069
1070
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 115 times.
115 if ((ret = ffio_ensure_seekback(pb, FFMIN(MAX_IAMF_OBU_HEADER_SIZE, max_size))) < 0)
1071 return ret;
1072 115 size = avio_read(pb, header, FFMIN(MAX_IAMF_OBU_HEADER_SIZE, max_size));
1073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 if (size < 0)
1074 return size;
1075 115 memset(header + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1076
1077 115 len = ff_iamf_parse_obu_header(header, size, &obu_size, &start_pos, &type, NULL, NULL);
1078
2/4
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 115 times.
115 if (len < 0 || obu_size > max_size) {
1079 av_log(log_ctx, AV_LOG_ERROR, "Failed to read obu header\n");
1080 avio_seek(pb, -size, SEEK_CUR);
1081 return len;
1082 }
1083
1084
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 75 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 25 times.
115 if (type >= IAMF_OBU_IA_PARAMETER_BLOCK && type < IAMF_OBU_IA_SEQUENCE_HEADER) {
1085 15 avio_seek(pb, -size, SEEK_CUR);
1086 15 break;
1087 }
1088
1089 100 avio_seek(pb, -(size - start_pos), SEEK_CUR);
1090
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 25 times.
100 switch (type) {
1091 25 case IAMF_OBU_IA_CODEC_CONFIG:
1092 25 ret = codec_config_obu(log_ctx, c, pb, obu_size);
1093 25 break;
1094 25 case IAMF_OBU_IA_AUDIO_ELEMENT:
1095 25 ret = audio_element_obu(log_ctx, c, pb, obu_size);
1096 25 break;
1097 25 case IAMF_OBU_IA_MIX_PRESENTATION:
1098 25 ret = mix_presentation_obu(log_ctx, c, pb, obu_size);
1099 25 break;
1100 25 default: {
1101 25 int64_t offset = avio_skip(pb, obu_size);
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (offset < 0)
1103 ret = offset;
1104 25 break;
1105 }
1106 }
1107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (ret < 0) {
1108 av_log(log_ctx, AV_LOG_ERROR, "Failed to read obu type %d\n", type);
1109 return ret;
1110 }
1111 100 max_size -= obu_size + start_pos;
1112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if (max_size < 0)
1113 return AVERROR_INVALIDDATA;
1114
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 90 times.
100 if (!max_size)
1115 10 break;
1116 }
1117
1118 25 return 0;
1119 }
1120