[MPlayer-dev-eng] Let af_lavcresample use float point sample format.

Alexander Strasser eclipse7 at gmx.net
Sat Apr 20 02:04:00 EEST 2024


Hi Ivan,

On 2024-04-15 21:40 +0300, Ivan Kalvachev wrote:
> While fixing ch_layout in af_lavcresample, I've noticed that libaf
> inserts two format change filters - one before lavcresample to do
> float->s16le and one after to do s16le->float. Since swresample
> handles float point sample format natively, it should be both faster
> and better quality to use it.
>
> If float point sample format is requested by libaf at initialization,
> use swresample float point sample format for the conversion.
> Adjust internal buffer size calculations to use a variable (bps).
> Store the used format in the filter context structure to avoid
> unnecessary reinitialization.

Cannot comment much on the inter workings of libaf and libswr, but
the code looks good to me.


> The "if()" has a strange alignment, because I plan on making more
> cosmetics with that statement, in separate commit.
>
> Please test.

Did some build testing and a limited amount of run time testing;
including playback of alternating samples that when decoded
produce signed 16 bit int or float output.

Worked as expected AFAICT.

Valgrind also didn't show errors.


> I plan on committing it this weekend, unless there are some unresolved issues.

I have found a little thing that should probably considered to
be updated. This is from our man page:

    .B lavcresample[=srate[:length[:linear[:count[:cutoff]]]]]
    Changes the sample rate of the audio stream to an integer <srate> in Hz.
    It only supports the 16-bit native-endian format.
    .br



Best regards,
  Alexander


[...]
> Index: libaf/af_lavcresample.c
> ===================================================================
> --- libaf/af_lavcresample.c	(revision 38460)
> +++ libaf/af_lavcresample.c	(working copy)
> @@ -45,6 +45,7 @@
>      int phase_shift;
>      double cutoff;
>
> +    int ctx_format;
>      int ctx_out_rate;
>      int ctx_in_rate;
>      int ctx_filter_size;
> @@ -58,6 +59,8 @@
>  static int control(struct af_instance_s* af, int cmd, void* arg)
>  {
>    AVChannelLayout ch_layout;
> +  enum AVSampleFormat av_format;
> +
>    af_resample_t* s   = (af_resample_t*)af->setup;
>    af_data_t *data= (af_data_t*)arg;
>    int out_rate, test_output_res; // helpers for checking input format
> @@ -69,14 +72,23 @@
>
>      af->data->nch    = data->nch;
>      if (af->data->nch > AF_NCH) af->data->nch = AF_NCH;
> -    af->data->format = AF_FORMAT_S16_NE;
> -    af->data->bps    = 2;
> +    if(data->format == AF_FORMAT_FLOAT_NE){
> +        af->data->format = AF_FORMAT_FLOAT_NE;
> +        av_format = AV_SAMPLE_FMT_FLT;
> +    }else
> +    {
> +        af->data->format = AF_FORMAT_S16_NE;
> +        av_format = AV_SAMPLE_FMT_S16;
> +    }
> +
> +    af->data->bps = af_fmt2bits(af->data->format)/8;
>      af->mul = (double)af->data->rate / data->rate;
>      af->delay = af->data->nch * s->filter_length / FFMIN(af->mul, 1); // *bps*.5
>
>      av_channel_layout_default(&ch_layout, af->data->nch);
>
> -    if (s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length ||
> +    if (s->ctx_format      != af->data->format ||
> +        s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length ||
>          s->ctx_phase_shift != s->phase_shift || s->ctx_linear != s->linear || s->ctx_cutoff != s->cutoff) {
>          swr_free(&s->swrctx);
>          if((s->swrctx=swr_alloc()) == NULL) return AF_ERROR;
> @@ -86,12 +98,13 @@
>          av_opt_set_int(s->swrctx, "phase_shift", s->phase_shift, 0);
>          av_opt_set_int(s->swrctx, "linear_interp", s->linear, 0);
>          av_opt_set_double(s->swrctx, "cutoff", s->cutoff, 0);
> -        av_opt_set_sample_fmt(s->swrctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
> -        av_opt_set_sample_fmt(s->swrctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
> +        if(av_opt_set_sample_fmt(s->swrctx, "in_sample_fmt",  av_format, 0) < 0) return AF_ERROR;
> +        if(av_opt_set_sample_fmt(s->swrctx, "out_sample_fmt", av_format, 0) < 0) return AF_ERROR;
>          if(av_opt_set_chlayout(s->swrctx, "in_chlayout",  &ch_layout, 0) < 0) return AF_ERROR;
>          if(av_opt_set_chlayout(s->swrctx, "out_chlayout", &ch_layout, 0) < 0) return AF_ERROR;
>
>          if(swr_init(s->swrctx) < 0) return AF_ERROR;
> +        s->ctx_format      = af->data->format;
>          s->ctx_out_rate    = af->data->rate;
>          s->ctx_in_rate     = data->rate;
>          s->ctx_filter_size = s->filter_length;
> @@ -143,6 +156,7 @@
>    int8_t *out;
>    int chans   = data->nch;
>    int in_len  = data->len;
> +  int bps     = data->bps;
>    int out_len = in_len * af->mul + 10;
>
>    if(AF_OK != RESIZE_LOCAL_BUFFER(af,data))
> @@ -160,9 +174,9 @@
>
>    memcpy(s->in[0], in, in_len);
>
> -  ret = swr_convert(s->swrctx, &s->tmp[0], out_len/chans/2, &s->in[0], in_len/chans/2);
> +  ret = swr_convert(s->swrctx, &s->tmp[0], out_len/chans/bps, &s->in[0], in_len/chans/bps);
>    if (ret < 0) return NULL;
> -  out_len= ret*chans*2;
> +  out_len= ret*chans*bps;
>
>    memcpy(out, s->tmp[0], out_len);
>


More information about the MPlayer-dev-eng mailing list