[Libav-user] downmixing 5.1 to stereo

luigi lgiancri at tiscali.it
Tue Sep 10 13:56:23 CEST 2013


the following code (adapted from resampling_audio.c written by Stefano 
Sabatini and included in ffmpeg doc/examples) is able do resample fltp 
to AV_SAMPLE_FMT_S16 but fails to downmix 5.1 to stereo. I've tried 
several solutions without hope. The routine takes a buffer decoded with 
av_decode_audio4 and  after resampling sends it to an output buffer. Can 
someone have a look at this code and spot where the mistake is?
Luigi


int32_t LG_ffmpeg_Audio_decoder::ResampleAudio( AVFrame *dec_fr )
{
     int64_t src_ch_layout = dec_fr->channel_layout, dst_ch_layout = 
AV_CH_LAYOUT_STEREO;

     int32_t src_rate = dec_fr->sample_rate, dst_rate = 48000;

     uint8_t **src_data = dec_fr->data;

     int32_t dst_nb_channels = 0;

     int32_t dst_linesize;

     int32_t src_nb_samples = dec_fr->nb_samples, dst_nb_samples, 
max_dst_nb_samples;

     enum AVSampleFormat src_sample_fmt = (AVSampleFormat)dec_fr->format;

     enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;

     int32_t dst_bufsize;

     const char *fmt;

     struct SwrContext *swr_ctx;

     int32_t ret;

     /* create resampler context */
     swr_ctx = swr_alloc();
     if (!swr_ctx)
     {
         fprintf(stderr, "Could not allocate resampler context\n");
         ret = AVERROR(ENOMEM);
         goto end;
     }

     /* set options */
     av_opt_set_int(swr_ctx, "in_channel_layout",    src_ch_layout, 0);
     av_opt_set_int(swr_ctx, "in_sample_rate",       src_rate, 0);
     av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);

     av_opt_set_int(swr_ctx, "out_channel_layout",    dst_ch_layout, 0);
     av_opt_set_int(swr_ctx, "out_sample_rate",       dst_rate, 0);
     av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);

     /* initialize the resampling context */
     if ((ret = swr_init(swr_ctx)) < 0)
     {
         fprintf(stderr, "Failed to initialize the resampling context\n");
         goto end;
     }

     /* compute the number of converted samples: buffering is avoided
     * ensuring that the output buffer will contain at least all the
     * converted input samples */
     max_dst_nb_samples = dst_nb_samples = 
av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

     /* buffer is going to be directly written to a rawaudio file, no 
alignment */
     dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);

     ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, 
dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0);

     if (ret < 0)
     {
         fprintf(stderr, "Could not allocate destination samples\n");
         goto end;
     }

     /* compute destination number of samples */
     dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + 
src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);

     if (dst_nb_samples > max_dst_nb_samples)
     {
         av_free(dst_data[0]);
         ret = av_samples_alloc(dst_data, &dst_linesize, 
dst_nb_channels, dst_nb_samples, dst_sample_fmt, 1);
         if (ret < 0)
               exit(0);// break;

         max_dst_nb_samples = dst_nb_samples;
      }

      /* convert to destination format */
          ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const 
uint8_t **)src_data, src_nb_samples);

      if (ret < 0)
      {
         fprintf(stderr, "Error while converting\n");
         goto end;
      }

      dst_bufsize = av_samples_get_buffer_size(&dst_linesize, 
dst_nb_channels, ret, dst_sample_fmt, 1);
     //    printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);

          InsertBufferInOutBuf((unsigned char *)dst_data[0], 
dst_bufsize  ) ;

      if ((ret = GetFormatFromSampleFmt(&fmt, dst_sample_fmt)) < 0)
         goto end;
//     fprintf(stderr, "Resampling succeeded. Play the output file with 
the command:\n"
//        "ffplay -f %s -channel_layout % -channels %d -ar %d %s\n",
//        fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename);

       goto end;

     end:

     if (dst_data)
         av_freep(&dst_data[0]);
     av_freep(&dst_data);

     swr_free(&swr_ctx);

     return ret < 0;
}



More information about the Libav-user mailing list