我正在开发一个多媒体应用程序,它使用 liveMedia 库通过 RTSP 流式传输视频和音频。我从相机读取原始视频帧,使用 libx264 对其进行编码,将其保存在 tbb::concurrent_queue 中并运行 RTSP 服务器。我使用 DynamicRTSPServer.cpp 和 live555MediaServer.cpp 作为示例来创建我的 RTSP 模块,但我遇到了一个问题 - 一个线程(执行 BasicTaskScheduler::doEventLoop )使用过多的处理器时间 - 超过 80-90% 的一个处理器内核(我有英特尔双核 T3100)。而对于我的视频流,我有很长的延迟,VLC 无法播放视频流(音频流播放正常)出现错误:主要警告:图片太迟无法显示(缺少 3780 毫秒)avcodec 错误:超过 5 秒迟到的视频->
我阅读了服务器的日志文件,发现我有很多失败的尝试从空队列中读取新数据。这是我的日志文件的片段(查看调试消息的时间 - 这是 FramedSource::doGetNextFrame 的不同调用)
[10:49:7:621]: videoframe readed. size: 0
[10:49:7:622]: videoframe readed. size: 0
[10:49:7:622]: videoframe readed. size: 0
[10:49:7:622]: videoframe readed. size: 0
[10:49:7:622]: videoframe readed. size: 0
[10:49:7:622]: videoframe readed. size: 0
[10:49:7:623]: videoframe readed. size: 0
[10:49:7:623]: videoframe readed. size: 0
[10:49:7:623]: videoframe readed. size: 0
[10:49:7:623]: videoframe readed. size: 0
[10:49:7:623]: videoframe readed. size: 0
[10:49:7:624]: videoframe readed. size: 0
我的视频流的帧率很低(相机只能达到 8 fps 或更低),当调用 doGetNextFrame 时,我的缓冲区在队列中还没有任何编码帧。在此尝试中,我有下一个调用堆栈:
ConcurrentQueueBuffer::doGetNextFrame()
FramedSource::getNextFrame(unsigned char* to, unsigned maxSize,
afterGettingFunc* afterGettingFunc,
void* afterGettingClientData,
onCloseFunc* onCloseFunc,
void* onCloseClientData)
StreamParser::ensureValidBytes1(unsigned numBytesNeeded)
StreamParser::ensureValidBytes(unsigned numBytesNeeded)
StreamParser::test4Bytes()
H264VideoStreamParser::parse()
MPEGVideoStreamFramer::continueReadProcessing()
MPEGVideoStreamFramer::continueReadProcessing(void* clientData,
unsigned char* /*ptr*/, unsigned /*size*/,
struct timeval /*presentationTime*/)
StreamParser::afterGettingBytes1(unsigned numBytesRead, struct timeval presentationTime)
StreamParser::afterGettingBytes(void* clientData,
unsigned numBytesRead,
unsigned /*numTruncatedBytes*/,
struct timeval presentationTime,
unsigned /*durationInMicroseconds*/)
FramedSource::afterGetting(FramedSource* source)
AlarmHandler::handleTimeout()
...
当编码器给我新的帧时,我试图改变我的缓冲区和锁定线程的逻辑,但在这种情况下,我的音频流也有很长的延迟。我在服务器启动时设置了一些延迟,以便在缓冲区中保存更多数据,但是 livemedia 从缓冲区读取数据的速度比编码器编码要快:(
这个问题的原因是什么?liveMedia 如何检测从 FramedSource 读取的尝试频率?
我的 H264BufferMediaSubsession 继承了 liveMedia 的 H264VideoFileServerMediaSubsession 并仅覆盖 createNewStreamSource() 虚拟方法,我在其中创建 FramedSource 它将从我的缓冲区中读取数据。