On Thu, 29 Nov 2012 23:36:05 -0500, Justin Ruggles <justin.rugg...@gmail.com> 
wrote:
> This allows AudioMix to be treated the same way as other conversion contexts
> and removes the requirement to allocate it at the same time as the
> AVAudioResampleContext.
> 
> The current matrix get/set functions are split between the public interface
> and AudioMix private functions.
> ---
> Updated patch also moves the AudioMix definition to audio_mix.c since
> none of the fields need to be accessed outside of that file.
> 
>  libavresample/audio_mix.c        |  186 
> ++++++++++++++++++++++++++++++++------
>  libavresample/audio_mix.h        |   47 ++++------
>  libavresample/audio_mix_matrix.c |  112 -----------------------
>  libavresample/internal.h         |    7 ++
>  libavresample/options.c          |    7 --
>  libavresample/utils.c            |   79 +++++++++++++++--
>  6 files changed, 257 insertions(+), 181 deletions(-)
> 
> diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
> index dd2f33d..ad68b7a 100644
> --- a/libavresample/audio_mix.c
> +++ b/libavresample/audio_mix.c
> @@ -28,6 +28,29 @@
>  #include "audio_data.h"
>  #include "audio_mix.h"
>  
> +struct AudioMix {
> +    AVAudioResampleContext *avr;
> +    enum AVSampleFormat fmt;
> +    enum AVMixCoeffType coeff_type;
> +    uint64_t in_layout;
> +    uint64_t out_layout;
> +    int in_channels;
> +    int out_channels;
> +
> +    int ptr_align;
> +    int samples_align;
> +    int has_optimized_func;
> +    const char *func_descr;
> +    const char *func_descr_generic;
> +    mix_func *mix;
> +    mix_func *mix_generic;
> +
> +    int16_t *matrix_q8[AVRESAMPLE_MAX_CHANNELS];
> +    int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
> +    float   *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
> +    void   **matrix;
> +};
> +
>  static const char *coeff_type_names[] = { "q8", "q15", "flt" };
>  
>  void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
> @@ -302,27 +325,37 @@ static int mix_function_init(AudioMix *am)
>      return 0;
>  }
>  
> -int ff_audio_mix_init(AVAudioResampleContext *avr)
> +AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
>  {
> +    AudioMix *am;
>      int ret;
>  
> +    am = av_mallocz(sizeof(*am));
> +    if (!am)
> +        return NULL;
> +    am->avr = avr;
> +
>      if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
>          avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
>          av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
>                 "mixing: %s\n",
>                 av_get_sample_fmt_name(avr->internal_sample_fmt));
> -        return AVERROR(EINVAL);
> +        goto error;
>      }
>  
> +    am->fmt          = avr->internal_sample_fmt;
> +    am->coeff_type   = avr->mix_coeff_type;
> +    am->in_layout    = avr->in_channel_layout;
> +    am->out_layout   = avr->out_channel_layout;
> +    am->in_channels  = avr->in_channels;
> +    am->out_channels = avr->out_channels;
> +
>      /* build matrix if the user did not already set one */
> -    if (avr->am->matrix) {
> -        if (avr->am->coeff_type != avr->mix_coeff_type      ||
> -            avr->am->in_layout  != avr->in_channel_layout   ||
> -            avr->am->out_layout != avr->out_channel_layout) {
> -            av_log(avr, AV_LOG_ERROR,
> -                   "Custom matrix does not match current parameters\n");
> -            return AVERROR(EINVAL);
> -        }
> +    if (avr->mix_matrix) {
> +        ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
> +        if (ret < 0)
> +            goto error;
> +        av_freep(&avr->mix_matrix);
>      } else {
>          int i, j;
>          char in_layout_name[128];
> @@ -330,7 +363,7 @@ int ff_audio_mix_init(AVAudioResampleContext *avr)
>          double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels 
> *
>                                          sizeof(*matrix_dbl));
>          if (!matrix_dbl)
> -            return AVERROR(ENOMEM);
> +            goto error;
>  
>          ret = avresample_build_matrix(avr->in_channel_layout,
>                                        avr->out_channel_layout,
> @@ -343,7 +376,7 @@ int ff_audio_mix_init(AVAudioResampleContext *avr)
>                                        avr->matrix_encoding);
>          if (ret < 0) {
>              av_free(matrix_dbl);
> -            return ret;
> +            goto error;
>          }
>  
>          av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
> @@ -360,32 +393,33 @@ int ff_audio_mix_init(AVAudioResampleContext *avr)
>              av_log(avr, AV_LOG_DEBUG, "\n");
>          }
>  
> -        ret = avresample_set_matrix(avr, matrix_dbl, avr->in_channels);
> +        ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
>          if (ret < 0) {
>              av_free(matrix_dbl);
> -            return ret;
> +            goto error;
>          }
>          av_free(matrix_dbl);
>      }
>  
> -    avr->am->fmt          = avr->internal_sample_fmt;
> -    avr->am->coeff_type   = avr->mix_coeff_type;
> -    avr->am->in_layout    = avr->in_channel_layout;
> -    avr->am->out_layout   = avr->out_channel_layout;
> -    avr->am->in_channels  = avr->in_channels;
> -    avr->am->out_channels = avr->out_channels;
> -
> -    ret = mix_function_init(avr->am);
> +    ret = mix_function_init(am);
>      if (ret < 0)
> -        return ret;
> +        goto error;
>  
> -    return 0;
> +    return am;
> +
> +error:
> +    av_free(am);
> +    return NULL;
>  }
>  
> -void ff_audio_mix_close(AudioMix *am)
> +void ff_audio_mix_free(AudioMix **am_p)
>  {
> -    if (!am)
> +    AudioMix *am;
> +
> +    if (!*am_p)
>          return;
> +    am = *am_p;
> +
>      if (am->matrix) {
>          av_free(am->matrix[0]);
>          am->matrix = NULL;
> @@ -393,6 +427,8 @@ void ff_audio_mix_close(AudioMix *am)
>      memset(am->matrix_q8,  0, sizeof(am->matrix_q8 ));
>      memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
>      memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
> +
> +    av_freep(am_p);
>  }
>  
>  int ff_audio_mix(AudioMix *am, AudioData *src)
> @@ -424,3 +460,101 @@ int ff_audio_mix(AudioMix *am, AudioData *src)
>  
>      return 0;
>  }
> +
> +int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
> +{
> +    int i, o;
> +
> +    if ( am->in_channels <= 0 ||  am->in_channels > AVRESAMPLE_MAX_CHANNELS 
> ||
> +        am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) 
> {
> +        av_log(am, AV_LOG_ERROR, "Invalid channel counts\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    switch (am->coeff_type) {
> +    case AV_MIX_COEFF_TYPE_Q8:
> +        if (!am->matrix_q8[0]) {
> +            av_log(am, AV_LOG_ERROR, "matrix is not set\n");
> +            return AVERROR(EINVAL);
> +        }
> +        for (o = 0; o < am->out_channels; o++)
> +            for (i = 0; i < am->in_channels; i++)
> +                matrix[o * stride + i] = am->matrix_q8[o][i] / 256.0;
> +        break;
> +    case AV_MIX_COEFF_TYPE_Q15:
> +        if (!am->matrix_q15[0]) {
> +            av_log(am, AV_LOG_ERROR, "matrix is not set\n");
> +            return AVERROR(EINVAL);
> +        }
> +        for (o = 0; o < am->out_channels; o++)
> +            for (i = 0; i < am->in_channels; i++)
> +                matrix[o * stride + i] = am->matrix_q15[o][i] / 32768.0;
> +        break;
> +    case AV_MIX_COEFF_TYPE_FLT:
> +        if (!am->matrix_flt[0]) {
> +            av_log(am, AV_LOG_ERROR, "matrix is not set\n");
> +            return AVERROR(EINVAL);
> +        }
> +        for (o = 0; o < am->out_channels; o++)
> +            for (i = 0; i < am->in_channels; i++)
> +                matrix[o * stride + i] = am->matrix_flt[o][i];

This looks macroifiable.

Otherwise LGTM

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to