FFmpeg
iamf_writer.c
Go to the documentation of this file.
1 /*
2  * Immersive Audio Model and Formats muxing helpers and structs
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/bprint.h"
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/iamf.h"
26 #include "libavutil/mem.h"
27 #include "libavcodec/get_bits.h"
28 #include "libavcodec/put_bits.h"
29 #include "avformat.h"
30 #include "avio_internal.h"
31 #include "iamf.h"
32 #include "iamf_writer.h"
33 
34 
35 static int update_extradata(IAMFCodecConfig *codec_config)
36 {
37  GetBitContext gb;
38  PutBitContext pb;
39  int ret;
40 
41  switch(codec_config->codec_id) {
42  case AV_CODEC_ID_OPUS:
43  if (codec_config->extradata_size != 19)
44  return AVERROR_INVALIDDATA;
45  codec_config->extradata_size -= 8;
46  AV_WB8(codec_config->extradata + 0, AV_RL8(codec_config->extradata + 8)); // version
47  AV_WB8(codec_config->extradata + 1, 2); // set channels to stereo
48  AV_WB16A(codec_config->extradata + 2, AV_RL16A(codec_config->extradata + 10)); // Byte swap pre-skip
49  AV_WB32A(codec_config->extradata + 4, AV_RL32A(codec_config->extradata + 12)); // Byte swap sample rate
50  AV_WB16A(codec_config->extradata + 8, 0); // set Output Gain to 0
51  AV_WB8(codec_config->extradata + 10, AV_RL8(codec_config->extradata + 18)); // Mapping family
52  break;
53  case AV_CODEC_ID_FLAC: {
54  uint8_t buf[13];
55 
56  init_put_bits(&pb, buf, sizeof(buf));
57  ret = init_get_bits8(&gb, codec_config->extradata, codec_config->extradata_size);
58  if (ret < 0)
59  return ret;
60 
61  put_bits32(&pb, get_bits_long(&gb, 32)); // min/max blocksize
62  put_bits63(&pb, 48, get_bits64(&gb, 48)); // min/max framesize
63  put_bits(&pb, 20, get_bits(&gb, 20)); // samplerate
64  skip_bits(&gb, 3);
65  put_bits(&pb, 3, 1); // set channels to stereo
66  ret = put_bits_left(&pb);
67  put_bits(&pb, ret, get_bits(&gb, ret));
68  flush_put_bits(&pb);
69 
70  memcpy(codec_config->extradata, buf, sizeof(buf));
71  break;
72  }
73  default:
74  break;
75  }
76 
77  return 0;
78 }
79 
81 {
82  switch (codec_config->codec_id) {
83  case AV_CODEC_ID_OPUS:
84  if (!codec_config->nb_samples)
85  return AVERROR(EINVAL);
86  // ceil(3840 / nb_samples)
87  codec_config->audio_roll_distance = -(1 + ((3840 - 1) / codec_config->nb_samples));
88  break;
89  case AV_CODEC_ID_AAC:
90  codec_config->audio_roll_distance = -1;
91  break;
92  case AV_CODEC_ID_FLAC:
99  codec_config->audio_roll_distance = 0;
100  break;
101  default:
102  return AVERROR(EINVAL);
103  }
104 
105  return 0;
106 }
107 
108 static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
109  IAMFCodecConfig *codec_config)
110 {
111  const AVStream *st = stg->streams[0];
113  int j, ret = 0;
114 
115  codec_config->codec_id = st->codecpar->codec_id;
116  codec_config->codec_tag = st->codecpar->codec_tag;
117  switch (codec_config->codec_id) {
118  case AV_CODEC_ID_OPUS:
119  codec_config->sample_rate = 48000;
120  codec_config->nb_samples = av_rescale(st->codecpar->frame_size, 48000, st->codecpar->sample_rate);
121  break;
122  default:
123  codec_config->sample_rate = st->codecpar->sample_rate;
124  codec_config->nb_samples = st->codecpar->frame_size;
125  break;
126  }
127  populate_audio_roll_distance(codec_config);
128  if (st->codecpar->extradata_size) {
130  return AVERROR_INVALIDDATA;
131 
133  if (!codec_config->extradata)
134  return AVERROR(ENOMEM);
135  memcpy(codec_config->extradata, st->codecpar->extradata, st->codecpar->extradata_size);
136  memset(codec_config->extradata + st->codecpar->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
137  codec_config->extradata_size = st->codecpar->extradata_size;
138  ret = update_extradata(codec_config);
139  if (ret < 0)
140  goto fail;
141  }
142 
143  for (j = 0; j < iamf->nb_codec_configs; j++) {
144  if (!memcmp(iamf->codec_configs[j], codec_config, offsetof(IAMFCodecConfig, extradata)) &&
145  (!codec_config->extradata_size || !memcmp(iamf->codec_configs[j]->extradata,
146  codec_config->extradata, codec_config->extradata_size)))
147  break;
148  }
149 
150  if (j < iamf->nb_codec_configs) {
151  av_free(iamf->codec_configs[j]->extradata);
152  av_free(iamf->codec_configs[j]);
153  iamf->codec_configs[j] = codec_config;
154  return j;
155  }
156 
157  tmp = av_realloc_array(iamf->codec_configs, iamf->nb_codec_configs + 1, sizeof(*iamf->codec_configs));
158  if (!tmp) {
159  ret = AVERROR(ENOMEM);
160  goto fail;
161  }
162 
163  iamf->codec_configs = tmp;
164  iamf->codec_configs[iamf->nb_codec_configs] = codec_config;
165  codec_config->codec_config_id = iamf->nb_codec_configs;
166 
167  return iamf->nb_codec_configs++;
168 
169 fail:
170  av_freep(&codec_config->extradata);
171  return ret;
172 }
173 
175  const IAMFAudioElement *audio_element, void *log_ctx)
176 {
178  IAMFCodecConfig *codec_config = NULL;
179 
181  sizeof(*iamf->param_definitions));
182  if (!tmp)
183  return AVERROR(ENOMEM);
184 
185  iamf->param_definitions = tmp;
186 
187  if (audio_element)
188  codec_config = iamf->codec_configs[audio_element->codec_config_id];
189 
190  if (!param->parameter_rate) {
191  if (!codec_config) {
192  av_log(log_ctx, AV_LOG_ERROR, "parameter_rate needed but not set for parameter_id %u\n",
193  param->parameter_id);
194  return AVERROR(EINVAL);
195  }
196  param->parameter_rate = codec_config->sample_rate;
197  }
198  if (codec_config) {
199  if (!param->duration)
200  param->duration = av_rescale(codec_config->nb_samples, param->parameter_rate, codec_config->sample_rate);
201  if (!param->constant_subblock_duration)
202  param->constant_subblock_duration = av_rescale(codec_config->nb_samples, param->parameter_rate, codec_config->sample_rate);
203  }
204 
206  if (!param_definition)
207  return AVERROR(ENOMEM);
208 
209  param_definition->mode = !!param->duration;
210  param_definition->param = param;
211  param_definition->audio_element = audio_element;
213 
214  return 0;
215 }
216 
217 int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
218 {
219  const AVIAMFAudioElement *iamf_audio_element;
220  IAMFAudioElement **tmp, *audio_element;
221  IAMFCodecConfig *codec_config;
222  int ret;
223 
225  return AVERROR(EINVAL);
226  if (!stg->nb_streams) {
227  av_log(log_ctx, AV_LOG_ERROR, "Audio Element id %"PRId64" has no streams\n", stg->id);
228  return AVERROR(EINVAL);
229  }
230 
231  iamf_audio_element = stg->params.iamf_audio_element;
232  if (iamf_audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
233  const AVIAMFLayer *layer = iamf_audio_element->layers[0];
234  if (iamf_audio_element->nb_layers != 1) {
235  av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of layers for SCENE_BASED audio element. Must be 1\n");
236  return AVERROR(EINVAL);
237  }
238  if (layer->ch_layout.order != AV_CHANNEL_ORDER_CUSTOM &&
240  av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout for SCENE_BASED audio element\n");
241  return AVERROR(EINVAL);
242  }
244  av_log(log_ctx, AV_LOG_ERROR, "Unsupported ambisonics mode %d\n", layer->ambisonics_mode);
245  return AVERROR_PATCHWELCOME;
246  }
247  for (int i = 0; i < stg->nb_streams; i++) {
248  if (stg->streams[i]->codecpar->ch_layout.nb_channels > 1) {
249  av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of channels in a stream for MONO mode ambisonics\n");
250  return AVERROR(EINVAL);
251  }
252  }
253  } else {
254  AVBPrint bp;
255 
256  if (iamf_audio_element->nb_layers < 1) {
257  av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of layers for CHANNEL_BASED audio element. Must be >= 1\n");
258  return AVERROR(EINVAL);
259  }
260 
261  for (int j, i = 0; i < iamf_audio_element->nb_layers; i++) {
262  const AVIAMFLayer *layer = iamf_audio_element->layers[i];
263 
264  for (j = 0; j < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts); j++)
265  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
267  break;
268 
271  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
273  break;
274 
278  av_log(log_ctx, AV_LOG_ERROR, "Unsupported channel layout in Audio Element id %"PRId64
279  ", Layer %d: %s\n",
280  stg->id, i, bp.str);
281  av_bprint_finalize(&bp, NULL);
282  return AVERROR(EINVAL);
283  }
284  }
285 
286  if (!i)
287  continue;
288 
289  const AVIAMFLayer *prev_layer = iamf_audio_element->layers[i-1];
290  uint64_t prev_mask = av_channel_layout_subset(&prev_layer->ch_layout, UINT64_MAX);
291  if (av_channel_layout_subset(&layer->ch_layout, prev_mask) != prev_mask || (layer->ch_layout.nb_channels <=
292  prev_layer->ch_layout.nb_channels)) {
294  av_bprintf(&bp, "Channel layout \"");
296  av_bprintf(&bp, "\" can't follow channel layout \"");
297  av_channel_layout_describe_bprint(&prev_layer->ch_layout, &bp);
298  av_bprintf(&bp, "\" in Scalable Audio Element id %"PRId64, stg->id);
299  av_log(log_ctx, AV_LOG_ERROR, "%s\n", bp.str);
300  av_bprint_finalize(&bp, NULL);
301  return AVERROR(EINVAL);
302  }
303  }
304  }
305 
306  for (int i = 0; i < iamf->nb_audio_elements; i++) {
307  if (stg->id == iamf->audio_elements[i]->audio_element_id) {
308  av_log(log_ctx, AV_LOG_ERROR, "Duplicated Audio Element id %"PRId64"\n", stg->id);
309  return AVERROR(EINVAL);
310  }
311  }
312 
313  codec_config = av_mallocz(sizeof(*codec_config));
314  if (!codec_config)
315  return AVERROR(ENOMEM);
316 
317  ret = fill_codec_config(iamf, stg, codec_config);
318  if (ret < 0) {
319  av_free(codec_config);
320  return ret;
321  }
322 
323  audio_element = av_mallocz(sizeof(*audio_element));
324  if (!audio_element)
325  return AVERROR(ENOMEM);
326 
327  audio_element->celement = stg->params.iamf_audio_element;
328  audio_element->audio_element_id = stg->id;
329  audio_element->codec_config_id = ret;
330 
331  audio_element->substreams = av_calloc(stg->nb_streams, sizeof(*audio_element->substreams));
332  if (!audio_element->substreams) {
333  ret = AVERROR(ENOMEM);
334  goto fail;
335  }
336  audio_element->nb_substreams = stg->nb_streams;
337 
338  audio_element->layers = av_calloc(iamf_audio_element->nb_layers, sizeof(*audio_element->layers));
339  if (!audio_element->layers) {
340  ret = AVERROR(ENOMEM);
341  goto fail;
342  }
343 
344  for (int i = 0, j = 0; i < iamf_audio_element->nb_layers; i++) {
345  int nb_channels = iamf_audio_element->layers[i]->ch_layout.nb_channels;
346 
347  IAMFLayer *layer = &audio_element->layers[i];
348 
349  if (i)
350  nb_channels -= iamf_audio_element->layers[i - 1]->ch_layout.nb_channels;
351  for (; nb_channels > 0 && j < stg->nb_streams; j++) {
352  const AVStream *st = stg->streams[j];
353  IAMFSubStream *substream = &audio_element->substreams[j];
354 
355  substream->audio_substream_id = st->id;
356  layer->substream_count++;
358  nb_channels -= st->codecpar->ch_layout.nb_channels;
359  }
360  if (nb_channels) {
361  av_log(log_ctx, AV_LOG_ERROR, "Invalid channel count across substreams in layer %u from stream group %u\n",
362  i, stg->index);
363  ret = AVERROR(EINVAL);
364  goto fail;
365  }
366  }
367 
368  for (int i = 0; i < audio_element->nb_substreams; i++) {
369  for (int j = i + 1; j < audio_element->nb_substreams; j++)
370  if (audio_element->substreams[i].audio_substream_id ==
371  audio_element->substreams[j].audio_substream_id) {
372  av_log(log_ctx, AV_LOG_ERROR, "Duplicate id %u in streams %u and %u from stream group %u\n",
373  audio_element->substreams[i].audio_substream_id, i, j, stg->index);
374  ret = AVERROR(EINVAL);
375  goto fail;
376  }
377  }
378 
379  if (iamf_audio_element->demixing_info) {
380  AVIAMFParamDefinition *param = iamf_audio_element->demixing_info;
382 
383  if (param->nb_subblocks != 1) {
384  av_log(log_ctx, AV_LOG_ERROR, "nb_subblocks in demixing_info for stream group %u is not 1\n", stg->index);
385  ret = AVERROR(EINVAL);
386  goto fail;
387  }
388 
389  if (!param_definition) {
390  ret = add_param_definition(iamf, param, audio_element, log_ctx);
391  if (ret < 0)
392  goto fail;
393  }
394  }
395  if (iamf_audio_element->recon_gain_info) {
396  AVIAMFParamDefinition *param = iamf_audio_element->recon_gain_info;
398 
399  if (param->nb_subblocks != 1) {
400  av_log(log_ctx, AV_LOG_ERROR, "nb_subblocks in recon_gain_info for stream group %u is not 1\n", stg->index);
401  ret = AVERROR(EINVAL);
402  goto fail;
403  }
404 
405  if (!param_definition) {
406  ret = add_param_definition(iamf, param, audio_element, log_ctx);
407  if (ret < 0)
408  goto fail;
409  }
410  }
411 
412  tmp = av_realloc_array(iamf->audio_elements, iamf->nb_audio_elements + 1, sizeof(*iamf->audio_elements));
413  if (!tmp) {
414  ret = AVERROR(ENOMEM);
415  goto fail;
416  }
417 
418  iamf->audio_elements = tmp;
419  iamf->audio_elements[iamf->nb_audio_elements++] = audio_element;
420 
421  return 0;
422 fail:
423  ff_iamf_free_audio_element(&audio_element);
424  return ret;
425 }
426 
427 int ff_iamf_add_mix_presentation(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
428 {
429  IAMFMixPresentation **tmp, *mix_presentation;
430  int ret;
431 
433  return AVERROR(EINVAL);
434  if (!stg->nb_streams) {
435  av_log(log_ctx, AV_LOG_ERROR, "Mix Presentation id %"PRId64" has no streams\n", stg->id);
436  return AVERROR(EINVAL);
437  }
438 
439  for (int i = 0; i < iamf->nb_mix_presentations; i++) {
440  if (stg->id == iamf->mix_presentations[i]->mix_presentation_id) {
441  av_log(log_ctx, AV_LOG_ERROR, "Duplicate Mix Presentation id %"PRId64"\n", stg->id);
442  return AVERROR(EINVAL);
443  }
444  }
445 
446  mix_presentation = av_mallocz(sizeof(*mix_presentation));
447  if (!mix_presentation)
448  return AVERROR(ENOMEM);
449 
450  mix_presentation->cmix = stg->params.iamf_mix_presentation;
451  mix_presentation->mix_presentation_id = stg->id;
452 
453  for (int i = 0; i < mix_presentation->cmix->nb_submixes; i++) {
454  const AVIAMFSubmix *submix = mix_presentation->cmix->submixes[i];
455  AVIAMFParamDefinition *param = submix->output_mix_config;
457 
458  if (!param) {
459  av_log(log_ctx, AV_LOG_ERROR, "output_mix_config is not present in submix %u from "
460  "Mix Presentation ID %"PRId64"\n", i, stg->id);
461  ret = AVERROR(EINVAL);
462  goto fail;
463  }
464 
466  if (!param_definition) {
467  ret = add_param_definition(iamf, param, NULL, log_ctx);
468  if (ret < 0)
469  goto fail;
470  }
471 
472  for (int j = 0; j < submix->nb_elements; j++) {
473  const AVIAMFSubmixElement *element = submix->elements[j];
474  param = element->element_mix_config;
475 
476  if (!param) {
477  av_log(log_ctx, AV_LOG_ERROR, "element_mix_config is not present for element %u in submix %u from "
478  "Mix Presentation ID %"PRId64"\n", j, i, stg->id);
479  ret = AVERROR(EINVAL);
480  goto fail;
481  }
483  if (!param_definition) {
484  ret = add_param_definition(iamf, param, NULL, log_ctx);
485  if (ret < 0)
486  goto fail;
487  }
488  }
489  }
490 
492  if (!tmp) {
493  ret = AVERROR(ENOMEM);
494  goto fail;
495  }
496 
497  iamf->mix_presentations = tmp;
498  iamf->mix_presentations[iamf->nb_mix_presentations++] = mix_presentation;
499 
500  return 0;
501 fail:
502  ff_iamf_free_mix_presentation(&mix_presentation);
503  return ret;
504 }
505 
506 static int iamf_write_codec_config(const IAMFContext *iamf,
507  const IAMFCodecConfig *codec_config,
508  AVIOContext *pb)
509 {
511  AVIOContext *dyn_bc;
512  uint8_t *dyn_buf = NULL;
513  PutBitContext pbc;
514  int dyn_size;
515 
516  int ret = avio_open_dyn_buf(&dyn_bc);
517  if (ret < 0)
518  return ret;
519 
520  ffio_write_leb(dyn_bc, codec_config->codec_config_id);
521  avio_wl32(dyn_bc, codec_config->codec_tag);
522 
523  ffio_write_leb(dyn_bc, codec_config->nb_samples);
524  avio_wb16(dyn_bc, codec_config->audio_roll_distance);
525 
526  switch(codec_config->codec_id) {
527  case AV_CODEC_ID_OPUS:
528  avio_write(dyn_bc, codec_config->extradata, codec_config->extradata_size);
529  break;
530  case AV_CODEC_ID_AAC:
531  return AVERROR_PATCHWELCOME;
532  case AV_CODEC_ID_FLAC:
533  avio_w8(dyn_bc, 0x80);
534  avio_wb24(dyn_bc, codec_config->extradata_size);
535  avio_write(dyn_bc, codec_config->extradata, codec_config->extradata_size);
536  break;
538  avio_w8(dyn_bc, 1);
539  avio_w8(dyn_bc, 16);
540  avio_wb32(dyn_bc, codec_config->sample_rate);
541  break;
543  avio_w8(dyn_bc, 1);
544  avio_w8(dyn_bc, 24);
545  avio_wb32(dyn_bc, codec_config->sample_rate);
546  break;
548  avio_w8(dyn_bc, 1);
549  avio_w8(dyn_bc, 32);
550  avio_wb32(dyn_bc, codec_config->sample_rate);
551  break;
553  avio_w8(dyn_bc, 0);
554  avio_w8(dyn_bc, 16);
555  avio_wb32(dyn_bc, codec_config->sample_rate);
556  break;
558  avio_w8(dyn_bc, 0);
559  avio_w8(dyn_bc, 24);
560  avio_wb32(dyn_bc, codec_config->sample_rate);
561  break;
563  avio_w8(dyn_bc, 0);
564  avio_w8(dyn_bc, 32);
565  avio_wb32(dyn_bc, codec_config->sample_rate);
566  break;
567  default:
568  break;
569  }
570 
571  init_put_bits(&pbc, header, sizeof(header));
573  put_bits(&pbc, 3, 0);
574  flush_put_bits(&pbc);
575 
576  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
577  avio_write(pb, header, put_bytes_count(&pbc, 1));
578  ffio_write_leb(pb, dyn_size);
579  avio_write(pb, dyn_buf, dyn_size);
580  ffio_free_dyn_buf(&dyn_bc);
581 
582  return 0;
583 }
584 
585 static inline int rescale_rational(AVRational q, int b)
586 {
587  return av_clip_int16(av_rescale(q.num, b, q.den));
588 }
589 
590 static void get_loudspeaker_layout(const AVIAMFLayer *layer,
591  int *playout, int *pexpanded_layout)
592 {
593  int layout, expanded_layout = -1;
594 
597  break;
598  }
601  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
603  break;
604  }
606  layout = 15;
607  for (expanded_layout = 0; expanded_layout < FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts); expanded_layout++) {
609  break;
610  }
611  if (expanded_layout >= FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts)) {
612  for (expanded_layout = 0; expanded_layout < FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts); expanded_layout++)
613  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
614  av_channel_layout_subset(&ff_iamf_expanded_scalable_ch_layouts[expanded_layout], UINT64_MAX))
615  break;
616  }
617  }
618  av_assert0((expanded_layout > 0 && expanded_layout < FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts)) ||
620 
621  *playout = layout;
622  *pexpanded_layout = expanded_layout;
623 }
624 
625 static int scalable_channel_layout_config(const IAMFAudioElement *audio_element,
626  AVIOContext *dyn_bc)
627 {
628  const AVIAMFAudioElement *element = audio_element->celement;
630  PutBitContext pb;
631 
632  init_put_bits(&pb, header, sizeof(header));
633  put_bits(&pb, 3, element->nb_layers);
634  put_bits(&pb, 5, 0);
635  flush_put_bits(&pb);
636  avio_write(dyn_bc, header, put_bytes_count(&pb, 1));
637  for (int i = 0; i < element->nb_layers; i++) {
638  const AVIAMFLayer *layer = element->layers[i];
639  int layout, expanded_layout;
640 
641  get_loudspeaker_layout(layer, &layout, &expanded_layout);
642  init_put_bits(&pb, header, sizeof(header));
643  put_bits(&pb, 4, layout);
644  put_bits(&pb, 1, !!layer->output_gain_flags);
645  put_bits(&pb, 1, !!(layer->flags & AV_IAMF_LAYER_FLAG_RECON_GAIN));
646  put_bits(&pb, 2, 0); // reserved
647  put_bits(&pb, 8, audio_element->layers[i].substream_count);
648  put_bits(&pb, 8, audio_element->layers[i].coupled_substream_count);
649  if (layer->output_gain_flags) {
650  put_bits(&pb, 6, layer->output_gain_flags);
651  put_bits(&pb, 2, 0);
652  put_bits(&pb, 16, rescale_rational(layer->output_gain, 1 << 8));
653  }
654  if (expanded_layout >= 0)
655  put_bits(&pb, 8, expanded_layout);
656  flush_put_bits(&pb);
657  avio_write(dyn_bc, header, put_bytes_count(&pb, 1));
658  }
659 
660  return 0;
661 }
662 
663 static int ambisonics_config(const IAMFAudioElement *audio_element,
664  AVIOContext *dyn_bc)
665 {
666  const AVIAMFAudioElement *element = audio_element->celement;
667  const IAMFLayer *ilayer = &audio_element->layers[0];
668  const AVIAMFLayer *layer = element->layers[0];
669 
670  if (audio_element->nb_substreams != ilayer->substream_count)
671  return AVERROR(EINVAL);
672 
673  ffio_write_leb(dyn_bc, layer->ambisonics_mode);
674  avio_w8(dyn_bc, layer->ch_layout.nb_channels); // output_channel_count
675  avio_w8(dyn_bc, audio_element->nb_substreams); // substream_count
676 
679  for (int i = 0; i < layer->ch_layout.nb_channels; i++)
680  avio_w8(dyn_bc, i);
681  else
682  for (int i = 0; i < layer->ch_layout.nb_channels; i++)
683  avio_w8(dyn_bc, layer->ch_layout.u.map[i].id);
684  } else {
685  int nb_demixing_matrix = (ilayer->coupled_substream_count + ilayer->substream_count) * layer->ch_layout.nb_channels;
686  if (nb_demixing_matrix != layer->nb_demixing_matrix)
687  return AVERROR(EINVAL);
688  avio_w8(dyn_bc, ilayer->coupled_substream_count);
689  for (int i = 0; i < layer->nb_demixing_matrix; i++)
690  avio_wb16(dyn_bc, rescale_rational(layer->demixing_matrix[i], 1 << 15));
691  }
692 
693  return 0;
694 }
695 
696 static int param_definition(const IAMFContext *iamf,
697  const IAMFParamDefinition *param_def,
698  AVIOContext *dyn_bc, void *log_ctx)
699 {
700  const AVIAMFParamDefinition *param = param_def->param;
701 
702  ffio_write_leb(dyn_bc, param->parameter_id);
703  ffio_write_leb(dyn_bc, param->parameter_rate);
704  avio_w8(dyn_bc, param->duration ? 0 : 1 << 7);
705  if (param->duration) {
706  ffio_write_leb(dyn_bc, param->duration);
708  if (param->constant_subblock_duration == 0) {
709  ffio_write_leb(dyn_bc, param->nb_subblocks);
710  for (int i = 0; i < param->nb_subblocks; i++) {
711  const void *subblock = av_iamf_param_definition_get_subblock(param, i);
712 
713  switch (param->type) {
715  const AVIAMFMixGain *mix = subblock;
716  ffio_write_leb(dyn_bc, mix->subblock_duration);
717  break;
718  }
720  const AVIAMFDemixingInfo *demix = subblock;
721  ffio_write_leb(dyn_bc, demix->subblock_duration);
722  break;
723  }
725  const AVIAMFReconGain *recon = subblock;
726  ffio_write_leb(dyn_bc, recon->subblock_duration);
727  break;
728  }
729  }
730  }
731  }
732  }
733 
734  return 0;
735 }
736 
737 static int iamf_write_audio_element(const IAMFContext *iamf,
738  const IAMFAudioElement *audio_element,
739  AVIOContext *pb, void *log_ctx)
740 {
741  const AVIAMFAudioElement *element = audio_element->celement;
742  const IAMFCodecConfig *codec_config = iamf->codec_configs[audio_element->codec_config_id];
744  AVIOContext *dyn_bc;
745  uint8_t *dyn_buf = NULL;
746  PutBitContext pbc;
747  int param_definition_types = AV_IAMF_PARAMETER_DEFINITION_DEMIXING, dyn_size;
748 
749  int ret = avio_open_dyn_buf(&dyn_bc);
750  if (ret < 0)
751  return ret;
752 
753  ffio_write_leb(dyn_bc, audio_element->audio_element_id);
754 
755  init_put_bits(&pbc, header, sizeof(header));
756  put_bits(&pbc, 3, element->audio_element_type);
757  put_bits(&pbc, 5, 0);
758  flush_put_bits(&pbc);
759  avio_write(dyn_bc, header, put_bytes_count(&pbc, 1));
760 
761  ffio_write_leb(dyn_bc, audio_element->codec_config_id);
762  ffio_write_leb(dyn_bc, audio_element->nb_substreams);
763 
764  for (int i = 0; i < audio_element->nb_substreams; i++)
765  ffio_write_leb(dyn_bc, audio_element->substreams[i].audio_substream_id);
766 
767  /* When audio_element_type = 1, num_parameters SHALL be set to 0 */
769  param_definition_types = 0;
770  else {
771  int layout = 0, expanded_layout = 0;
772  get_loudspeaker_layout(element->layers[0], &layout, &expanded_layout);
773  /* When the loudspeaker_layout = 15, the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
774  if (layout == 15) {
775  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
776  /* expanded_loudspeaker_layout SHALL only be present when num_layers = 1 and loudspeaker_layout is set to 15 */
777  if (element->nb_layers > 1) {
778  av_log(log_ctx, AV_LOG_ERROR, "expanded_loudspeaker_layout present when using more than one layer in "
779  "Stream Group #%u\n",
780  audio_element->audio_element_id);
781  return AVERROR(EINVAL);
782  }
783  }
784  /* When the loudspeaker_layout of the (non-)scalable channel audio (i.e., num_layers = 1) is less than or equal to 3.1.2ch,
785  * (i.e., Mono, Stereo, or 3.1.2ch), the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
786  else if (element->nb_layers == 1 && (layout == 0 || layout == 1 || layout == 8))
787  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
788  /* When num_layers > 1, the type PARAMETER_DEFINITION_RECON_GAIN SHALL be present */
789  if (element->nb_layers > 1)
790  param_definition_types |= AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
791  /* When codec_id = fLaC or ipcm, the type PARAMETER_DEFINITION_RECON_GAIN SHALL NOT be present. */
792  if (codec_config->codec_tag == MKTAG('f','L','a','C') ||
793  codec_config->codec_tag == MKTAG('i','p','c','m'))
794  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
795  if ((param_definition_types & AV_IAMF_PARAMETER_DEFINITION_DEMIXING) && !element->demixing_info) {
796  if (element->nb_layers > 1) {
797  get_loudspeaker_layout(element->layers[element->nb_layers-1], &layout, &expanded_layout);
798  /* When the highest loudspeaker_layout of the scalable channel audio (i.e., num_layers > 1) is greater than 3.1.2ch,
799  * (i.e., 5.1.2ch, 5.1.4ch, 7.1.2ch, or 7.1.4ch), type PARAMETER_DEFINITION_DEMIXING SHALL be present. */
800  if (layout == 3 || layout == 4 || layout == 6 || layout == 7) {
801  av_log(log_ctx, AV_LOG_ERROR, "demixing_info needed but not set in Stream Group #%u\n",
802  audio_element->audio_element_id);
803  return AVERROR(EINVAL);
804  }
805  }
806  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
807  }
808  }
809 
810  ffio_write_leb(dyn_bc, av_popcount(param_definition_types)); // num_parameters
811 
812  if (param_definition_types & AV_IAMF_PARAMETER_DEFINITION_DEMIXING) {
813  const AVIAMFParamDefinition *param = element->demixing_info;
814  const IAMFParamDefinition *param_def;
815  const AVIAMFDemixingInfo *demix;
816 
817  demix = av_iamf_param_definition_get_subblock(param, 0);
819 
820  param_def = ff_iamf_get_param_definition(iamf, param->parameter_id);
821  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
822  if (ret < 0)
823  return ret;
824 
825  avio_w8(dyn_bc, demix->dmixp_mode << 5); // dmixp_mode
826  avio_w8(dyn_bc, element->default_w << 4); // default_w
827  }
828  if (param_definition_types & AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) {
829  const AVIAMFParamDefinition *param = element->recon_gain_info;
830  const IAMFParamDefinition *param_def;
831 
832  if (!param) {
833  av_log(log_ctx, AV_LOG_ERROR, "recon_gain_info needed but not set in Stream Group #%u\n",
834  audio_element->audio_element_id);
835  return AVERROR(EINVAL);
836  }
838 
839  param_def = ff_iamf_get_param_definition(iamf, param->parameter_id);
840  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
841  if (ret < 0)
842  return ret;
843  }
844 
846  ret = scalable_channel_layout_config(audio_element, dyn_bc);
847  if (ret < 0)
848  return ret;
849  } else {
850  ret = ambisonics_config(audio_element, dyn_bc);
851  if (ret < 0)
852  return ret;
853  }
854 
855  init_put_bits(&pbc, header, sizeof(header));
857  put_bits(&pbc, 3, 0);
858  flush_put_bits(&pbc);
859 
860  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
861  avio_write(pb, header, put_bytes_count(&pbc, 1));
862  ffio_write_leb(pb, dyn_size);
863  avio_write(pb, dyn_buf, dyn_size);
864  ffio_free_dyn_buf(&dyn_bc);
865 
866  return 0;
867 }
868 
870  const IAMFMixPresentation *mix_presentation,
871  AVIOContext *pb, void *log_ctx)
872 {
874  const AVIAMFMixPresentation *mix = mix_presentation->cmix;
875  const AVDictionaryEntry *tag = NULL;
876  PutBitContext pbc;
877  AVIOContext *dyn_bc;
878  uint8_t *dyn_buf = NULL;
879  int dyn_size;
880 
881  int ret = avio_open_dyn_buf(&dyn_bc);
882  if (ret < 0)
883  return ret;
884 
885  ffio_write_leb(dyn_bc, mix_presentation->mix_presentation_id); // mix_presentation_id
886  ffio_write_leb(dyn_bc, av_dict_count(mix->annotations)); // count_label
887 
888  while ((tag = av_dict_iterate(mix->annotations, tag)))
889  avio_put_str(dyn_bc, tag->key);
890  while ((tag = av_dict_iterate(mix->annotations, tag)))
891  avio_put_str(dyn_bc, tag->value);
892 
893  ffio_write_leb(dyn_bc, mix->nb_submixes);
894  for (int i = 0; i < mix->nb_submixes; i++) {
895  const AVIAMFSubmix *sub_mix = mix->submixes[i];
896  const IAMFParamDefinition *param_def;
897 
898  ffio_write_leb(dyn_bc, sub_mix->nb_elements);
899  for (int j = 0; j < sub_mix->nb_elements; j++) {
900  const IAMFAudioElement *audio_element = NULL;
901  const AVIAMFSubmixElement *submix_element = sub_mix->elements[j];
902 
903  for (int k = 0; k < iamf->nb_audio_elements; k++)
904  if (iamf->audio_elements[k]->audio_element_id == submix_element->audio_element_id) {
905  audio_element = iamf->audio_elements[k];
906  break;
907  }
908 
909  av_assert0(audio_element);
910  ffio_write_leb(dyn_bc, submix_element->audio_element_id);
911 
912  if (av_dict_count(submix_element->annotations) != av_dict_count(mix->annotations)) {
913  av_log(log_ctx, AV_LOG_ERROR, "Inconsistent amount of labels in submix %d from Mix Presentation id #%u\n",
914  j, audio_element->audio_element_id);
915  return AVERROR(EINVAL);
916  }
917  while ((tag = av_dict_iterate(submix_element->annotations, tag)))
918  avio_put_str(dyn_bc, tag->value);
919 
920  init_put_bits(&pbc, header, sizeof(header));
921  put_bits(&pbc, 2, submix_element->headphones_rendering_mode);
922  put_bits(&pbc, 6, 0); // reserved
923  flush_put_bits(&pbc);
924  avio_write(dyn_bc, header, put_bytes_count(&pbc, 1));
925  ffio_write_leb(dyn_bc, 0); // rendering_config_extension_size
926 
927  param_def = ff_iamf_get_param_definition(iamf, submix_element->element_mix_config->parameter_id);
928  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
929  if (ret < 0)
930  return ret;
931 
932  avio_wb16(dyn_bc, rescale_rational(submix_element->default_mix_gain, 1 << 8));
933  }
934 
935  param_def = ff_iamf_get_param_definition(iamf, sub_mix->output_mix_config->parameter_id);
936  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
937  if (ret < 0)
938  return ret;
939  avio_wb16(dyn_bc, rescale_rational(sub_mix->default_mix_gain, 1 << 8));
940 
941  ffio_write_leb(dyn_bc, sub_mix->nb_layouts); // nb_layouts
942  for (int i = 0; i < sub_mix->nb_layouts; i++) {
943  const AVIAMFSubmixLayout *submix_layout = sub_mix->layouts[i];
944  int layout, info_type;
945  int dialogue = submix_layout->dialogue_anchored_loudness.num &&
946  submix_layout->dialogue_anchored_loudness.den;
947  int album = submix_layout->album_anchored_loudness.num &&
948  submix_layout->album_anchored_loudness.den;
949 
953  break;
954  }
956  av_log(log_ctx, AV_LOG_ERROR, "Invalid Sound System value in a submix\n");
957  return AVERROR(EINVAL);
958  }
959  } else if (submix_layout->layout_type != AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL) {
960  av_log(log_ctx, AV_LOG_ERROR, "Unsupported Layout Type value in a submix\n");
961  return AVERROR(EINVAL);
962  }
963  init_put_bits(&pbc, header, sizeof(header));
964  put_bits(&pbc, 2, submix_layout->layout_type); // layout_type
966  put_bits(&pbc, 4, ff_iamf_sound_system_map[layout].id); // sound_system
967  put_bits(&pbc, 2, 0); // reserved
968  } else
969  put_bits(&pbc, 6, 0); // reserved
970  flush_put_bits(&pbc);
971  avio_write(dyn_bc, header, put_bytes_count(&pbc, 1));
972 
973  info_type = (submix_layout->true_peak.num && submix_layout->true_peak.den);
974  info_type |= (dialogue || album) << 1;
975  avio_w8(dyn_bc, info_type);
976  avio_wb16(dyn_bc, rescale_rational(submix_layout->integrated_loudness, 1 << 8));
977  avio_wb16(dyn_bc, rescale_rational(submix_layout->digital_peak, 1 << 8));
978  if (info_type & 1)
979  avio_wb16(dyn_bc, rescale_rational(submix_layout->true_peak, 1 << 8));
980  if (info_type & 2) {
981  avio_w8(dyn_bc, dialogue + album); // num_anchored_loudness
982  if (dialogue) {
984  avio_wb16(dyn_bc, rescale_rational(submix_layout->dialogue_anchored_loudness, 1 << 8));
985  }
986  if (album) {
988  avio_wb16(dyn_bc, rescale_rational(submix_layout->album_anchored_loudness, 1 << 8));
989  }
990  }
991  }
992  }
993 
994  init_put_bits(&pbc, header, sizeof(header));
996  put_bits(&pbc, 3, 0);
997  flush_put_bits(&pbc);
998 
999  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
1000  avio_write(pb, header, put_bytes_count(&pbc, 1));
1001  ffio_write_leb(pb, dyn_size);
1002  avio_write(pb, dyn_buf, dyn_size);
1003  ffio_free_dyn_buf(&dyn_bc);
1004 
1005  return 0;
1006 }
1007 
1008 int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void *log_ctx)
1009 {
1010  int ret;
1011 
1012  // Sequence Header
1014 
1015  ffio_write_leb(pb, 6);
1016  avio_wb32(pb, MKBETAG('i','a','m','f'));
1017  avio_w8(pb, iamf->nb_audio_elements > 1); // primary_profile
1018  avio_w8(pb, iamf->nb_audio_elements > 1); // additional_profile
1019 
1020  for (int i = 0; i < iamf->nb_codec_configs; i++) {
1021  ret = iamf_write_codec_config(iamf, iamf->codec_configs[i], pb);
1022  if (ret < 0)
1023  return ret;
1024  }
1025 
1026  for (int i = 0; i < iamf->nb_audio_elements; i++) {
1027  ret = iamf_write_audio_element(iamf, iamf->audio_elements[i], pb, log_ctx);
1028  if (ret < 0)
1029  return ret;
1030  }
1031 
1032  for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1033  ret = iamf_write_mixing_presentation(iamf, iamf->mix_presentations[i], pb, log_ctx);
1034  if (ret < 0)
1035  return ret;
1036  }
1037 
1038  return 0;
1039 }
1040 
1041 static int write_parameter_block(const IAMFContext *iamf, AVIOContext *pb,
1042  const AVIAMFParamDefinition *param, void *log_ctx)
1043 {
1046  PutBitContext pbc;
1047  AVIOContext *dyn_bc;
1048  uint8_t *dyn_buf = NULL;
1049  int dyn_size, ret;
1050 
1052  av_log(log_ctx, AV_LOG_DEBUG, "Ignoring side data with unknown type %u\n",
1053  param->type);
1054  return 0;
1055  }
1056 
1057  if (!param_definition) {
1058  av_log(log_ctx, AV_LOG_ERROR, "Non-existent Parameter Definition with ID %u referenced by a packet\n",
1059  param->parameter_id);
1060  return AVERROR(EINVAL);
1061  }
1062 
1063  if (param->type != param_definition->param->type) {
1064  av_log(log_ctx, AV_LOG_ERROR, "Inconsistent values for Parameter Definition "
1065  "with ID %u in a packet\n",
1066  param->parameter_id);
1067  return AVERROR(EINVAL);
1068  }
1069 
1070  ret = avio_open_dyn_buf(&dyn_bc);
1071  if (ret < 0)
1072  return ret;
1073 
1074  // Sequence Header
1075  init_put_bits(&pbc, header, sizeof(header));
1077  put_bits(&pbc, 3, 0);
1078  flush_put_bits(&pbc);
1079  avio_write(pb, header, put_bytes_count(&pbc, 1));
1080 
1081  ffio_write_leb(dyn_bc, param->parameter_id);
1082  if (!param_definition->mode) {
1083  ffio_write_leb(dyn_bc, param->duration);
1085  if (param->constant_subblock_duration == 0)
1086  ffio_write_leb(dyn_bc, param->nb_subblocks);
1087  }
1088 
1089  for (int i = 0; i < param->nb_subblocks; i++) {
1090  const void *subblock = av_iamf_param_definition_get_subblock(param, i);
1091 
1092  switch (param->type) {
1094  const AVIAMFMixGain *mix = subblock;
1095  if (!param_definition->mode && param->constant_subblock_duration == 0)
1096  ffio_write_leb(dyn_bc, mix->subblock_duration);
1097 
1098  ffio_write_leb(dyn_bc, mix->animation_type);
1099 
1100  avio_wb16(dyn_bc, rescale_rational(mix->start_point_value, 1 << 8));
1101  if (mix->animation_type >= AV_IAMF_ANIMATION_TYPE_LINEAR)
1102  avio_wb16(dyn_bc, rescale_rational(mix->end_point_value, 1 << 8));
1103  if (mix->animation_type == AV_IAMF_ANIMATION_TYPE_BEZIER) {
1104  avio_wb16(dyn_bc, rescale_rational(mix->control_point_value, 1 << 8));
1105  avio_w8(dyn_bc, av_clip_uint8(av_rescale(mix->control_point_relative_time.num, 1 << 8,
1106  mix->control_point_relative_time.den)));
1107  }
1108  break;
1109  }
1111  const AVIAMFDemixingInfo *demix = subblock;
1112  if (!param_definition->mode && param->constant_subblock_duration == 0)
1113  ffio_write_leb(dyn_bc, demix->subblock_duration);
1114 
1115  avio_w8(dyn_bc, demix->dmixp_mode << 5);
1116  break;
1117  }
1119  const AVIAMFReconGain *recon = subblock;
1120  const AVIAMFAudioElement *audio_element = param_definition->audio_element->celement;
1121 
1122  if (!param_definition->mode && param->constant_subblock_duration == 0)
1123  ffio_write_leb(dyn_bc, recon->subblock_duration);
1124 
1125  if (!audio_element) {
1126  av_log(log_ctx, AV_LOG_ERROR, "Invalid Parameter Definition with ID %u referenced by a packet\n", param->parameter_id);
1127  return AVERROR(EINVAL);
1128  }
1129 
1130  for (int j = 0; j < audio_element->nb_layers; j++) {
1131  const AVIAMFLayer *layer = audio_element->layers[j];
1132 
1133  if (layer->flags & AV_IAMF_LAYER_FLAG_RECON_GAIN) {
1134  unsigned int recon_gain_flags = 0;
1135  int k = 0;
1136 
1137  for (; k < 7; k++)
1138  recon_gain_flags |= (1 << k) * !!recon->recon_gain[j][k];
1139  for (; k < 12; k++)
1140  recon_gain_flags |= (2 << k) * !!recon->recon_gain[j][k];
1141  if (recon_gain_flags >> 8)
1142  recon_gain_flags |= (1 << k);
1143 
1144  ffio_write_leb(dyn_bc, recon_gain_flags);
1145  for (k = 0; k < 12; k++) {
1146  if (recon->recon_gain[j][k])
1147  avio_w8(dyn_bc, recon->recon_gain[j][k]);
1148  }
1149  }
1150  }
1151  break;
1152  }
1153  default:
1154  av_unreachable("param_definition_type should have been checked above");
1155  }
1156  }
1157 
1158  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
1159  ffio_write_leb(pb, dyn_size);
1160  avio_write(pb, dyn_buf, dyn_size);
1161  ffio_free_dyn_buf(&dyn_bc);
1162 
1163  return 0;
1164 }
1165 
1167  const AVPacket *pkt, void *log_ctx)
1168 {
1172  NULL);
1173  AVIAMFParamDefinition *demix =
1176  NULL);
1177  AVIAMFParamDefinition *recon =
1180  NULL);
1181 
1182  if (mix) {
1183  int ret = write_parameter_block(iamf, pb, mix, log_ctx);
1184  if (ret < 0)
1185  return ret;
1186  }
1187  if (demix) {
1188  int ret = write_parameter_block(iamf, pb, demix, log_ctx);
1189  if (ret < 0)
1190  return ret;
1191  }
1192  if (recon) {
1193  int ret = write_parameter_block(iamf, pb, recon, log_ctx);
1194  if (ret < 0)
1195  return ret;
1196  }
1197 
1198  return 0;
1199 }
1200 
1202  unsigned int audio_substream_id)
1203 {
1204  for (int i = 0; i < c->nb_audio_elements; i++) {
1205  IAMFAudioElement *audio_element = c->audio_elements[i];
1206  for (int j = 0; j < audio_element->nb_substreams; j++) {
1207  IAMFSubStream *substream = &audio_element->substreams[j];
1208  if (substream->audio_substream_id == audio_substream_id)
1209  return audio_element;
1210  }
1211  }
1212 
1213  return NULL;
1214 }
1215 
1217  unsigned audio_substream_id, const AVPacket *pkt)
1218 {
1220  PutBitContext pbc;
1221  const IAMFAudioElement *audio_element;
1222  IAMFCodecConfig *codec_config;
1223  AVIOContext *dyn_bc;
1224  const uint8_t *side_data;
1225  uint8_t *dyn_buf = NULL;
1226  unsigned int skip_samples = 0, discard_padding = 0;
1227  size_t side_data_size;
1228  int dyn_size, type = audio_substream_id <= 17 ?
1230  int ret;
1231 
1232  audio_element = get_audio_element(iamf, audio_substream_id);
1233  if (!audio_element)
1234  return AVERROR(EINVAL);
1235  codec_config = ff_iamf_get_codec_config(iamf, audio_element->codec_config_id);
1236  if (!codec_config)
1237  return AVERROR(EINVAL);
1238 
1239  if (!pkt->size) {
1240  size_t new_extradata_size;
1241  const uint8_t *new_extradata = av_packet_get_side_data(pkt,
1243  &new_extradata_size);
1244 
1245  if (!new_extradata || new_extradata_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
1246  return AVERROR_INVALIDDATA;
1247 
1248  av_free(codec_config->extradata);
1249  codec_config->extradata = av_malloc(new_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
1250  if (!codec_config->extradata) {
1251  codec_config->extradata_size = 0;
1252  return AVERROR(ENOMEM);
1253  }
1254  memcpy(codec_config->extradata, new_extradata, new_extradata_size);
1255  memset(codec_config->extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1256  codec_config->extradata_size = new_extradata_size;
1257 
1258  return update_extradata(codec_config);
1259  }
1260 
1262  &side_data_size);
1263 
1264  if (side_data && side_data_size >= 10) {
1265  skip_samples = AV_RL32(side_data);
1266  discard_padding = AV_RL32(side_data + 4);
1267  }
1268 
1269  if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
1270  // IAMF's num_samples_to_trim_at_start is the same as Opus's pre-skip.
1271  skip_samples = pkt->dts < 0
1272  ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
1273  : 0;
1274  discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
1275  }
1276 
1277  ret = avio_open_dyn_buf(&dyn_bc);
1278  if (ret < 0)
1279  return ret;
1280 
1281  init_put_bits(&pbc, header, sizeof(header));
1282  put_bits(&pbc, 5, type);
1283  put_bits(&pbc, 1, 0); // obu_redundant_copy
1284  put_bits(&pbc, 1, skip_samples || discard_padding);
1285  put_bits(&pbc, 1, 0); // obu_extension_flag
1286  flush_put_bits(&pbc);
1287  avio_write(pb, header, put_bytes_count(&pbc, 1));
1288 
1289  if (skip_samples || discard_padding) {
1290  ffio_write_leb(dyn_bc, discard_padding);
1291  ffio_write_leb(dyn_bc, skip_samples);
1292  }
1293 
1294  if (audio_substream_id > 17)
1295  ffio_write_leb(dyn_bc, audio_substream_id);
1296 
1297  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
1298  ffio_write_leb(pb, dyn_size + pkt->size);
1299  avio_write(pb, dyn_buf, dyn_size);
1300  ffio_free_dyn_buf(&dyn_bc);
1301  avio_write(pb, pkt->data, pkt->size);
1302 
1303  return 0;
1304 }
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:338
iamf.h
ff_iamf_free_mix_presentation
void ff_iamf_free_mix_presentation(IAMFMixPresentation **pmix_presentation)
Definition: iamf.c:158
AVIAMFSubmix::elements
AVIAMFSubmixElement ** elements
Array of submix elements.
Definition: iamf.h:568
AV_IAMF_SUBMIX_LAYOUT_TYPE_LOUDSPEAKERS
@ AV_IAMF_SUBMIX_LAYOUT_TYPE_LOUDSPEAKERS
The layout follows the loudspeaker sound system convention of ITU-2051-3.
Definition: iamf.h:501
AVIAMFAudioElement::nb_layers
unsigned int nb_layers
Number of layers, or channel groups, in the Audio Element.
Definition: iamf.h:371
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:71
AVStreamGroup::id
int64_t id
Group type-specific group ID.
Definition: avformat.h:1116
AVIAMFSubmix::layouts
AVIAMFSubmixLayout ** layouts
Array of submix layouts.
Definition: iamf.h:583
mix
static int mix(int c0, int c1)
Definition: 4xm.c:717
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
IAMF_OBU_IA_SEQUENCE_HEADER
@ IAMF_OBU_IA_SEQUENCE_HEADER
Definition: iamf.h:63
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
AVIAMFAudioElement::default_w
unsigned int default_w
Default weight value as defined in section 3.6 of IAMF.
Definition: iamf.h:396
AV_PKT_DATA_NEW_EXTRADATA
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: packet.h:56
IAMFAudioElement::nb_substreams
unsigned int nb_substreams
Definition: iamf.h:99
AVIAMFAudioElement::layers
AVIAMFLayer ** layers
Definition: iamf.h:362
av_dict_count
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:37
get_bits_long
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:424
init_put_bits
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:62
AVChannelLayout::map
AVChannelCustom * map
This member must be used when the channel order is AV_CHANNEL_ORDER_CUSTOM.
Definition: channel_layout.h:370
AVIAMFMixPresentation::nb_submixes
unsigned int nb_submixes
Number of submixes in the presentation.
Definition: iamf.h:632
put_bits
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:154
AVIAMFParamDefinition::type
enum AVIAMFParamDefinitionType type
Parameters type.
Definition: iamf.h:213
AVPacket::data
uint8_t * data
Definition: packet.h:595
b
#define b
Definition: input.c:43
put_bytes_count
static int put_bytes_count(const PutBitContext *s, int round_up)
Definition: put_bits.h:110
AVIAMFSubmixLayout::layout_type
enum AVIAMFSubmixLayoutType layout_type
Definition: iamf.h:520
IAMFParamDefinition::param
AVIAMFParamDefinition * param
Definition: iamf.h:123
put_bits32
static av_unused void put_bits32(PutBitContext *s, uint32_t value)
Write exactly 32 bits into a bitstream.
Definition: put_bits.h:301
AVIAMFParamDefinition
Parameters as defined in section 3.6.1 of IAMF.
Definition: iamf.h:193
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:61
AVIAMFSubmixElement::default_mix_gain
AVRational default_mix_gain
Default mix gain value to apply when there are no AVIAMFParamDefinition with element_mix_config's par...
Definition: iamf.h:472
add_param_definition
static int add_param_definition(IAMFContext *iamf, AVIAMFParamDefinition *param, const IAMFAudioElement *audio_element, void *log_ctx)
Definition: iamf_writer.c:174
AV_CODEC_ID_FLAC
@ AV_CODEC_ID_FLAC
Definition: codec_id.h:472
AVChannelLayout::order
enum AVChannelOrder order
Channel order used in this layout.
Definition: channel_layout.h:324
av_popcount
#define av_popcount
Definition: common.h:154
ff_iamf_get_param_definition
static IAMFParamDefinition * ff_iamf_get_param_definition(const IAMFContext *iamf, unsigned int parameter_id)
Definition: iamf.h:185
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:329
AV_RL8
#define AV_RL8(x)
Definition: intreadwrite.h:394
avio_get_dyn_buf
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1377
av_channel_layout_describe_bprint
int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, AVBPrint *bp)
bprint variant of av_channel_layout_describe().
Definition: channel_layout.c:600
IAMFMixPresentation::cmix
const AVIAMFMixPresentation * cmix
Definition: iamf.h:108
write_parameter_block
static int write_parameter_block(const IAMFContext *iamf, AVIOContext *pb, const AVIAMFParamDefinition *param, void *log_ctx)
Definition: iamf_writer.c:1041
AVIAMFSubmixLayout::digital_peak
AVRational digital_peak
The digital (sampled) peak value of the audio signal, as defined in ITU-1770-4.
Definition: iamf.h:538
skip_bits
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:383
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:337
get_loudspeaker_layout
static void get_loudspeaker_layout(const AVIAMFLayer *layer, int *playout, int *pexpanded_layout)
Definition: iamf_writer.c:590
fill_codec_config
static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg, IAMFCodecConfig *codec_config)
Definition: iamf_writer.c:108
AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM
@ AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM
IAMF Recon Gain Info Parameter Data associated with the audio frame.
Definition: packet.h:320
AVIAMFSubmixLayout::integrated_loudness
AVRational integrated_loudness
The program integrated loudness information, as defined in ITU-1770-4.
Definition: iamf.h:533
IAMFCodecConfig::extradata
uint8_t * extradata
Definition: iamf.h:74
AV_CODEC_ID_PCM_S16BE
@ AV_CODEC_ID_PCM_S16BE
Definition: codec_id.h:339
IAMFParamDefinition
Definition: iamf.h:121
fail
#define fail()
Definition: checkasm.h:224
IAMFCodecConfig::codec_tag
uint32_t codec_tag
Definition: iamf.h:69
GetBitContext
Definition: get_bits.h:109
AVIAMFSubmixLayout
Submix layout as defined in section 3.7.6 of IAMF.
Definition: iamf.h:517
IAMF_ANCHOR_ELEMENT_ALBUM
@ IAMF_ANCHOR_ELEMENT_ALBUM
Definition: iamf.h:142
put_bits_left
static int put_bits_left(PutBitContext *s)
Definition: put_bits.h:135
AV_BPRINT_SIZE_AUTOMATIC
#define AV_BPRINT_SIZE_AUTOMATIC
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
IAMF_OBU_IA_PARAMETER_BLOCK
@ IAMF_OBU_IA_PARAMETER_BLOCK
Definition: iamf.h:41
AVIAMFAudioElement::audio_element_type
enum AVIAMFAudioElementType audio_element_type
Audio element type as defined in section 3.6 of IAMF.
Definition: iamf.h:391
AVIAMFReconGain
Recon Gain Info Parameter Data as defined in section 3.8.3 of IAMF.
Definition: iamf.h:148
AVRational::num
int num
Numerator.
Definition: rational.h:59
AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN
@ AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN
Subblocks are of struct type AVIAMFReconGain.
Definition: iamf.h:181
rescale_rational
static int rescale_rational(AVRational q, int b)
Definition: iamf_writer.c:585
IAMFContext::audio_elements
IAMFAudioElement ** audio_elements
Definition: iamf.h:131
AVIAMFSubmixElement::annotations
AVDictionary * annotations
A dictionary of strings describing the submix in different languages.
Definition: iamf.h:493
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:544
IAMFCodecConfig::sample_rate
int sample_rate
Definition: iamf.h:72
IAMF_OBU_IA_MIX_PRESENTATION
@ IAMF_OBU_IA_MIX_PRESENTATION
Definition: iamf.h:40
AVCodecParameters::frame_size
int frame_size
Audio frame size, if known.
Definition: codec_par.h:227
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1365
AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION
@ AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION
Definition: avformat.h:1089
AV_IAMF_ANIMATION_TYPE_BEZIER
@ AV_IAMF_ANIMATION_TYPE_BEZIER
Definition: iamf.h:69
update_extradata
static int update_extradata(IAMFCodecConfig *codec_config)
Definition: iamf_writer.c:35
ff_iamf_add_audio_element
int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
Definition: iamf_writer.c:217
intreadwrite.h
IAMFSubStream::audio_substream_id
unsigned int audio_substream_id
Definition: iamf.h:83
IAMFLayer::substream_count
unsigned int substream_count
Definition: iamf.h:78
AVIAMFSubmixLayout::dialogue_anchored_loudness
AVRational dialogue_anchored_loudness
The Dialogue loudness information, as defined in ITU-1770-4.
Definition: iamf.h:546
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:217
av_iamf_param_definition_get_subblock
static av_always_inline void * av_iamf_param_definition_get_subblock(const AVIAMFParamDefinition *par, unsigned int idx)
Get the subblock at the specified.
Definition: iamf.h:260
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
AVIAMFSubmixElement::headphones_rendering_mode
enum AVIAMFHeadphonesMode headphones_rendering_mode
A value that indicates whether the referenced channel-based Audio Element shall be rendered to stereo...
Definition: iamf.h:481
AVStreamGroup::index
unsigned int index
Group index in AVFormatContext.
Definition: avformat.h:1108
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
put_bits63
static void put_bits63(PutBitContext *s, int n, uint64_t value)
Write up to 63 bits into a bitstream.
Definition: put_bits.h:344
get_bits.h
AVIAMFLayer::ch_layout
AVChannelLayout ch_layout
Definition: iamf.h:297
ffio_write_leb
void ffio_write_leb(AVIOContext *s, unsigned val)
Definition: aviobuf.c:947
IAMFContext::nb_mix_presentations
int nb_mix_presentations
Definition: iamf.h:134
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
PutBitContext
Definition: put_bits.h:50
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
if
if(ret)
Definition: filter_design.txt:179
IAMFAudioElement::audio_element_id
unsigned int audio_element_id
Definition: iamf.h:96
AVIAMFDemixingInfo
Demixing Info Parameter Data as defined in section 3.8.2 of IAMF.
Definition: iamf.h:128
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:767
IAMFSoundSystemMap::layout
AVChannelLayout layout
Definition: iamf.h:164
AV_CHANNEL_ORDER_AMBISONIC
@ AV_CHANNEL_ORDER_AMBISONIC
The audio is represented as the decomposition of the sound field into spherical harmonics.
Definition: channel_layout.h:155
av_clip_int16
#define av_clip_int16
Definition: common.h:115
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
IAMF_OBU_IA_AUDIO_ELEMENT
@ IAMF_OBU_IA_AUDIO_ELEMENT
Definition: iamf.h:39
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVIAMFParamDefinition::duration
unsigned int duration
The accumulated duration of all blocks in this parameter definition, in units of 1 / parameter_rate.
Definition: iamf.h:231
get_audio_element
static IAMFAudioElement * get_audio_element(const IAMFContext *c, unsigned int audio_substream_id)
Definition: iamf_writer.c:1201
av_unreachable
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition: avassert.h:116
ff_iamf_get_codec_config
static IAMFCodecConfig * ff_iamf_get_codec_config(const IAMFContext *c, unsigned int codec_config_id)
Definition: iamf.h:172
AVIAMFLayer
A layer defining a Channel Layout in the Audio Element.
Definition: iamf.h:294
IAMFContext::nb_codec_configs
int nb_codec_configs
Definition: iamf.h:130
IAMF_OBU_IA_CODEC_CONFIG
@ IAMF_OBU_IA_CODEC_CONFIG
Definition: iamf.h:38
IAMFSubStream
Definition: iamf.h:82
IAMFAudioElement::layers
IAMFLayer * layers
Definition: iamf.h:103
ff_iamf_add_mix_presentation
int ff_iamf_add_mix_presentation(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
Definition: iamf_writer.c:427
avio_w8
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:184
AV_IAMF_ANIMATION_TYPE_LINEAR
@ AV_IAMF_ANIMATION_TYPE_LINEAR
Definition: iamf.h:68
AV_IAMF_AMBISONICS_MODE_MONO
@ AV_IAMF_AMBISONICS_MODE_MONO
Definition: iamf.h:273
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition: codec_par.h:207
IAMFAudioElement::celement
const AVIAMFAudioElement * celement
Definition: iamf.h:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVCodecParameters::sample_rate
int sample_rate
The number of audio samples per second.
Definition: codec_par.h:213
AVIAMFLayer::output_gain_flags
unsigned int output_gain_flags
Output gain channel flags as defined in section 3.6.2 of IAMF.
Definition: iamf.h:310
ff_iamf_expanded_scalable_ch_layouts
const AVChannelLayout ff_iamf_expanded_scalable_ch_layouts[13]
Definition: iamf.c:48
populate_audio_roll_distance
static int populate_audio_roll_distance(IAMFCodecConfig *codec_config)
Definition: iamf_writer.c:80
AVIAMFSubmixElement::audio_element_id
unsigned int audio_element_id
The id of the Audio Element this submix element references.
Definition: iamf.h:455
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:75
AVIAMFSubmix
Submix layout as defined in section 3.7 of IAMF.
Definition: iamf.h:559
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:462
IAMFLayer
Definition: iamf.h:77
IAMFAudioElement
Definition: iamf.h:89
AVIAMFReconGain::subblock_duration
unsigned int subblock_duration
Duration for the given subblock, in units of 1 / parameter_rate.
Definition: iamf.h:156
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
IAMFCodecConfig::nb_samples
unsigned nb_samples
Definition: iamf.h:70
AV_CODEC_ID_PCM_S24LE
@ AV_CODEC_ID_PCM_S24LE
Definition: codec_id.h:350
IAMFContext::nb_param_definitions
int nb_param_definitions
Definition: iamf.h:136
AVIAMFDemixingInfo::subblock_duration
unsigned int subblock_duration
Duration for the given subblock, in units of 1 / parameter_rate.
Definition: iamf.h:136
AVPacket::size
int size
Definition: packet.h:596
IAMFCodecConfig
Definition: iamf.h:66
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
ff_iamf_sound_system_map
const struct IAMFSoundSystemMap ff_iamf_sound_system_map[14]
Definition: iamf.c:120
IAMFCodecConfig::extradata_size
int extradata_size
Definition: iamf.h:73
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
IAMFLayer::coupled_substream_count
unsigned int coupled_substream_count
Definition: iamf.h:79
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
ff_iamf_write_parameter_blocks
int ff_iamf_write_parameter_blocks(const IAMFContext *iamf, AVIOContext *pb, const AVPacket *pkt, void *log_ctx)
Definition: iamf_writer.c:1166
AVStreamGroup::iamf_audio_element
struct AVIAMFAudioElement * iamf_audio_element
Definition: avformat.h:1130
iamf_write_mixing_presentation
static int iamf_write_mixing_presentation(const IAMFContext *iamf, const IAMFMixPresentation *mix_presentation, AVIOContext *pb, void *log_ctx)
Definition: iamf_writer.c:869
AV_CODEC_ID_OPUS
@ AV_CODEC_ID_OPUS
Definition: codec_id.h:520
AV_RL16A
#define AV_RL16A(p)
Definition: intreadwrite.h:554
IAMFContext
Definition: iamf.h:128
header
static const uint8_t header[24]
Definition: sdr2.c:68
scalable_channel_layout_config
static int scalable_channel_layout_config(const IAMFAudioElement *audio_element, AVIOContext *dyn_bc)
Definition: iamf_writer.c:625
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:594
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:206
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:368
IAMFAudioElement::substreams
IAMFSubStream * substreams
Definition: iamf.h:98
iamf_write_codec_config
static int iamf_write_codec_config(const IAMFContext *iamf, const IAMFCodecConfig *codec_config, AVIOContext *pb)
Definition: iamf_writer.c:506
AVIAMFParamDefinition::constant_subblock_duration
unsigned int constant_subblock_duration
The duration of every subblock in the case where all subblocks, with the optional exception of the la...
Definition: iamf.h:238
AVIAMFAudioElement
Information on how to combine one or more audio streams, as defined in section 3.6 of IAMF.
Definition: iamf.h:359
avio_wl32
void avio_wl32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:360
AVIAMFMixGain
Mix Gain Parameter Data as defined in section 3.8.1 of IAMF.
Definition: iamf.h:77
AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
@ AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT
Definition: avformat.h:1088
AVStreamGroup::streams
AVStream ** streams
A list of streams in the group.
Definition: avformat.h:1164
AVStreamGroup::iamf_mix_presentation
struct AVIAMFMixPresentation * iamf_mix_presentation
Definition: avformat.h:1131
av_channel_layout_compare
int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
Check whether two channel layouts are semantically the same, i.e.
Definition: channel_layout.c:811
layout
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel layout
Definition: filter_design.txt:18
AVChannelLayout::u
union AVChannelLayout::@515 u
Details about which channels are present in this layout.
get_bits64
static uint64_t get_bits64(GetBitContext *s, int n)
Read 0-64 bits.
Definition: get_bits.h:456
IAMFContext::param_definitions
IAMFParamDefinition ** param_definitions
Definition: iamf.h:135
bprint.h
IAMFContext::nb_audio_elements
int nb_audio_elements
Definition: iamf.h:132
av_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
AVIAMFParamDefinition::parameter_id
unsigned int parameter_id
Identifier for the parameter substream.
Definition: iamf.h:218
avio_internal.h
AVIAMFLayer::demixing_matrix
AVRational * demixing_matrix
Demixing matrix as defined in section 3.6.3 of IAMF.
Definition: iamf.h:336
av_packet_get_side_data
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, size_t *size)
Get side information from packet.
Definition: packet.c:252
AVIAMFMixPresentation
Information on how to render and mix one or more AVIAMFAudioElement to generate the final audio outpu...
Definition: iamf.h:616
param_definition
static int param_definition(const IAMFContext *iamf, const IAMFParamDefinition *param_def, AVIOContext *dyn_bc, void *log_ctx)
Definition: iamf_writer.c:696
AV_WB16A
#define AV_WB16A(p, v)
Definition: intreadwrite.h:564
IAMFContext::codec_configs
IAMFCodecConfig ** codec_configs
Definition: iamf.h:129
AV_CODEC_ID_PCM_S32BE
@ AV_CODEC_ID_PCM_S32BE
Definition: codec_id.h:347
AVStreamGroup::params
union AVStreamGroup::@447 params
Group type-specific parameters.
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
IAMF_OBU_IA_AUDIO_FRAME
@ IAMF_OBU_IA_AUDIO_FRAME
Definition: iamf.h:43
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AVIAMFParamDefinition::nb_subblocks
unsigned int nb_subblocks
Number of subblocks in the array.
Definition: iamf.h:208
AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE
@ AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE
Definition: iamf.h:349
AVIAMFLayer::nb_demixing_matrix
unsigned int nb_demixing_matrix
The length of the Demixing matrix array.
Definition: iamf.h:343
AV_WB32A
#define AV_WB32A(p, v)
Definition: intreadwrite.h:578
AV_WB8
#define AV_WB8(p, d)
Definition: intreadwrite.h:392
ff_iamf_write_audio_frame
int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb, unsigned audio_substream_id, const AVPacket *pkt)
Definition: iamf_writer.c:1216
ff_iamf_write_descriptors
int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void *log_ctx)
Definition: iamf_writer.c:1008
AVIAMFSubmix::nb_layouts
unsigned int nb_layouts
Number of layouts in the submix.
Definition: iamf.h:590
ambisonics_config
static int ambisonics_config(const IAMFAudioElement *audio_element, AVIOContext *dyn_bc)
Definition: iamf_writer.c:663
tag
uint32_t tag
Definition: movenc.c:2046
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1438
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:756
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:744
ff_iamf_free_audio_element
void ff_iamf_free_audio_element(IAMFAudioElement **paudio_element)
Definition: iamf.c:143
avformat.h
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:122
IAMF_OBU_IA_AUDIO_FRAME_ID0
@ IAMF_OBU_IA_AUDIO_FRAME_ID0
Definition: iamf.h:44
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
AVStreamGroup
Definition: avformat.h:1097
IAMFMixPresentation
Definition: iamf.h:107
AV_CHANNEL_ORDER_CUSTOM
@ AV_CHANNEL_ORDER_CUSTOM
The channel order does not correspond to any other predefined order and is stored as an explicit map.
Definition: channel_layout.h:132
AVStreamGroup::nb_streams
unsigned int nb_streams
Number of elements in AVStreamGroup.streams.
Definition: avformat.h:1151
channel_layout.h
AVIAMFSubmix::default_mix_gain
AVRational default_mix_gain
Default mix gain value to apply when there are no AVIAMFParamDefinition with output_mix_config's para...
Definition: iamf.h:606
AVIAMFSubmixLayout::album_anchored_loudness
AVRational album_anchored_loudness
The Album loudness information, as defined in ITU-1770-4.
Definition: iamf.h:550
av_channel_layout_subset
uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, uint64_t mask)
Find out what channels from a given set are present in a channel layout, without regard for their pos...
Definition: channel_layout.c:867
AVIAMFSubmixLayout::true_peak
AVRational true_peak
The true peak of the audio signal, as defined in ITU-1770-4.
Definition: iamf.h:542
AVRational::den
int den
Denominator.
Definition: rational.h:60
AVIAMFSubmixLayout::sound_system
AVChannelLayout sound_system
Channel layout matching one of Sound Systems A to J of ITU-2051-3, plus 7.1.2ch, 3....
Definition: iamf.h:528
IAMFCodecConfig::codec_id
enum AVCodecID codec_id
Definition: iamf.h:68
IAMFCodecConfig::codec_config_id
unsigned codec_config_id
Definition: iamf.h:67
AV_PKT_DATA_SKIP_SAMPLES
@ AV_PKT_DATA_SKIP_SAMPLES
Recommends skipping the specified number of samples.
Definition: packet.h:153
IAMF_ANCHOR_ELEMENT_DIALOGUE
@ IAMF_ANCHOR_ELEMENT_DIALOGUE
Definition: iamf.h:141
AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN
@ AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN
Subblocks are of struct type AVIAMFMixGain.
Definition: iamf.h:173
AV_RL32A
#define AV_RL32A(p)
Definition: intreadwrite.h:568
MAX_IAMF_OBU_HEADER_SIZE
#define MAX_IAMF_OBU_HEADER_SIZE
Definition: iamf.h:34
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
AVIAMFSubmix::nb_elements
unsigned int nb_elements
Number of elements in the submix.
Definition: iamf.h:575
AV_CODEC_ID_PCM_S32LE
@ AV_CODEC_ID_PCM_S32LE
Definition: codec_id.h:346
AVIAMFAudioElement::demixing_info
AVIAMFParamDefinition * demixing_info
Demixing information used to reconstruct a scalable channel audio representation.
Definition: iamf.h:379
AVIAMFDemixingInfo::dmixp_mode
unsigned int dmixp_mode
Pre-defined combination of demixing parameters.
Definition: iamf.h:140
mem.h
AVIAMFSubmix::output_mix_config
AVIAMFParamDefinition * output_mix_config
Information required for post-processing the mixed audio signal to generate the audio signal for play...
Definition: iamf.h:598
AVStreamGroup::type
enum AVStreamGroupParamsType type
Group type.
Definition: avformat.h:1124
IAMFContext::mix_presentations
IAMFMixPresentation ** mix_presentations
Definition: iamf.h:133
AVIAMFLayer::ambisonics_mode
enum AVIAMFAmbisonicsMode ambisonics_mode
Ambisonics mode as defined in section 3.6.3 of IAMF.
Definition: iamf.h:328
flush_put_bits
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:153
avio_wb24
void avio_wb24(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:458
AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL
@ AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL
The layout is binaural.
Definition: iamf.h:508
AVIAMFLayer::flags
unsigned int flags
A bitmask which may contain a combination of AV_IAMF_LAYER_FLAG_* flags.
Definition: iamf.h:302
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVDictionaryEntry
Definition: dict.h:90
AVIAMFLayer::output_gain
AVRational output_gain
Output gain as defined in section 3.6.2 of IAMF.
Definition: iamf.h:316
AV_IAMF_AMBISONICS_MODE_PROJECTION
@ AV_IAMF_AMBISONICS_MODE_PROJECTION
Definition: iamf.h:274
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:57
AVPacket
This structure stores compressed data.
Definition: packet.h:572
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
iamf.h
AVIAMFSubmixElement::element_mix_config
AVIAMFParamDefinition * element_mix_config
Information required required for applying any processing to the referenced and rendered Audio Elemen...
Definition: iamf.h:464
AVIAMFParamDefinition::parameter_rate
unsigned int parameter_rate
Sample rate for the parameter substream.
Definition: iamf.h:222
ff_iamf_scalable_ch_layouts
const AVChannelLayout ff_iamf_scalable_ch_layouts[10]
Definition: iamf.c:27
AVIAMFSubmixElement
Submix element as defined in section 3.7 of IAMF.
Definition: iamf.h:449
avio_wb16
void avio_wb16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:446
AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL
@ AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL
Definition: iamf.h:348
IAMFAudioElement::codec_config_id
unsigned int codec_config_id
Definition: iamf.h:101
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
AVIAMFAudioElement::recon_gain_info
AVIAMFParamDefinition * recon_gain_info
Recon gain information used to reconstruct a scalable channel audio representation.
Definition: iamf.h:386
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
avio_put_str
int avio_put_str(AVIOContext *s, const char *str)
Write a NULL-terminated string.
Definition: aviobuf.c:376
put_bits.h
IAMFCodecConfig::audio_roll_distance
int audio_roll_distance
Definition: iamf.h:71
AVIAMFMixPresentation::submixes
AVIAMFSubmix ** submixes
Array of submixes.
Definition: iamf.h:625
IAMFMixPresentation::mix_presentation_id
unsigned int mix_presentation_id
Definition: iamf.h:114
AVIAMFReconGain::recon_gain
uint8_t recon_gain[6][12]
Array of gain values to be applied to each channel for each layer defined in the Audio Element refere...
Definition: iamf.h:166
AV_CODEC_ID_PCM_S24BE
@ AV_CODEC_ID_PCM_S24BE
Definition: codec_id.h:351
AV_PKT_DATA_IAMF_MIX_GAIN_PARAM
@ AV_PKT_DATA_IAMF_MIX_GAIN_PARAM
IAMF Mix Gain Parameter Data associated with the audio frame.
Definition: packet.h:304
AVChannelCustom::id
enum AVChannel id
Definition: channel_layout.h:284
av_dict_iterate
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition: dict.c:42
AVPacket::time_base
AVRational time_base
Time base of the packet's timestamps.
Definition: packet.h:639
AV_IAMF_PARAMETER_DEFINITION_DEMIXING
@ AV_IAMF_PARAMETER_DEFINITION_DEMIXING
Subblocks are of struct type AVIAMFDemixingInfo.
Definition: iamf.h:177
iamf_write_audio_element
static int iamf_write_audio_element(const IAMFContext *iamf, const IAMFAudioElement *audio_element, AVIOContext *pb, void *log_ctx)
Definition: iamf_writer.c:737
iamf_writer.h
AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM
@ AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM
IAMF Demixing Info Parameter Data associated with the audio frame.
Definition: packet.h:312