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