blob: b4fb906556c141ece60b37ce4d3de2ed12b34bb3
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 | |
36 | int avresample_open(AVAudioResampleContext *avr) |
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 */ |
46 | avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout); |
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 | } |
52 | avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout); |
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 | } |
58 | avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels); |
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 || |
62 | avr->in_channel_layout != avr->out_channel_layout)); |
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 */ |
70 | if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE && |
71 | (avr->mixing_needed || avr->resample_needed)) { |
72 | enum AVSampleFormat in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); |
73 | enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); |
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) { |
77 | avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P; |
78 | } else if (avr->mixing_needed) { |
79 | avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; |
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 */ |
87 | avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; |
88 | } else { |
89 | /* if one is s32 and the other is s32, s16, or u8, use s32 */ |
90 | avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P; |
91 | } |
92 | } else { |
93 | /* if one is flt and the other is flt, s16 or u8, use flt */ |
94 | avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; |
95 | } |
96 | } else { |
97 | /* if either is dbl, use dbl */ |
98 | avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; |
99 | } |
100 | } |
101 | av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n", |
102 | av_get_sample_fmt_name(avr->internal_sample_fmt)); |
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 && |
108 | !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels)) { |
109 | avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); |
110 | } |
111 | |
112 | /* set sample format conversion parameters */ |
113 | if (avr->resample_needed || avr->mixing_needed) |
114 | avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt; |
115 | else |
116 | avr->in_convert_needed = avr->use_channel_map && |
117 | !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels); |
118 | |
119 | if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed) |
120 | avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt; |
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) { |
132 | avr->remap_point = REMAP_IN_CONVERT; |
133 | av_log(avr, AV_LOG_TRACE, "remap channels during in_convert\n"); |
134 | } else if (avr->out_convert_needed) { |
135 | avr->remap_point = REMAP_OUT_CONVERT; |
136 | av_log(avr, AV_LOG_TRACE, "remap channels during out_convert\n"); |
137 | } else { |
138 | avr->remap_point = REMAP_OUT_COPY; |
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) { |
177 | avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels), |
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) { |
186 | avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels, |
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) { |
195 | avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0, |
196 | avr->out_sample_fmt, "out_buffer"); |
197 | if (!avr->out_buffer) { |
198 | ret = AVERROR(EINVAL); |
199 | goto error; |
200 | } |
201 | } |
202 | avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels, |
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) { |
211 | avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt, |
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, |
229 | avr->remap_point == REMAP_OUT_CONVERT); |
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 | |
257 | int avresample_is_open(AVAudioResampleContext *avr) |
258 | { |
259 | return !!avr->out_fifo; |
260 | } |
261 | |
262 | void avresample_close(AVAudioResampleContext *avr) |
263 | { |
264 | ff_audio_data_free(&avr->in_buffer); |
265 | ff_audio_data_free(&avr->resample_out_buffer); |
266 | ff_audio_data_free(&avr->out_buffer); |
267 | av_audio_fifo_free(avr->out_fifo); |
268 | avr->out_fifo = NULL; |
269 | ff_audio_convert_free(&avr->ac_in); |
270 | ff_audio_convert_free(&avr->ac_out); |
271 | ff_audio_resample_free(&avr->resample); |
272 | ff_audio_mix_free(&avr->am); |
273 | av_freep(&avr->mix_matrix); |
274 | |
275 | avr->use_channel_map = 0; |
276 | } |
277 | |
278 | void avresample_free(AVAudioResampleContext **avr) |
279 | { |
280 | if (!*avr) |
281 | return; |
282 | avresample_close(*avr); |
283 | av_opt_free(*avr); |
284 | av_freep(avr); |
285 | } |
286 | |
287 | static int handle_buffered_output(AVAudioResampleContext *avr, |
288 | AudioData *output, AudioData *converted) |
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); |
299 | ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0, |
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"); |
310 | return ff_audio_data_read_from_fifo(avr->out_fifo, output, |
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; |
318 | ret = ff_audio_data_copy(output, converted, |
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; |
344 | ff_audio_data_set_channels(avr->in_buffer, |
345 | avr->in_buffer->allocated_channels); |
346 | } |
347 | if (avr->resample_out_buffer) { |
348 | avr->resample_out_buffer->nb_samples = 0; |
349 | ff_audio_data_set_channels(avr->resample_out_buffer, |
350 | avr->resample_out_buffer->allocated_channels); |
351 | } |
352 | if (avr->out_buffer) { |
353 | avr->out_buffer->nb_samples = 0; |
354 | ff_audio_data_set_channels(avr->out_buffer, |
355 | avr->out_buffer->allocated_channels); |
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) { |
406 | ret = ff_audio_data_realloc(avr->in_buffer, |
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 | } |
423 | ff_audio_data_set_channels(avr->in_buffer, avr->in_channels); |
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 { |
488 | ret = ff_audio_data_realloc(avr->out_buffer, |
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 | |
505 | int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in) |
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 | |
526 | static int config_changed(AVAudioResampleContext *avr, |
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) { |
535 | ret |= AVERROR_INPUT_CHANGED; |
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) { |
543 | ret |= AVERROR_OUTPUT_CHANGED; |
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 | |
603 | int avresample_convert_frame(AVAudioResampleContext *avr, |
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 | |
637 | int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix, |
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 | |
645 | in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout); |
646 | out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout); |
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 | |
674 | in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout); |
675 | out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout); |
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 | |
697 | int avresample_set_channel_mapping(AVAudioResampleContext *avr, |
698 | const int *channel_map) |
699 | { |
700 | ChannelMapInfo *info = &avr->ch_map_info; |
701 | int in_channels, ch, i; |
702 | |
703 | in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout); |
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 | |
748 | int avresample_available(AVAudioResampleContext *avr) |
749 | { |
750 | return av_audio_fifo_size(avr->out_fifo); |
751 | } |
752 | |
753 | int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples) |
754 | { |
755 | int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples; |
756 | |
757 | if (avr->resample_needed) { |
758 | samples = av_rescale_rnd(samples, |
759 | avr->out_sample_rate, |
760 | avr->in_sample_rate, |
761 | AV_ROUND_UP); |
762 | } |
763 | |
764 | samples += avresample_available(avr); |
765 | |
766 | if (samples > INT_MAX) |
767 | return AVERROR(EINVAL); |
768 | |
769 | return samples; |
770 | } |
771 | |
772 | int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples) |
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 | { |
781 | return LIBAVRESAMPLE_VERSION_INT; |
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 | } |
794 |