EDIT 9 avril 2013: J'ai trouvé comment utiliser libswresample pour cela ... beaucoup plus rapidement!
À un certain moment au cours des 2-3 dernières années, le format de sortie du décodeur AAC de FFmpeg changé de AV_SAMPLE_FMT_S16 à AV_SAMPLE_FMT_FLTP. Cela signifie que chaque canal audio possède son propre tampon, et chaque valeur d'échantillon est une valeur à virgule flottante de 32 bits mise à l'échelle de -1,0 à +1,0.
Considérant qu'avec AV_SAMPLE_FMT_S16 les données sont dans un seul tampon, avec les échantillons entrelacés, et chaque échantillon est un entier signé de -32767 à +32767.
Et si vous avez vraiment besoin de votre fichier audio comme AV_SAMPLE_FMT_S16, vous devez effectuer la conversion vous-même. Je me suis dit à deux façons de le faire:
1. Utilisez libswresample (recommandé)
#include "libswresample/swresample.h"
...
SwrContext *swr;
...
// Set up SWR context once you've got codec information
swr = swr_alloc();
av_opt_set_int(swr, "in_channel_layout", audioCodec->channel_layout, 0);
av_opt_set_int(swr, "out_channel_layout", audioCodec->channel_layout, 0);
av_opt_set_int(swr, "in_sample_rate", audioCodec->sample_rate, 0);
av_opt_set_int(swr, "out_sample_rate", audioCodec->sample_rate, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
swr_init(swr);
...
// In your decoder loop, after decoding an audio frame:
AVFrame *audioFrame = ...;
int16_t* outputBuffer = ...;
swr_convert(&outputBuffer, audioFrame->nb_samples, audioFrame->extended_data, audioFrame->nb_samples);
Et c'est tout ce que vous avez à faire!
2. le faire manuellement en C (réponse originale, non recommandé)
Donc, dans votre boucle de décodage, lorsque vous avez un paquet audio vous décodez comme ceci:
AVCodecContext *audioCodec; // init'd elsewhere
AVFrame *audioFrame; // init'd elsewhere
AVPacket packet; // init'd elsewhere
int16_t* outputBuffer; // init'd elsewhere
int out_size = 0;
...
int len = avcodec_decode_audio4(audioCodec, audioFrame, &out_size, &packet);
Et puis, si vous avez une image complète de l'audio, vous pouvez le convertir assez facilement:
// Convert from AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_S16
int in_samples = audioFrame->nb_samples;
int in_linesize = audioFrame->linesize[0];
int i=0;
float* inputChannel0 = (float*)audioFrame->extended_data[0];
// Mono
if (audioFrame->channels==1) {
for (i=0 ; i<in_samples ; i++) {
float sample = *inputChannel0++;
if (sample<-1.0f) sample=-1.0f; else if (sample>1.0f) sample=1.0f;
outputBuffer[i] = (int16_t) (sample * 32767.0f);
}
}
// Stereo
else {
float* inputChannel1 = (float*)audioFrame->extended_data[1];
for (i=0 ; i<in_samples ; i++) {
outputBuffer[i*2] = (int16_t) ((*inputChannel0++) * 32767.0f);
outputBuffer[i*2+1] = (int16_t) ((*inputChannel1++) * 32767.0f);
}
}
// outputBuffer now contains 16-bit PCM!
J'ai laissé deux choses pour plus de clarté ... e Le serrage dans le chemin mono doit idéalement être dupliqué dans le chemin stéréo. Et le code peut être facilement optimisé.
Avez-vous déjà trouver la réponse à cette question? Suis confronté exactement le même problème –