2

我正在使用 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 更详细?

谢谢!

4

0 回答 0