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