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