annotate ffmpeg/libavresample/utils.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
yading@11 3 *
yading@11 4 * This file is part of Libav.
yading@11 5 *
yading@11 6 * Libav is free software; you can redistribute it and/or
yading@11 7 * modify it under the terms of the GNU Lesser General Public
yading@11 8 * License as published by the Free Software Foundation; either
yading@11 9 * version 2.1 of the License, or (at your option) any later version.
yading@11 10 *
yading@11 11 * Libav is distributed in the hope that it will be useful,
yading@11 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 14 * Lesser General Public License for more details.
yading@11 15 *
yading@11 16 * You should have received a copy of the GNU Lesser General Public
yading@11 17 * License along with Libav; if not, write to the Free Software
yading@11 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 19 */
yading@11 20
yading@11 21 #include "libavutil/common.h"
yading@11 22 #include "libavutil/dict.h"
yading@11 23 // #include "libavutil/error.h"
yading@11 24 #include "libavutil/log.h"
yading@11 25 #include "libavutil/mem.h"
yading@11 26 #include "libavutil/opt.h"
yading@11 27
yading@11 28 #include "avresample.h"
yading@11 29 #include "internal.h"
yading@11 30 #include "audio_data.h"
yading@11 31 #include "audio_convert.h"
yading@11 32 #include "audio_mix.h"
yading@11 33 #include "resample.h"
yading@11 34
yading@11 35 int avresample_open(AVAudioResampleContext *avr)
yading@11 36 {
yading@11 37 int ret;
yading@11 38
yading@11 39 /* set channel mixing parameters */
yading@11 40 avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
yading@11 41 if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
yading@11 42 av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
yading@11 43 avr->in_channel_layout);
yading@11 44 return AVERROR(EINVAL);
yading@11 45 }
yading@11 46 avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
yading@11 47 if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
yading@11 48 av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
yading@11 49 avr->out_channel_layout);
yading@11 50 return AVERROR(EINVAL);
yading@11 51 }
yading@11 52 avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
yading@11 53 avr->downmix_needed = avr->in_channels > avr->out_channels;
yading@11 54 avr->upmix_needed = avr->out_channels > avr->in_channels ||
yading@11 55 (!avr->downmix_needed && (avr->mix_matrix ||
yading@11 56 avr->in_channel_layout != avr->out_channel_layout));
yading@11 57 avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;
yading@11 58
yading@11 59 /* set resampling parameters */
yading@11 60 avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate ||
yading@11 61 avr->force_resampling;
yading@11 62
yading@11 63 /* select internal sample format if not specified by the user */
yading@11 64 if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE &&
yading@11 65 (avr->mixing_needed || avr->resample_needed)) {
yading@11 66 enum AVSampleFormat in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
yading@11 67 enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
yading@11 68 int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt),
yading@11 69 av_get_bytes_per_sample(out_fmt));
yading@11 70 if (max_bps <= 2) {
yading@11 71 avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
yading@11 72 } else if (avr->mixing_needed) {
yading@11 73 avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
yading@11 74 } else {
yading@11 75 if (max_bps <= 4) {
yading@11 76 if (in_fmt == AV_SAMPLE_FMT_S32P ||
yading@11 77 out_fmt == AV_SAMPLE_FMT_S32P) {
yading@11 78 if (in_fmt == AV_SAMPLE_FMT_FLTP ||
yading@11 79 out_fmt == AV_SAMPLE_FMT_FLTP) {
yading@11 80 /* if one is s32 and the other is flt, use dbl */
yading@11 81 avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
yading@11 82 } else {
yading@11 83 /* if one is s32 and the other is s32, s16, or u8, use s32 */
yading@11 84 avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P;
yading@11 85 }
yading@11 86 } else {
yading@11 87 /* if one is flt and the other is flt, s16 or u8, use flt */
yading@11 88 avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
yading@11 89 }
yading@11 90 } else {
yading@11 91 /* if either is dbl, use dbl */
yading@11 92 avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
yading@11 93 }
yading@11 94 }
yading@11 95 av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n",
yading@11 96 av_get_sample_fmt_name(avr->internal_sample_fmt));
yading@11 97 }
yading@11 98
yading@11 99 /* treat all mono as planar for easier comparison */
yading@11 100 if (avr->in_channels == 1)
yading@11 101 avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
yading@11 102 if (avr->out_channels == 1)
yading@11 103 avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
yading@11 104
yading@11 105 /* we may need to add an extra conversion in order to remap channels if
yading@11 106 the output format is not planar */
yading@11 107 if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
yading@11 108 !av_sample_fmt_is_planar(avr->out_sample_fmt)) {
yading@11 109 avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
yading@11 110 }
yading@11 111
yading@11 112 /* set sample format conversion parameters */
yading@11 113 if (avr->resample_needed || avr->mixing_needed)
yading@11 114 avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt;
yading@11 115 else
yading@11 116 avr->in_convert_needed = avr->use_channel_map &&
yading@11 117 !av_sample_fmt_is_planar(avr->out_sample_fmt);
yading@11 118
yading@11 119 if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
yading@11 120 avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
yading@11 121 else
yading@11 122 avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
yading@11 123
yading@11 124 avr->in_copy_needed = !avr->in_convert_needed && (avr->mixing_needed ||
yading@11 125 (avr->use_channel_map && avr->resample_needed));
yading@11 126
yading@11 127 if (avr->use_channel_map) {
yading@11 128 if (avr->in_copy_needed) {
yading@11 129 avr->remap_point = REMAP_IN_COPY;
yading@11 130 av_dlog(avr, "remap channels during in_copy\n");
yading@11 131 } else if (avr->in_convert_needed) {
yading@11 132 avr->remap_point = REMAP_IN_CONVERT;
yading@11 133 av_dlog(avr, "remap channels during in_convert\n");
yading@11 134 } else if (avr->out_convert_needed) {
yading@11 135 avr->remap_point = REMAP_OUT_CONVERT;
yading@11 136 av_dlog(avr, "remap channels during out_convert\n");
yading@11 137 } else {
yading@11 138 avr->remap_point = REMAP_OUT_COPY;
yading@11 139 av_dlog(avr, "remap channels during out_copy\n");
yading@11 140 }
yading@11 141
yading@11 142 #ifdef DEBUG
yading@11 143 {
yading@11 144 int ch;
yading@11 145 av_dlog(avr, "output map: ");
yading@11 146 if (avr->ch_map_info.do_remap)
yading@11 147 for (ch = 0; ch < avr->in_channels; ch++)
yading@11 148 av_dlog(avr, " % 2d", avr->ch_map_info.channel_map[ch]);
yading@11 149 else
yading@11 150 av_dlog(avr, "n/a");
yading@11 151 av_dlog(avr, "\n");
yading@11 152 av_dlog(avr, "copy map: ");
yading@11 153 if (avr->ch_map_info.do_copy)
yading@11 154 for (ch = 0; ch < avr->in_channels; ch++)
yading@11 155 av_dlog(avr, " % 2d", avr->ch_map_info.channel_copy[ch]);
yading@11 156 else
yading@11 157 av_dlog(avr, "n/a");
yading@11 158 av_dlog(avr, "\n");
yading@11 159 av_dlog(avr, "zero map: ");
yading@11 160 if (avr->ch_map_info.do_zero)
yading@11 161 for (ch = 0; ch < avr->in_channels; ch++)
yading@11 162 av_dlog(avr, " % 2d", avr->ch_map_info.channel_zero[ch]);
yading@11 163 else
yading@11 164 av_dlog(avr, "n/a");
yading@11 165 av_dlog(avr, "\n");
yading@11 166 av_dlog(avr, "input map: ");
yading@11 167 for (ch = 0; ch < avr->in_channels; ch++)
yading@11 168 av_dlog(avr, " % 2d", avr->ch_map_info.input_map[ch]);
yading@11 169 av_dlog(avr, "\n");
yading@11 170 }
yading@11 171 #endif
yading@11 172 } else
yading@11 173 avr->remap_point = REMAP_NONE;
yading@11 174
yading@11 175 /* allocate buffers */
yading@11 176 if (avr->in_copy_needed || avr->in_convert_needed) {
yading@11 177 avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
yading@11 178 0, avr->internal_sample_fmt,
yading@11 179 "in_buffer");
yading@11 180 if (!avr->in_buffer) {
yading@11 181 ret = AVERROR(EINVAL);
yading@11 182 goto error;
yading@11 183 }
yading@11 184 }
yading@11 185 if (avr->resample_needed) {
yading@11 186 avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
yading@11 187 0, avr->internal_sample_fmt,
yading@11 188 "resample_out_buffer");
yading@11 189 if (!avr->resample_out_buffer) {
yading@11 190 ret = AVERROR(EINVAL);
yading@11 191 goto error;
yading@11 192 }
yading@11 193 }
yading@11 194 if (avr->out_convert_needed) {
yading@11 195 avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
yading@11 196 avr->out_sample_fmt, "out_buffer");
yading@11 197 if (!avr->out_buffer) {
yading@11 198 ret = AVERROR(EINVAL);
yading@11 199 goto error;
yading@11 200 }
yading@11 201 }
yading@11 202 avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
yading@11 203 1024);
yading@11 204 if (!avr->out_fifo) {
yading@11 205 ret = AVERROR(ENOMEM);
yading@11 206 goto error;
yading@11 207 }
yading@11 208
yading@11 209 /* setup contexts */
yading@11 210 if (avr->in_convert_needed) {
yading@11 211 avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
yading@11 212 avr->in_sample_fmt, avr->in_channels,
yading@11 213 avr->in_sample_rate,
yading@11 214 avr->remap_point == REMAP_IN_CONVERT);
yading@11 215 if (!avr->ac_in) {
yading@11 216 ret = AVERROR(ENOMEM);
yading@11 217 goto error;
yading@11 218 }
yading@11 219 }
yading@11 220 if (avr->out_convert_needed) {
yading@11 221 enum AVSampleFormat src_fmt;
yading@11 222 if (avr->in_convert_needed)
yading@11 223 src_fmt = avr->internal_sample_fmt;
yading@11 224 else
yading@11 225 src_fmt = avr->in_sample_fmt;
yading@11 226 avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
yading@11 227 avr->out_channels,
yading@11 228 avr->out_sample_rate,
yading@11 229 avr->remap_point == REMAP_OUT_CONVERT);
yading@11 230 if (!avr->ac_out) {
yading@11 231 ret = AVERROR(ENOMEM);
yading@11 232 goto error;
yading@11 233 }
yading@11 234 }
yading@11 235 if (avr->resample_needed) {
yading@11 236 avr->resample = ff_audio_resample_init(avr);
yading@11 237 if (!avr->resample) {
yading@11 238 ret = AVERROR(ENOMEM);
yading@11 239 goto error;
yading@11 240 }
yading@11 241 }
yading@11 242 if (avr->mixing_needed) {
yading@11 243 avr->am = ff_audio_mix_alloc(avr);
yading@11 244 if (!avr->am) {
yading@11 245 ret = AVERROR(ENOMEM);
yading@11 246 goto error;
yading@11 247 }
yading@11 248 }
yading@11 249
yading@11 250 return 0;
yading@11 251
yading@11 252 error:
yading@11 253 avresample_close(avr);
yading@11 254 return ret;
yading@11 255 }
yading@11 256
yading@11 257 void avresample_close(AVAudioResampleContext *avr)
yading@11 258 {
yading@11 259 ff_audio_data_free(&avr->in_buffer);
yading@11 260 ff_audio_data_free(&avr->resample_out_buffer);
yading@11 261 ff_audio_data_free(&avr->out_buffer);
yading@11 262 av_audio_fifo_free(avr->out_fifo);
yading@11 263 avr->out_fifo = NULL;
yading@11 264 ff_audio_convert_free(&avr->ac_in);
yading@11 265 ff_audio_convert_free(&avr->ac_out);
yading@11 266 ff_audio_resample_free(&avr->resample);
yading@11 267 ff_audio_mix_free(&avr->am);
yading@11 268 av_freep(&avr->mix_matrix);
yading@11 269
yading@11 270 avr->use_channel_map = 0;
yading@11 271 }
yading@11 272
yading@11 273 void avresample_free(AVAudioResampleContext **avr)
yading@11 274 {
yading@11 275 if (!*avr)
yading@11 276 return;
yading@11 277 avresample_close(*avr);
yading@11 278 av_opt_free(*avr);
yading@11 279 av_freep(avr);
yading@11 280 }
yading@11 281
yading@11 282 static int handle_buffered_output(AVAudioResampleContext *avr,
yading@11 283 AudioData *output, AudioData *converted)
yading@11 284 {
yading@11 285 int ret;
yading@11 286
yading@11 287 if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
yading@11 288 (converted && output->allocated_samples < converted->nb_samples)) {
yading@11 289 if (converted) {
yading@11 290 /* if there are any samples in the output FIFO or if the
yading@11 291 user-supplied output buffer is not large enough for all samples,
yading@11 292 we add to the output FIFO */
yading@11 293 av_dlog(avr, "[FIFO] add %s to out_fifo\n", converted->name);
yading@11 294 ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0,
yading@11 295 converted->nb_samples);
yading@11 296 if (ret < 0)
yading@11 297 return ret;
yading@11 298 }
yading@11 299
yading@11 300 /* if the user specified an output buffer, read samples from the output
yading@11 301 FIFO to the user output */
yading@11 302 if (output && output->allocated_samples > 0) {
yading@11 303 av_dlog(avr, "[FIFO] read from out_fifo to output\n");
yading@11 304 av_dlog(avr, "[end conversion]\n");
yading@11 305 return ff_audio_data_read_from_fifo(avr->out_fifo, output,
yading@11 306 output->allocated_samples);
yading@11 307 }
yading@11 308 } else if (converted) {
yading@11 309 /* copy directly to output if it is large enough or there is not any
yading@11 310 data in the output FIFO */
yading@11 311 av_dlog(avr, "[copy] %s to output\n", converted->name);
yading@11 312 output->nb_samples = 0;
yading@11 313 ret = ff_audio_data_copy(output, converted,
yading@11 314 avr->remap_point == REMAP_OUT_COPY ?
yading@11 315 &avr->ch_map_info : NULL);
yading@11 316 if (ret < 0)
yading@11 317 return ret;
yading@11 318 av_dlog(avr, "[end conversion]\n");
yading@11 319 return output->nb_samples;
yading@11 320 }
yading@11 321 av_dlog(avr, "[end conversion]\n");
yading@11 322 return 0;
yading@11 323 }
yading@11 324
yading@11 325 int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
yading@11 326 uint8_t **output, int out_plane_size,
yading@11 327 int out_samples, uint8_t **input,
yading@11 328 int in_plane_size, int in_samples)
yading@11 329 {
yading@11 330 AudioData input_buffer;
yading@11 331 AudioData output_buffer;
yading@11 332 AudioData *current_buffer;
yading@11 333 int ret, direct_output;
yading@11 334
yading@11 335 /* reset internal buffers */
yading@11 336 if (avr->in_buffer) {
yading@11 337 avr->in_buffer->nb_samples = 0;
yading@11 338 ff_audio_data_set_channels(avr->in_buffer,
yading@11 339 avr->in_buffer->allocated_channels);
yading@11 340 }
yading@11 341 if (avr->resample_out_buffer) {
yading@11 342 avr->resample_out_buffer->nb_samples = 0;
yading@11 343 ff_audio_data_set_channels(avr->resample_out_buffer,
yading@11 344 avr->resample_out_buffer->allocated_channels);
yading@11 345 }
yading@11 346 if (avr->out_buffer) {
yading@11 347 avr->out_buffer->nb_samples = 0;
yading@11 348 ff_audio_data_set_channels(avr->out_buffer,
yading@11 349 avr->out_buffer->allocated_channels);
yading@11 350 }
yading@11 351
yading@11 352 av_dlog(avr, "[start conversion]\n");
yading@11 353
yading@11 354 /* initialize output_buffer with output data */
yading@11 355 direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0;
yading@11 356 if (output) {
yading@11 357 ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
yading@11 358 avr->out_channels, out_samples,
yading@11 359 avr->out_sample_fmt, 0, "output");
yading@11 360 if (ret < 0)
yading@11 361 return ret;
yading@11 362 output_buffer.nb_samples = 0;
yading@11 363 }
yading@11 364
yading@11 365 if (input) {
yading@11 366 /* initialize input_buffer with input data */
yading@11 367 ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
yading@11 368 avr->in_channels, in_samples,
yading@11 369 avr->in_sample_fmt, 1, "input");
yading@11 370 if (ret < 0)
yading@11 371 return ret;
yading@11 372 current_buffer = &input_buffer;
yading@11 373
yading@11 374 if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
yading@11 375 !avr->out_convert_needed && direct_output && out_samples >= in_samples) {
yading@11 376 /* in some rare cases we can copy input to output and upmix
yading@11 377 directly in the output buffer */
yading@11 378 av_dlog(avr, "[copy] %s to output\n", current_buffer->name);
yading@11 379 ret = ff_audio_data_copy(&output_buffer, current_buffer,
yading@11 380 avr->remap_point == REMAP_OUT_COPY ?
yading@11 381 &avr->ch_map_info : NULL);
yading@11 382 if (ret < 0)
yading@11 383 return ret;
yading@11 384 current_buffer = &output_buffer;
yading@11 385 } else if (avr->remap_point == REMAP_OUT_COPY &&
yading@11 386 (!direct_output || out_samples < in_samples)) {
yading@11 387 /* if remapping channels during output copy, we may need to
yading@11 388 * use an intermediate buffer in order to remap before adding
yading@11 389 * samples to the output fifo */
yading@11 390 av_dlog(avr, "[copy] %s to out_buffer\n", current_buffer->name);
yading@11 391 ret = ff_audio_data_copy(avr->out_buffer, current_buffer,
yading@11 392 &avr->ch_map_info);
yading@11 393 if (ret < 0)
yading@11 394 return ret;
yading@11 395 current_buffer = avr->out_buffer;
yading@11 396 } else if (avr->in_copy_needed || avr->in_convert_needed) {
yading@11 397 /* if needed, copy or convert input to in_buffer, and downmix if
yading@11 398 applicable */
yading@11 399 if (avr->in_convert_needed) {
yading@11 400 ret = ff_audio_data_realloc(avr->in_buffer,
yading@11 401 current_buffer->nb_samples);
yading@11 402 if (ret < 0)
yading@11 403 return ret;
yading@11 404 av_dlog(avr, "[convert] %s to in_buffer\n", current_buffer->name);
yading@11 405 ret = ff_audio_convert(avr->ac_in, avr->in_buffer,
yading@11 406 current_buffer);
yading@11 407 if (ret < 0)
yading@11 408 return ret;
yading@11 409 } else {
yading@11 410 av_dlog(avr, "[copy] %s to in_buffer\n", current_buffer->name);
yading@11 411 ret = ff_audio_data_copy(avr->in_buffer, current_buffer,
yading@11 412 avr->remap_point == REMAP_IN_COPY ?
yading@11 413 &avr->ch_map_info : NULL);
yading@11 414 if (ret < 0)
yading@11 415 return ret;
yading@11 416 }
yading@11 417 ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
yading@11 418 if (avr->downmix_needed) {
yading@11 419 av_dlog(avr, "[downmix] in_buffer\n");
yading@11 420 ret = ff_audio_mix(avr->am, avr->in_buffer);
yading@11 421 if (ret < 0)
yading@11 422 return ret;
yading@11 423 }
yading@11 424 current_buffer = avr->in_buffer;
yading@11 425 }
yading@11 426 } else {
yading@11 427 /* flush resampling buffer and/or output FIFO if input is NULL */
yading@11 428 if (!avr->resample_needed)
yading@11 429 return handle_buffered_output(avr, output ? &output_buffer : NULL,
yading@11 430 NULL);
yading@11 431 current_buffer = NULL;
yading@11 432 }
yading@11 433
yading@11 434 if (avr->resample_needed) {
yading@11 435 AudioData *resample_out;
yading@11 436
yading@11 437 if (!avr->out_convert_needed && direct_output && out_samples > 0)
yading@11 438 resample_out = &output_buffer;
yading@11 439 else
yading@11 440 resample_out = avr->resample_out_buffer;
yading@11 441 av_dlog(avr, "[resample] %s to %s\n", current_buffer->name,
yading@11 442 resample_out->name);
yading@11 443 ret = ff_audio_resample(avr->resample, resample_out,
yading@11 444 current_buffer);
yading@11 445 if (ret < 0)
yading@11 446 return ret;
yading@11 447
yading@11 448 /* if resampling did not produce any samples, just return 0 */
yading@11 449 if (resample_out->nb_samples == 0) {
yading@11 450 av_dlog(avr, "[end conversion]\n");
yading@11 451 return 0;
yading@11 452 }
yading@11 453
yading@11 454 current_buffer = resample_out;
yading@11 455 }
yading@11 456
yading@11 457 if (avr->upmix_needed) {
yading@11 458 av_dlog(avr, "[upmix] %s\n", current_buffer->name);
yading@11 459 ret = ff_audio_mix(avr->am, current_buffer);
yading@11 460 if (ret < 0)
yading@11 461 return ret;
yading@11 462 }
yading@11 463
yading@11 464 /* if we resampled or upmixed directly to output, return here */
yading@11 465 if (current_buffer == &output_buffer) {
yading@11 466 av_dlog(avr, "[end conversion]\n");
yading@11 467 return current_buffer->nb_samples;
yading@11 468 }
yading@11 469
yading@11 470 if (avr->out_convert_needed) {
yading@11 471 if (direct_output && out_samples >= current_buffer->nb_samples) {
yading@11 472 /* convert directly to output */
yading@11 473 av_dlog(avr, "[convert] %s to output\n", current_buffer->name);
yading@11 474 ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer);
yading@11 475 if (ret < 0)
yading@11 476 return ret;
yading@11 477
yading@11 478 av_dlog(avr, "[end conversion]\n");
yading@11 479 return output_buffer.nb_samples;
yading@11 480 } else {
yading@11 481 ret = ff_audio_data_realloc(avr->out_buffer,
yading@11 482 current_buffer->nb_samples);
yading@11 483 if (ret < 0)
yading@11 484 return ret;
yading@11 485 av_dlog(avr, "[convert] %s to out_buffer\n", current_buffer->name);
yading@11 486 ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
yading@11 487 current_buffer);
yading@11 488 if (ret < 0)
yading@11 489 return ret;
yading@11 490 current_buffer = avr->out_buffer;
yading@11 491 }
yading@11 492 }
yading@11 493
yading@11 494 return handle_buffered_output(avr, output ? &output_buffer : NULL,
yading@11 495 current_buffer);
yading@11 496 }
yading@11 497
yading@11 498 int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
yading@11 499 int stride)
yading@11 500 {
yading@11 501 int in_channels, out_channels, i, o;
yading@11 502
yading@11 503 if (avr->am)
yading@11 504 return ff_audio_mix_get_matrix(avr->am, matrix, stride);
yading@11 505
yading@11 506 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
yading@11 507 out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
yading@11 508
yading@11 509 if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
yading@11 510 out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
yading@11 511 av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
yading@11 512 return AVERROR(EINVAL);
yading@11 513 }
yading@11 514
yading@11 515 if (!avr->mix_matrix) {
yading@11 516 av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
yading@11 517 return AVERROR(EINVAL);
yading@11 518 }
yading@11 519
yading@11 520 for (o = 0; o < out_channels; o++)
yading@11 521 for (i = 0; i < in_channels; i++)
yading@11 522 matrix[o * stride + i] = avr->mix_matrix[o * in_channels + i];
yading@11 523
yading@11 524 return 0;
yading@11 525 }
yading@11 526
yading@11 527 int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
yading@11 528 int stride)
yading@11 529 {
yading@11 530 int in_channels, out_channels, i, o;
yading@11 531
yading@11 532 if (avr->am)
yading@11 533 return ff_audio_mix_set_matrix(avr->am, matrix, stride);
yading@11 534
yading@11 535 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
yading@11 536 out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
yading@11 537
yading@11 538 if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
yading@11 539 out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
yading@11 540 av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
yading@11 541 return AVERROR(EINVAL);
yading@11 542 }
yading@11 543
yading@11 544 if (avr->mix_matrix)
yading@11 545 av_freep(&avr->mix_matrix);
yading@11 546 avr->mix_matrix = av_malloc(in_channels * out_channels *
yading@11 547 sizeof(*avr->mix_matrix));
yading@11 548 if (!avr->mix_matrix)
yading@11 549 return AVERROR(ENOMEM);
yading@11 550
yading@11 551 for (o = 0; o < out_channels; o++)
yading@11 552 for (i = 0; i < in_channels; i++)
yading@11 553 avr->mix_matrix[o * in_channels + i] = matrix[o * stride + i];
yading@11 554
yading@11 555 return 0;
yading@11 556 }
yading@11 557
yading@11 558 int avresample_set_channel_mapping(AVAudioResampleContext *avr,
yading@11 559 const int *channel_map)
yading@11 560 {
yading@11 561 ChannelMapInfo *info = &avr->ch_map_info;
yading@11 562 int in_channels, ch, i;
yading@11 563
yading@11 564 in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
yading@11 565 if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS) {
yading@11 566 av_log(avr, AV_LOG_ERROR, "Invalid input channel layout\n");
yading@11 567 return AVERROR(EINVAL);
yading@11 568 }
yading@11 569
yading@11 570 memset(info, 0, sizeof(*info));
yading@11 571 memset(info->input_map, -1, sizeof(info->input_map));
yading@11 572
yading@11 573 for (ch = 0; ch < in_channels; ch++) {
yading@11 574 if (channel_map[ch] >= in_channels) {
yading@11 575 av_log(avr, AV_LOG_ERROR, "Invalid channel map\n");
yading@11 576 return AVERROR(EINVAL);
yading@11 577 }
yading@11 578 if (channel_map[ch] < 0) {
yading@11 579 info->channel_zero[ch] = 1;
yading@11 580 info->channel_map[ch] = -1;
yading@11 581 info->do_zero = 1;
yading@11 582 } else if (info->input_map[channel_map[ch]] >= 0) {
yading@11 583 info->channel_copy[ch] = info->input_map[channel_map[ch]];
yading@11 584 info->channel_map[ch] = -1;
yading@11 585 info->do_copy = 1;
yading@11 586 } else {
yading@11 587 info->channel_map[ch] = channel_map[ch];
yading@11 588 info->input_map[channel_map[ch]] = ch;
yading@11 589 info->do_remap = 1;
yading@11 590 }
yading@11 591 }
yading@11 592 /* Fill-in unmapped input channels with unmapped output channels.
yading@11 593 This is used when remapping during conversion from interleaved to
yading@11 594 planar format. */
yading@11 595 for (ch = 0, i = 0; ch < in_channels && i < in_channels; ch++, i++) {
yading@11 596 while (ch < in_channels && info->input_map[ch] >= 0)
yading@11 597 ch++;
yading@11 598 while (i < in_channels && info->channel_map[i] >= 0)
yading@11 599 i++;
yading@11 600 if (ch >= in_channels || i >= in_channels)
yading@11 601 break;
yading@11 602 info->input_map[ch] = i;
yading@11 603 }
yading@11 604
yading@11 605 avr->use_channel_map = 1;
yading@11 606 return 0;
yading@11 607 }
yading@11 608
yading@11 609 int avresample_available(AVAudioResampleContext *avr)
yading@11 610 {
yading@11 611 return av_audio_fifo_size(avr->out_fifo);
yading@11 612 }
yading@11 613
yading@11 614 int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples)
yading@11 615 {
yading@11 616 if (!output)
yading@11 617 return av_audio_fifo_drain(avr->out_fifo, nb_samples);
yading@11 618 return av_audio_fifo_read(avr->out_fifo, (void**)output, nb_samples);
yading@11 619 }
yading@11 620
yading@11 621 unsigned avresample_version(void)
yading@11 622 {
yading@11 623 return LIBAVRESAMPLE_VERSION_INT;
yading@11 624 }
yading@11 625
yading@11 626 const char *avresample_license(void)
yading@11 627 {
yading@11 628 #define LICENSE_PREFIX "libavresample license: "
yading@11 629 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
yading@11 630 }
yading@11 631
yading@11 632 const char *avresample_configuration(void)
yading@11 633 {
yading@11 634 return FFMPEG_CONFIGURATION;
yading@11 635 }