FFmpeg
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/common.h"
22 #include "libavutil/dict.h"
23 // #include "libavutil/error.h"
24 #include "libavutil/frame.h"
25 #include "libavutil/log.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/opt.h"
28 
29 #include "avresample.h"
30 #include "internal.h"
31 #include "audio_data.h"
32 #include "audio_convert.h"
33 #include "audio_mix.h"
34 #include "resample.h"
35 
37 {
38  int ret;
39 
40  if (avresample_is_open(avr)) {
41  av_log(avr, AV_LOG_ERROR, "The resampling context is already open.\n");
42  return AVERROR(EINVAL);
43  }
44 
45  /* set channel mixing parameters */
47  if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
48  av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
49  avr->in_channel_layout);
50  return AVERROR(EINVAL);
51  }
53  if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
54  av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
55  avr->out_channel_layout);
56  return AVERROR(EINVAL);
57  }
59  avr->downmix_needed = avr->in_channels > avr->out_channels;
60  avr->upmix_needed = avr->out_channels > avr->in_channels ||
61  (!avr->downmix_needed && (avr->mix_matrix ||
63  avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;
64 
65  /* set resampling parameters */
66  avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate ||
67  avr->force_resampling;
68 
69  /* select internal sample format if not specified by the user */
71  (avr->mixing_needed || avr->resample_needed)) {
74  int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt),
75  av_get_bytes_per_sample(out_fmt));
76  if (max_bps <= 2) {
78  } else if (avr->mixing_needed) {
80  } else {
81  if (max_bps <= 4) {
82  if (in_fmt == AV_SAMPLE_FMT_S32P ||
83  out_fmt == AV_SAMPLE_FMT_S32P) {
84  if (in_fmt == AV_SAMPLE_FMT_FLTP ||
85  out_fmt == AV_SAMPLE_FMT_FLTP) {
86  /* if one is s32 and the other is flt, use dbl */
88  } else {
89  /* if one is s32 and the other is s32, s16, or u8, use s32 */
91  }
92  } else {
93  /* if one is flt and the other is flt, s16 or u8, use flt */
95  }
96  } else {
97  /* if either is dbl, use dbl */
99  }
100  }
101  av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n",
103  }
104 
105  /* we may need to add an extra conversion in order to remap channels if
106  the output format is not planar */
107  if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
110  }
111 
112  /* set sample format conversion parameters */
113  if (avr->resample_needed || avr->mixing_needed)
115  else
116  avr->in_convert_needed = avr->use_channel_map &&
118 
119  if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
121  else
122  avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
123 
124  avr->in_copy_needed = !avr->in_convert_needed && (avr->mixing_needed ||
125  (avr->use_channel_map && avr->resample_needed));
126 
127  if (avr->use_channel_map) {
128  if (avr->in_copy_needed) {
129  avr->remap_point = REMAP_IN_COPY;
130  av_log(avr, AV_LOG_TRACE, "remap channels during in_copy\n");
131  } else if (avr->in_convert_needed) {
133  av_log(avr, AV_LOG_TRACE, "remap channels during in_convert\n");
134  } else if (avr->out_convert_needed) {
136  av_log(avr, AV_LOG_TRACE, "remap channels during out_convert\n");
137  } else {
139  av_log(avr, AV_LOG_TRACE, "remap channels during out_copy\n");
140  }
141 
142 #ifdef DEBUG
143  {
144  int ch;
145  av_log(avr, AV_LOG_TRACE, "output map: ");
146  if (avr->ch_map_info.do_remap)
147  for (ch = 0; ch < avr->in_channels; ch++)
148  av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_map[ch]);
149  else
150  av_log(avr, AV_LOG_TRACE, "n/a");
151  av_log(avr, AV_LOG_TRACE, "\n");
152  av_log(avr, AV_LOG_TRACE, "copy map: ");
153  if (avr->ch_map_info.do_copy)
154  for (ch = 0; ch < avr->in_channels; ch++)
155  av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_copy[ch]);
156  else
157  av_log(avr, AV_LOG_TRACE, "n/a");
158  av_log(avr, AV_LOG_TRACE, "\n");
159  av_log(avr, AV_LOG_TRACE, "zero map: ");
160  if (avr->ch_map_info.do_zero)
161  for (ch = 0; ch < avr->in_channels; ch++)
162  av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_zero[ch]);
163  else
164  av_log(avr, AV_LOG_TRACE, "n/a");
165  av_log(avr, AV_LOG_TRACE, "\n");
166  av_log(avr, AV_LOG_TRACE, "input map: ");
167  for (ch = 0; ch < avr->in_channels; ch++)
168  av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.input_map[ch]);
169  av_log(avr, AV_LOG_TRACE, "\n");
170  }
171 #endif
172  } else
173  avr->remap_point = REMAP_NONE;
174 
175  /* allocate buffers */
176  if (avr->in_copy_needed || avr->in_convert_needed) {
178  0, avr->internal_sample_fmt,
179  "in_buffer");
180  if (!avr->in_buffer) {
181  ret = AVERROR(EINVAL);
182  goto error;
183  }
184  }
185  if (avr->resample_needed) {
187  1024, avr->internal_sample_fmt,
188  "resample_out_buffer");
189  if (!avr->resample_out_buffer) {
190  ret = AVERROR(EINVAL);
191  goto error;
192  }
193  }
194  if (avr->out_convert_needed) {
196  avr->out_sample_fmt, "out_buffer");
197  if (!avr->out_buffer) {
198  ret = AVERROR(EINVAL);
199  goto error;
200  }
201  }
203  1024);
204  if (!avr->out_fifo) {
205  ret = AVERROR(ENOMEM);
206  goto error;
207  }
208 
209  /* setup contexts */
210  if (avr->in_convert_needed) {
212  avr->in_sample_fmt, avr->in_channels,
213  avr->in_sample_rate,
214  avr->remap_point == REMAP_IN_CONVERT);
215  if (!avr->ac_in) {
216  ret = AVERROR(ENOMEM);
217  goto error;
218  }
219  }
220  if (avr->out_convert_needed) {
221  enum AVSampleFormat src_fmt;
222  if (avr->in_convert_needed)
223  src_fmt = avr->internal_sample_fmt;
224  else
225  src_fmt = avr->in_sample_fmt;
226  avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
227  avr->out_channels,
228  avr->out_sample_rate,
230  if (!avr->ac_out) {
231  ret = AVERROR(ENOMEM);
232  goto error;
233  }
234  }
235  if (avr->resample_needed) {
236  avr->resample = ff_audio_resample_init(avr);
237  if (!avr->resample) {
238  ret = AVERROR(ENOMEM);
239  goto error;
240  }
241  }
242  if (avr->mixing_needed) {
243  avr->am = ff_audio_mix_alloc(avr);
244  if (!avr->am) {
245  ret = AVERROR(ENOMEM);
246  goto error;
247  }
248  }
249 
250  return 0;
251 
252 error:
253  avresample_close(avr);
254  return ret;
255 }
256 
258 {
259  return !!avr->out_fifo;
260 }
261 
263 {
268  avr->out_fifo = NULL;
272  ff_audio_mix_free(&avr->am);
273  av_freep(&avr->mix_matrix);
274 
275  avr->use_channel_map = 0;
276 }
277 
279 {
280  if (!*avr)
281  return;
282  avresample_close(*avr);
283  av_opt_free(*avr);
284  av_freep(avr);
285 }
286 
289 {
290  int ret;
291 
292  if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
293  (converted && output->allocated_samples < converted->nb_samples)) {
294  if (converted) {
295  /* if there are any samples in the output FIFO or if the
296  user-supplied output buffer is not large enough for all samples,
297  we add to the output FIFO */
298  av_log(avr, AV_LOG_TRACE, "[FIFO] add %s to out_fifo\n", converted->name);
300  converted->nb_samples);
301  if (ret < 0)
302  return ret;
303  }
304 
305  /* if the user specified an output buffer, read samples from the output
306  FIFO to the user output */
307  if (output && output->allocated_samples > 0) {
308  av_log(avr, AV_LOG_TRACE, "[FIFO] read from out_fifo to output\n");
309  av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
311  output->allocated_samples);
312  }
313  } else if (converted) {
314  /* copy directly to output if it is large enough or there is not any
315  data in the output FIFO */
316  av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", converted->name);
317  output->nb_samples = 0;
319  avr->remap_point == REMAP_OUT_COPY ?
320  &avr->ch_map_info : NULL);
321  if (ret < 0)
322  return ret;
323  av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
324  return output->nb_samples;
325  }
326  av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
327  return 0;
328 }
329 
330 int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
331  uint8_t **output, int out_plane_size,
332  int out_samples,
333  uint8_t * const *input,
334  int in_plane_size, int in_samples)
335 {
336  AudioData input_buffer;
337  AudioData output_buffer;
338  AudioData *current_buffer;
339  int ret, direct_output;
340 
341  /* reset internal buffers */
342  if (avr->in_buffer) {
343  avr->in_buffer->nb_samples = 0;
346  }
347  if (avr->resample_out_buffer) {
351  }
352  if (avr->out_buffer) {
353  avr->out_buffer->nb_samples = 0;
356  }
357 
358  av_log(avr, AV_LOG_TRACE, "[start conversion]\n");
359 
360  /* initialize output_buffer with output data */
361  direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0;
362  if (output) {
363  ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
364  avr->out_channels, out_samples,
365  avr->out_sample_fmt, 0, "output");
366  if (ret < 0)
367  return ret;
368  output_buffer.nb_samples = 0;
369  }
370 
371  if (input) {
372  /* initialize input_buffer with input data */
373  ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
374  avr->in_channels, in_samples,
375  avr->in_sample_fmt, 1, "input");
376  if (ret < 0)
377  return ret;
378  current_buffer = &input_buffer;
379 
380  if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
381  !avr->out_convert_needed && direct_output && out_samples >= in_samples) {
382  /* in some rare cases we can copy input to output and upmix
383  directly in the output buffer */
384  av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", current_buffer->name);
385  ret = ff_audio_data_copy(&output_buffer, current_buffer,
386  avr->remap_point == REMAP_OUT_COPY ?
387  &avr->ch_map_info : NULL);
388  if (ret < 0)
389  return ret;
390  current_buffer = &output_buffer;
391  } else if (avr->remap_point == REMAP_OUT_COPY &&
392  (!direct_output || out_samples < in_samples)) {
393  /* if remapping channels during output copy, we may need to
394  * use an intermediate buffer in order to remap before adding
395  * samples to the output fifo */
396  av_log(avr, AV_LOG_TRACE, "[copy] %s to out_buffer\n", current_buffer->name);
397  ret = ff_audio_data_copy(avr->out_buffer, current_buffer,
398  &avr->ch_map_info);
399  if (ret < 0)
400  return ret;
401  current_buffer = avr->out_buffer;
402  } else if (avr->in_copy_needed || avr->in_convert_needed) {
403  /* if needed, copy or convert input to in_buffer, and downmix if
404  applicable */
405  if (avr->in_convert_needed) {
407  current_buffer->nb_samples);
408  if (ret < 0)
409  return ret;
410  av_log(avr, AV_LOG_TRACE, "[convert] %s to in_buffer\n", current_buffer->name);
411  ret = ff_audio_convert(avr->ac_in, avr->in_buffer,
412  current_buffer);
413  if (ret < 0)
414  return ret;
415  } else {
416  av_log(avr, AV_LOG_TRACE, "[copy] %s to in_buffer\n", current_buffer->name);
417  ret = ff_audio_data_copy(avr->in_buffer, current_buffer,
418  avr->remap_point == REMAP_IN_COPY ?
419  &avr->ch_map_info : NULL);
420  if (ret < 0)
421  return ret;
422  }
424  if (avr->downmix_needed) {
425  av_log(avr, AV_LOG_TRACE, "[downmix] in_buffer\n");
426  ret = ff_audio_mix(avr->am, avr->in_buffer);
427  if (ret < 0)
428  return ret;
429  }
430  current_buffer = avr->in_buffer;
431  }
432  } else {
433  /* flush resampling buffer and/or output FIFO if input is NULL */
434  if (!avr->resample_needed)
435  return handle_buffered_output(avr, output ? &output_buffer : NULL,
436  NULL);
437  current_buffer = NULL;
438  }
439 
440  if (avr->resample_needed) {
441  AudioData *resample_out;
442 
443  if (!avr->out_convert_needed && direct_output && out_samples > 0)
444  resample_out = &output_buffer;
445  else
446  resample_out = avr->resample_out_buffer;
447  av_log(avr, AV_LOG_TRACE, "[resample] %s to %s\n",
448  current_buffer ? current_buffer->name : "null",
449  resample_out->name);
450  ret = ff_audio_resample(avr->resample, resample_out,
451  current_buffer);
452  if (ret < 0)
453  return ret;
454 
455  /* if resampling did not produce any samples, just return 0 */
456  if (resample_out->nb_samples == 0) {
457  av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
458  return 0;
459  }
460 
461  current_buffer = resample_out;
462  }
463 
464  if (avr->upmix_needed) {
465  av_log(avr, AV_LOG_TRACE, "[upmix] %s\n", current_buffer->name);
466  ret = ff_audio_mix(avr->am, current_buffer);
467  if (ret < 0)
468  return ret;
469  }
470 
471  /* if we resampled or upmixed directly to output, return here */
472  if (current_buffer == &output_buffer) {
473  av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
474  return current_buffer->nb_samples;
475  }
476 
477  if (avr->out_convert_needed) {
478  if (direct_output && out_samples >= current_buffer->nb_samples) {
479  /* convert directly to output */
480  av_log(avr, AV_LOG_TRACE, "[convert] %s to output\n", current_buffer->name);
481  ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer);
482  if (ret < 0)
483  return ret;
484 
485  av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
486  return output_buffer.nb_samples;
487  } else {
489  current_buffer->nb_samples);
490  if (ret < 0)
491  return ret;
492  av_log(avr, AV_LOG_TRACE, "[convert] %s to out_buffer\n", current_buffer->name);
493  ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
494  current_buffer);
495  if (ret < 0)
496  return ret;
497  current_buffer = avr->out_buffer;
498  }
499  }
500 
501  return handle_buffered_output(avr, output ? &output_buffer : NULL,
502  current_buffer);
503 }
504 
506 {
507  if (avresample_is_open(avr)) {
508  avresample_close(avr);
509  }
510 
511  if (in) {
512  avr->in_channel_layout = in->channel_layout;
513  avr->in_sample_rate = in->sample_rate;
514  avr->in_sample_fmt = in->format;
515  }
516 
517  if (out) {
518  avr->out_channel_layout = out->channel_layout;
519  avr->out_sample_rate = out->sample_rate;
520  avr->out_sample_fmt = out->format;
521  }
522 
523  return 0;
524 }
525 
527  AVFrame *out, AVFrame *in)
528 {
529  int ret = 0;
530 
531  if (in) {
532  if (avr->in_channel_layout != in->channel_layout ||
533  avr->in_sample_rate != in->sample_rate ||
534  avr->in_sample_fmt != in->format) {
536  }
537  }
538 
539  if (out) {
540  if (avr->out_channel_layout != out->channel_layout ||
541  avr->out_sample_rate != out->sample_rate ||
542  avr->out_sample_fmt != out->format) {
544  }
545  }
546 
547  return ret;
548 }
549 
550 static inline int convert_frame(AVAudioResampleContext *avr,
551  AVFrame *out, AVFrame *in)
552 {
553  int ret;
554  uint8_t **out_data = NULL, **in_data = NULL;
555  int out_linesize = 0, in_linesize = 0;
556  int out_nb_samples = 0, in_nb_samples = 0;
557 
558  if (out) {
559  out_data = out->extended_data;
560  out_linesize = out->linesize[0];
561  out_nb_samples = out->nb_samples;
562  }
563 
564  if (in) {
565  in_data = in->extended_data;
566  in_linesize = in->linesize[0];
567  in_nb_samples = in->nb_samples;
568  }
569 
570  ret = avresample_convert(avr, out_data, out_linesize,
571  out_nb_samples,
572  in_data, in_linesize,
573  in_nb_samples);
574 
575  if (ret < 0) {
576  if (out)
577  out->nb_samples = 0;
578  return ret;
579  }
580 
581  if (out)
582  out->nb_samples = ret;
583 
584  return 0;
585 }
586 
587 static inline int available_samples(AVFrame *out)
588 {
589  int samples;
590  int bytes_per_sample = av_get_bytes_per_sample(out->format);
591  if (!bytes_per_sample)
592  return AVERROR(EINVAL);
593 
594  samples = out->linesize[0] / bytes_per_sample;
595  if (av_sample_fmt_is_planar(out->format)) {
596  return samples;
597  } else {
598  int channels = av_get_channel_layout_nb_channels(out->channel_layout);
599  return samples / channels;
600  }
601 }
602 
604  AVFrame *out, AVFrame *in)
605 {
606  int ret, setup = 0;
607 
608  if (!avresample_is_open(avr)) {
609  if ((ret = avresample_config(avr, out, in)) < 0)
610  return ret;
611  if ((ret = avresample_open(avr)) < 0)
612  return ret;
613  setup = 1;
614  } else {
615  // return as is or reconfigure for input changes?
616  if ((ret = config_changed(avr, out, in)))
617  return ret;
618  }
619 
620  if (out) {
621  if (!out->linesize[0]) {
622  out->nb_samples = avresample_get_out_samples(avr, in->nb_samples);
623  if ((ret = av_frame_get_buffer(out, 0)) < 0) {
624  if (setup)
625  avresample_close(avr);
626  return ret;
627  }
628  } else {
629  if (!out->nb_samples)
630  out->nb_samples = available_samples(out);
631  }
632  }
633 
634  return convert_frame(avr, out, in);
635 }
636 
638  int stride)
639 {
640  int in_channels, out_channels, i, o;
641 
642  if (avr->am)
643  return ff_audio_mix_get_matrix(avr->am, matrix, stride);
644 
647 
648  if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
649  out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
650  av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
651  return AVERROR(EINVAL);
652  }
653 
654  if (!avr->mix_matrix) {
655  av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
656  return AVERROR(EINVAL);
657  }
658 
659  for (o = 0; o < out_channels; o++)
660  for (i = 0; i < in_channels; i++)
661  matrix[o * stride + i] = avr->mix_matrix[o * in_channels + i];
662 
663  return 0;
664 }
665 
666 int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
667  int stride)
668 {
669  int in_channels, out_channels, i, o;
670 
671  if (avr->am)
672  return ff_audio_mix_set_matrix(avr->am, matrix, stride);
673 
676 
677  if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
678  out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
679  av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
680  return AVERROR(EINVAL);
681  }
682 
683  if (avr->mix_matrix)
684  av_freep(&avr->mix_matrix);
685  avr->mix_matrix = av_malloc(in_channels * out_channels *
686  sizeof(*avr->mix_matrix));
687  if (!avr->mix_matrix)
688  return AVERROR(ENOMEM);
689 
690  for (o = 0; o < out_channels; o++)
691  for (i = 0; i < in_channels; i++)
692  avr->mix_matrix[o * in_channels + i] = matrix[o * stride + i];
693 
694  return 0;
695 }
696 
698  const int *channel_map)
699 {
701  int in_channels, ch, i;
702 
704  if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS) {
705  av_log(avr, AV_LOG_ERROR, "Invalid input channel layout\n");
706  return AVERROR(EINVAL);
707  }
708 
709  memset(info, 0, sizeof(*info));
710  memset(info->input_map, -1, sizeof(info->input_map));
711 
712  for (ch = 0; ch < in_channels; ch++) {
713  if (channel_map[ch] >= in_channels) {
714  av_log(avr, AV_LOG_ERROR, "Invalid channel map\n");
715  return AVERROR(EINVAL);
716  }
717  if (channel_map[ch] < 0) {
718  info->channel_zero[ch] = 1;
719  info->channel_map[ch] = -1;
720  info->do_zero = 1;
721  } else if (info->input_map[channel_map[ch]] >= 0) {
722  info->channel_copy[ch] = info->input_map[channel_map[ch]];
723  info->channel_map[ch] = -1;
724  info->do_copy = 1;
725  } else {
726  info->channel_map[ch] = channel_map[ch];
727  info->input_map[channel_map[ch]] = ch;
728  info->do_remap = 1;
729  }
730  }
731  /* Fill-in unmapped input channels with unmapped output channels.
732  This is used when remapping during conversion from interleaved to
733  planar format. */
734  for (ch = 0, i = 0; ch < in_channels && i < in_channels; ch++, i++) {
735  while (ch < in_channels && info->input_map[ch] >= 0)
736  ch++;
737  while (i < in_channels && info->channel_map[i] >= 0)
738  i++;
739  if (ch >= in_channels || i >= in_channels)
740  break;
741  info->input_map[ch] = i;
742  }
743 
744  avr->use_channel_map = 1;
745  return 0;
746 }
747 
749 {
750  return av_audio_fifo_size(avr->out_fifo);
751 }
752 
754 {
755  int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples;
756 
757  if (avr->resample_needed) {
759  avr->out_sample_rate,
760  avr->in_sample_rate,
761  AV_ROUND_UP);
762  }
763 
765 
766  if (samples > INT_MAX)
767  return AVERROR(EINVAL);
768 
769  return samples;
770 }
771 
773 {
774  if (!output)
775  return av_audio_fifo_drain(avr->out_fifo, nb_samples);
776  return av_audio_fifo_read(avr->out_fifo, (void**)output, nb_samples);
777 }
778 
779 unsigned avresample_version(void)
780 {
782 }
783 
784 const char *avresample_license(void)
785 {
786 #define LICENSE_PREFIX "libavresample license: "
787  return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
788 }
789 
790 const char *avresample_configuration(void)
791 {
792  return FFMPEG_CONFIGURATION;
793 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:30
AVAudioResampleContext::in_sample_fmt
enum AVSampleFormat in_sample_fmt
input sample format
Definition: internal.h:57
AVAudioResampleContext::mix_matrix
double * mix_matrix
mix matrix only used if avresample_set_matrix() is called before avresample_open()
Definition: internal.h:103
av_audio_fifo_free
void av_audio_fifo_free(AVAudioFifo *af)
Free an AVAudioFifo.
Definition: audio_fifo.c:45
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:69
stride
int stride
Definition: mace.c:144
ff_audio_convert_free
void ff_audio_convert_free(AudioConvert **ac)
Free AudioConvert.
AVAudioResampleContext::in_convert_needed
int in_convert_needed
input sample format conversion is needed
Definition: internal.h:84
ff_sample_fmt_is_planar
int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
Definition: audio_data.c:51
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
ChannelMapInfo::do_copy
int do_copy
copy needed
Definition: internal.h:47
opt.h
out
FILE * out
Definition: movenc.c:54
av_frame_get_buffer
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:338
AVAudioResampleContext::downmix_needed
int downmix_needed
downmixing is needed
Definition: internal.h:80
ff_audio_data_alloc
AudioData * ff_audio_data_alloc(int channels, int nb_samples, enum AVSampleFormat sample_fmt, const char *name)
Allocate AudioData.
Definition: audio_data.c:119
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
ff_audio_data_set_channels
int ff_audio_data_set_channels(AudioData *a, int channels)
Definition: audio_data.c:59
audio_convert.h
AVRESAMPLE_MAX_CHANNELS
#define AVRESAMPLE_MAX_CHANNELS
Definition: avresample.h:104
ff_audio_data_add_to_fifo
int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset, int nb_samples)
Add samples in AudioData to an AVAudioFifo.
Definition: audio_data.c:351
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:324
AVAudioResampleContext::out_channels
int out_channels
number of output channels
Definition: internal.h:78
AV_SAMPLE_FMT_S32P
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: samplefmt.h:68
ff_audio_resample_free
void ff_audio_resample_free(ResampleContext **c)
Free a ResampleContext.
Definition: resample.c:224
avresample.h
ff_audio_mix_set_matrix
int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
Set the current mixing matrix.
Definition: audio_mix.c:653
ff_audio_data_free
void ff_audio_data_free(AudioData **a)
Free AudioData.
Definition: audio_data.c:217
ff_audio_data_read_from_fifo
int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
Read samples from an AVAudioFifo to AudioData.
Definition: audio_data.c:366
avresample_get_delay
attribute_deprecated int avresample_get_delay(AVAudioResampleContext *avr)
Definition: resample.c:438
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
avresample_convert_frame
int avresample_convert_frame(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
Definition: utils.c:603
avresample_read
int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples)
Definition: utils.c:772
resample.h
AudioData
Audio buffer used for intermediate storage between conversion phases.
Definition: audio_data.h:37
AVAudioResampleContext
Definition: internal.h:53
ChannelMapInfo
Definition: internal.h:43
av_audio_fifo_drain
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
Drain data from an AVAudioFifo.
Definition: audio_fifo.c:201
AVAudioResampleContext::ch_map_info
ChannelMapInfo ch_map_info
Definition: internal.h:107
AV_ROUND_UP
@ AV_ROUND_UP
Round toward +infinity.
Definition: mathematics.h:83
ff_audio_mix
int ff_audio_mix(AudioMix *am, AudioData *src)
Apply channel mixing to audio data using the current mixing matrix.
Definition: audio_mix.c:428
avresample_get_out_samples
int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples)
Definition: utils.c:753
av_get_planar_sample_fmt
enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt)
Get the planar alternative form of the given sample format.
Definition: samplefmt.c:84
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:220
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
AVAudioResampleContext::in_buffer
AudioData * in_buffer
buffer for converted input
Definition: internal.h:88
REMAP_IN_CONVERT
@ REMAP_IN_CONVERT
Definition: internal.h:38
AVAudioResampleContext::ac_out
AudioConvert * ac_out
output sample format conversion context
Definition: internal.h:94
ChannelMapInfo::channel_map
int channel_map[AVRESAMPLE_MAX_CHANNELS]
source index of each output channel, -1 if not remapped
Definition: internal.h:44
REMAP_NONE
@ REMAP_NONE
Definition: internal.h:36
AVAudioResampleContext::ac_in
AudioConvert * ac_in
input sample format conversion context
Definition: internal.h:93
avresample_open
int avresample_open(AVAudioResampleContext *avr)
Definition: utils.c:36
avresample_license
const char * avresample_license(void)
Definition: utils.c:784
ChannelMapInfo::do_remap
int do_remap
remap needed
Definition: internal.h:45
convert_frame
static int convert_frame(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
Definition: utils.c:550
avresample_set_channel_mapping
int avresample_set_channel_mapping(AVAudioResampleContext *avr, const int *channel_map)
Definition: utils.c:697
info
MIPS optimizations info
Definition: mips.txt:2
AVERROR_INPUT_CHANGED
#define AVERROR_INPUT_CHANGED
Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
Definition: error.h:73
av_sample_fmt_is_planar
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition: samplefmt.c:112
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
AVAudioResampleContext::in_copy_needed
int in_copy_needed
input data copy is needed
Definition: internal.h:86
channels
channels
Definition: aptx.h:33
AVAudioResampleContext::upmix_needed
int upmix_needed
upmixing is needed
Definition: internal.h:81
av_get_sample_fmt_name
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
Definition: samplefmt.c:49
LICENSE_PREFIX
#define LICENSE_PREFIX
ff_audio_resample_init
ResampleContext * ff_audio_resample_init(AVAudioResampleContext *avr)
Allocate and initialize a ResampleContext.
Definition: resample.c:120
NULL
#define NULL
Definition: coverity.c:32
av_audio_fifo_alloc
AVAudioFifo * av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, int nb_samples)
Allocate an AVAudioFifo.
Definition: audio_fifo.c:59
internal.h
AVAudioResampleContext::out_convert_needed
int out_convert_needed
output sample format conversion is needed
Definition: internal.h:85
av_opt_free
void av_opt_free(void *obj)
Free all allocated objects in obj.
Definition: opt.c:1611
AVAudioResampleContext::resample_out_buffer
AudioData * resample_out_buffer
buffer for output from resampler
Definition: internal.h:89
audio_data.h
converted
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common like for each output line the vertical scaler pulls lines from a ring buffer When the ring buffer does not contain the wanted then it is pulled from the input slice through the input converter and horizontal scaler The result is also stored in the ring buffer to serve future vertical scaler requests When no more output can be generated because lines from a future slice would be then all remaining lines in the current slice are converted
Definition: swscale.txt:46
av_get_channel_layout_nb_channels
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
Definition: channel_layout.c:226
av_rescale_rnd
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition: mathematics.c:58
avresample_free
void avresample_free(AVAudioResampleContext **avr)
Definition: utils.c:278
handle_buffered_output
static int handle_buffered_output(AVAudioResampleContext *avr, AudioData *output, AudioData *converted)
Definition: utils.c:287
AVAudioResampleContext::resample
ResampleContext * resample
resampling context
Definition: internal.h:95
ChannelMapInfo::channel_copy
int channel_copy[AVRESAMPLE_MAX_CHANNELS]
dest index to copy from
Definition: internal.h:46
AudioData::name
const char * name
name for debug logging
Definition: audio_data.h:55
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:59
REMAP_OUT_CONVERT
@ REMAP_OUT_CONVERT
Definition: internal.h:40
AVAudioResampleContext::force_resampling
int force_resampling
force resampling
Definition: internal.h:68
AVERROR_OUTPUT_CHANGED
#define AVERROR_OUTPUT_CHANGED
Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
Definition: error.h:74
LIBAVRESAMPLE_VERSION_INT
#define LIBAVRESAMPLE_VERSION_INT
Definition: version.h:34
AVAudioResampleContext::out_sample_rate
int out_sample_rate
output sample rate
Definition: internal.h:61
avresample_convert
int attribute_align_arg avresample_convert(AVAudioResampleContext *avr, uint8_t **output, int out_plane_size, int out_samples, uint8_t *const *input, int in_plane_size, int in_samples)
Definition: utils.c:330
frame.h
config_changed
static int config_changed(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
Definition: utils.c:526
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
AVAudioResampleContext::am
AudioMix * am
channel mixing context
Definition: internal.h:96
av_audio_fifo_size
int av_audio_fifo_size(AVAudioFifo *af)
Get the current number of samples in the AVAudioFifo available for reading.
Definition: audio_fifo.c:228
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
AV_SAMPLE_FMT_S16P
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: samplefmt.h:67
AVAudioResampleContext::out_sample_fmt
enum AVSampleFormat out_sample_fmt
output sample format
Definition: internal.h:60
avresample_version
unsigned avresample_version(void)
Definition: utils.c:779
avresample_close
void avresample_close(AVAudioResampleContext *avr)
Definition: utils.c:262
in
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Definition: audio_convert.c:326
av_audio_fifo_read
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
Read data from an AVAudioFifo.
Definition: audio_fifo.c:181
i
int i
Definition: input.c:407
AVAudioResampleContext::in_channel_layout
uint64_t in_channel_layout
input channel layout
Definition: internal.h:56
log.h
avresample_available
int avresample_available(AVAudioResampleContext *avr)
Definition: utils.c:748
AVAudioResampleContext::in_channels
int in_channels
number of input channels
Definition: internal.h:77
av_get_bytes_per_sample
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:106
available_samples
static int available_samples(AVFrame *out)
Definition: utils.c:587
AudioData::allocated_channels
int allocated_channels
allocated channel count
Definition: audio_data.h:46
AVAudioResampleContext::in_sample_rate
int in_sample_rate
input sample rate
Definition: internal.h:58
ff_audio_mix_free
void ff_audio_mix_free(AudioMix **am_p)
Free an AudioMix context.
Definition: audio_mix.c:409
common.h
avresample_set_matrix
int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix, int stride)
Definition: utils.c:666
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
AVAudioResampleContext::resample_needed
int resample_needed
resampling is needed
Definition: internal.h:83
avresample_get_matrix
int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix, int stride)
Definition: utils.c:637
REMAP_IN_COPY
@ REMAP_IN_COPY
Definition: internal.h:37
uint8_t
uint8_t
Definition: audio_convert.c:194
ff_audio_mix_alloc
AudioMix * ff_audio_mix_alloc(AVAudioResampleContext *avr)
Allocate and initialize an AudioMix context.
Definition: audio_mix.c:341
avresample_config
int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
Definition: utils.c:505
ChannelMapInfo::input_map
int input_map[AVRESAMPLE_MAX_CHANNELS]
dest index of each input channel
Definition: internal.h:50
AudioData::nb_samples
int nb_samples
current number of samples
Definition: audio_data.h:43
ret
ret
Definition: filter_design.txt:187
REMAP_OUT_COPY
@ REMAP_OUT_COPY
Definition: internal.h:39
AVAudioResampleContext::out_fifo
AVAudioFifo * out_fifo
FIFO for output samples
Definition: internal.h:91
AVAudioResampleContext::out_buffer
AudioData * out_buffer
buffer for converted output
Definition: internal.h:90
ff_audio_data_realloc
int ff_audio_data_realloc(AudioData *a, int nb_samples)
Reallocate AudioData.
Definition: audio_data.c:162
dict.h
AVAudioResampleContext::internal_sample_fmt
enum AVSampleFormat internal_sample_fmt
internal sample format
Definition: internal.h:62
AVAudioResampleContext::remap_point
enum RemapPoint remap_point
Definition: internal.h:106
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:70
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
ff_audio_convert_alloc
AudioConvert * ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map)
Allocate and initialize AudioConvert context for sample format conversion.
ff_audio_mix_get_matrix
int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
Get the current mixing matrix.
Definition: audio_mix.c:483
AVAudioResampleContext::mixing_needed
int mixing_needed
either upmixing or downmixing is needed
Definition: internal.h:82
mem.h
ChannelMapInfo::channel_zero
int channel_zero[AVRESAMPLE_MAX_CHANNELS]
dest index to zero
Definition: internal.h:48
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AVAudioResampleContext::resample_channels
int resample_channels
number of channels used for resampling
Definition: internal.h:79
ff_audio_resample
int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src)
Resample audio data.
Definition: resample.c:334
AVAudioResampleContext::use_channel_map
int use_channel_map
Definition: internal.h:105
ChannelMapInfo::do_zero
int do_zero
zeroing needed
Definition: internal.h:49
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
avresample_is_open
int avresample_is_open(AVAudioResampleContext *avr)
Definition: utils.c:257
avresample_configuration
const char * avresample_configuration(void)
Definition: utils.c:790
ff_audio_data_init
int ff_audio_data_init(AudioData *a, uint8_t *const *src, int plane_size, int channels, int nb_samples, enum AVSampleFormat sample_fmt, int read_only, const char *name)
Initialize AudioData using a given source.
Definition: audio_data.c:73
ff_audio_data_copy
int ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map)
Copy data from one AudioData to another.
Definition: audio_data.c:225
ff_audio_convert
int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in)
Convert audio data from one sample format to another.
audio_mix.h
AVAudioResampleContext::out_channel_layout
uint64_t out_channel_layout
output channel layout
Definition: internal.h:59