FFMpeg:使用avcodec提取音频帧会产生噪声

时间:2018-10-22 15:02:18

标签: c++ audio ffmpeg android-ndk

在我的Android应用中,我实现了FFMpeg库,并尝试使用它,以便可以实时从音频文件中提取音频样本。

这就是我所做的(我在这里简化了代码,以便于阅读):

AVPacket packet;
AVCodecContext *codecContext = NULL;
AVFormatContext *formatContext;
AVFrame *frame = NULL;
SwrContext *swrContext;

int audio_stream_index = -1;
int ret;
uint8_t *localBuffer;


int FFMpegPlayer::createFFmpeg(const char *filename)
{
    int ret;
    AVCodec *dec;

    frame = av_frame_alloc();
    av_register_all();

    avformat_open_input(&formatContext, filename, NULL, NULL))
    avformat_find_stream_info(formatContext, NULL))

    // select the audio stream
    audio_stream_index = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);

    // create decoding context
    codecContext = avcodec_alloc_context3(dec);

    avcodec_parameters_to_context(codecContext, formatContext->streams[audio_stream_index]->codecpar);
    av_opt_set_int(codecContext, "refcounted_frames", 1, 0);

    // init the audio decoder
    avcodec_open2(codecContext, dec, NULL))
    swrContext = swr_alloc();

    // we assume here that the audio file is a 44100 Hz stereo audio file
    localBuffer = (uint8_t *) av_malloc(44100 * 2);
    swr_alloc_set_opts(swrContext, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, codecContext->sample_rate,
                       codecContext->channel_layout, codecContext->sample_fmt, codecContext->sample_rate, 0,
                       NULL);
    swr_init(swrContext);

    return 0;
}

void FFMpegPlayer::getPcmFloat(float *buffer)
{
    // init :
    int i, ch, dataSize;
    bool extraxted = false;
    float sample = 0;

    // extract :
    while (av_read_frame(formatContext, &packet) >= 0 && !extraxted)
    {
        if (packet.stream_index == audio_stream_index)
        {
            // send the packet with the compressed data to the decoder
            ret = avcodec_send_packet(codecContext, &packet);

            // read all the output frames (in general there may be any number of them
            while (ret >= 0)
            {
                ret = avcodec_receive_frame(codecContext, frame);
                if (ret == AVERROR(EAGAIN))
                {
                    LOGW("AVERROR(EAGAIN)\n");
                    break;
                }
                else if (ret == AVERROR_EOF)
                {
                    LOGW("AVERROR_EOF\n");
                    break;
                }

                dataSize = av_get_bytes_per_sample(codecContext->sample_fmt);
                swr_convert(swrContext, &localBuffer, 44100 * 2, (const uint8_t **) frame->data, frame->nb_samples);

                int a = 0;
                for (i = 0; i < frame->nb_samples; i++)
                {
                    for (ch = 0; ch < codecContext->channels; ch++)
                    {
                        memcpy(&sample, &localBuffer[(codecContext->channels * i + ch) * dataSize], dataSize);
                        buffer[a] = sample;
                        a++;
                    }
                }

                // exit extract:
                extraxted = true;
            }
        }
    }
}

每当我需要音频样本时,我都会调用getPcmFloat()函数。

借助该代码,我可以清晰地收听音频文件。

问题是:我的声音有些crack啪作响,我不知道声音来自何处或如何解决。

有人知道如何在没有毛刺的情况下获得准确的帧吗?

感谢您的帮助。

0 个答案:

没有答案