FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/iamf_parse.c
Date: 2026-11-04 10:59:43
Exec Total Coverage
Lines: 622 854 72.8%
Functions: 16 16 100.0%
Branches: 301 493 61.1%

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