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, void *log_ctx)
110 {
111  const AVStream *st = stg->streams[0];
113  int j, ret = 0;
114 
115  if (!st->codecpar->frame_size) {
116  av_log(log_ctx, AV_LOG_ERROR, "frame_size is unset for stream id %d\n",
117  st->id);
118  return AVERROR(EINVAL);
119  }
120 
121  codec_config->codec_id = st->codecpar->codec_id;
122  codec_config->codec_tag = st->codecpar->codec_tag;
123  switch (codec_config->codec_id) {
124  case AV_CODEC_ID_OPUS:
125  codec_config->sample_rate = 48000;
126  codec_config->nb_samples = av_rescale(st->codecpar->frame_size, 48000, st->codecpar->sample_rate);
127  break;
128  default:
129  codec_config->sample_rate = st->codecpar->sample_rate;
130  codec_config->nb_samples = st->codecpar->frame_size;
131  break;
132  }
133  populate_audio_roll_distance(codec_config);
134  if (st->codecpar->extradata_size) {
136  return AVERROR_INVALIDDATA;
137 
139  if (!codec_config->extradata)
140  return AVERROR(ENOMEM);
141  memcpy(codec_config->extradata, st->codecpar->extradata, st->codecpar->extradata_size);
142  memset(codec_config->extradata + st->codecpar->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
143  codec_config->extradata_size = st->codecpar->extradata_size;
144  ret = update_extradata(codec_config);
145  if (ret < 0)
146  goto fail;
147  }
148 
149  for (j = 0; j < iamf->nb_codec_configs; j++) {
150  if (!memcmp(iamf->codec_configs[j], codec_config, offsetof(IAMFCodecConfig, extradata)) &&
151  (!codec_config->extradata_size || !memcmp(iamf->codec_configs[j]->extradata,
152  codec_config->extradata, codec_config->extradata_size)))
153  break;
154  }
155 
156  if (j < iamf->nb_codec_configs) {
157  av_free(iamf->codec_configs[j]->extradata);
158  av_free(iamf->codec_configs[j]);
159  iamf->codec_configs[j] = codec_config;
160  return j;
161  }
162 
163  tmp = av_realloc_array(iamf->codec_configs, iamf->nb_codec_configs + 1, sizeof(*iamf->codec_configs));
164  if (!tmp) {
165  ret = AVERROR(ENOMEM);
166  goto fail;
167  }
168 
169  iamf->codec_configs = tmp;
170  iamf->codec_configs[iamf->nb_codec_configs] = codec_config;
171  codec_config->codec_config_id = iamf->nb_codec_configs;
172 
173  return iamf->nb_codec_configs++;
174 
175 fail:
176  av_freep(&codec_config->extradata);
177  return ret;
178 }
179 
181  const IAMFAudioElement *audio_element, void *log_ctx)
182 {
184  IAMFCodecConfig *codec_config = NULL;
185 
187  sizeof(*iamf->param_definitions));
188  if (!tmp)
189  return AVERROR(ENOMEM);
190 
191  iamf->param_definitions = tmp;
192 
193  if (audio_element)
194  codec_config = iamf->codec_configs[audio_element->codec_config_id];
195 
196  if (!param->parameter_rate) {
197  if (!codec_config) {
198  av_log(log_ctx, AV_LOG_ERROR, "parameter_rate needed but not set for parameter_id %u\n",
199  param->parameter_id);
200  return AVERROR(EINVAL);
201  }
202  param->parameter_rate = codec_config->sample_rate;
203  }
204  if (codec_config) {
205  if (!param->duration)
206  param->duration = av_rescale(codec_config->nb_samples, param->parameter_rate, codec_config->sample_rate);
207  if (!param->constant_subblock_duration)
208  param->constant_subblock_duration = av_rescale(codec_config->nb_samples, param->parameter_rate, codec_config->sample_rate);
209  }
210 
212  if (!param_definition)
213  return AVERROR(ENOMEM);
214 
215  param_definition->mode = !!param->duration;
216  param_definition->param = param;
217  param_definition->audio_element = audio_element;
219 
220  return 0;
221 }
222 
223 int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
224 {
225  const AVIAMFAudioElement *iamf_audio_element;
226  IAMFAudioElement **tmp, *audio_element;
227  IAMFCodecConfig *codec_config;
228  int ret;
229 
231  return AVERROR(EINVAL);
232  if (!stg->nb_streams) {
233  av_log(log_ctx, AV_LOG_ERROR, "Audio Element id %"PRId64" has no streams\n", stg->id);
234  return AVERROR(EINVAL);
235  }
236 
237  iamf_audio_element = stg->params.iamf_audio_element;
238  if (iamf_audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE) {
239  const AVIAMFLayer *layer = iamf_audio_element->layers[0];
240  if (iamf_audio_element->nb_layers != 1) {
241  av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of layers for SCENE_BASED audio element. Must be 1\n");
242  return AVERROR(EINVAL);
243  }
244  if (layer->ch_layout.order != AV_CHANNEL_ORDER_CUSTOM &&
246  av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout for SCENE_BASED audio element\n");
247  return AVERROR(EINVAL);
248  }
250  av_log(log_ctx, AV_LOG_ERROR, "Unsupported ambisonics mode %d\n", layer->ambisonics_mode);
251  return AVERROR_PATCHWELCOME;
252  }
253  for (int i = 0; i < stg->nb_streams; i++) {
254  if (stg->streams[i]->codecpar->ch_layout.nb_channels > 1) {
255  av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of channels in a stream for MONO mode ambisonics\n");
256  return AVERROR(EINVAL);
257  }
258  }
259  } else {
260  AVBPrint bp;
261 
262  if (iamf_audio_element->nb_layers < 1) {
263  av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of layers for CHANNEL_BASED audio element. Must be >= 1\n");
264  return AVERROR(EINVAL);
265  }
266 
267  for (int j, i = 0; i < iamf_audio_element->nb_layers; i++) {
268  const AVIAMFLayer *layer = iamf_audio_element->layers[i];
269 
270  for (j = 0; j < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts); j++)
271  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
273  break;
274 
277  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
279  break;
280 
284  av_log(log_ctx, AV_LOG_ERROR, "Unsupported channel layout in Audio Element id %"PRId64
285  ", Layer %d: %s\n",
286  stg->id, i, bp.str);
287  av_bprint_finalize(&bp, NULL);
288  return AVERROR(EINVAL);
289  }
290  }
291 
292  if (!i)
293  continue;
294 
295  const AVIAMFLayer *prev_layer = iamf_audio_element->layers[i-1];
296  uint64_t prev_mask = av_channel_layout_subset(&prev_layer->ch_layout, UINT64_MAX);
297  if (av_channel_layout_subset(&layer->ch_layout, prev_mask) != prev_mask || (layer->ch_layout.nb_channels <=
298  prev_layer->ch_layout.nb_channels)) {
300  av_bprintf(&bp, "Channel layout \"");
302  av_bprintf(&bp, "\" can't follow channel layout \"");
303  av_channel_layout_describe_bprint(&prev_layer->ch_layout, &bp);
304  av_bprintf(&bp, "\" in Scalable Audio Element id %"PRId64, stg->id);
305  av_log(log_ctx, AV_LOG_ERROR, "%s\n", bp.str);
306  av_bprint_finalize(&bp, NULL);
307  return AVERROR(EINVAL);
308  }
309  }
310  }
311 
312  for (int i = 0; i < iamf->nb_audio_elements; i++) {
313  if (stg->id == iamf->audio_elements[i]->audio_element_id) {
314  av_log(log_ctx, AV_LOG_ERROR, "Duplicated Audio Element id %"PRId64"\n", stg->id);
315  return AVERROR(EINVAL);
316  }
317  }
318 
319  codec_config = av_mallocz(sizeof(*codec_config));
320  if (!codec_config)
321  return AVERROR(ENOMEM);
322 
323  ret = fill_codec_config(iamf, stg, codec_config, log_ctx);
324  if (ret < 0) {
325  av_free(codec_config);
326  return ret;
327  }
328 
329  audio_element = av_mallocz(sizeof(*audio_element));
330  if (!audio_element)
331  return AVERROR(ENOMEM);
332 
333  audio_element->celement = stg->params.iamf_audio_element;
334  audio_element->audio_element_id = stg->id;
335  audio_element->codec_config_id = ret;
336 
337  audio_element->substreams = av_calloc(stg->nb_streams, sizeof(*audio_element->substreams));
338  if (!audio_element->substreams) {
339  ret = AVERROR(ENOMEM);
340  goto fail;
341  }
342  audio_element->nb_substreams = stg->nb_streams;
343 
344  audio_element->layers = av_calloc(iamf_audio_element->nb_layers, sizeof(*audio_element->layers));
345  if (!audio_element->layers) {
346  ret = AVERROR(ENOMEM);
347  goto fail;
348  }
349 
350  for (int i = 0, j = 0; i < iamf_audio_element->nb_layers; i++) {
351  int nb_channels = iamf_audio_element->layers[i]->ch_layout.nb_channels;
352 
353  IAMFLayer *layer = &audio_element->layers[i];
354 
355  if (i)
356  nb_channels -= iamf_audio_element->layers[i - 1]->ch_layout.nb_channels;
357  for (; nb_channels > 0 && j < stg->nb_streams; j++) {
358  const AVStream *st = stg->streams[j];
359  IAMFSubStream *substream = &audio_element->substreams[j];
360 
361  substream->audio_substream_id = st->id;
362  layer->substream_count++;
364  nb_channels -= st->codecpar->ch_layout.nb_channels;
365  }
366  if (nb_channels) {
367  av_log(log_ctx, AV_LOG_ERROR, "Invalid channel count across substreams in layer %u from stream group %u\n",
368  i, stg->index);
369  ret = AVERROR(EINVAL);
370  goto fail;
371  }
372  }
373 
374  for (int i = 0; i < audio_element->nb_substreams; i++) {
375  for (int j = i + 1; j < audio_element->nb_substreams; j++)
376  if (audio_element->substreams[i].audio_substream_id ==
377  audio_element->substreams[j].audio_substream_id) {
378  av_log(log_ctx, AV_LOG_ERROR, "Duplicate id %u in streams %u and %u from stream group %u\n",
379  audio_element->substreams[i].audio_substream_id, i, j, stg->index);
380  ret = AVERROR(EINVAL);
381  goto fail;
382  }
383  }
384 
385  if (iamf_audio_element->demixing_info) {
386  AVIAMFParamDefinition *param = iamf_audio_element->demixing_info;
388 
389  if (param->nb_subblocks != 1) {
390  av_log(log_ctx, AV_LOG_ERROR, "nb_subblocks in demixing_info for stream group %u is not 1\n", stg->index);
391  ret = AVERROR(EINVAL);
392  goto fail;
393  }
394 
395  if (!param_definition) {
396  ret = add_param_definition(iamf, param, audio_element, log_ctx);
397  if (ret < 0)
398  goto fail;
399  }
400  }
401  if (iamf_audio_element->recon_gain_info) {
402  AVIAMFParamDefinition *param = iamf_audio_element->recon_gain_info;
404 
405  if (param->nb_subblocks != 1) {
406  av_log(log_ctx, AV_LOG_ERROR, "nb_subblocks in recon_gain_info for stream group %u is not 1\n", stg->index);
407  ret = AVERROR(EINVAL);
408  goto fail;
409  }
410 
411  if (!param_definition) {
412  ret = add_param_definition(iamf, param, audio_element, log_ctx);
413  if (ret < 0)
414  goto fail;
415  }
416  }
417 
418  tmp = av_realloc_array(iamf->audio_elements, iamf->nb_audio_elements + 1, sizeof(*iamf->audio_elements));
419  if (!tmp) {
420  ret = AVERROR(ENOMEM);
421  goto fail;
422  }
423 
424  iamf->audio_elements = tmp;
425  iamf->audio_elements[iamf->nb_audio_elements++] = audio_element;
426 
427  return 0;
428 fail:
429  ff_iamf_free_audio_element(&audio_element);
430  return ret;
431 }
432 
433 int ff_iamf_add_mix_presentation(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx)
434 {
435  IAMFMixPresentation **tmp, *mix_presentation;
436  int ret;
437 
439  return AVERROR(EINVAL);
440  if (!stg->nb_streams) {
441  av_log(log_ctx, AV_LOG_ERROR, "Mix Presentation id %"PRId64" has no streams\n", stg->id);
442  return AVERROR(EINVAL);
443  }
444 
445  for (int i = 0; i < iamf->nb_mix_presentations; i++) {
446  if (stg->id == iamf->mix_presentations[i]->mix_presentation_id) {
447  av_log(log_ctx, AV_LOG_ERROR, "Duplicate Mix Presentation id %"PRId64"\n", stg->id);
448  return AVERROR(EINVAL);
449  }
450  }
451 
452  mix_presentation = av_mallocz(sizeof(*mix_presentation));
453  if (!mix_presentation)
454  return AVERROR(ENOMEM);
455 
456  mix_presentation->cmix = stg->params.iamf_mix_presentation;
457  mix_presentation->mix_presentation_id = stg->id;
458 
459  for (int i = 0; i < mix_presentation->cmix->nb_submixes; i++) {
460  const AVIAMFSubmix *submix = mix_presentation->cmix->submixes[i];
461  AVIAMFParamDefinition *param = submix->output_mix_config;
463 
464  if (!param) {
465  av_log(log_ctx, AV_LOG_ERROR, "output_mix_config is not present in submix %u from "
466  "Mix Presentation ID %"PRId64"\n", i, stg->id);
467  ret = AVERROR(EINVAL);
468  goto fail;
469  }
470 
472  if (!param_definition) {
473  ret = add_param_definition(iamf, param, NULL, log_ctx);
474  if (ret < 0)
475  goto fail;
476  }
477 
478  for (int j = 0; j < submix->nb_elements; j++) {
479  const AVIAMFSubmixElement *element = submix->elements[j];
480  param = element->element_mix_config;
481 
482  if (!param) {
483  av_log(log_ctx, AV_LOG_ERROR, "element_mix_config is not present for element %u in submix %u from "
484  "Mix Presentation ID %"PRId64"\n", j, i, stg->id);
485  ret = AVERROR(EINVAL);
486  goto fail;
487  }
489  if (!param_definition) {
490  ret = add_param_definition(iamf, param, NULL, log_ctx);
491  if (ret < 0)
492  goto fail;
493  }
494  }
495  }
496 
498  if (!tmp) {
499  ret = AVERROR(ENOMEM);
500  goto fail;
501  }
502 
503  iamf->mix_presentations = tmp;
504  iamf->mix_presentations[iamf->nb_mix_presentations++] = mix_presentation;
505 
506  return 0;
507 fail:
508  ff_iamf_free_mix_presentation(&mix_presentation);
509  return ret;
510 }
511 
512 static int iamf_write_codec_config(const IAMFContext *iamf,
513  const IAMFCodecConfig *codec_config,
514  AVIOContext *pb)
515 {
517  AVIOContext *dyn_bc;
518  uint8_t *dyn_buf = NULL;
519  PutBitContext pbc;
520  int dyn_size;
521 
522  int ret = avio_open_dyn_buf(&dyn_bc);
523  if (ret < 0)
524  return ret;
525 
526  ffio_write_leb(dyn_bc, codec_config->codec_config_id);
527  avio_wl32(dyn_bc, codec_config->codec_tag);
528 
529  ffio_write_leb(dyn_bc, codec_config->nb_samples);
530  avio_wb16(dyn_bc, codec_config->audio_roll_distance);
531 
532  switch(codec_config->codec_id) {
533  case AV_CODEC_ID_OPUS:
534  avio_write(dyn_bc, codec_config->extradata, codec_config->extradata_size);
535  break;
536  case AV_CODEC_ID_AAC:
537  return AVERROR_PATCHWELCOME;
538  case AV_CODEC_ID_FLAC:
539  avio_w8(dyn_bc, 0x80);
540  avio_wb24(dyn_bc, codec_config->extradata_size);
541  avio_write(dyn_bc, codec_config->extradata, codec_config->extradata_size);
542  break;
544  avio_w8(dyn_bc, 1);
545  avio_w8(dyn_bc, 16);
546  avio_wb32(dyn_bc, codec_config->sample_rate);
547  break;
549  avio_w8(dyn_bc, 1);
550  avio_w8(dyn_bc, 24);
551  avio_wb32(dyn_bc, codec_config->sample_rate);
552  break;
554  avio_w8(dyn_bc, 1);
555  avio_w8(dyn_bc, 32);
556  avio_wb32(dyn_bc, codec_config->sample_rate);
557  break;
559  avio_w8(dyn_bc, 0);
560  avio_w8(dyn_bc, 16);
561  avio_wb32(dyn_bc, codec_config->sample_rate);
562  break;
564  avio_w8(dyn_bc, 0);
565  avio_w8(dyn_bc, 24);
566  avio_wb32(dyn_bc, codec_config->sample_rate);
567  break;
569  avio_w8(dyn_bc, 0);
570  avio_w8(dyn_bc, 32);
571  avio_wb32(dyn_bc, codec_config->sample_rate);
572  break;
573  default:
574  break;
575  }
576 
577  init_put_bits(&pbc, header, sizeof(header));
579  put_bits(&pbc, 3, 0);
580  flush_put_bits(&pbc);
581 
582  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
583  avio_write(pb, header, put_bytes_count(&pbc, 1));
584  ffio_write_leb(pb, dyn_size);
585  avio_write(pb, dyn_buf, dyn_size);
586  ffio_free_dyn_buf(&dyn_bc);
587 
588  return 0;
589 }
590 
591 static inline int rescale_rational(AVRational q, int b)
592 {
593  return av_clip_int16(av_rescale(q.num, b, q.den));
594 }
595 
596 static void get_loudspeaker_layout(const AVIAMFLayer *layer,
597  int *playout, int *pexpanded_layout)
598 {
599  int layout, expanded_layout = -1;
600 
603  break;
604  }
607  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
609  break;
610  }
612  layout = 15;
613  for (expanded_layout = 0; expanded_layout < FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts); expanded_layout++) {
615  break;
616  }
617  if (expanded_layout >= FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts)) {
618  for (expanded_layout = 0; expanded_layout < FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts); expanded_layout++)
619  if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
620  av_channel_layout_subset(&ff_iamf_expanded_scalable_ch_layouts[expanded_layout], UINT64_MAX))
621  break;
622  }
623  }
624  av_assert0((expanded_layout > 0 && expanded_layout < FF_ARRAY_ELEMS(ff_iamf_expanded_scalable_ch_layouts)) ||
626 
627  *playout = layout;
628  *pexpanded_layout = expanded_layout;
629 }
630 
631 static int scalable_channel_layout_config(const IAMFAudioElement *audio_element,
632  AVIOContext *dyn_bc)
633 {
634  const AVIAMFAudioElement *element = audio_element->celement;
636  PutBitContext pb;
637 
638  init_put_bits(&pb, header, sizeof(header));
639  put_bits(&pb, 3, element->nb_layers);
640  put_bits(&pb, 5, 0);
641  flush_put_bits(&pb);
642  avio_write(dyn_bc, header, put_bytes_count(&pb, 1));
643  for (int i = 0; i < element->nb_layers; i++) {
644  const AVIAMFLayer *layer = element->layers[i];
645  int layout, expanded_layout;
646 
647  get_loudspeaker_layout(layer, &layout, &expanded_layout);
648  init_put_bits(&pb, header, sizeof(header));
649  put_bits(&pb, 4, layout);
650  put_bits(&pb, 1, !!layer->output_gain_flags);
651  put_bits(&pb, 1, !!(layer->flags & AV_IAMF_LAYER_FLAG_RECON_GAIN));
652  put_bits(&pb, 2, 0); // reserved
653  put_bits(&pb, 8, audio_element->layers[i].substream_count);
654  put_bits(&pb, 8, audio_element->layers[i].coupled_substream_count);
655  if (layer->output_gain_flags) {
656  put_bits(&pb, 6, layer->output_gain_flags);
657  put_bits(&pb, 2, 0);
658  put_bits(&pb, 16, rescale_rational(layer->output_gain, 1 << 8));
659  }
660  if (expanded_layout >= 0)
661  put_bits(&pb, 8, expanded_layout);
662  flush_put_bits(&pb);
663  avio_write(dyn_bc, header, put_bytes_count(&pb, 1));
664  }
665 
666  return 0;
667 }
668 
669 static int ambisonics_config(const IAMFAudioElement *audio_element,
670  AVIOContext *dyn_bc)
671 {
672  const AVIAMFAudioElement *element = audio_element->celement;
673  const IAMFLayer *ilayer = &audio_element->layers[0];
674  const AVIAMFLayer *layer = element->layers[0];
675 
676  if (audio_element->nb_substreams != ilayer->substream_count)
677  return AVERROR(EINVAL);
678 
679  ffio_write_leb(dyn_bc, layer->ambisonics_mode);
680  avio_w8(dyn_bc, layer->ch_layout.nb_channels); // output_channel_count
681  avio_w8(dyn_bc, audio_element->nb_substreams); // substream_count
682 
685  for (int i = 0; i < layer->ch_layout.nb_channels; i++)
686  avio_w8(dyn_bc, i);
687  else
688  for (int i = 0; i < layer->ch_layout.nb_channels; i++)
689  avio_w8(dyn_bc, layer->ch_layout.u.map[i].id);
690  } else {
691  int nb_demixing_matrix = (ilayer->coupled_substream_count + ilayer->substream_count) * layer->ch_layout.nb_channels;
692  if (nb_demixing_matrix != layer->nb_demixing_matrix)
693  return AVERROR(EINVAL);
694  avio_w8(dyn_bc, ilayer->coupled_substream_count);
695  for (int i = 0; i < layer->nb_demixing_matrix; i++)
696  avio_wb16(dyn_bc, rescale_rational(layer->demixing_matrix[i], 1 << 15));
697  }
698 
699  return 0;
700 }
701 
702 static int param_definition(const IAMFContext *iamf,
703  const IAMFParamDefinition *param_def,
704  AVIOContext *dyn_bc, void *log_ctx)
705 {
706  const AVIAMFParamDefinition *param = param_def->param;
707 
708  ffio_write_leb(dyn_bc, param->parameter_id);
709  ffio_write_leb(dyn_bc, param->parameter_rate);
710  avio_w8(dyn_bc, param->duration ? 0 : 1 << 7);
711  if (param->duration) {
712  ffio_write_leb(dyn_bc, param->duration);
714  if (param->constant_subblock_duration == 0) {
715  ffio_write_leb(dyn_bc, param->nb_subblocks);
716  for (int i = 0; i < param->nb_subblocks; i++) {
717  const void *subblock = av_iamf_param_definition_get_subblock(param, i);
718 
719  switch (param->type) {
721  const AVIAMFMixGain *mix = subblock;
722  ffio_write_leb(dyn_bc, mix->subblock_duration);
723  break;
724  }
726  const AVIAMFDemixingInfo *demix = subblock;
727  ffio_write_leb(dyn_bc, demix->subblock_duration);
728  break;
729  }
731  const AVIAMFReconGain *recon = subblock;
732  ffio_write_leb(dyn_bc, recon->subblock_duration);
733  break;
734  }
735  }
736  }
737  }
738  }
739 
740  return 0;
741 }
742 
743 static int iamf_write_audio_element(const IAMFContext *iamf,
744  const IAMFAudioElement *audio_element,
745  AVIOContext *pb, void *log_ctx)
746 {
747  const AVIAMFAudioElement *element = audio_element->celement;
748  const IAMFCodecConfig *codec_config = iamf->codec_configs[audio_element->codec_config_id];
750  AVIOContext *dyn_bc;
751  uint8_t *dyn_buf = NULL;
752  PutBitContext pbc;
753  int param_definition_types = AV_IAMF_PARAMETER_DEFINITION_DEMIXING, dyn_size;
754 
755  int ret = avio_open_dyn_buf(&dyn_bc);
756  if (ret < 0)
757  return ret;
758 
759  ffio_write_leb(dyn_bc, audio_element->audio_element_id);
760 
761  init_put_bits(&pbc, header, sizeof(header));
762  put_bits(&pbc, 3, element->audio_element_type);
763  put_bits(&pbc, 5, 0);
764  flush_put_bits(&pbc);
765  avio_write(dyn_bc, header, put_bytes_count(&pbc, 1));
766 
767  ffio_write_leb(dyn_bc, audio_element->codec_config_id);
768  ffio_write_leb(dyn_bc, audio_element->nb_substreams);
769 
770  for (int i = 0; i < audio_element->nb_substreams; i++)
771  ffio_write_leb(dyn_bc, audio_element->substreams[i].audio_substream_id);
772 
773  /* When audio_element_type = 1, num_parameters SHALL be set to 0 */
775  param_definition_types = 0;
776  else {
777  int layout = 0, expanded_layout = 0;
778  get_loudspeaker_layout(element->layers[0], &layout, &expanded_layout);
779  /* When the loudspeaker_layout = 15, the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
780  if (layout == 15) {
781  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
782  /* expanded_loudspeaker_layout SHALL only be present when num_layers = 1 and loudspeaker_layout is set to 15 */
783  if (element->nb_layers > 1) {
784  av_log(log_ctx, AV_LOG_ERROR, "expanded_loudspeaker_layout present when using more than one layer in "
785  "Stream Group #%u\n",
786  audio_element->audio_element_id);
787  return AVERROR(EINVAL);
788  }
789  }
790  /* When the loudspeaker_layout of the (non-)scalable channel audio (i.e., num_layers = 1) is less than or equal to 3.1.2ch,
791  * (i.e., Mono, Stereo, or 3.1.2ch), the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
792  else if (element->nb_layers == 1 && (layout == 0 || layout == 1 || layout == 8))
793  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
794  /* When num_layers > 1, the type PARAMETER_DEFINITION_RECON_GAIN SHALL be present */
795  if (element->nb_layers > 1)
796  param_definition_types |= AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
797  /* When codec_id = fLaC or ipcm, the type PARAMETER_DEFINITION_RECON_GAIN SHALL NOT be present. */
798  if (codec_config->codec_tag == MKTAG('f','L','a','C') ||
799  codec_config->codec_tag == MKTAG('i','p','c','m'))
800  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
801  if ((param_definition_types & AV_IAMF_PARAMETER_DEFINITION_DEMIXING) && !element->demixing_info) {
802  if (element->nb_layers > 1) {
803  get_loudspeaker_layout(element->layers[element->nb_layers-1], &layout, &expanded_layout);
804  /* When the highest loudspeaker_layout of the scalable channel audio (i.e., num_layers > 1) is greater than 3.1.2ch,
805  * (i.e., 5.1.2ch, 5.1.4ch, 7.1.2ch, or 7.1.4ch), type PARAMETER_DEFINITION_DEMIXING SHALL be present. */
806  if (layout == 3 || layout == 4 || layout == 6 || layout == 7) {
807  av_log(log_ctx, AV_LOG_ERROR, "demixing_info needed but not set in Stream Group #%u\n",
808  audio_element->audio_element_id);
809  return AVERROR(EINVAL);
810  }
811  }
812  param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
813  }
814  }
815 
816  ffio_write_leb(dyn_bc, av_popcount(param_definition_types)); // num_parameters
817 
818  if (param_definition_types & AV_IAMF_PARAMETER_DEFINITION_DEMIXING) {
819  const AVIAMFParamDefinition *param = element->demixing_info;
820  const IAMFParamDefinition *param_def;
821  const AVIAMFDemixingInfo *demix;
822 
823  demix = av_iamf_param_definition_get_subblock(param, 0);
825 
826  param_def = ff_iamf_get_param_definition(iamf, param->parameter_id);
827  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
828  if (ret < 0)
829  return ret;
830 
831  avio_w8(dyn_bc, demix->dmixp_mode << 5); // dmixp_mode
832  avio_w8(dyn_bc, element->default_w << 4); // default_w
833  }
834  if (param_definition_types & AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) {
835  const AVIAMFParamDefinition *param = element->recon_gain_info;
836  const IAMFParamDefinition *param_def;
837 
838  if (!param) {
839  av_log(log_ctx, AV_LOG_ERROR, "recon_gain_info needed but not set in Stream Group #%u\n",
840  audio_element->audio_element_id);
841  return AVERROR(EINVAL);
842  }
844 
845  param_def = ff_iamf_get_param_definition(iamf, param->parameter_id);
846  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
847  if (ret < 0)
848  return ret;
849  }
850 
852  ret = scalable_channel_layout_config(audio_element, dyn_bc);
853  if (ret < 0)
854  return ret;
855  } else {
856  ret = ambisonics_config(audio_element, dyn_bc);
857  if (ret < 0)
858  return ret;
859  }
860 
861  init_put_bits(&pbc, header, sizeof(header));
863  put_bits(&pbc, 3, 0);
864  flush_put_bits(&pbc);
865 
866  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
867  avio_write(pb, header, put_bytes_count(&pbc, 1));
868  ffio_write_leb(pb, dyn_size);
869  avio_write(pb, dyn_buf, dyn_size);
870  ffio_free_dyn_buf(&dyn_bc);
871 
872  return 0;
873 }
874 
876  const IAMFMixPresentation *mix_presentation,
877  AVIOContext *pb, void *log_ctx)
878 {
880  const AVIAMFMixPresentation *mix = mix_presentation->cmix;
881  const AVDictionaryEntry *tag = NULL;
882  PutBitContext pbc;
883  AVIOContext *dyn_bc;
884  uint8_t *dyn_buf = NULL;
885  int dyn_size;
886 
887  int ret = avio_open_dyn_buf(&dyn_bc);
888  if (ret < 0)
889  return ret;
890 
891  ffio_write_leb(dyn_bc, mix_presentation->mix_presentation_id); // mix_presentation_id
892  ffio_write_leb(dyn_bc, av_dict_count(mix->annotations)); // count_label
893 
894  while ((tag = av_dict_iterate(mix->annotations, tag)))
895  avio_put_str(dyn_bc, tag->key);
896  while ((tag = av_dict_iterate(mix->annotations, tag)))
897  avio_put_str(dyn_bc, tag->value);
898 
899  ffio_write_leb(dyn_bc, mix->nb_submixes);
900  for (int i = 0; i < mix->nb_submixes; i++) {
901  const AVIAMFSubmix *sub_mix = mix->submixes[i];
902  const IAMFParamDefinition *param_def;
903 
904  ffio_write_leb(dyn_bc, sub_mix->nb_elements);
905  for (int j = 0; j < sub_mix->nb_elements; j++) {
906  const IAMFAudioElement *audio_element = NULL;
907  const AVIAMFSubmixElement *submix_element = sub_mix->elements[j];
908 
909  for (int k = 0; k < iamf->nb_audio_elements; k++)
910  if (iamf->audio_elements[k]->audio_element_id == submix_element->audio_element_id) {
911  audio_element = iamf->audio_elements[k];
912  break;
913  }
914 
915  av_assert0(audio_element);
916  ffio_write_leb(dyn_bc, submix_element->audio_element_id);
917 
918  if (av_dict_count(submix_element->annotations) != av_dict_count(mix->annotations)) {
919  av_log(log_ctx, AV_LOG_ERROR, "Inconsistent amount of labels in submix %d from Mix Presentation id #%u\n",
920  j, audio_element->audio_element_id);
921  return AVERROR(EINVAL);
922  }
923  while ((tag = av_dict_iterate(submix_element->annotations, tag)))
924  avio_put_str(dyn_bc, tag->value);
925 
926  init_put_bits(&pbc, header, sizeof(header));
927  put_bits(&pbc, 2, submix_element->headphones_rendering_mode);
928  put_bits(&pbc, 6, 0); // reserved
929  flush_put_bits(&pbc);
930  avio_write(dyn_bc, header, put_bytes_count(&pbc, 1));
931  ffio_write_leb(dyn_bc, 0); // rendering_config_extension_size
932 
933  param_def = ff_iamf_get_param_definition(iamf, submix_element->element_mix_config->parameter_id);
934  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
935  if (ret < 0)
936  return ret;
937 
938  avio_wb16(dyn_bc, rescale_rational(submix_element->default_mix_gain, 1 << 8));
939  }
940 
941  param_def = ff_iamf_get_param_definition(iamf, sub_mix->output_mix_config->parameter_id);
942  ret = param_definition(iamf, param_def, dyn_bc, log_ctx);
943  if (ret < 0)
944  return ret;
945  avio_wb16(dyn_bc, rescale_rational(sub_mix->default_mix_gain, 1 << 8));
946 
947  ffio_write_leb(dyn_bc, sub_mix->nb_layouts); // nb_layouts
948  for (int i = 0; i < sub_mix->nb_layouts; i++) {
949  const AVIAMFSubmixLayout *submix_layout = sub_mix->layouts[i];
950  int layout, info_type;
951  int dialogue = submix_layout->dialogue_anchored_loudness.num &&
952  submix_layout->dialogue_anchored_loudness.den;
953  int album = submix_layout->album_anchored_loudness.num &&
954  submix_layout->album_anchored_loudness.den;
955 
959  break;
960  }
962  av_log(log_ctx, AV_LOG_ERROR, "Invalid Sound System value in a submix\n");
963  return AVERROR(EINVAL);
964  }
965  } else if (submix_layout->layout_type != AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL) {
966  av_log(log_ctx, AV_LOG_ERROR, "Unsupported Layout Type value in a submix\n");
967  return AVERROR(EINVAL);
968  }
969  init_put_bits(&pbc, header, sizeof(header));
970  put_bits(&pbc, 2, submix_layout->layout_type); // layout_type
972  put_bits(&pbc, 4, ff_iamf_sound_system_map[layout].id); // sound_system
973  put_bits(&pbc, 2, 0); // reserved
974  } else
975  put_bits(&pbc, 6, 0); // reserved
976  flush_put_bits(&pbc);
977  avio_write(dyn_bc, header, put_bytes_count(&pbc, 1));
978 
979  info_type = (submix_layout->true_peak.num && submix_layout->true_peak.den);
980  info_type |= (dialogue || album) << 1;
981  avio_w8(dyn_bc, info_type);
982  avio_wb16(dyn_bc, rescale_rational(submix_layout->integrated_loudness, 1 << 8));
983  avio_wb16(dyn_bc, rescale_rational(submix_layout->digital_peak, 1 << 8));
984  if (info_type & 1)
985  avio_wb16(dyn_bc, rescale_rational(submix_layout->true_peak, 1 << 8));
986  if (info_type & 2) {
987  avio_w8(dyn_bc, dialogue + album); // num_anchored_loudness
988  if (dialogue) {
990  avio_wb16(dyn_bc, rescale_rational(submix_layout->dialogue_anchored_loudness, 1 << 8));
991  }
992  if (album) {
994  avio_wb16(dyn_bc, rescale_rational(submix_layout->album_anchored_loudness, 1 << 8));
995  }
996  }
997  }
998  }
999 
1000  init_put_bits(&pbc, header, sizeof(header));
1002  put_bits(&pbc, 3, 0);
1003  flush_put_bits(&pbc);
1004 
1005  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
1006  avio_write(pb, header, put_bytes_count(&pbc, 1));
1007  ffio_write_leb(pb, dyn_size);
1008  avio_write(pb, dyn_buf, dyn_size);
1009  ffio_free_dyn_buf(&dyn_bc);
1010 
1011  return 0;
1012 }
1013 
1014 int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void *log_ctx)
1015 {
1016  int ret;
1017 
1018  // Sequence Header
1020 
1021  ffio_write_leb(pb, 6);
1022  avio_wb32(pb, MKBETAG('i','a','m','f'));
1023  avio_w8(pb, iamf->nb_audio_elements > 1); // primary_profile
1024  avio_w8(pb, iamf->nb_audio_elements > 1); // additional_profile
1025 
1026  for (int i = 0; i < iamf->nb_codec_configs; i++) {
1027  ret = iamf_write_codec_config(iamf, iamf->codec_configs[i], pb);
1028  if (ret < 0)
1029  return ret;
1030  }
1031 
1032  for (int i = 0; i < iamf->nb_audio_elements; i++) {
1033  ret = iamf_write_audio_element(iamf, iamf->audio_elements[i], pb, log_ctx);
1034  if (ret < 0)
1035  return ret;
1036  }
1037 
1038  for (int i = 0; i < iamf->nb_mix_presentations; i++) {
1039  ret = iamf_write_mixing_presentation(iamf, iamf->mix_presentations[i], pb, log_ctx);
1040  if (ret < 0)
1041  return ret;
1042  }
1043 
1044  return 0;
1045 }
1046 
1047 static int write_parameter_block(const IAMFContext *iamf, AVIOContext *pb,
1048  const AVIAMFParamDefinition *param, void *log_ctx)
1049 {
1052  PutBitContext pbc;
1053  AVIOContext *dyn_bc;
1054  uint8_t *dyn_buf = NULL;
1055  int dyn_size, ret;
1056 
1058  av_log(log_ctx, AV_LOG_DEBUG, "Ignoring side data with unknown type %u\n",
1059  param->type);
1060  return 0;
1061  }
1062 
1063  if (!param_definition) {
1064  av_log(log_ctx, AV_LOG_ERROR, "Non-existent Parameter Definition with ID %u referenced by a packet\n",
1065  param->parameter_id);
1066  return AVERROR(EINVAL);
1067  }
1068 
1069  if (param->type != param_definition->param->type) {
1070  av_log(log_ctx, AV_LOG_ERROR, "Inconsistent values for Parameter Definition "
1071  "with ID %u in a packet\n",
1072  param->parameter_id);
1073  return AVERROR(EINVAL);
1074  }
1075 
1076  ret = avio_open_dyn_buf(&dyn_bc);
1077  if (ret < 0)
1078  return ret;
1079 
1080  // Sequence Header
1081  init_put_bits(&pbc, header, sizeof(header));
1083  put_bits(&pbc, 3, 0);
1084  flush_put_bits(&pbc);
1085  avio_write(pb, header, put_bytes_count(&pbc, 1));
1086 
1087  ffio_write_leb(dyn_bc, param->parameter_id);
1088  if (!param_definition->mode) {
1089  ffio_write_leb(dyn_bc, param->duration);
1091  if (param->constant_subblock_duration == 0)
1092  ffio_write_leb(dyn_bc, param->nb_subblocks);
1093  }
1094 
1095  for (int i = 0; i < param->nb_subblocks; i++) {
1096  const void *subblock = av_iamf_param_definition_get_subblock(param, i);
1097 
1098  switch (param->type) {
1100  const AVIAMFMixGain *mix = subblock;
1101  if (!param_definition->mode && param->constant_subblock_duration == 0)
1102  ffio_write_leb(dyn_bc, mix->subblock_duration);
1103 
1104  ffio_write_leb(dyn_bc, mix->animation_type);
1105 
1106  avio_wb16(dyn_bc, rescale_rational(mix->start_point_value, 1 << 8));
1107  if (mix->animation_type >= AV_IAMF_ANIMATION_TYPE_LINEAR)
1108  avio_wb16(dyn_bc, rescale_rational(mix->end_point_value, 1 << 8));
1109  if (mix->animation_type == AV_IAMF_ANIMATION_TYPE_BEZIER) {
1110  avio_wb16(dyn_bc, rescale_rational(mix->control_point_value, 1 << 8));
1111  avio_w8(dyn_bc, av_clip_uint8(av_rescale(mix->control_point_relative_time.num, 1 << 8,
1112  mix->control_point_relative_time.den)));
1113  }
1114  break;
1115  }
1117  const AVIAMFDemixingInfo *demix = subblock;
1118  if (!param_definition->mode && param->constant_subblock_duration == 0)
1119  ffio_write_leb(dyn_bc, demix->subblock_duration);
1120 
1121  avio_w8(dyn_bc, demix->dmixp_mode << 5);
1122  break;
1123  }
1125  const AVIAMFReconGain *recon = subblock;
1126  const AVIAMFAudioElement *audio_element = param_definition->audio_element->celement;
1127 
1128  if (!param_definition->mode && param->constant_subblock_duration == 0)
1129  ffio_write_leb(dyn_bc, recon->subblock_duration);
1130 
1131  if (!audio_element) {
1132  av_log(log_ctx, AV_LOG_ERROR, "Invalid Parameter Definition with ID %u referenced by a packet\n", param->parameter_id);
1133  return AVERROR(EINVAL);
1134  }
1135 
1136  for (int j = 0; j < audio_element->nb_layers; j++) {
1137  const AVIAMFLayer *layer = audio_element->layers[j];
1138 
1139  if (layer->flags & AV_IAMF_LAYER_FLAG_RECON_GAIN) {
1140  unsigned int recon_gain_flags = 0;
1141  int k = 0;
1142 
1143  for (; k < 7; k++)
1144  recon_gain_flags |= (1 << k) * !!recon->recon_gain[j][k];
1145  for (; k < 12; k++)
1146  recon_gain_flags |= (2 << k) * !!recon->recon_gain[j][k];
1147  if (recon_gain_flags >> 8)
1148  recon_gain_flags |= (1 << k);
1149 
1150  ffio_write_leb(dyn_bc, recon_gain_flags);
1151  for (k = 0; k < 12; k++) {
1152  if (recon->recon_gain[j][k])
1153  avio_w8(dyn_bc, recon->recon_gain[j][k]);
1154  }
1155  }
1156  }
1157  break;
1158  }
1159  default:
1160  av_unreachable("param_definition_type should have been checked above");
1161  }
1162  }
1163 
1164  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
1165  ffio_write_leb(pb, dyn_size);
1166  avio_write(pb, dyn_buf, dyn_size);
1167  ffio_free_dyn_buf(&dyn_bc);
1168 
1169  return 0;
1170 }
1171 
1173  const AVPacket *pkt, void *log_ctx)
1174 {
1178  NULL);
1179  AVIAMFParamDefinition *demix =
1182  NULL);
1183  AVIAMFParamDefinition *recon =
1186  NULL);
1187 
1188  if (mix) {
1189  int ret = write_parameter_block(iamf, pb, mix, log_ctx);
1190  if (ret < 0)
1191  return ret;
1192  }
1193  if (demix) {
1194  int ret = write_parameter_block(iamf, pb, demix, log_ctx);
1195  if (ret < 0)
1196  return ret;
1197  }
1198  if (recon) {
1199  int ret = write_parameter_block(iamf, pb, recon, log_ctx);
1200  if (ret < 0)
1201  return ret;
1202  }
1203 
1204  return 0;
1205 }
1206 
1208  unsigned int audio_substream_id)
1209 {
1210  for (int i = 0; i < c->nb_audio_elements; i++) {
1211  IAMFAudioElement *audio_element = c->audio_elements[i];
1212  for (int j = 0; j < audio_element->nb_substreams; j++) {
1213  IAMFSubStream *substream = &audio_element->substreams[j];
1214  if (substream->audio_substream_id == audio_substream_id)
1215  return audio_element;
1216  }
1217  }
1218 
1219  return NULL;
1220 }
1221 
1223  unsigned audio_substream_id, const AVPacket *pkt)
1224 {
1226  PutBitContext pbc;
1227  const IAMFAudioElement *audio_element;
1228  IAMFCodecConfig *codec_config;
1229  AVIOContext *dyn_bc;
1230  const uint8_t *side_data;
1231  uint8_t *dyn_buf = NULL;
1232  unsigned int skip_samples = 0, discard_padding = 0;
1233  size_t side_data_size;
1234  int dyn_size, type = audio_substream_id <= 17 ?
1236  int ret;
1237 
1238  audio_element = get_audio_element(iamf, audio_substream_id);
1239  if (!audio_element)
1240  return AVERROR(EINVAL);
1241  codec_config = ff_iamf_get_codec_config(iamf, audio_element->codec_config_id);
1242  if (!codec_config)
1243  return AVERROR(EINVAL);
1244 
1245  if (!pkt->size) {
1246  size_t new_extradata_size;
1247  const uint8_t *new_extradata = av_packet_get_side_data(pkt,
1249  &new_extradata_size);
1250 
1251  if (!new_extradata || new_extradata_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
1252  return AVERROR_INVALIDDATA;
1253 
1254  av_free(codec_config->extradata);
1255  codec_config->extradata = av_malloc(new_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
1256  if (!codec_config->extradata) {
1257  codec_config->extradata_size = 0;
1258  return AVERROR(ENOMEM);
1259  }
1260  memcpy(codec_config->extradata, new_extradata, new_extradata_size);
1261  memset(codec_config->extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1262  codec_config->extradata_size = new_extradata_size;
1263 
1264  return update_extradata(codec_config);
1265  }
1266 
1268  &side_data_size);
1269 
1270  if (side_data && side_data_size >= 10) {
1271  skip_samples = AV_RL32(side_data);
1272  discard_padding = AV_RL32(side_data + 4);
1273  }
1274 
1275  if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
1276  // IAMF's num_samples_to_trim_at_start is the same as Opus's pre-skip.
1277  skip_samples = pkt->dts < 0
1278  ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
1279  : 0;
1280  discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
1281  }
1282 
1283  ret = avio_open_dyn_buf(&dyn_bc);
1284  if (ret < 0)
1285  return ret;
1286 
1287  init_put_bits(&pbc, header, sizeof(header));
1288  put_bits(&pbc, 5, type);
1289  put_bits(&pbc, 1, 0); // obu_redundant_copy
1290  put_bits(&pbc, 1, skip_samples || discard_padding);
1291  put_bits(&pbc, 1, 0); // obu_extension_flag
1292  flush_put_bits(&pbc);
1293  avio_write(pb, header, put_bytes_count(&pbc, 1));
1294 
1295  if (skip_samples || discard_padding) {
1296  ffio_write_leb(dyn_bc, discard_padding);
1297  ffio_write_leb(dyn_bc, skip_samples);
1298  }
1299 
1300  if (audio_substream_id > 17)
1301  ffio_write_leb(dyn_bc, audio_substream_id);
1302 
1303  dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf);
1304  ffio_write_leb(pb, dyn_size + pkt->size);
1305  avio_write(pb, dyn_buf, dyn_size);
1306  ffio_free_dyn_buf(&dyn_bc);
1307  avio_write(pb, pkt->data, pkt->size);
1308 
1309  return 0;
1310 }
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:339
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:1136
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:180
AVChannelLayout::u
union AVChannelLayout::@516 u
Details about which channels are present in this layout.
AV_CODEC_ID_FLAC
@ AV_CODEC_ID_FLAC
Definition: codec_id.h:473
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:1047
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:596
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:340
IAMFParamDefinition
Definition: iamf.h:121
fail
#define fail()
Definition: checkasm.h:225
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:591
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
AVStreamGroup::params
union AVStreamGroup::@448 params
Group type-specific parameters.
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:1108
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:223
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:1128
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:770
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:1207
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:433
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:463
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:351
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
fill_codec_config
static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg, IAMFCodecConfig *codec_config, void *log_ctx)
Definition: iamf_writer.c:108
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:1172
AVStreamGroup::iamf_audio_element
struct AVIAMFAudioElement * iamf_audio_element
Definition: avformat.h:1150
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:875
AV_CODEC_ID_OPUS
@ AV_CODEC_ID_OPUS
Definition: codec_id.h:521
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:631
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:512
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:1107
AVStreamGroup::streams
AVStream ** streams
A list of streams in the group.
Definition: avformat.h:1185
AVStreamGroup::iamf_mix_presentation
struct AVIAMFMixPresentation * iamf_mix_presentation
Definition: avformat.h:1151
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
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:702
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:348
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:1222
ff_iamf_write_descriptors
int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void *log_ctx)
Definition: iamf_writer.c:1014
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:669
tag
uint32_t tag
Definition: movenc.c:2049
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:759
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:747
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:1117
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:1172
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:347
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:1144
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:352
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:743
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