C语言 使用 libavcodec 将音频编码为 aac
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2410459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Encode audio to aac with libavcodec
提问by ryan
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.
我正在使用 libavcodec(截至 10 年 3 月 3 日的最新 git)将原始 pcm 编码为 aac(启用了 libfaac 支持)。我通过每次使用 codec_context->frame_size 样本重复调用 avcodec_encode_audio 来做到这一点。前四个调用成功返回,但第五个调用永远不会返回。当我使用 gdb 中断时,堆栈已损坏。
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.
如果我使用 audacity 将 pcm 数据导出到 .wav 文件,那么我可以使用命令行 ffmpeg 转换为 aac 没有任何问题,所以我确定这是我做错了。
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)
我写了一个小测试程序来重复我的问题。它从文件中读取测试数据,该文件可在此处获得:http: //birdie.protoven.com/audio.pcm(约 2 秒的签名 16 位 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.
如果我直接使用 FAAC,我可以让它全部工作,但是如果我可以只使用 libavcodec,代码会更简洁一些,因为我也在编码视频,并将两者都写入 mp4。
ffmpeg version info:
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
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);
}
采纳答案by ryan
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.
如果比特率小于 386000,问题似乎就会消失。不知道为什么会这样,因为我可以以比直接使用 FAAC 更高的比特率进行编码。但是 128000 对我来说已经足够了,所以我可以继续前进。
回答by FrancescoBLT
I'm attempting to compress in aac format too an have some other problems in encoding. There are some features in last revision of ffmpeg (2.8.0). In 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 in example:
我也在尝试以 aac 格式压缩,但在编码方面还有一些其他问题。ffmpeg (2.8.0) 的最新版本中有一些功能。首先,您是否检查过样本格式是否受支持?在我的版本中,唯一支持的格式是 AV_SAMPLE_FMT_FLTP。格式检查在示例中:
/* check that a given sample format is supported by the encoder */ int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt) { const enum AVSampleFormat *p = codec->sample_fmts;
/* 检查编码器是否支持给定的样本格式 */ 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;
}
}
If you observe supported formats, only AV_SAMPLE_FMT_FLTP is supported by 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. regards
如果您观察支持的格式,则 AAC 编解码器仅支持 AV_SAMPLE_FMT_FLTP。您应该使用 swresample(按照建议)以平面浮点格式进行转换,或者您可以手动进行。您应该使用带有严格实验选项的 avcodec_open2 以打开编解码器。问候

