使用live555库推流h264,一般从testOnDemandRTSPServer.cpp 修改而来,不过其中都是通过从本地文件,或作类似文件描述符“fd”源中读数据,这类数据源,需要对数据源进行分析处理,拿h264裸文件来说,就需要根据NAL 00 00 00 01 来切分出一帧帧的数据,这是一个消耗资源的操作,如果我们是已经就绪的h264帧数据在内存里,就不需要这一部分,否则造成明显的推流延迟。
testOnDemandRTSPServer.cpp中测试 h264推流的代码。
// A H.264 video elementary stream:
{
char const* streamName = "h264ESVideoTest";
char const* inputFileName = "test.264";
ServerMediaSession* sms
= ServerMediaSession::createNew(*env, streamName, streamName,
descriptionString);
sms->addSubsession(H264VideoFileServerMediaSubsession
::createNew(*env, inputFileName, reuseFirstSource));
rtspServer->addServerMediaSession(sms);
announceStream(rtspServer, sms, streamName, inputFileName);
}
被添加到 ServerMediaSession的 ServerMediaSubsession ——H264VideoFileServerMediaSubsession,是继承自FileServerMediaSubsession。 要实现从内存buffer中读264数据的 ServerMediaSubsession, 需要实现自己的 ServerMediaSubsession. 之前有写过一篇:https://blog.csdn.net/u012459903/article/details/86676702
实现了两个自己的类:
class H264LiveVideoServerMediaSubssion : public OnDemandServerMediaSubsession
class H264FramedLiveSource : public FramedSource
在H264LiveVideoServerMediaSubssion 中实现两个关键的函数:createNewStreamSource() ,用来创建source
createNewRTPSink() 创建sink。 对于FileServerMeidiaSubsession, 创建的输入源。但是之前的这篇blog在创建 StreamSource的时候依然用了 return H264VideoStreamFramer::createNew(envir(), liveSource); 把得到的流再用 H264VideoStreamFramer进行了一遍”过滤“,这个H264VideoStramFramer内部会重新从流数据中遍历,找出 NAL, 分离出h264帧,这个过程是多余的并且消耗资源,导致实际推流有明显延迟。这里更正:
#if 0
// Create a framer for the Video Elementary Stream:
//return H264VideoStreamFramer::createNew(envir(), liveSource);
#else
//不需要parse, 直接就是完整的一帧
return H264VideoStreamDiscreteFramer::createNew(envir(), liveSource);
#endif
使用 H264VideoStreamDiscreteFramer来代替H264VideoStreamFramer。 注意这个H264VideoStreamDiscreteFramer 要求输入的数据不带 NAL头。不然一直在抱怨。