2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
4 * This file is part of Libav.
6 * Libav 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.
11 * Libav 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "libavutil/common.h"
22 #include "libavutil/dict.h"
23 #include "libavutil/error.h"
24 #include "libavutil/log.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
28 #include "avresample.h"
29 #include "audio_data.h"
32 int avresample_open(AVAudioResampleContext
*avr
)
36 /* set channel mixing parameters */
37 avr
->in_channels
= av_get_channel_layout_nb_channels(avr
->in_channel_layout
);
38 if (avr
->in_channels
<= 0 || avr
->in_channels
> AVRESAMPLE_MAX_CHANNELS
) {
39 av_log(avr
, AV_LOG_ERROR
, "Invalid input channel layout: %"PRIu64
"\n",
40 avr
->in_channel_layout
);
41 return AVERROR(EINVAL
);
43 avr
->out_channels
= av_get_channel_layout_nb_channels(avr
->out_channel_layout
);
44 if (avr
->out_channels
<= 0 || avr
->out_channels
> AVRESAMPLE_MAX_CHANNELS
) {
45 av_log(avr
, AV_LOG_ERROR
, "Invalid output channel layout: %"PRIu64
"\n",
46 avr
->out_channel_layout
);
47 return AVERROR(EINVAL
);
49 avr
->resample_channels
= FFMIN(avr
->in_channels
, avr
->out_channels
);
50 avr
->downmix_needed
= avr
->in_channels
> avr
->out_channels
;
51 avr
->upmix_needed
= avr
->out_channels
> avr
->in_channels
||
52 (!avr
->downmix_needed
&& (avr
->am
->matrix
||
53 avr
->in_channel_layout
!= avr
->out_channel_layout
));
54 avr
->mixing_needed
= avr
->downmix_needed
|| avr
->upmix_needed
;
56 /* set resampling parameters */
57 avr
->resample_needed
= avr
->in_sample_rate
!= avr
->out_sample_rate
||
58 avr
->force_resampling
;
60 /* select internal sample format if not specified by the user */
61 if (avr
->internal_sample_fmt
== AV_SAMPLE_FMT_NONE
&&
62 (avr
->mixing_needed
|| avr
->resample_needed
)) {
63 enum AVSampleFormat in_fmt
= av_get_planar_sample_fmt(avr
->in_sample_fmt
);
64 enum AVSampleFormat out_fmt
= av_get_planar_sample_fmt(avr
->out_sample_fmt
);
65 int max_bps
= FFMAX(av_get_bytes_per_sample(in_fmt
),
66 av_get_bytes_per_sample(out_fmt
));
68 avr
->internal_sample_fmt
= AV_SAMPLE_FMT_S16P
;
69 } else if (avr
->mixing_needed
) {
70 avr
->internal_sample_fmt
= AV_SAMPLE_FMT_FLTP
;
73 if (in_fmt
== AV_SAMPLE_FMT_S32P
||
74 out_fmt
== AV_SAMPLE_FMT_S32P
) {
75 if (in_fmt
== AV_SAMPLE_FMT_FLTP
||
76 out_fmt
== AV_SAMPLE_FMT_FLTP
) {
77 /* if one is s32 and the other is flt, use dbl */
78 avr
->internal_sample_fmt
= AV_SAMPLE_FMT_DBLP
;
80 /* if one is s32 and the other is s32, s16, or u8, use s32 */
81 avr
->internal_sample_fmt
= AV_SAMPLE_FMT_S32P
;
84 /* if one is flt and the other is flt, s16 or u8, use flt */
85 avr
->internal_sample_fmt
= AV_SAMPLE_FMT_FLTP
;
88 /* if either is dbl, use dbl */
89 avr
->internal_sample_fmt
= AV_SAMPLE_FMT_DBLP
;
92 av_log(avr
, AV_LOG_DEBUG
, "Using %s as internal sample format\n",
93 av_get_sample_fmt_name(avr
->internal_sample_fmt
));
96 /* set sample format conversion parameters */
97 if (avr
->in_channels
== 1)
98 avr
->in_sample_fmt
= av_get_planar_sample_fmt(avr
->in_sample_fmt
);
99 if (avr
->out_channels
== 1)
100 avr
->out_sample_fmt
= av_get_planar_sample_fmt(avr
->out_sample_fmt
);
101 avr
->in_convert_needed
= (avr
->resample_needed
|| avr
->mixing_needed
) &&
102 avr
->in_sample_fmt
!= avr
->internal_sample_fmt
;
103 if (avr
->resample_needed
|| avr
->mixing_needed
)
104 avr
->out_convert_needed
= avr
->internal_sample_fmt
!= avr
->out_sample_fmt
;
106 avr
->out_convert_needed
= avr
->in_sample_fmt
!= avr
->out_sample_fmt
;
108 /* allocate buffers */
109 if (avr
->mixing_needed
|| avr
->in_convert_needed
) {
110 avr
->in_buffer
= ff_audio_data_alloc(FFMAX(avr
->in_channels
, avr
->out_channels
),
111 0, avr
->internal_sample_fmt
,
113 if (!avr
->in_buffer
) {
114 ret
= AVERROR(EINVAL
);
118 if (avr
->resample_needed
) {
119 avr
->resample_out_buffer
= ff_audio_data_alloc(avr
->out_channels
,
120 0, avr
->internal_sample_fmt
,
121 "resample_out_buffer");
122 if (!avr
->resample_out_buffer
) {
123 ret
= AVERROR(EINVAL
);
127 if (avr
->out_convert_needed
) {
128 avr
->out_buffer
= ff_audio_data_alloc(avr
->out_channels
, 0,
129 avr
->out_sample_fmt
, "out_buffer");
130 if (!avr
->out_buffer
) {
131 ret
= AVERROR(EINVAL
);
135 avr
->out_fifo
= av_audio_fifo_alloc(avr
->out_sample_fmt
, avr
->out_channels
,
137 if (!avr
->out_fifo
) {
138 ret
= AVERROR(ENOMEM
);
143 if (avr
->in_convert_needed
) {
144 avr
->ac_in
= ff_audio_convert_alloc(avr
, avr
->internal_sample_fmt
,
145 avr
->in_sample_fmt
, avr
->in_channels
);
147 ret
= AVERROR(ENOMEM
);
151 if (avr
->out_convert_needed
) {
152 enum AVSampleFormat src_fmt
;
153 if (avr
->in_convert_needed
)
154 src_fmt
= avr
->internal_sample_fmt
;
156 src_fmt
= avr
->in_sample_fmt
;
157 avr
->ac_out
= ff_audio_convert_alloc(avr
, avr
->out_sample_fmt
, src_fmt
,
160 ret
= AVERROR(ENOMEM
);
164 if (avr
->resample_needed
) {
165 avr
->resample
= ff_audio_resample_init(avr
);
166 if (!avr
->resample
) {
167 ret
= AVERROR(ENOMEM
);
171 if (avr
->mixing_needed
) {
172 ret
= ff_audio_mix_init(avr
);
180 avresample_close(avr
);
184 void avresample_close(AVAudioResampleContext
*avr
)
186 ff_audio_data_free(&avr
->in_buffer
);
187 ff_audio_data_free(&avr
->resample_out_buffer
);
188 ff_audio_data_free(&avr
->out_buffer
);
189 av_audio_fifo_free(avr
->out_fifo
);
190 avr
->out_fifo
= NULL
;
191 av_freep(&avr
->ac_in
);
192 av_freep(&avr
->ac_out
);
193 ff_audio_resample_free(&avr
->resample
);
194 ff_audio_mix_close(avr
->am
);
198 void avresample_free(AVAudioResampleContext
**avr
)
202 avresample_close(*avr
);
203 av_freep(&(*avr
)->am
);
208 static int handle_buffered_output(AVAudioResampleContext
*avr
,
209 AudioData
*output
, AudioData
*converted
)
213 if (!output
|| av_audio_fifo_size(avr
->out_fifo
) > 0 ||
214 (converted
&& output
->allocated_samples
< converted
->nb_samples
)) {
216 /* if there are any samples in the output FIFO or if the
217 user-supplied output buffer is not large enough for all samples,
218 we add to the output FIFO */
219 av_dlog(avr
, "[FIFO] add %s to out_fifo\n", converted
->name
);
220 ret
= ff_audio_data_add_to_fifo(avr
->out_fifo
, converted
, 0,
221 converted
->nb_samples
);
226 /* if the user specified an output buffer, read samples from the output
227 FIFO to the user output */
228 if (output
&& output
->allocated_samples
> 0) {
229 av_dlog(avr
, "[FIFO] read from out_fifo to output\n");
230 av_dlog(avr
, "[end conversion]\n");
231 return ff_audio_data_read_from_fifo(avr
->out_fifo
, output
,
232 output
->allocated_samples
);
234 } else if (converted
) {
235 /* copy directly to output if it is large enough or there is not any
236 data in the output FIFO */
237 av_dlog(avr
, "[copy] %s to output\n", converted
->name
);
238 output
->nb_samples
= 0;
239 ret
= ff_audio_data_copy(output
, converted
);
242 av_dlog(avr
, "[end conversion]\n");
243 return output
->nb_samples
;
245 av_dlog(avr
, "[end conversion]\n");
249 int attribute_align_arg
avresample_convert(AVAudioResampleContext
*avr
,
250 uint8_t **output
, int out_plane_size
,
251 int out_samples
, uint8_t **input
,
252 int in_plane_size
, int in_samples
)
254 AudioData input_buffer
;
255 AudioData output_buffer
;
256 AudioData
*current_buffer
;
257 int ret
, direct_output
;
259 /* reset internal buffers */
260 if (avr
->in_buffer
) {
261 avr
->in_buffer
->nb_samples
= 0;
262 ff_audio_data_set_channels(avr
->in_buffer
,
263 avr
->in_buffer
->allocated_channels
);
265 if (avr
->resample_out_buffer
) {
266 avr
->resample_out_buffer
->nb_samples
= 0;
267 ff_audio_data_set_channels(avr
->resample_out_buffer
,
268 avr
->resample_out_buffer
->allocated_channels
);
270 if (avr
->out_buffer
) {
271 avr
->out_buffer
->nb_samples
= 0;
272 ff_audio_data_set_channels(avr
->out_buffer
,
273 avr
->out_buffer
->allocated_channels
);
276 av_dlog(avr
, "[start conversion]\n");
278 /* initialize output_buffer with output data */
279 direct_output
= output
&& av_audio_fifo_size(avr
->out_fifo
) == 0;
281 ret
= ff_audio_data_init(&output_buffer
, output
, out_plane_size
,
282 avr
->out_channels
, out_samples
,
283 avr
->out_sample_fmt
, 0, "output");
286 output_buffer
.nb_samples
= 0;
290 /* initialize input_buffer with input data */
291 ret
= ff_audio_data_init(&input_buffer
, input
, in_plane_size
,
292 avr
->in_channels
, in_samples
,
293 avr
->in_sample_fmt
, 1, "input");
296 current_buffer
= &input_buffer
;
298 if (avr
->upmix_needed
&& !avr
->in_convert_needed
&& !avr
->resample_needed
&&
299 !avr
->out_convert_needed
&& direct_output
&& out_samples
>= in_samples
) {
300 /* in some rare cases we can copy input to output and upmix
301 directly in the output buffer */
302 av_dlog(avr
, "[copy] %s to output\n", current_buffer
->name
);
303 ret
= ff_audio_data_copy(&output_buffer
, current_buffer
);
306 current_buffer
= &output_buffer
;
307 } else if (avr
->mixing_needed
|| avr
->in_convert_needed
) {
308 /* if needed, copy or convert input to in_buffer, and downmix if
310 if (avr
->in_convert_needed
) {
311 ret
= ff_audio_data_realloc(avr
->in_buffer
,
312 current_buffer
->nb_samples
);
315 av_dlog(avr
, "[convert] %s to in_buffer\n", current_buffer
->name
);
316 ret
= ff_audio_convert(avr
->ac_in
, avr
->in_buffer
,
321 av_dlog(avr
, "[copy] %s to in_buffer\n", current_buffer
->name
);
322 ret
= ff_audio_data_copy(avr
->in_buffer
, current_buffer
);
326 ff_audio_data_set_channels(avr
->in_buffer
, avr
->in_channels
);
327 if (avr
->downmix_needed
) {
328 av_dlog(avr
, "[downmix] in_buffer\n");
329 ret
= ff_audio_mix(avr
->am
, avr
->in_buffer
);
333 current_buffer
= avr
->in_buffer
;
336 /* flush resampling buffer and/or output FIFO if input is NULL */
337 if (!avr
->resample_needed
)
338 return handle_buffered_output(avr
, output ?
&output_buffer
: NULL
,
340 current_buffer
= NULL
;
343 if (avr
->resample_needed
) {
344 AudioData
*resample_out
;
347 if (!avr
->out_convert_needed
&& direct_output
&& out_samples
> 0)
348 resample_out
= &output_buffer
;
350 resample_out
= avr
->resample_out_buffer
;
351 av_dlog(avr
, "[resample] %s to %s\n", current_buffer
->name
,
353 ret
= ff_audio_resample(avr
->resample
, resample_out
,
354 current_buffer
, &consumed
);
358 /* if resampling did not produce any samples, just return 0 */
359 if (resample_out
->nb_samples
== 0) {
360 av_dlog(avr
, "[end conversion]\n");
364 current_buffer
= resample_out
;
367 if (avr
->upmix_needed
) {
368 av_dlog(avr
, "[upmix] %s\n", current_buffer
->name
);
369 ret
= ff_audio_mix(avr
->am
, current_buffer
);
374 /* if we resampled or upmixed directly to output, return here */
375 if (current_buffer
== &output_buffer
) {
376 av_dlog(avr
, "[end conversion]\n");
377 return current_buffer
->nb_samples
;
380 if (avr
->out_convert_needed
) {
381 if (direct_output
&& out_samples
>= current_buffer
->nb_samples
) {
382 /* convert directly to output */
383 av_dlog(avr
, "[convert] %s to output\n", current_buffer
->name
);
384 ret
= ff_audio_convert(avr
->ac_out
, &output_buffer
, current_buffer
);
388 av_dlog(avr
, "[end conversion]\n");
389 return output_buffer
.nb_samples
;
391 ret
= ff_audio_data_realloc(avr
->out_buffer
,
392 current_buffer
->nb_samples
);
395 av_dlog(avr
, "[convert] %s to out_buffer\n", current_buffer
->name
);
396 ret
= ff_audio_convert(avr
->ac_out
, avr
->out_buffer
,
400 current_buffer
= avr
->out_buffer
;
404 return handle_buffered_output(avr
, output ?
&output_buffer
: NULL
,
408 int avresample_available(AVAudioResampleContext
*avr
)
410 return av_audio_fifo_size(avr
->out_fifo
);
413 int avresample_read(AVAudioResampleContext
*avr
, uint8_t **output
, int nb_samples
)
416 return av_audio_fifo_drain(avr
->out_fifo
, nb_samples
);
417 return av_audio_fifo_read(avr
->out_fifo
, (void**)output
, nb_samples
);
420 unsigned avresample_version(void)
422 return LIBAVRESAMPLE_VERSION_INT
;
425 const char *avresample_license(void)
427 #define LICENSE_PREFIX "libavresample license: "
428 return LICENSE_PREFIX LIBAV_LICENSE
+ sizeof(LICENSE_PREFIX
) - 1;
431 const char *avresample_configuration(void)
433 return LIBAV_CONFIGURATION
;