FFmpeg - rééchantillonnage de AV_SAMPLE_FMT_FLTP à AV_SAMPLE_FMT_S16 eu la très mauvaise qualité du son (lent, de musique, de bruit)

J'ai été confondu avec rééchantillonnage le résultat dans une nouvelle ffmpeg.
Je décode AAC, audio en PCM, le ffmpeg afficher les informations audio comme:

Stream #0:0: Audio: aac, 44100 Hz, stereo, fltp, 122 kb/s

Dans de nouveaux ffmpeg, la sortie des échantillons sont fltp format, donc je dois le convertir en AV_SAMPLE_FMT_FLTP à AV_SAMPLE_FMT_S16

PS: dans le vieux ffmpeg que libavcodec 54.12.100, il est directement S16, n'ont donc pas besoin de rééchantillonnage et sans que la qualité du son problème.

Puis j'ai essayé trois façons de rééchantillonnage,

  1. à l'aide de swr_convert
  2. à l'aide de avresample_convert
  3. convertir à la main

Mais tous de leur donner le même résultat, la qualité du son est vraiment mauvais, très lent et de musique, avec un peu de bruit aussi.

Mon rééchantillonnage code est comme suit:

void resampling(AVFrame* frame_, AVCodecContext* pCodecCtx, int64_t want_sample_rate, uint8_t* outbuf){
    SwrContext      *swrCtx_ = 0;
    AVAudioResampleContext *avr = 0;

    //Initializing the sample rate convert. We only really use it to convert float output into int.
    int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO;

#ifdef AV_SAMPLEING
    avr = avresample_alloc_context();
    av_opt_set_int(avr, "in_channel_layout", frame_->channel_layout, 0);
    av_opt_set_int(avr, "out_channel_layout", wanted_channel_layout, 0);
    av_opt_set_int(avr, "in_sample_rate", frame_->sample_rate, 0);
    av_opt_set_int(avr, "out_sample_rate", 44100, 0);
    av_opt_set_int(avr, "in_sample_fmt", pCodecCtx->sample_fmt, 0); //AV_SAMPLE_FMT_FLTP
    av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
    av_opt_set_int(avr, "internal_sample_fmt", pCodecCtx->sample_fmt, 0);
    avresample_open(avr);
    avresample_convert(avr, &outbuf, frame_->linesize[0], frame_->nb_samples, frame_->extended_data, frame_->linesize[0], frame_->nb_samples);
    avresample_close(avr);
    return;
#endif

#ifdef USER_SAMPLEING
    if (pCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP)
    {
            int nb_samples = frame_->nb_samples;
            int channels = frame_->channels;
            int outputBufferLen = nb_samples & channels * 2;
            auto outputBuffer = (int16_t*)outbuf;

            for (int i = 0; i < nb_samples; i++)
            {
                    for (int c = 0; c < channels; c++)
                    {
                            float* extended_data = (float*)frame_->extended_data[c];
                            float sample = extended_data[i];
                            if (sample < -1.0f) sample = -1.0f;
                            else if (sample > 1.0f) sample = 1.0f;
                            outputBuffer[i * channels + c] = (int16_t)round(sample * 32767.0f);
                    }
            }
            return;
    }
#endif
    swrCtx_ = swr_alloc_set_opts(
            NULL, //swrCtx_,
            wanted_channel_layout,
            AV_SAMPLE_FMT_S16,
            want_sample_rate,
            pCodecCtx->channel_layout,
            pCodecCtx->sample_fmt,
            pCodecCtx->sample_rate,
            0,
            NULL);

    if (!swrCtx_ || swr_init(swrCtx_) < 0) {
            printf("swr_init: Failed to initialize the resampling context");
            return;
    }

    //convert audio to AV_SAMPLE_FMT_S16
    int swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const uint8_t **)frame_->extended_data, frame_->nb_samples);
    if (swrRet < 0) {
            printf("swr_convert: Error while converting %d", swrRet);
            return;
    }
}

Que dois faire?

PS1: jouer avec ffplay est juste tout droit.

PS2: enregistrer resample S16 PCM dans le fichier et jouer il aura la même qualité de son problème.

Merci beaucoup pour votre aide et vos suggestions!


J'ai aussi remarqué que, dans le vieux-ffmpeg, aac est recongized comme FLT format et directement décodé en PCM 16 bits, tandis que dans les nouveaux ffmpeg, aac est compté comme FLTP format et de produire toujours 32 bits IEEE sortie float.

Donc le même code de produire assez différentes sorties avec les différentes versions de ffmpeg.
Ensuite, je voudrais vous demander quelle est la bonne façon de convertir un AAC audio PCM 16 bits dans la nouvelle version?

Merci beaucoup d'avance!

Pourquoi ne pas laisser FFmpeg faire le travail et de sortie PCM 16 bits pour vous?
S'il vous plaît dites-moi comment? C'est censé être un flux audio. Ici, j'ai fait mon test de fichier aac, afin d'analyser le problème facilement, mais le résultat est le même. Merci de m'expliquer comment décoder les formats AAC et de sortie directement PCM 16 bits? (dans le vieux ffmpeg, c'est exactement comme cela par défaut, je l'apprécie beaucoup) Merci beaucoup!
-f s16le -acodec pcm_s16le
C'est dans le code, je ne peux pas utiliser externe fichier exe. S'il vous plaît dites-moi comment ce code avec ffmpeg. Merci!
Il y a de nombreuses façons d'interface avec FFmpeg. Je ne peux pas vous aider, mais le principe est le même. Définir le format s16le et la sortie audio codec pcm_s16le.

OriginalL'auteur kaienfr | 2014-04-02