FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/iamf_parse.c
Date: 2026-08-15 14:54:27
Exec Total Coverage
Lines: 600 841 71.3%
Functions: 14 15 93.3%
Branches: 288 483 59.6%

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 10 static int opus_decoder_config(IAMFCodecConfig *codec_config,
37 AVIOContext *pb, int len)
38 {
39 10 int ret, left = len - avio_tell(pb);
40
41
3/6
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 if (left < 11 || codec_config->audio_roll_distance >= 0 || left > INT_MAX - 8)
42 return AVERROR_INVALIDDATA;
43
44 10 codec_config->extradata = av_malloc(left + 8);
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!codec_config->extradata)
46 return AVERROR(ENOMEM);
47
48 10 AV_WB32A(codec_config->extradata, MKBETAG('O','p','u','s'));
49 10 AV_WB32A(codec_config->extradata + 4, MKBETAG('H','e','a','d'));
50 10 ret = ffio_read_size(pb, codec_config->extradata + 8, left);
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
52 return ret;
53
54 10 codec_config->extradata_size = left + 8;
55 10 codec_config->sample_rate = 48000;
56
57 10 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 24 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 24 times.
24 if (codec_config->audio_roll_distance)
123 return AVERROR_INVALIDDATA;
124
125 24 avio_skip(pb, 4); // METADATA_BLOCK_HEADER
126
127 24 left = len - avio_tell(pb);
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (left < FLAC_STREAMINFO_SIZE)
129 return AVERROR_INVALIDDATA;
130
131 24 codec_config->extradata = av_malloc(left);
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!codec_config->extradata)
133 return AVERROR(ENOMEM);
134
135 24 ret = ffio_read_size(pb, codec_config->extradata, left);
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
137 return ret;
138
139 24 codec_config->extradata_size = left;
140 24 codec_config->sample_rate = AV_RB24(codec_config->extradata + 10) >> 4;
141
142 24 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 36 static int codec_config_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
167 {
168 36 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 36 buf = av_malloc(len);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!buf)
179 return AVERROR(ENOMEM);
180
181 36 ret = ffio_read_size(pb, buf, len);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
183 goto fail;
184
185 36 ffio_init_context(&b, buf, len, 0, NULL, NULL, NULL, NULL);
186 36 pbc = &b.pub;
187
188 36 codec_config_id = ffio_read_leb(pbc);
189 36 codec_id = avio_rb32(pbc);
190 36 nb_samples = ffio_read_leb(pbc);
191 36 audio_roll_distance = avio_rb16(pbc);
192
193
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
36 switch(codec_id) {
194 10 case MKBETAG('O','p','u','s'):
195 10 avcodec_id = AV_CODEC_ID_OPUS;
196 10 break;
197 2 case MKBETAG('m','p','4','a'):
198 2 avcodec_id = AV_CODEC_ID_AAC;
199 2 break;
200 24 case MKBETAG('f','L','a','C'):
201 24 avcodec_id = AV_CODEC_ID_FLAC;
202 24 break;
203 default:
204 avcodec_id = AV_CODEC_ID_NONE;
205 break;
206 }
207
208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 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 36 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 36 times.
36 if (!tmp) {
216 ret = AVERROR(ENOMEM);
217 goto fail;
218 }
219 36 c->codec_configs = tmp;
220
221 36 codec_config = av_mallocz(sizeof(*codec_config));
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!codec_config) {
223 ret = AVERROR(ENOMEM);
224 goto fail;
225 }
226
227 36 codec_config->codec_config_id = codec_config_id;
228 36 codec_config->codec_id = avcodec_id;
229 36 codec_config->nb_samples = nb_samples;
230 36 codec_config->audio_roll_distance = audio_roll_distance;
231
232
3/5
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
36 switch(codec_id) {
233 10 case MKBETAG('O','p','u','s'):
234 10 ret = opus_decoder_config(codec_config, pbc, len);
235 10 break;
236 2 case MKBETAG('m','p','4','a'):
237 2 ret = aac_decoder_config(codec_config, pbc, len, s);
238 2 break;
239 24 case MKBETAG('f','L','a','C'):
240 24 ret = flac_decoder_config(codec_config, pbc, len);
241 24 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 36 times.
36 if (ret < 0)
249 goto fail;
250
251
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 if ((codec_config->nb_samples > INT_MAX) || codec_config->nb_samples <= 0 ||
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 (-codec_config->audio_roll_distance > INT_MAX / codec_config->nb_samples)) {
253 ret = AVERROR_INVALIDDATA;
254 goto fail;
255 }
256
257 36 c->codec_configs[c->nb_codec_configs++] = codec_config;
258
259 36 len -= avio_tell(pbc);
260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (len)
261 av_log(s, AV_LOG_WARNING, "Underread in codec_config_obu. %d bytes left at the end\n", len);
262
263 36 ret = 0;
264 36 fail:
265 36 av_free(buf);
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0) {
267 if (codec_config)
268 av_free(codec_config->extradata);
269 av_free(codec_config);
270 }
271 36 return ret;
272 }
273
274 170 static int update_extradata(AVCodecParameters *codecpar)
275 {
276 GetBitContext gb;
277 PutBitContext pb;
278 int ret;
279
280
3/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
170 switch(codecpar->codec_id) {
281 40 case AV_CODEC_ID_OPUS:
282 40 AV_WB8(codecpar->extradata + 9, codecpar->ch_layout.nb_channels);
283 40 AV_WL16A(codecpar->extradata + 10, AV_RB16A(codecpar->extradata + 10)); // Byte swap pre-skip
284 40 AV_WL32A(codecpar->extradata + 12, AV_RB32A(codecpar->extradata + 12)); // Byte swap sample rate
285 40 AV_WL16A(codecpar->extradata + 16, AV_RB16A(codecpar->extradata + 16)); // Byte swap Output Gain
286 40 break;
287 2 case AV_CODEC_ID_AAC: {
288 uint8_t buf[6];
289 2 int size = FFMIN(codecpar->extradata_size, sizeof(buf));
290
291 2 init_put_bits(&pb, buf, sizeof(buf));
292 2 ret = init_get_bits8(&gb, codecpar->extradata, size);
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
294 return ret;
295
296 2 ret = get_bits(&gb, 5);
297 2 put_bits(&pb, 5, ret);
298
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
299 put_bits(&pb, 6, get_bits(&gb, 6));
300 2 ret = get_bits(&gb, 4);
301 2 put_bits(&pb, 4, ret);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret == 0x0f)
303 put_bits(&pb, 24, get_bits(&gb, 24));
304
305 2 skip_bits(&gb, 4);
306 2 put_bits(&pb, 4, codecpar->ch_layout.nb_channels); // set channel config
307 2 ret = get_bits_left(&gb);
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
309 return AVERROR_INVALIDDATA;
310
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 ret = FFMIN(ret, put_bits_left(&pb));
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 while (ret >= 32) {
312 put_bits32(&pb, get_bits_long(&gb, 32));
313 ret -= 32;
314 }
315 2 put_bits(&pb, ret, get_bits_long(&gb, ret));
316 2 flush_put_bits(&pb);
317
318 2 memcpy(codecpar->extradata, buf, put_bytes_output(&pb));
319 2 break;
320 }
321 128 case AV_CODEC_ID_FLAC: {
322 uint8_t buf[13];
323 128 int size = FFMIN(codecpar->extradata_size, sizeof(buf));
324
325 128 init_put_bits(&pb, buf, sizeof(buf));
326 128 ret = init_get_bits8(&gb, codecpar->extradata, size);
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 if (ret < 0)
328 return ret;
329
330 128 put_bits32(&pb, get_bits_long(&gb, 32)); // min/max blocksize
331 128 put_bits63(&pb, 48, get_bits64(&gb, 48)); // min/max framesize
332 128 put_bits(&pb, 20, get_bits(&gb, 20)); // samplerate
333 128 skip_bits(&gb, 3);
334 128 put_bits(&pb, 3, codecpar->ch_layout.nb_channels - 1);
335 128 ret = get_bits_left(&gb);
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128 times.
128 if (ret < 0)
337 return AVERROR_INVALIDDATA;
338
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 128 times.
128 ret = FFMIN(ret, put_bits_left(&pb));
339 128 put_bits(&pb, ret, get_bits(&gb, ret));
340 128 flush_put_bits(&pb);
341
342 128 memcpy(codecpar->extradata, buf, put_bytes_output(&pb));
343 128 break;
344 }
345 }
346
347 170 return 0;
348 }
349
350 156 static int parse_coupled_substream(AVChannelLayout *out, AVChannelLayout *in, int n)
351 {
352
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 129 times.
156 if (in->u.mask & AV_CH_LAYOUT_STEREO) {
353 27 out->u.map[n++].id = AV_CHAN_FRONT_LEFT;
354 27 out->u.map[n++].id = AV_CHAN_FRONT_RIGHT;
355 27 in->u.mask &= ~AV_CH_LAYOUT_STEREO;
356
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 127 times.
129 } else if (in->u.mask & (AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)) {
357 2 out->u.map[n++].id = AV_CHAN_FRONT_LEFT_OF_CENTER;
358 2 out->u.map[n++].id = AV_CHAN_FRONT_RIGHT_OF_CENTER;
359 2 in->u.mask &= ~(AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER);
360
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 108 times.
127 } else if (in->u.mask & (AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)) {
361 19 out->u.map[n++].id = AV_CHAN_SIDE_LEFT;
362 19 out->u.map[n++].id = AV_CHAN_SIDE_RIGHT;
363 19 in->u.mask &= ~(AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT);
364
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 98 times.
108 } else if (in->u.mask & (AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)) {
365 10 out->u.map[n++].id = AV_CHAN_BACK_LEFT;
366 10 out->u.map[n++].id = AV_CHAN_BACK_RIGHT;
367 10 in->u.mask &= ~(AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT);
368
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 84 times.
98 } else if (in->u.mask & (AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT)) {
369 14 out->u.map[n++].id = AV_CHAN_TOP_FRONT_LEFT;
370 14 out->u.map[n++].id = AV_CHAN_TOP_FRONT_RIGHT;
371 14 in->u.mask &= ~(AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT);
372
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 82 times.
84 } else if (in->u.mask & (AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT)) {
373 2 out->u.map[n++].id = AV_CHAN_TOP_SIDE_LEFT;
374 2 out->u.map[n++].id = AV_CHAN_TOP_SIDE_RIGHT;
375 2 in->u.mask &= ~(AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT);
376
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 68 times.
82 } else if (in->u.mask & (AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT)) {
377 14 out->u.map[n++].id = AV_CHAN_TOP_BACK_LEFT;
378 14 out->u.map[n++].id = AV_CHAN_TOP_BACK_RIGHT;
379 14 in->u.mask &= ~(AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT);
380 }
381
382 156 return n;
383 }
384
385 27 static int scalable_channel_layout_config(void *s, AVIOContext *pb,
386 IAMFAudioElement *audio_element,
387 const IAMFCodecConfig *codec_config)
388 {
389 27 int nb_layers, k = 0;
390
391 27 nb_layers = avio_r8(pb) >> 5; // get_bits(&gb, 3);
392 // skip_bits(&gb, 5); //reserved
393
394
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 if (nb_layers > 6 || nb_layers == 0)
395 return AVERROR_INVALIDDATA;
396
397 27 audio_element->layers = av_calloc(nb_layers, sizeof(*audio_element->layers));
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!audio_element->layers)
399 return AVERROR(ENOMEM);
400
401 27 audio_element->nb_layers = nb_layers;
402
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 27 times.
95 for (int i = 0, n = 0; i < nb_layers; i++) {
403 68 AVChannelLayout ch_layout = { 0 };
404 AVIAMFLayer *layer;
405 int loudspeaker_layout, output_gain_is_present_flag;
406 int substream_count, coupled_substream_count;
407 68 int expanded_loudspeaker_layout = -1;
408 68 int ret, byte = avio_r8(pb);
409 int channels;
410
411 68 layer = av_iamf_audio_element_add_layer(audio_element->element);
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (!layer)
413 return AVERROR(ENOMEM);
414
415 68 loudspeaker_layout = byte >> 4; // get_bits(&gb, 4);
416 68 output_gain_is_present_flag = (byte >> 3) & 1; //get_bits1(&gb);
417
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 63 times.
68 if ((byte >> 2) & 1)
418 5 layer->flags |= AV_IAMF_LAYER_FLAG_RECON_GAIN;
419 68 substream_count = avio_r8(pb);
420 68 coupled_substream_count = avio_r8(pb);
421
422
2/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
68 if (!substream_count || coupled_substream_count > substream_count ||
423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 substream_count + k > audio_element->nb_substreams)
424 return AVERROR_INVALIDDATA;
425
426 68 audio_element->layers[i].substream_count = substream_count;
427 68 audio_element->layers[i].coupled_substream_count = coupled_substream_count;
428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (output_gain_is_present_flag) {
429 layer->output_gain_flags = avio_r8(pb) >> 2; // get_bits(&gb, 6);
430 layer->output_gain = av_make_q(sign_extend(avio_rb16(pb), 16), 1 << 8);
431 }
432
433
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
68 if (loudspeaker_layout == 15) {
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (i) {
435 av_log(s, AV_LOG_ERROR, "expanded_loudspeaker_layout set with more than one layer in Audio Element #%d\n",
436 audio_element->audio_element_id);
437 return AVERROR_INVALIDDATA;
438 }
439 2 expanded_loudspeaker_layout = avio_r8(pb);
440 }
441
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
68 if (expanded_loudspeaker_layout >= 0 && expanded_loudspeaker_layout < 13) {
442 2 av_channel_layout_copy(&ch_layout, &ff_iamf_expanded_scalable_ch_layouts[expanded_loudspeaker_layout]);
443
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 } else if (loudspeaker_layout < 10) {
444 66 av_channel_layout_copy(&ch_layout, &ff_iamf_scalable_ch_layouts[loudspeaker_layout]);
445
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 25 times.
66 if (i) {
446 41 uint64_t mask = av_channel_layout_subset(&audio_element->element->layers[i-1]->ch_layout, UINT64_MAX);
447 // When the first layer is Mono, the second layer may not have the C channel (e.g. Stereo)
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (audio_element->element->layers[i-1]->ch_layout.nb_channels == 1)
449 n--;
450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 else if ((ch_layout.u.mask & mask) != mask)
451 return AVERROR_INVALIDDATA;
452 41 ch_layout.u.mask &= ~mask;
453 }
454 } else {
455 if (expanded_loudspeaker_layout >= 0)
456 avpriv_request_sample(s, "expanded_loudspeaker_layout %d", expanded_loudspeaker_layout);
457 else
458 avpriv_request_sample(s, "loudspeaker_layout %d", loudspeaker_layout);
459 return AVERROR_PATCHWELCOME;
460 }
461
462 68 channels = ch_layout.nb_channels;
463
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 27 times.
68 if (i) {
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ch_layout.nb_channels <= audio_element->element->layers[i-1]->ch_layout.nb_channels)
465 return AVERROR_INVALIDDATA;
466 41 channels -= audio_element->element->layers[i-1]->ch_layout.nb_channels;
467 }
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (channels != substream_count + coupled_substream_count)
469 return AVERROR_INVALIDDATA;
470
471
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 68 times.
194 for (int j = 0; j < substream_count; j++) {
472 126 IAMFSubStream *substream = &audio_element->substreams[k++];
473
474
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 38 times.
126 substream->codecpar->ch_layout = coupled_substream_count-- > 0 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO :
475 (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
476
477 126 ret = update_extradata(substream->codecpar);
478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 if (ret < 0)
479 return ret;
480 }
481
482 68 ret = av_channel_layout_custom_init(&layer->ch_layout, ch_layout.nb_channels);
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
484 return ret;
485
2/2
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 68 times.
286 for (int j = 0; j < n; j++)
486 218 layer->ch_layout.u.map[j].id = av_channel_layout_channel_from_index(&audio_element->element->layers[i-1]->ch_layout, j);
487
488 68 coupled_substream_count = audio_element->layers[i].coupled_substream_count;
489
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 68 times.
156 while (coupled_substream_count--) {
490 88 n = parse_coupled_substream(&layer->ch_layout, &ch_layout, n);
491 }
492
493 68 substream_count -= audio_element->layers[i].coupled_substream_count;
494 68 n = parse_coupled_substream(&layer->ch_layout, &ch_layout, n); // In case the first layer is Mono
495
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 68 times.
106 while (substream_count--) {
496
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 19 times.
38 if (ch_layout.u.mask & AV_CH_FRONT_CENTER) {
497 19 layer->ch_layout.u.map[n++].id = AV_CHAN_FRONT_CENTER;
498 19 ch_layout.u.mask &= ~AV_CH_FRONT_CENTER;
499 }
500
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 19 times.
38 if (ch_layout.u.mask & AV_CH_LOW_FREQUENCY) {
501 19 layer->ch_layout.u.map[n++].id = AV_CHAN_LOW_FREQUENCY;
502 19 ch_layout.u.mask &= ~AV_CH_LOW_FREQUENCY;
503 }
504 }
505
506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (n != ch_layout.nb_channels)
507 return AVERROR_INVALIDDATA;
508
509 68 ret = av_channel_layout_retype(&layer->ch_layout, AV_CHANNEL_ORDER_NATIVE, 0);
510
3/4
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 43 times.
68 if (ret < 0 && ret != AVERROR(ENOSYS))
511 return ret;
512 }
513
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (k != audio_element->nb_substreams)
515 return AVERROR_INVALIDDATA;
516
517 27 return 0;
518 }
519
520 11 static int ambisonics_config(void *s, AVIOContext *pb,
521 IAMFAudioElement *audio_element,
522 const IAMFCodecConfig *codec_config)
523 {
524 AVIAMFLayer *layer;
525 unsigned ambisonics_mode;
526 int output_channel_count, substream_count, order;
527 int ret;
528
529 11 ambisonics_mode = ffio_read_leb(pb);
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ambisonics_mode > 1)
531 return AVERROR_INVALIDDATA;
532
533 11 output_channel_count = avio_r8(pb); // C
534 11 substream_count = avio_r8(pb); // N
535
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (audio_element->nb_substreams != substream_count || output_channel_count == 0)
536 return AVERROR_INVALIDDATA;
537
538 11 order = floor(sqrt(output_channel_count - 1));
539 /* incomplete order - some harmonics are missing */
540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if ((order + 1) * (order + 1) != output_channel_count)
541 return AVERROR_INVALIDDATA;
542
543 11 audio_element->layers = av_mallocz(sizeof(*audio_element->layers));
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!audio_element->layers)
545 return AVERROR(ENOMEM);
546
547 11 audio_element->nb_layers = 1;
548 11 audio_element->layers->substream_count = substream_count;
549
550 11 layer = av_iamf_audio_element_add_layer(audio_element->element);
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!layer)
552 return AVERROR(ENOMEM);
553
554 11 layer->ambisonics_mode = ambisonics_mode;
555
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
11 if (ambisonics_mode == 0) {
556
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < substream_count; i++) {
557 16 IAMFSubStream *substream = &audio_element->substreams[i];
558
559 16 substream->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
560
561 16 ret = update_extradata(substream->codecpar);
562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
563 return ret;
564 }
565
566 4 ret = av_channel_layout_custom_init(&layer->ch_layout, output_channel_count);
567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
568 return ret;
569
570
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (int i = 0; i < output_channel_count; i++)
571 16 layer->ch_layout.u.map[i].id = avio_r8(pb) + AV_CHAN_AMBISONIC_BASE;
572
573 4 ret = av_channel_layout_retype(&layer->ch_layout, AV_CHANNEL_ORDER_AMBISONIC, 0);
574
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (ret < 0 && ret != AVERROR(ENOSYS))
575 return ret;
576 } else {
577 7 int coupled_substream_count = avio_r8(pb); // M
578 7 int count = substream_count + coupled_substream_count;
579 7 int nb_demixing_matrix = count * output_channel_count;
580
581 7 audio_element->layers->coupled_substream_count = coupled_substream_count;
582
583 7 layer->ch_layout = (AVChannelLayout){ .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = output_channel_count };
584 7 layer->demixing_matrix = av_malloc_array(nb_demixing_matrix, sizeof(*layer->demixing_matrix));
585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!layer->demixing_matrix)
586 return AVERROR(ENOMEM);
587
588 7 layer->nb_demixing_matrix = nb_demixing_matrix;
589
590
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 7 times.
119 for (int i = 0; i < layer->nb_demixing_matrix; i++)
591 112 layer->demixing_matrix[i] = av_make_q(sign_extend(avio_rb16(pb), 16), 1 << 15);
592
593
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 7 times.
35 for (int i = 0; i < substream_count; i++) {
594 28 IAMFSubStream *substream = &audio_element->substreams[i];
595
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 substream->codecpar->ch_layout = coupled_substream_count-- > 0 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO :
597 (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
598
599
600 28 ret = update_extradata(substream->codecpar);
601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
602 return ret;
603 }
604 }
605
606 11 return 0;
607 }
608
609 104 static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
610 unsigned int type,
611 const IAMFAudioElement *audio_element,
612 const IAMFCodecConfig *codec_config,
613 AVIAMFParamDefinition **out_param_definition)
614 {
615 104 IAMFParamDefinition *param_definition = NULL;
616 AVIAMFParamDefinition *param;
617 unsigned int parameter_id, parameter_rate, mode;
618 104 unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0;
619 104 unsigned int total_duration = 0;
620 size_t param_size;
621
622 104 parameter_id = ffio_read_leb(pb);
623
624
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 63 times.
158 for (int i = 0; i < c->nb_param_definitions; i++)
625
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 54 times.
95 if (c->param_definitions[i]->param->parameter_id == parameter_id) {
626 41 param_definition = c->param_definitions[i];
627 41 break;
628 }
629
630 104 parameter_rate = ffio_read_leb(pb);
631 104 mode = avio_r8(pb) >> 7;
632
633
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 82 times.
104 if (mode == 0) {
634 22 duration = ffio_read_leb(pb);
635
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (!duration || duration > av_rescale(codec_config->nb_samples,
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 codec_config->sample_rate, parameter_rate)) {
637 av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
638 return AVERROR_INVALIDDATA;
639 }
640 22 constant_subblock_duration = ffio_read_leb(pb);
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (constant_subblock_duration == 0)
642 nb_subblocks = ffio_read_leb(pb);
643 else {
644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (constant_subblock_duration > duration) {
645 av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
646 return AVERROR_INVALIDDATA;
647 }
648 22 nb_subblocks = duration / constant_subblock_duration;
649 22 total_duration = duration;
650 }
651 }
652
653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
104 if (nb_subblocks > duration) {
654 av_log(s, AV_LOG_ERROR, "Invalid duration or subblock count in parameter_id %u\n", parameter_id);
655 return AVERROR_INVALIDDATA;
656 }
657
658 104 param = av_iamf_param_definition_alloc(type, nb_subblocks, &param_size);
659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
104 if (!param)
660 return AVERROR(ENOMEM);
661
662
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 104 times.
126 for (int i = 0; i < nb_subblocks; i++) {
663 22 void *subblock = av_iamf_param_definition_get_subblock(param, i);
664 22 unsigned int subblock_duration = constant_subblock_duration;
665
666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (constant_subblock_duration == 0) {
667 subblock_duration = ffio_read_leb(pb);
668 if (subblock_duration > duration - total_duration) {
669 av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
670 av_free(param);
671 return AVERROR_INVALIDDATA;
672 }
673 total_duration += subblock_duration;
674
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 } else if (i == nb_subblocks - 1)
675 22 subblock_duration = duration - i * constant_subblock_duration;
676
677
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
22 switch (type) {
678 case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
679 AVIAMFMixGain *mix = subblock;
680 mix->subblock_duration = subblock_duration;
681 break;
682 }
683 17 case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
684 17 AVIAMFDemixingInfo *demix = subblock;
685 17 demix->subblock_duration = subblock_duration;
686 // DefaultDemixingInfoParameterData
687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 av_assert0(audio_element);
688 17 demix->dmixp_mode = avio_r8(pb) >> 5;
689 17 audio_element->element->default_w = avio_r8(pb) >> 4;
690 17 break;
691 }
692 5 case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
693 5 AVIAMFReconGain *recon = subblock;
694 5 recon->subblock_duration = subblock_duration;
695 5 break;
696 }
697 default:
698 av_free(param);
699 return AVERROR_INVALIDDATA;
700 }
701 }
702
703
3/6
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
104 if (!mode && !constant_subblock_duration && total_duration != duration) {
704 av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
705 av_free(param);
706 return AVERROR_INVALIDDATA;
707 }
708
709 104 param->parameter_id = parameter_id;
710 104 param->parameter_rate = parameter_rate;
711 104 param->duration = duration;
712 104 param->constant_subblock_duration = constant_subblock_duration;
713 104 param->nb_subblocks = nb_subblocks;
714
715
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 63 times.
104 if (param_definition) {
716
2/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
41 if (param_definition->param_size != param_size || memcmp(param_definition->param, param, param_size)) {
717 av_log(s, AV_LOG_ERROR, "Inconsistent parameters for parameter_id %u\n", parameter_id);
718 av_free(param);
719 return AVERROR_INVALIDDATA;
720 }
721 } else {
722 63 IAMFParamDefinition **tmp = av_realloc_array(c->param_definitions, c->nb_param_definitions + 1,
723 sizeof(*c->param_definitions));
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (!tmp) {
725 av_free(param);
726 return AVERROR(ENOMEM);
727 }
728 63 c->param_definitions = tmp;
729
730 63 param_definition = av_mallocz(sizeof(*param_definition));
731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (!param_definition) {
732 av_free(param);
733 return AVERROR(ENOMEM);
734 }
735 63 param_definition->param = param;
736 63 param_definition->mode = !mode;
737 63 param_definition->param_size = param_size;
738 63 param_definition->audio_element = audio_element;
739
740 63 c->param_definitions[c->nb_param_definitions++] = param_definition;
741 }
742
743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
104 av_assert0(out_param_definition);
744 104 *out_param_definition = param;
745
746 104 return 0;
747 }
748
749 38 static int audio_element_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
750 {
751 const IAMFCodecConfig *codec_config;
752 AVIAMFAudioElement *element;
753 38 IAMFAudioElement **tmp, *audio_element = NULL;
754 FFIOContext b;
755 AVIOContext *pbc;
756 uint8_t *buf;
757 unsigned audio_element_id, nb_substreams, codec_config_id, num_parameters;
758 int audio_element_type, ret;
759
760 38 buf = av_malloc(len);
761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!buf)
762 return AVERROR(ENOMEM);
763
764 38 ret = ffio_read_size(pb, buf, len);
765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (ret < 0)
766 goto fail;
767
768 38 ffio_init_context(&b, buf, len, 0, NULL, NULL, NULL, NULL);
769 38 pbc = &b.pub;
770
771 38 audio_element_id = ffio_read_leb(pbc);
772
773
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 38 times.
40 for (int i = 0; i < c->nb_audio_elements; i++)
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (c->audio_elements[i]->audio_element_id == audio_element_id) {
775 av_log(s, AV_LOG_ERROR, "Duplicate audio_element_id %d\n", audio_element_id);
776 ret = AVERROR_INVALIDDATA;
777 goto fail;
778 }
779
780 38 audio_element_type = avio_r8(pbc) >> 5;
781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (audio_element_type > AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
782 av_log(s, AV_LOG_DEBUG, "Unknown audio_element_type referenced in an audio element. Ignoring\n");
783 ret = 0;
784 goto fail;
785 }
786
787 38 codec_config_id = ffio_read_leb(pbc);
788
789 38 codec_config = ff_iamf_get_codec_config(c, codec_config_id);
790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!codec_config) {
791 av_log(s, AV_LOG_ERROR, "Non existent codec config id %d referenced in an audio element\n", codec_config_id);
792 ret = AVERROR_INVALIDDATA;
793 goto fail;
794 }
795
796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (codec_config->codec_id == AV_CODEC_ID_NONE) {
797 av_log(s, AV_LOG_DEBUG, "Unknown codec id referenced in an audio element. Ignoring\n");
798 ret = 0;
799 goto fail;
800 }
801
802 38 tmp = av_realloc_array(c->audio_elements, c->nb_audio_elements + 1, sizeof(*c->audio_elements));
803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!tmp) {
804 ret = AVERROR(ENOMEM);
805 goto fail;
806 }
807 38 c->audio_elements = tmp;
808
809 38 audio_element = av_mallocz(sizeof(*audio_element));
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!audio_element) {
811 ret = AVERROR(ENOMEM);
812 goto fail;
813 }
814
815 38 nb_substreams = ffio_read_leb(pbc);
816 /* Each substream consumes at least one byte (its leb128 id) from the
817 * remaining OBU buffer, so a count larger than that cannot be valid and
818 * would only serve to force an oversized allocation. */
819
2/4
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
38 if (nb_substreams > len - avio_tell(pbc) || !nb_substreams) {
820 ret = AVERROR_INVALIDDATA;
821 goto fail;
822 }
823 38 audio_element->codec_config_id = codec_config_id;
824 38 audio_element->audio_element_id = audio_element_id;
825 38 audio_element->substreams = av_calloc(nb_substreams, sizeof(*audio_element->substreams));
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!audio_element->substreams) {
827 ret = AVERROR(ENOMEM);
828 goto fail;
829 }
830 38 audio_element->nb_substreams = nb_substreams;
831
832 38 element = audio_element->element = av_iamf_audio_element_alloc();
833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!element) {
834 ret = AVERROR(ENOMEM);
835 goto fail;
836 }
837 38 audio_element->celement = element;
838
839 38 element->audio_element_type = audio_element_type;
840
841
2/2
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 38 times.
208 for (int i = 0; i < audio_element->nb_substreams; i++) {
842 170 IAMFSubStream *substream = &audio_element->substreams[i];
843
844 170 substream->codecpar = avcodec_parameters_alloc();
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (!substream->codecpar) {
846 ret = AVERROR(ENOMEM);
847 goto fail;
848 }
849
850 170 substream->audio_substream_id = ffio_read_leb(pbc);
851
852 170 substream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
853 170 substream->codecpar->codec_id = codec_config->codec_id;
854 170 substream->codecpar->frame_size = codec_config->nb_samples;
855 170 substream->codecpar->sample_rate = codec_config->sample_rate;
856 170 substream->codecpar->seek_preroll = -codec_config->audio_roll_distance * codec_config->nb_samples;
857
858
1/2
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
170 switch(substream->codecpar->codec_id) {
859 170 case AV_CODEC_ID_AAC:
860 case AV_CODEC_ID_FLAC:
861 case AV_CODEC_ID_OPUS:
862 170 substream->codecpar->extradata = av_malloc(codec_config->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (!substream->codecpar->extradata) {
864 ret = AVERROR(ENOMEM);
865 goto fail;
866 }
867 170 memcpy(substream->codecpar->extradata, codec_config->extradata, codec_config->extradata_size);
868 170 memset(substream->codecpar->extradata + codec_config->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
869 170 substream->codecpar->extradata_size = codec_config->extradata_size;
870 170 break;
871 }
872 }
873
874 38 num_parameters = ffio_read_leb(pbc);
875
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 if (num_parameters > 2 && audio_element_type == 0) {
876 av_log(s, AV_LOG_ERROR, "Audio Element parameter count %u is invalid"
877 " for Channel representations\n", num_parameters);
878 ret = AVERROR_INVALIDDATA;
879 goto fail;
880 }
881
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
38 if (num_parameters && audio_element_type != 0) {
882 av_log(s, AV_LOG_ERROR, "Audio Element parameter count %u is invalid"
883 " for Scene representations\n", num_parameters);
884 ret = AVERROR_INVALIDDATA;
885 goto fail;
886 }
887
888
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 38 times.
60 for (int i = 0; i < num_parameters; i++) {
889 unsigned type;
890
891 22 type = ffio_read_leb(pbc);
892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (type == AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN)
893 ret = AVERROR_INVALIDDATA;
894
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 5 times.
22 else if (type == AV_IAMF_PARAMETER_DEFINITION_DEMIXING) {
895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (element->demixing_info) {
896 ret = AVERROR_INVALIDDATA;
897 goto fail;
898 }
899 17 ret = param_parse(s, c, pbc, type,
900 audio_element, codec_config,
901 &element->demixing_info);
902
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 } else if (type == AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) {
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (element->recon_gain_info) {
904 ret = AVERROR_INVALIDDATA;
905 goto fail;
906 }
907 5 ret = param_parse(s, c, pbc, type,
908 audio_element, codec_config,
909 &element->recon_gain_info);
910 } else {
911 unsigned param_definition_size = ffio_read_leb(pbc);
912 avio_skip(pbc, param_definition_size);
913 }
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (ret < 0)
915 goto fail;
916 }
917
918
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 11 times.
38 if (audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
919 27 ret = scalable_channel_layout_config(s, pbc, audio_element, codec_config);
920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
921 goto fail;
922
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 } else if (audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
923 11 ret = ambisonics_config(s, pbc, audio_element, codec_config);
924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
925 goto fail;
926 } else {
927 av_unreachable("audio_element_type should have been checked above");
928 }
929
930 38 c->audio_elements[c->nb_audio_elements++] = audio_element;
931
932 38 len -= avio_tell(pbc);
933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (len)
934 av_log(s, AV_LOG_WARNING, "Underread in audio_element_obu. %d bytes left at the end\n", len);
935
936 38 ret = 0;
937 38 fail:
938 38 av_free(buf);
939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (ret < 0)
940 ff_iamf_free_audio_element(&audio_element);
941 38 return ret;
942 }
943
944 114 static int label_string(AVIOContext *pb, char **label)
945 {
946 uint8_t buf[128];
947
948 114 avio_get_str(pb, sizeof(buf), buf, sizeof(buf));
949
950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (pb->error)
951 return pb->error;
952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (pb->eof_reached)
953 return AVERROR_INVALIDDATA;
954 114 *label = av_strdup(buf);
955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (!*label)
956 return AVERROR(ENOMEM);
957
958 114 return 0;
959 }
960
961 36 static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
962 {
963 AVIAMFMixPresentation *mix;
964 36 const IAMFCodecConfig *codec_config = NULL;
965 36 IAMFMixPresentation **tmp, *mix_presentation = NULL;
966 FFIOContext b;
967 AVIOContext *pbc;
968 uint8_t *buf;
969 unsigned nb_submixes, mix_presentation_id;
970 int ret;
971
972 36 buf = av_malloc(len);
973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!buf)
974 return AVERROR(ENOMEM);
975
976 36 ret = ffio_read_size(pb, buf, len);
977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
978 goto fail;
979
980 36 ffio_init_context(&b, buf, len, 0, NULL, NULL, NULL, NULL);
981 36 pbc = &b.pub;
982
983 36 mix_presentation_id = ffio_read_leb(pbc);
984
985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 for (int i = 0; i < c->nb_mix_presentations; i++)
986 if (c->mix_presentations[i]->mix_presentation_id == mix_presentation_id) {
987 av_log(s, AV_LOG_ERROR, "Duplicate mix_presentation_id %d\n", mix_presentation_id);
988 ret = AVERROR_INVALIDDATA;
989 goto fail;
990 }
991
992 36 tmp = av_realloc_array(c->mix_presentations, c->nb_mix_presentations + 1, sizeof(*c->mix_presentations));
993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!tmp) {
994 ret = AVERROR(ENOMEM);
995 goto fail;
996 }
997 36 c->mix_presentations = tmp;
998
999 36 mix_presentation = av_mallocz(sizeof(*mix_presentation));
1000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!mix_presentation) {
1001 ret = AVERROR(ENOMEM);
1002 goto fail;
1003 }
1004
1005 36 mix_presentation->mix_presentation_id = mix_presentation_id;
1006 36 mix = mix_presentation->mix = av_iamf_mix_presentation_alloc();
1007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!mix) {
1008 ret = AVERROR(ENOMEM);
1009 goto fail;
1010 }
1011 36 mix_presentation->cmix = mix;
1012
1013 36 mix_presentation->count_label = ffio_read_leb(pbc);
1014
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (mix_presentation->count_label > len - avio_tell(pbc)) {
1015 mix_presentation->count_label = 0;
1016 ret = AVERROR_INVALIDDATA;
1017 goto fail;
1018 }
1019 36 mix_presentation->language_label = av_calloc(mix_presentation->count_label,
1020 sizeof(*mix_presentation->language_label));
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!mix_presentation->language_label) {
1022 mix_presentation->count_label = 0;
1023 ret = AVERROR(ENOMEM);
1024 goto fail;
1025 }
1026
1027
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 for (int i = 0; i < mix_presentation->count_label; i++) {
1028 36 ret = label_string(pbc, &mix_presentation->language_label[i]);
1029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
1030 goto fail;
1031 }
1032
1033
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 for (int i = 0; i < mix_presentation->count_label; i++) {
1034 36 char *annotation = NULL;
1035 36 ret = label_string(pbc, &annotation);
1036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
1037 goto fail;
1038 36 ret = av_dict_set(&mix->annotations, mix_presentation->language_label[i], annotation,
1039 AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
1040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
1041 goto fail;
1042 }
1043
1044 36 nb_submixes = ffio_read_leb(pbc);
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!nb_submixes) {
1046 av_log(s, AV_LOG_ERROR, "Mix presentation %u has no submixes\n", mix_presentation_id);
1047 ret = AVERROR_INVALIDDATA;
1048 goto fail;
1049 }
1050
1051
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 36 times.
76 for (int i = 0; i < nb_submixes; i++) {
1052 AVIAMFSubmix *sub_mix;
1053 unsigned nb_elements, nb_layouts;
1054
1055 40 sub_mix = av_iamf_mix_presentation_add_submix(mix);
1056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!sub_mix) {
1057 ret = AVERROR(ENOMEM);
1058 goto fail;
1059 }
1060
1061 40 nb_elements = ffio_read_leb(pbc);
1062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!nb_elements) {
1063 av_log(s, AV_LOG_ERROR, "Submix %d from Mix presentation %u has no audio elements\n",
1064 i, mix_presentation_id);
1065 ret = AVERROR_INVALIDDATA;
1066 goto fail;
1067 }
1068
1069
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 40 times.
82 for (int j = 0; j < nb_elements; j++) {
1070 AVIAMFSubmixElement *submix_element;
1071 42 IAMFAudioElement *audio_element = NULL;
1072 42 const IAMFCodecConfig *config = NULL;
1073 unsigned int rendering_config_extension_size;
1074
1075 42 submix_element = av_iamf_submix_add_element(sub_mix);
1076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!submix_element) {
1077 ret = AVERROR(ENOMEM);
1078 goto fail;
1079 }
1080
1081 42 submix_element->audio_element_id = ffio_read_leb(pbc);
1082
1083
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 for (int k = 0; k < c->nb_audio_elements; k++)
1084
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 2 times.
44 if (c->audio_elements[k]->audio_element_id == submix_element->audio_element_id) {
1085 42 audio_element = c->audio_elements[k];
1086 42 break;
1087 }
1088
1089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!audio_element) {
1090 av_log(s, AV_LOG_ERROR, "Invalid Audio Element with id %u referenced by Mix Parameters %u\n",
1091 submix_element->audio_element_id, mix_presentation_id);
1092 ret = AVERROR_INVALIDDATA;
1093 goto fail;
1094 }
1095 42 config = ff_iamf_get_codec_config(c, audio_element->codec_config_id);
1096
1097
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 42 times.
84 for (int k = 0; k < mix_presentation->count_label; k++) {
1098 42 char *annotation = NULL;
1099 42 ret = label_string(pbc, &annotation);
1100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
1101 goto fail;
1102 42 ret = av_dict_set(&submix_element->annotations, mix_presentation->language_label[k], annotation,
1103 AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
1104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
1105 goto fail;
1106 }
1107
1108 42 submix_element->headphones_rendering_mode = avio_r8(pbc) >> 6;
1109
1110 42 rendering_config_extension_size = ffio_read_leb(pbc);
1111 42 avio_skip(pbc, rendering_config_extension_size);
1112
1113 42 ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
1114 audio_element, config,
1115 &submix_element->element_mix_config);
1116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
1117 goto fail;
1118 42 submix_element->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
1119
1120
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
42 if (!codec_config || (config->nb_samples >
1121 6 av_rescale(codec_config->nb_samples,
1122 6 codec_config->sample_rate,
1123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 config->sample_rate)))
1124 36 codec_config = config;
1125 }
1126
1127 40 ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
1128 NULL, codec_config,
1129 &sub_mix->output_mix_config);
1130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (ret < 0)
1131 goto fail;
1132 40 sub_mix->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
1133
1134 40 nb_layouts = ffio_read_leb(pbc);
1135
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 40 times.
123 for (int j = 0; j < nb_layouts; j++) {
1136 AVIAMFSubmixLayout *submix_layout;
1137 int info_type;
1138 83 int byte = avio_r8(pbc);
1139
1140 83 submix_layout = av_iamf_submix_add_layout(sub_mix);
1141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (!submix_layout) {
1142 ret = AVERROR(ENOMEM);
1143 goto fail;
1144 }
1145
1146 83 submix_layout->layout_type = byte >> 6;
1147
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 if (submix_layout->layout_type < AV_IAMF_SUBMIX_LAYOUT_TYPE_LOUDSPEAKERS ||
1148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 submix_layout->layout_type > AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL) {
1149 av_log(s, AV_LOG_ERROR, "Invalid Layout type %u in a submix from Mix Presentation %u\n",
1150 submix_layout->layout_type, mix_presentation_id);
1151 ret = AVERROR_INVALIDDATA;
1152 goto fail;
1153 }
1154
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 4 times.
83 if (submix_layout->layout_type == 2) {
1155 int sound_system;
1156 79 sound_system = (byte >> 2) & 0xF;
1157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (sound_system >= FF_ARRAY_ELEMS(ff_iamf_sound_system_map)) {
1158 ret = AVERROR_INVALIDDATA;
1159 goto fail;
1160 }
1161 79 av_channel_layout_copy(&submix_layout->sound_system, &ff_iamf_sound_system_map[sound_system].layout);
1162 } else
1163 4 submix_layout->sound_system = (AVChannelLayout)AV_CHANNEL_LAYOUT_BINAURAL;
1164
1165 83 info_type = avio_r8(pbc);
1166 83 submix_layout->integrated_loudness = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
1167 83 submix_layout->digital_peak = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
1168
1169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (info_type & 1)
1170 submix_layout->true_peak = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
1171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (info_type & 2) {
1172 unsigned int num_anchored_loudness = avio_r8(pbc);
1173
1174 for (int k = 0; k < num_anchored_loudness; k++) {
1175 unsigned int anchor_element = avio_r8(pbc);
1176 AVRational anchored_loudness = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
1177 if (anchor_element == IAMF_ANCHOR_ELEMENT_DIALOGUE)
1178 submix_layout->dialogue_anchored_loudness = anchored_loudness;
1179 else if (anchor_element <= IAMF_ANCHOR_ELEMENT_ALBUM)
1180 submix_layout->album_anchored_loudness = anchored_loudness;
1181 else
1182 av_log(s, AV_LOG_DEBUG, "Unknown anchor_element. Ignoring\n");
1183 }
1184 }
1185
1186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (info_type & 0xFC) {
1187 unsigned int info_type_size = ffio_read_leb(pbc);
1188 avio_skip(pbc, info_type_size);
1189 }
1190 }
1191 }
1192
1193 36 c->mix_presentations[c->nb_mix_presentations++] = mix_presentation;
1194
1195 36 len -= avio_tell(pbc);
1196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (len)
1197 av_log(s, AV_LOG_WARNING, "Underread in mix_presentation_obu. %d bytes left at the end\n", len);
1198
1199 36 ret = 0;
1200 36 fail:
1201 36 av_free(buf);
1202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (ret < 0)
1203 ff_iamf_free_mix_presentation(&mix_presentation);
1204 36 return ret;
1205 }
1206
1207 10118 int ff_iamf_parse_obu_header(const uint8_t *buf, int buf_size,
1208 unsigned *obu_size, int *start_pos, enum IAMF_OBU_Type *type,
1209 unsigned *skip_samples, unsigned *discard_padding)
1210 {
1211 GetBitContext gb;
1212 int ret, extension_flag, trimming, start;
1213 10118 unsigned skip = 0, discard = 0;
1214 unsigned size;
1215
1216 10118 ret = init_get_bits8(&gb, buf, FFMIN(buf_size, MAX_IAMF_OBU_HEADER_SIZE));
1217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10118 times.
10118 if (ret < 0)
1218 return ret;
1219
1220 10118 *type = get_bits(&gb, 5);
1221 10118 /*redundant =*/ get_bits1(&gb);
1222 10118 trimming = get_bits1(&gb);
1223 10118 extension_flag = get_bits1(&gb);
1224
1225 10118 *obu_size = get_leb(&gb);
1226
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10109 times.
10118 if (*obu_size > INT_MAX)
1227 9 return AVERROR_INVALIDDATA;
1228
1229 10109 start = get_bits_count(&gb) / 8;
1230
1231
2/2
✓ Branch 0 taken 2628 times.
✓ Branch 1 taken 7481 times.
10109 if (trimming) {
1232 2628 discard = get_leb(&gb); // num_samples_to_trim_at_end
1233 2628 skip = get_leb(&gb); // num_samples_to_trim_at_start
1234 }
1235
1236
2/2
✓ Branch 0 taken 2063 times.
✓ Branch 1 taken 8046 times.
10109 if (skip_samples)
1237 2063 *skip_samples = skip;
1238
2/2
✓ Branch 0 taken 2063 times.
✓ Branch 1 taken 8046 times.
10109 if (discard_padding)
1239 2063 *discard_padding = discard;
1240
1241
2/2
✓ Branch 0 taken 828 times.
✓ Branch 1 taken 9281 times.
10109 if (extension_flag) {
1242 unsigned int extension_bytes;
1243 828 extension_bytes = get_leb(&gb);
1244
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 806 times.
828 if (extension_bytes > INT_MAX / 8)
1245 22 return AVERROR_INVALIDDATA;
1246 806 skip_bits_long(&gb, extension_bytes * 8);
1247 }
1248
1249
2/2
✓ Branch 1 taken 555 times.
✓ Branch 2 taken 9532 times.
10087 if (get_bits_left(&gb) < 0)
1250 555 return AVERROR_INVALIDDATA;
1251
1252 9532 size = *obu_size + start;
1253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9532 times.
9532 if (size > INT_MAX)
1254 return AVERROR_INVALIDDATA;
1255
1256 9532 *obu_size -= get_bits_count(&gb) / 8 - start;
1257 9532 *start_pos = size - *obu_size;
1258
1259 9532 return size;
1260 }
1261
1262 36 int ff_iamfdec_read_descriptors(IAMFContext *c, AVIOContext *pb,
1263 int max_size, void *log_ctx)
1264 {
1265 uint8_t header[MAX_IAMF_OBU_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
1266 int ret;
1267
1268 134 while (1) {
1269 unsigned obu_size;
1270 enum IAMF_OBU_Type type;
1271 int start_pos, len, size;
1272
1273
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
170 if ((ret = ffio_ensure_seekback(pb, FFMIN(MAX_IAMF_OBU_HEADER_SIZE, max_size))) < 0)
1274 return ret;
1275 170 size = avio_read(pb, header, FFMIN(MAX_IAMF_OBU_HEADER_SIZE, max_size));
1276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 if (size < 0)
1277 return size;
1278 170 memset(header + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1279
1280 170 len = ff_iamf_parse_obu_header(header, size, &obu_size, &start_pos, &type, NULL, NULL);
1281
2/4
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 170 times.
170 if (len < 0 || obu_size > max_size) {
1282 av_log(log_ctx, AV_LOG_ERROR, "Failed to read obu header\n");
1283 avio_seek(pb, -size, SEEK_CUR);
1284 return len;
1285 }
1286
1287
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 110 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 36 times.
170 if (type >= IAMF_OBU_IA_PARAMETER_BLOCK && type < IAMF_OBU_IA_SEQUENCE_HEADER) {
1288 24 avio_seek(pb, -size, SEEK_CUR);
1289 24 break;
1290 }
1291
1292 146 avio_seek(pb, -(size - start_pos), SEEK_CUR);
1293
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 36 times.
146 switch (type) {
1294 36 case IAMF_OBU_IA_CODEC_CONFIG:
1295 36 ret = codec_config_obu(log_ctx, c, pb, obu_size);
1296 36 break;
1297 38 case IAMF_OBU_IA_AUDIO_ELEMENT:
1298 38 ret = audio_element_obu(log_ctx, c, pb, obu_size);
1299 38 break;
1300 36 case IAMF_OBU_IA_MIX_PRESENTATION:
1301 36 ret = mix_presentation_obu(log_ctx, c, pb, obu_size);
1302 36 break;
1303 36 default: {
1304 36 int64_t offset = avio_skip(pb, obu_size);
1305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (offset < 0)
1306 ret = offset;
1307 36 break;
1308 }
1309 }
1310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (ret < 0) {
1311 av_log(log_ctx, AV_LOG_ERROR, "Failed to read obu type %d\n", type);
1312 return ret;
1313 }
1314 146 max_size -= obu_size + start_pos;
1315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (max_size < 0)
1316 return AVERROR_INVALIDDATA;
1317
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 134 times.
146 if (!max_size)
1318 12 break;
1319 }
1320
1321 36 return 0;
1322 }
1323