LCOV - code coverage report
Current view: top level - src/libavresample - utils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 101 416 24.3 %
Date: 2017-03-16 17:17:40 Functions: 10 20 50.0 %

          Line data    Source code
       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           1 : int avresample_open(AVAudioResampleContext *avr)
      37             : {
      38             :     int ret;
      39             : 
      40           1 :     if (avresample_is_open(avr)) {
      41           0 :         av_log(avr, AV_LOG_ERROR, "The resampling context is already open.\n");
      42           0 :         return AVERROR(EINVAL);
      43             :     }
      44             : 
      45             :     /* set channel mixing parameters */
      46           1 :     avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
      47           1 :     if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
      48           0 :         av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
      49             :                avr->in_channel_layout);
      50           0 :         return AVERROR(EINVAL);
      51             :     }
      52           1 :     avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
      53           1 :     if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
      54           0 :         av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
      55             :                avr->out_channel_layout);
      56           0 :         return AVERROR(EINVAL);
      57             :     }
      58           1 :     avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
      59           1 :     avr->downmix_needed    = avr->in_channels  > avr->out_channels;
      60           2 :     avr->upmix_needed      = avr->out_channels > avr->in_channels ||
      61           3 :                              (!avr->downmix_needed && (avr->mix_matrix ||
      62           1 :                               avr->in_channel_layout != avr->out_channel_layout));
      63           1 :     avr->mixing_needed     = avr->downmix_needed || avr->upmix_needed;
      64             : 
      65             :     /* set resampling parameters */
      66           2 :     avr->resample_needed   = avr->in_sample_rate != avr->out_sample_rate ||
      67           1 :                              avr->force_resampling;
      68             : 
      69             :     /* select internal sample format if not specified by the user */
      70           2 :     if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE &&
      71           2 :         (avr->mixing_needed || avr->resample_needed)) {
      72           0 :         enum AVSampleFormat  in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt);
      73           0 :         enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
      74           0 :         int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt),
      75             :                             av_get_bytes_per_sample(out_fmt));
      76           0 :         if (max_bps <= 2) {
      77           0 :             avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P;
      78           0 :         } else if (avr->mixing_needed) {
      79           0 :             avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
      80             :         } else {
      81           0 :             if (max_bps <= 4) {
      82           0 :                 if (in_fmt  == AV_SAMPLE_FMT_S32P ||
      83             :                     out_fmt == AV_SAMPLE_FMT_S32P) {
      84           0 :                     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           0 :                         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           0 :                         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           0 :                     avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP;
      95             :                 }
      96             :             } else {
      97             :                 /* if either is dbl, use dbl */
      98           0 :                 avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP;
      99             :             }
     100             :         }
     101           0 :         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           1 :     if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
     108           0 :         !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels)) {
     109           0 :         avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
     110             :     }
     111             : 
     112             :     /* set sample format conversion parameters */
     113           1 :     if (avr->resample_needed || avr->mixing_needed)
     114           0 :         avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt;
     115             :     else
     116           1 :         avr->in_convert_needed = avr->use_channel_map &&
     117           0 :                                  !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels);
     118             : 
     119           1 :     if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
     120           0 :         avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
     121             :     else
     122           1 :         avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt;
     123             : 
     124           2 :     avr->in_copy_needed = !avr->in_convert_needed && (avr->mixing_needed ||
     125           1 :                           (avr->use_channel_map && avr->resample_needed));
     126             : 
     127           1 :     if (avr->use_channel_map) {
     128           0 :         if (avr->in_copy_needed) {
     129           0 :             avr->remap_point = REMAP_IN_COPY;
     130           0 :             av_log(avr, AV_LOG_TRACE, "remap channels during in_copy\n");
     131           0 :         } else if (avr->in_convert_needed) {
     132           0 :             avr->remap_point = REMAP_IN_CONVERT;
     133           0 :             av_log(avr, AV_LOG_TRACE, "remap channels during in_convert\n");
     134           0 :         } else if (avr->out_convert_needed) {
     135           0 :             avr->remap_point = REMAP_OUT_CONVERT;
     136           0 :             av_log(avr, AV_LOG_TRACE, "remap channels during out_convert\n");
     137             :         } else {
     138           0 :             avr->remap_point = REMAP_OUT_COPY;
     139           0 :             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           1 :         avr->remap_point = REMAP_NONE;
     174             : 
     175             :     /* allocate buffers */
     176           1 :     if (avr->in_copy_needed || avr->in_convert_needed) {
     177           0 :         avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
     178             :                                              0, avr->internal_sample_fmt,
     179             :                                              "in_buffer");
     180           0 :         if (!avr->in_buffer) {
     181           0 :             ret = AVERROR(EINVAL);
     182           0 :             goto error;
     183             :         }
     184             :     }
     185           1 :     if (avr->resample_needed) {
     186           0 :         avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
     187             :                                                        1024, avr->internal_sample_fmt,
     188             :                                                        "resample_out_buffer");
     189           0 :         if (!avr->resample_out_buffer) {
     190           0 :             ret = AVERROR(EINVAL);
     191           0 :             goto error;
     192             :         }
     193             :     }
     194           1 :     if (avr->out_convert_needed) {
     195           0 :         avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
     196             :                                               avr->out_sample_fmt, "out_buffer");
     197           0 :         if (!avr->out_buffer) {
     198           0 :             ret = AVERROR(EINVAL);
     199           0 :             goto error;
     200             :         }
     201             :     }
     202           1 :     avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
     203             :                                         1024);
     204           1 :     if (!avr->out_fifo) {
     205           0 :         ret = AVERROR(ENOMEM);
     206           0 :         goto error;
     207             :     }
     208             : 
     209             :     /* setup contexts */
     210           1 :     if (avr->in_convert_needed) {
     211           0 :         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           0 :                                             avr->remap_point == REMAP_IN_CONVERT);
     215           0 :         if (!avr->ac_in) {
     216           0 :             ret = AVERROR(ENOMEM);
     217           0 :             goto error;
     218             :         }
     219             :     }
     220           1 :     if (avr->out_convert_needed) {
     221             :         enum AVSampleFormat src_fmt;
     222           0 :         if (avr->in_convert_needed)
     223           0 :             src_fmt = avr->internal_sample_fmt;
     224             :         else
     225           0 :             src_fmt = avr->in_sample_fmt;
     226           0 :         avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
     227             :                                              avr->out_channels,
     228             :                                              avr->out_sample_rate,
     229           0 :                                              avr->remap_point == REMAP_OUT_CONVERT);
     230           0 :         if (!avr->ac_out) {
     231           0 :             ret = AVERROR(ENOMEM);
     232           0 :             goto error;
     233             :         }
     234             :     }
     235           1 :     if (avr->resample_needed) {
     236           0 :         avr->resample = ff_audio_resample_init(avr);
     237           0 :         if (!avr->resample) {
     238           0 :             ret = AVERROR(ENOMEM);
     239           0 :             goto error;
     240             :         }
     241             :     }
     242           1 :     if (avr->mixing_needed) {
     243           0 :         avr->am = ff_audio_mix_alloc(avr);
     244           0 :         if (!avr->am) {
     245           0 :             ret = AVERROR(ENOMEM);
     246           0 :             goto error;
     247             :         }
     248             :     }
     249             : 
     250           1 :     return 0;
     251             : 
     252             : error:
     253           0 :     avresample_close(avr);
     254           0 :     return ret;
     255             : }
     256             : 
     257           1 : int avresample_is_open(AVAudioResampleContext *avr)
     258             : {
     259           1 :     return !!avr->out_fifo;
     260             : }
     261             : 
     262           2 : void avresample_close(AVAudioResampleContext *avr)
     263             : {
     264           2 :     ff_audio_data_free(&avr->in_buffer);
     265           2 :     ff_audio_data_free(&avr->resample_out_buffer);
     266           2 :     ff_audio_data_free(&avr->out_buffer);
     267           2 :     av_audio_fifo_free(avr->out_fifo);
     268           2 :     avr->out_fifo = NULL;
     269           2 :     ff_audio_convert_free(&avr->ac_in);
     270           2 :     ff_audio_convert_free(&avr->ac_out);
     271           2 :     ff_audio_resample_free(&avr->resample);
     272           2 :     ff_audio_mix_free(&avr->am);
     273           2 :     av_freep(&avr->mix_matrix);
     274             : 
     275           2 :     avr->use_channel_map = 0;
     276           2 : }
     277             : 
     278           1 : void avresample_free(AVAudioResampleContext **avr)
     279             : {
     280           1 :     if (!*avr)
     281           0 :         return;
     282           1 :     avresample_close(*avr);
     283           1 :     av_opt_free(*avr);
     284           1 :     av_freep(avr);
     285             : }
     286             : 
     287         956 : static int handle_buffered_output(AVAudioResampleContext *avr,
     288             :                                   AudioData *output, AudioData *converted)
     289             : {
     290             :     int ret;
     291             : 
     292         956 :     if (!output || av_audio_fifo_size(avr->out_fifo) > 0 ||
     293           0 :         (converted && output->allocated_samples < converted->nb_samples)) {
     294         956 :         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         955 :             av_log(avr, AV_LOG_TRACE, "[FIFO] add %s to out_fifo\n", converted->name);
     299         955 :             ret = ff_audio_data_add_to_fifo(avr->out_fifo, converted, 0,
     300             :                                             converted->nb_samples);
     301         955 :             if (ret < 0)
     302           0 :                 return ret;
     303             :         }
     304             : 
     305             :         /* if the user specified an output buffer, read samples from the output
     306             :            FIFO to the user output */
     307        1911 :         if (output && output->allocated_samples > 0) {
     308           1 :             av_log(avr, AV_LOG_TRACE, "[FIFO] read from out_fifo to output\n");
     309           1 :             av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
     310           1 :             return ff_audio_data_read_from_fifo(avr->out_fifo, output,
     311             :                                                 output->allocated_samples);
     312             :         }
     313           0 :     } 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           0 :         av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", converted->name);
     317           0 :         output->nb_samples = 0;
     318           0 :         ret = ff_audio_data_copy(output, converted,
     319           0 :                                  avr->remap_point == REMAP_OUT_COPY ?
     320             :                                  &avr->ch_map_info : NULL);
     321           0 :         if (ret < 0)
     322           0 :             return ret;
     323           0 :         av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
     324           0 :         return output->nb_samples;
     325             :     }
     326         955 :     av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
     327         955 :     return 0;
     328             : }
     329             : 
     330         956 : 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         956 :     if (avr->in_buffer) {
     343           0 :         avr->in_buffer->nb_samples = 0;
     344           0 :         ff_audio_data_set_channels(avr->in_buffer,
     345           0 :                                    avr->in_buffer->allocated_channels);
     346             :     }
     347         956 :     if (avr->resample_out_buffer) {
     348           0 :         avr->resample_out_buffer->nb_samples = 0;
     349           0 :         ff_audio_data_set_channels(avr->resample_out_buffer,
     350           0 :                                    avr->resample_out_buffer->allocated_channels);
     351             :     }
     352         956 :     if (avr->out_buffer) {
     353           0 :         avr->out_buffer->nb_samples = 0;
     354           0 :         ff_audio_data_set_channels(avr->out_buffer,
     355           0 :                                    avr->out_buffer->allocated_channels);
     356             :     }
     357             : 
     358         956 :     av_log(avr, AV_LOG_TRACE, "[start conversion]\n");
     359             : 
     360             :     /* initialize output_buffer with output data */
     361         956 :     direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0;
     362         956 :     if (output) {
     363           1 :         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           1 :         if (ret < 0)
     367           0 :             return ret;
     368           1 :         output_buffer.nb_samples = 0;
     369             :     }
     370             : 
     371         956 :     if (input) {
     372             :         /* initialize input_buffer with input data */
     373         955 :         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         955 :         if (ret < 0)
     377           0 :             return ret;
     378         955 :         current_buffer = &input_buffer;
     379             : 
     380         955 :         if (avr->upmix_needed && !avr->in_convert_needed && !avr->resample_needed &&
     381           0 :             !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           0 :             av_log(avr, AV_LOG_TRACE, "[copy] %s to output\n", current_buffer->name);
     385           0 :             ret = ff_audio_data_copy(&output_buffer, current_buffer,
     386           0 :                                      avr->remap_point == REMAP_OUT_COPY ?
     387             :                                      &avr->ch_map_info : NULL);
     388           0 :             if (ret < 0)
     389           0 :                 return ret;
     390           0 :             current_buffer = &output_buffer;
     391         955 :         } else if (avr->remap_point == REMAP_OUT_COPY &&
     392           0 :                    (!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           0 :             av_log(avr, AV_LOG_TRACE, "[copy] %s to out_buffer\n", current_buffer->name);
     397           0 :             ret = ff_audio_data_copy(avr->out_buffer, current_buffer,
     398             :                                      &avr->ch_map_info);
     399           0 :             if (ret < 0)
     400           0 :                 return ret;
     401           0 :             current_buffer = avr->out_buffer;
     402         955 :         } 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           0 :             if (avr->in_convert_needed) {
     406           0 :                 ret = ff_audio_data_realloc(avr->in_buffer,
     407             :                                             current_buffer->nb_samples);
     408           0 :                 if (ret < 0)
     409           0 :                     return ret;
     410           0 :                 av_log(avr, AV_LOG_TRACE, "[convert] %s to in_buffer\n", current_buffer->name);
     411           0 :                 ret = ff_audio_convert(avr->ac_in, avr->in_buffer,
     412             :                                        current_buffer);
     413           0 :                 if (ret < 0)
     414           0 :                     return ret;
     415             :             } else {
     416           0 :                 av_log(avr, AV_LOG_TRACE, "[copy] %s to in_buffer\n", current_buffer->name);
     417           0 :                 ret = ff_audio_data_copy(avr->in_buffer, current_buffer,
     418           0 :                                          avr->remap_point == REMAP_IN_COPY ?
     419             :                                          &avr->ch_map_info : NULL);
     420           0 :                 if (ret < 0)
     421           0 :                     return ret;
     422             :             }
     423           0 :             ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
     424           0 :             if (avr->downmix_needed) {
     425           0 :                 av_log(avr, AV_LOG_TRACE, "[downmix] in_buffer\n");
     426           0 :                 ret = ff_audio_mix(avr->am, avr->in_buffer);
     427           0 :                 if (ret < 0)
     428           0 :                     return ret;
     429             :             }
     430           0 :             current_buffer = avr->in_buffer;
     431             :         }
     432             :     } else {
     433             :         /* flush resampling buffer and/or output FIFO if input is NULL */
     434           1 :         if (!avr->resample_needed)
     435           1 :             return handle_buffered_output(avr, output ? &output_buffer : NULL,
     436             :                                           NULL);
     437           0 :         current_buffer = NULL;
     438             :     }
     439             : 
     440         955 :     if (avr->resample_needed) {
     441             :         AudioData *resample_out;
     442             : 
     443           0 :         if (!avr->out_convert_needed && direct_output && out_samples > 0)
     444           0 :             resample_out = &output_buffer;
     445             :         else
     446           0 :             resample_out = avr->resample_out_buffer;
     447           0 :         av_log(avr, AV_LOG_TRACE, "[resample] %s to %s\n",
     448             :                 current_buffer ? current_buffer->name : "null",
     449             :                 resample_out->name);
     450           0 :         ret = ff_audio_resample(avr->resample, resample_out,
     451             :                                 current_buffer);
     452           0 :         if (ret < 0)
     453           0 :             return ret;
     454             : 
     455             :         /* if resampling did not produce any samples, just return 0 */
     456           0 :         if (resample_out->nb_samples == 0) {
     457           0 :             av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
     458           0 :             return 0;
     459             :         }
     460             : 
     461           0 :         current_buffer = resample_out;
     462             :     }
     463             : 
     464         955 :     if (avr->upmix_needed) {
     465           0 :         av_log(avr, AV_LOG_TRACE, "[upmix] %s\n", current_buffer->name);
     466           0 :         ret = ff_audio_mix(avr->am, current_buffer);
     467           0 :         if (ret < 0)
     468           0 :             return ret;
     469             :     }
     470             : 
     471             :     /* if we resampled or upmixed directly to output, return here */
     472         955 :     if (current_buffer == &output_buffer) {
     473           0 :         av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
     474           0 :         return current_buffer->nb_samples;
     475             :     }
     476             : 
     477         955 :     if (avr->out_convert_needed) {
     478           0 :         if (direct_output && out_samples >= current_buffer->nb_samples) {
     479             :             /* convert directly to output */
     480           0 :             av_log(avr, AV_LOG_TRACE, "[convert] %s to output\n", current_buffer->name);
     481           0 :             ret = ff_audio_convert(avr->ac_out, &output_buffer, current_buffer);
     482           0 :             if (ret < 0)
     483           0 :                 return ret;
     484             : 
     485           0 :             av_log(avr, AV_LOG_TRACE, "[end conversion]\n");
     486           0 :             return output_buffer.nb_samples;
     487             :         } else {
     488           0 :             ret = ff_audio_data_realloc(avr->out_buffer,
     489             :                                         current_buffer->nb_samples);
     490           0 :             if (ret < 0)
     491           0 :                 return ret;
     492           0 :             av_log(avr, AV_LOG_TRACE, "[convert] %s to out_buffer\n", current_buffer->name);
     493           0 :             ret = ff_audio_convert(avr->ac_out, avr->out_buffer,
     494             :                                    current_buffer);
     495           0 :             if (ret < 0)
     496           0 :                 return ret;
     497           0 :             current_buffer = avr->out_buffer;
     498             :         }
     499             :     }
     500             : 
     501         955 :     return handle_buffered_output(avr, output ? &output_buffer : NULL,
     502             :                                   current_buffer);
     503             : }
     504             : 
     505           0 : int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
     506             : {
     507           0 :     if (avresample_is_open(avr)) {
     508           0 :         avresample_close(avr);
     509             :     }
     510             : 
     511           0 :     if (in) {
     512           0 :         avr->in_channel_layout  = in->channel_layout;
     513           0 :         avr->in_sample_rate     = in->sample_rate;
     514           0 :         avr->in_sample_fmt      = in->format;
     515             :     }
     516             : 
     517           0 :     if (out) {
     518           0 :         avr->out_channel_layout = out->channel_layout;
     519           0 :         avr->out_sample_rate    = out->sample_rate;
     520           0 :         avr->out_sample_fmt     = out->format;
     521             :     }
     522             : 
     523           0 :     return 0;
     524             : }
     525             : 
     526           0 : static int config_changed(AVAudioResampleContext *avr,
     527             :                           AVFrame *out, AVFrame *in)
     528             : {
     529           0 :     int ret = 0;
     530             : 
     531           0 :     if (in) {
     532           0 :         if (avr->in_channel_layout != in->channel_layout ||
     533           0 :             avr->in_sample_rate    != in->sample_rate ||
     534           0 :             avr->in_sample_fmt     != in->format) {
     535           0 :             ret |= AVERROR_INPUT_CHANGED;
     536             :         }
     537             :     }
     538             : 
     539           0 :     if (out) {
     540           0 :         if (avr->out_channel_layout != out->channel_layout ||
     541           0 :             avr->out_sample_rate    != out->sample_rate ||
     542           0 :             avr->out_sample_fmt     != out->format) {
     543           0 :             ret |= AVERROR_OUTPUT_CHANGED;
     544             :         }
     545             :     }
     546             : 
     547           0 :     return ret;
     548             : }
     549             : 
     550           0 : static inline int convert_frame(AVAudioResampleContext *avr,
     551             :                                 AVFrame *out, AVFrame *in)
     552             : {
     553             :     int ret;
     554           0 :     uint8_t **out_data = NULL, **in_data = NULL;
     555           0 :     int out_linesize = 0, in_linesize = 0;
     556           0 :     int out_nb_samples = 0, in_nb_samples = 0;
     557             : 
     558           0 :     if (out) {
     559           0 :         out_data       = out->extended_data;
     560           0 :         out_linesize   = out->linesize[0];
     561           0 :         out_nb_samples = out->nb_samples;
     562             :     }
     563             : 
     564           0 :     if (in) {
     565           0 :         in_data       = in->extended_data;
     566           0 :         in_linesize   = in->linesize[0];
     567           0 :         in_nb_samples = in->nb_samples;
     568             :     }
     569             : 
     570           0 :     ret = avresample_convert(avr, out_data, out_linesize,
     571             :                              out_nb_samples,
     572             :                              in_data, in_linesize,
     573             :                              in_nb_samples);
     574             : 
     575           0 :     if (ret < 0) {
     576           0 :         if (out)
     577           0 :             out->nb_samples = 0;
     578           0 :         return ret;
     579             :     }
     580             : 
     581           0 :     if (out)
     582           0 :         out->nb_samples = ret;
     583             : 
     584           0 :     return 0;
     585             : }
     586             : 
     587           0 : static inline int available_samples(AVFrame *out)
     588             : {
     589             :     int samples;
     590           0 :     int bytes_per_sample = av_get_bytes_per_sample(out->format);
     591           0 :     if (!bytes_per_sample)
     592           0 :         return AVERROR(EINVAL);
     593             : 
     594           0 :     samples = out->linesize[0] / bytes_per_sample;
     595           0 :     if (av_sample_fmt_is_planar(out->format)) {
     596           0 :         return samples;
     597             :     } else {
     598           0 :         int channels = av_get_channel_layout_nb_channels(out->channel_layout);
     599           0 :         return samples / channels;
     600             :     }
     601             : }
     602             : 
     603           0 : int avresample_convert_frame(AVAudioResampleContext *avr,
     604             :                              AVFrame *out, AVFrame *in)
     605             : {
     606           0 :     int ret, setup = 0;
     607             : 
     608           0 :     if (!avresample_is_open(avr)) {
     609           0 :         if ((ret = avresample_config(avr, out, in)) < 0)
     610           0 :             return ret;
     611           0 :         if ((ret = avresample_open(avr)) < 0)
     612           0 :             return ret;
     613           0 :         setup = 1;
     614             :     } else {
     615             :         // return as is or reconfigure for input changes?
     616           0 :         if ((ret = config_changed(avr, out, in)))
     617           0 :             return ret;
     618             :     }
     619             : 
     620           0 :     if (out) {
     621           0 :         if (!out->linesize[0]) {
     622           0 :             out->nb_samples = avresample_get_out_samples(avr, in->nb_samples);
     623           0 :             if ((ret = av_frame_get_buffer(out, 0)) < 0) {
     624           0 :                 if (setup)
     625           0 :                     avresample_close(avr);
     626           0 :                 return ret;
     627             :             }
     628             :         } else {
     629           0 :             if (!out->nb_samples)
     630           0 :                 out->nb_samples = available_samples(out);
     631             :         }
     632             :     }
     633             : 
     634           0 :     return convert_frame(avr, out, in);
     635             : }
     636             : 
     637           0 : int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
     638             :                           int stride)
     639             : {
     640             :     int in_channels, out_channels, i, o;
     641             : 
     642           0 :     if (avr->am)
     643           0 :         return ff_audio_mix_get_matrix(avr->am, matrix, stride);
     644             : 
     645           0 :     in_channels  = av_get_channel_layout_nb_channels(avr->in_channel_layout);
     646           0 :     out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
     647             : 
     648           0 :     if ( in_channels <= 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS ||
     649           0 :         out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
     650           0 :         av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
     651           0 :         return AVERROR(EINVAL);
     652             :     }
     653             : 
     654           0 :     if (!avr->mix_matrix) {
     655           0 :         av_log(avr, AV_LOG_ERROR, "matrix is not set\n");
     656           0 :         return AVERROR(EINVAL);
     657             :     }
     658             : 
     659           0 :     for (o = 0; o < out_channels; o++)
     660           0 :         for (i = 0; i < in_channels; i++)
     661           0 :             matrix[o * stride + i] = avr->mix_matrix[o * in_channels + i];
     662             : 
     663           0 :     return 0;
     664             : }
     665             : 
     666           0 : int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
     667             :                           int stride)
     668             : {
     669             :     int in_channels, out_channels, i, o;
     670             : 
     671           0 :     if (avr->am)
     672           0 :         return ff_audio_mix_set_matrix(avr->am, matrix, stride);
     673             : 
     674           0 :     in_channels  = av_get_channel_layout_nb_channels(avr->in_channel_layout);
     675           0 :     out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
     676             : 
     677           0 :     if ( in_channels <= 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS ||
     678           0 :         out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
     679           0 :         av_log(avr, AV_LOG_ERROR, "Invalid channel layouts\n");
     680           0 :         return AVERROR(EINVAL);
     681             :     }
     682             : 
     683           0 :     if (avr->mix_matrix)
     684           0 :         av_freep(&avr->mix_matrix);
     685           0 :     avr->mix_matrix = av_malloc(in_channels * out_channels *
     686             :                                 sizeof(*avr->mix_matrix));
     687           0 :     if (!avr->mix_matrix)
     688           0 :         return AVERROR(ENOMEM);
     689             : 
     690           0 :     for (o = 0; o < out_channels; o++)
     691           0 :         for (i = 0; i < in_channels; i++)
     692           0 :             avr->mix_matrix[o * in_channels + i] = matrix[o * stride + i];
     693             : 
     694           0 :     return 0;
     695             : }
     696             : 
     697           0 : int avresample_set_channel_mapping(AVAudioResampleContext *avr,
     698             :                                    const int *channel_map)
     699             : {
     700           0 :     ChannelMapInfo *info = &avr->ch_map_info;
     701             :     int in_channels, ch, i;
     702             : 
     703           0 :     in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
     704           0 :     if (in_channels <= 0 ||  in_channels > AVRESAMPLE_MAX_CHANNELS) {
     705           0 :         av_log(avr, AV_LOG_ERROR, "Invalid input channel layout\n");
     706           0 :         return AVERROR(EINVAL);
     707             :     }
     708             : 
     709           0 :     memset(info, 0, sizeof(*info));
     710           0 :     memset(info->input_map, -1, sizeof(info->input_map));
     711             : 
     712           0 :     for (ch = 0; ch < in_channels; ch++) {
     713           0 :         if (channel_map[ch] >= in_channels) {
     714           0 :             av_log(avr, AV_LOG_ERROR, "Invalid channel map\n");
     715           0 :             return AVERROR(EINVAL);
     716             :         }
     717           0 :         if (channel_map[ch] < 0) {
     718           0 :             info->channel_zero[ch] =  1;
     719           0 :             info->channel_map[ch]  = -1;
     720           0 :             info->do_zero          =  1;
     721           0 :         } else if (info->input_map[channel_map[ch]] >= 0) {
     722           0 :             info->channel_copy[ch] = info->input_map[channel_map[ch]];
     723           0 :             info->channel_map[ch]  = -1;
     724           0 :             info->do_copy          =  1;
     725             :         } else {
     726           0 :             info->channel_map[ch]            = channel_map[ch];
     727           0 :             info->input_map[channel_map[ch]] = ch;
     728           0 :             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           0 :     for (ch = 0, i = 0; ch < in_channels && i < in_channels; ch++, i++) {
     735           0 :         while (ch < in_channels && info->input_map[ch] >= 0)
     736           0 :             ch++;
     737           0 :         while (i < in_channels && info->channel_map[i] >= 0)
     738           0 :             i++;
     739           0 :         if (ch >= in_channels || i >= in_channels)
     740             :             break;
     741           0 :         info->input_map[ch] = i;
     742             :     }
     743             : 
     744           0 :     avr->use_channel_map = 1;
     745           0 :     return 0;
     746             : }
     747             : 
     748        2865 : int avresample_available(AVAudioResampleContext *avr)
     749             : {
     750        2865 :     return av_audio_fifo_size(avr->out_fifo);
     751             : }
     752             : 
     753           0 : int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples)
     754             : {
     755           0 :     int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples;
     756             : 
     757           0 :     if (avr->resample_needed) {
     758           0 :         samples = av_rescale_rnd(samples,
     759           0 :                                  avr->out_sample_rate,
     760           0 :                                  avr->in_sample_rate,
     761             :                                  AV_ROUND_UP);
     762             :     }
     763             : 
     764           0 :     samples += avresample_available(avr);
     765             : 
     766           0 :     if (samples > INT_MAX)
     767           0 :         return AVERROR(EINVAL);
     768             : 
     769           0 :     return samples;
     770             : }
     771             : 
     772        1908 : int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples)
     773             : {
     774        1908 :     if (!output)
     775         954 :         return av_audio_fifo_drain(avr->out_fifo, nb_samples);
     776         954 :     return av_audio_fifo_read(avr->out_fifo, (void**)output, nb_samples);
     777             : }
     778             : 
     779        5143 : unsigned avresample_version(void)
     780             : {
     781        5143 :     return LIBAVRESAMPLE_VERSION_INT;
     782             : }
     783             : 
     784           0 : const char *avresample_license(void)
     785             : {
     786             : #define LICENSE_PREFIX "libavresample license: "
     787           0 :     return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
     788             : }
     789             : 
     790        5143 : const char *avresample_configuration(void)
     791             : {
     792        5143 :     return FFMPEG_CONFIGURATION;
     793             : }

Generated by: LCOV version 1.12