使用 libavcodec 将音频编码为 aac

Posted

技术标签:

【中文标题】使用 libavcodec 将音频编码为 aac【英文标题】:Encode audio to aac with libavcodec 【发布时间】:2011-01-25 12:15:49 【问题描述】:

我正在使用 libavcodec(截至 2010 年 3 月 3 日的最新 git)将原始 pcm 编码为 aac (启用 libfaac 支持)。我通过调用 avcodec_encode_audio 来做到这一点 每次重复使用 codec_context->frame_size 样本。前四个 调用成功返回,但第五次调用永远不会返回。当我使用 gdb 要中断,堆栈已损坏。

如果我使用 audacity 将 pcm 数据导出到 .wav 文件,那么我可以使用 命令行 ffmpeg 转换为 aac 没有任何问题,所以我确定它是 我做错了什么。

我编写了一个小测试程序来复制我的问题。它读取 来自文件的测试数据,可在此处获得: http://birdie.protoven.com/audio.pcm(约 2 秒有符号的 16 位 LE pcm)

如果我直接使用 FAAC,我可以让它全部工作,但如果我可以只使用 libavcodec,代码会更简洁一些,因为我也在编码视频,并将两者都写入 mp4。

ffmpeg 版本信息:

FFmpeg version git-c280040, Copyright (c) 2000-2010 the FFmpeg developers
  built on Mar  3 2010 15:40:46 with gcc 4.4.1
  configuration: --enable-libfaac --enable-gpl --enable-nonfree --enable-version3 --enable-postproc --enable-pthreads --enable-debug=3 --enable-shared
  libavutil     50.10. 0 / 50.10. 0
  libavcodec    52.55. 0 / 52.55. 0
  libavformat   52.54. 0 / 52.54. 0
  libavdevice   52. 2. 0 / 52. 2. 0
  libswscale     0.10. 0 /  0.10. 0
  libpostproc   51. 2. 0 / 51. 2. 0

是否有我未设置的内容,或我的编解码器中的设置不正确 上下文,也许?非常感谢任何帮助!

这是我的测试代码:

#include <stdio.h>
#include <libavcodec/avcodec.h>

void EncodeTest(int sampleRate, int channels, int audioBitrate,
    uint8_t *audioData, size_t audiosize)

    AVCodecContext  *audioCodec;
    AVCodec *codec;
    uint8_t *buf;
    int bufSize, frameBytes;

    avcodec_register_all();

    //Set up audio encoder
    codec = avcodec_find_encoder(CODEC_ID_AAC);
    if (codec == NULL) return;
    audioCodec = avcodec_alloc_context();
    audioCodec->bit_rate = audioBitrate;
    audioCodec->sample_fmt = SAMPLE_FMT_S16;
    audioCodec->sample_rate = sampleRate;
    audioCodec->channels = channels;
    audioCodec->profile = FF_PROFILE_AAC_MAIN;
    audioCodec->time_base = (AVRational)1, sampleRate;
    audioCodec->codec_type = CODEC_TYPE_AUDIO;
    if (avcodec_open(audioCodec, codec) < 0) return;

    bufSize = FF_MIN_BUFFER_SIZE * 10;
    buf = (uint8_t *)malloc(bufSize);
    if (buf == NULL) return;

    frameBytes = audioCodec->frame_size * audioCodec->channels * 2;
    while (audioSize >= frameBytes)
    
        int packetSize;

        packetSize = avcodec_encode_audio(audioCodec, buf, bufSize, (short *)audioData);
        printf("encoder returned %d bytes of data\n", packetSize);
        audioData += frameBytes;
        audioSize -= frameBytes;
    


int main()

    FILE *stream = fopen("audio.pcm", "rb");
    size_t size;
    uint8_t *buf;

    if (stream == NULL)
    
        printf("Unable to open file\n");
        return 1;
    

    fseek(stream, 0, SEEK_END);
    size = ftell(stream);
    fseek(stream, 0, SEEK_SET);
    buf = (uint8_t *)malloc(size);
    fread(buf, sizeof(uint8_t), size, stream);
    fclose(stream);

    EncodeTest(32000, 2, 448000, buf, size);

【问题讨论】:

你能和我分享整个项目吗?我也在研究 libav 来编码视频/音频。 【参考方案1】:

如果比特率小于 386000,问题似乎就消失了。不知道为什么会这样,因为我可以以高于直接使用 FAAC 的比特率进行编码。但是 128000 对我的目的来说已经足够了,所以我可以继续前进。

【讨论】:

【参考方案2】:

我也在尝试以 aac 格式进行压缩,但在编码方面还有一些其他问题。 ffmpeg(2.8.0)的最新版本中有一些功能。首先,您是否检查了是否支持示例格式?在我的版本中,唯一支持的格式是 AV_SAMPLE_FMT_FLTP。格式检查例如:

/* 检查编码器是否支持给定的样本格式 */ int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt) const enum AVSampleFormat *p = codec->sample_fmts;

while (*p != AV_SAMPLE_FMT_NONE) 
    if (*p == sample_fmt)
        return 1;
    p++;

return 0;

如果您观察到支持的格式,AAC 编解码器仅支持 AV_SAMPLE_FMT_FLTP。您应该使用 swresample(如建议的那样)以平面浮点格式进行转换,或者您可以手动进行。 您应该使用带有严格实验选项的 avcodec_open2 来打开编解码器。 问候

【讨论】:

以上是关于使用 libavcodec 将音频编码为 aac的主要内容,如果未能解决你的问题,请参考以下文章

Gstreamer:使用 AAC 编码将麦克风音频编码为 mp4

从 mp4 中提取音轨并将其保存到可播放的音频文件中

最简单的基于FFMPEG的音频编码器(PCM编码为AAC)

编码aac音轨时FFmpeg媒体信息不正确

android音视频音频硬编解码pcm&aac&wav

android音视频音频硬编解码pcm&aac&wav