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