[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