我正在使用 libav 将原始 RGB24 帧编码为 h264 并将其复用到 flv。这一切正常,我已经流式传输超过 48 小时,没有任何问题!我的下一步是将音频添加到流中。我将捕捉现场音频,我想使用 speex、mp3 或 nelly moser 对其进行实时编码。
背景资料
我是数字音频的新手,因此我可能做错了。但基本上我的应用程序获得了一个带有交错音频的“浮动”缓冲区。这个“audioIn”函数被我正在使用的应用程序框架调用。缓冲区每个通道包含 256 个样本,我有 2 个通道。因为我可能混用了术语,所以我是这样使用数据的:
// input = array with audio samples
// bufferSize = 256
// nChannels = 2
void audioIn(float * input, int bufferSize, int nChannels) {
// convert from float to S16
short* buf = new signed short[bufferSize * 2];
for(int i = 0; i < bufferSize; ++i) { // loop over all samples
int dx = i * 2;
buf[dx + 0] = (float)input[dx + 0] * numeric_limits<short>::max(); // convert frame of the first channel
buf[dx + 1] = (float)input[dx + 1] * numeric_limits<short>::max(); // convert frame of the second channel
}
// add this to the libav wrapper.
av.addAudioFrame((unsigned char*)buf, bufferSize, nChannels);
delete[] buf;
}
现在我有一个缓冲区,其中每个样本都是 16 位,我将 this 传递short* buffer
给我的包装av.addAudioFrame()
函数。在这个函数中,我在对音频进行编码之前创建了一个缓冲区。从我读到的,AVCodecContext
音频编码器的frame_size
. 调用时,此 frame_size 必须与缓冲区中的样本数匹配avcodec_encode_audio2()
。我为什么这么认为,是因为这里记录的内容。
然后,尤其是以下行:如果未设置,则除最后一帧外的所有帧都frame->nb_samples
必须等于avctx->frame_size
。*(如果我对此有误,请在此处纠正我)。
编码后,我调用av_interleaved_write_frame()
实际写入帧。当我使用 mp3 作为编解码器时,我的应用程序运行大约 1-2 分钟,然后接收视频/音频流(flv、tcp)的服务器断开连接并显示消息“ Frame too large: 14485504
”。生成此消息是因为 rtmp-server 正在获取一个很大的帧。这可能是因为我没有正确地与 libav 交错。
问题:
即使在浏览libav的源代码时,我也不确定有很多位,因此我希望如果有人有一个编码音频的工作示例,该示例来自来自“外部”libav的缓冲区(即您自己的)应用)。即如何为编码器创建一个足够大的缓冲区?当您需要等待此缓冲区填满时,如何使“实时”流工作?
正如我在上面所写的,我需要在编码之前跟踪缓冲区。其他人是否有一些代码可以做到这一点?我现在正在使用 AVAudioFifo。编码音频和填充/读取缓冲区的功能也在这里:https ://gist.github.com/62f717bbaa69ac7196be
我用 --enable-debug=3 编译并禁用优化,但我没有看到任何调试信息。如何使 libav 更详细?
谢谢!