使用 libavcodec 将音频编码为 aac
我正在使用 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);
}
I'm using libavcodec (latest git as of 3/3/10) to encode raw pcm to aac
(libfaac support enabled). I do this by calling avcodec_encode_audio
repeatedly with codec_context->frame_size samples each time. The first four
calls return successfully, but the fifth call never returns. When I use gdb
to break, the stack is corrupt.
If I use audacity to export the pcm data to a .wav file, then I can use
command-line ffmpeg to convert to aac without any issues, so I'm sure it's
something I'm doing wrong.
I've written a small test program that duplicates my problem. It reads the
test data from a file, which is available here:
http://birdie.protoven.com/audio.pcm (~2 seconds of signed 16 bit LE pcm)
I can make it all work if I use FAAC directly, but the code would be a little cleaner if I could just use libavcodec, as I'm also encoding video, and writing both to an mp4.
ffmpeg version info:
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
Is there something I'm not setting, or setting incorrectly in my codec
context, maybe? Any help is greatly appreciated!
Here is my test code:
#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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果比特率低于 386000,问题似乎就会消失。不知道为什么会这样,因为我可以以比直接使用 FAAC 更高的比特率进行编码。但 128000 对于我的目的来说已经足够了,所以我可以继续前进。
The problem seems to go away if the bitrate is less than 386000. Not sure why this is, as I can encode at bitrates higher than that using FAAC directly. But 128000 is good enough for my purposes, so I'm able to move forward.
我也尝试以 aac 格式进行压缩,但在编码方面遇到了一些其他问题。 ffmpeg 的最新版本(2.8.0)中有一些功能。首先,您检查是否支持示例格式?在我的版本中,唯一支持的格式是 AV_SAMPLE_FMT_FLTP。格式检查例如:
如果您观察支持的格式,则 AAC 编解码器仅支持 AV_SAMPLE_FMT_FLTP。您应该使用 swresample (按照建议)转换为 planare float 格式,或者您也可以手动完成。
您应该使用 avcodec_open2 和 options strict 实验来打开编解码器。
I'm attempting to compress in aac format too and have some other problems in encoding. There are some features in the last revision of ffmpeg (2.8.0). First, did you check if the sample format is supported? In my version the only supported format is AV_SAMPLE_FMT_FLTP. Format checking is for example:
If you observe supported formats, only AV_SAMPLE_FMT_FLTP is supported by the AAC codec. You should use swresample (as suggested) to convert in planare float format, or you can do it by hand.
You should use avcodec_open2 with options strict sperimental in order to open codec.