live555 describe部分代码分析

   最近准备用live555实现传输H264编码的实时流,略过live555的源码下载编译操作。以 “live.2018.11.26.tar.gz” 为例,简要分析了一下rtsp会话中的describe部分源码。以下两张导图分别是rtsp会话过程以及部分类间的继承关系。

rtsp 会话过程

部分类间的继承关系

DESCRIBE:调用 fOurServer.lookupServerMediaSession 在表中寻找会话相关信息 fOurServer 是在创建rtspserver的时候,new了一个 DynamicRTSPServer类型的对象,然后通过一层一层的构造函数,最终赋值给 GenericMediaServer 类中的成员。
fOurServer 是 GenericMediaServer 类的引用类型,lookupServerMediaSessio 是虚函数,父类指针或引用调用子类对象的虚函数时,最终执行的是子类的虚函数。所以,lookupServerMediaSession 最终执行体是在 DynamicRTSPServer 类中对父类的重载函数。
lookupServerMediaSession 函数中,会根据streamName,在哈希表中查找相关会话,若无匹配的会话,则新建会话并加入表中。

createNewSMS(envir(), streamName, fid); addServerMediaSession(sms);
createNewSMS函数中,根据streamName后缀名,创建调用不同的子会话类型并向新建的会话中加入该类型的子会话。

以 ".264" 类型的文件为例,调用 H264VideoFileServerMediaSubsession 类,新建子会话: sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
session->generateSDPDescription() -----> subsession->sdpLines();
sdpLines是 OnDemandServerMediaSubsession 类实现的。
sdpLines() 主要动作有:
1、createNewStreamSource,在 OnDemandServerMediaSubsession 类中,该函数为纯虚函数,
最终实现在子类 H264VideoFileServerMediaSubsession 中,
{
ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName);
if (fileSource == NULL) return NULL;
fFileSize = fileSource->fileSize();

// Create a framer for the Video Elementary Stream:
return H264VideoStreamFramer::createNew(envir(), fileSource);
}
注意,此时的fileSource 类型为 ByteStreamFileSource 类型,通过 H264VideoStreamFramer::createNew 传入, 再通过一层一层的构造函数,传递给 FramedFilter 类中的 fInputSource变量,所以此时 fInputSource 指针指向的实际对象为 ByteStreamFileSource类型的对象。
在一层一层的构造函数调用中,调用到 在 H264or5VideoStreamFramer 的构造函数时,
使用 inputSource 为参数,new 了一个H264or5VideoStreamParser 类型的对象并赋值给 fParser。 在构造Parser的过程中,又会层层调用基类构造函数,最终,StreamParser 类中的 fInputSource 值也是 ByteStreamFileSource类型。
在sdpLines() 中,使用 FramedSource* inputSource 来接收 createNewStreamSource 的返回值,
所以,此时父类指针 inputSource 指向的对象为 H264VideoStreamFramer类型的对象。

2、createNewRTPSink(dummyGroupsock, rtpPayloadType, inputSource); 该函数返回一个rtpSink的指针,实际类型为 H264VideoRTPSink,原理同上。

3、setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate); setSDPLinesFromRTPSink() 是 OnDemandServerMediaSubsession 类的成员函数,在其中调用了纯虚函数: rtpSink->auxSDPLine(); 由于rtpSink指针实际指向的对象类型为 H264VideoRTPSink, 所以我们在 H264VideoRTPSink.cpp 查看 该函数的实现。此时的subsession 类型为 H264VideoFileServerMediaSubsession,所以需要在 H264VideoFileServerMediaSubsession.cpp 寻找sdpLines的实现。

sdpLines()中,又调用了 继承自父类OnDemandServerMediaSubsession类的 setSDPLinesFromRTPSink函数, 在该函数中又调用了 H264VideoFileServerMediaSubsession 子类中的 getAuxSDPLine()函数。

跟踪 H264VideoFileServerMediaSubsession::getAuxSDPLine:
---> fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
//此时的inputSource为 H264VideoStreamFramer 类型
//fDummyRTPSink 为 H264VideoRTPSink 类型

在startPlaying中,有一个赋值操作:
fSource = (FramedSource*)&source;
// fSource 时MediaSink类的成员,最终被H264VideoRTPSink类继承,
// 此时source 指向的对象类型为 H264VideoStreamFramer 类型的对象
//所以步骤2中新new的 H264VideoRTPSink 对象中fSource 成员的值,
//经过赋值过后,最终指向的对象类型为 H264VideoStreamFramer 类型

--->continuePlaying (实际调用的是 H264or5VideoRTPSink::continuePlaying())
//该函数为MediaSink类的纯虚成员函数,最终由子类 H264or5VideoRTPSink 实现
//在该函数中,为 H264or5VideoRTPSink 类型的成员 fOurFragmenter,以fSource为参数,新
//new 了一个 H264or5Fragmenter 类型的对象,通过层层构造函数,最终为 基类
//FramedFilter 中的 fInputSource 类型赋值,所以 fOurFragmenter 指针指向的对象的成员 fInputSource
//最终指向的类型为 H264VideoStreamFramer。
//再次对 fSource进行了赋值参数,fSource = fOurFragmenter; 此时fSource指向的对象类型就变成了
//H264or5Fragmenter 类型
--->MultiFramedRTPSink::continuePlaying(); ---> buildAndSendPacket(True); --->packFrame();
---> fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(),
              afterGettingFrame, this, ourHandleClosure, this);


//getNextFrame 为基类 FramedSource 的成员函数,在其中调用子类的 doGetNextFrame()
//此时fSource 指向的对象类型为 H264or5Fragmenter,所以调用的 doGetNextFrame。
//应该是H264or5Fragmenter::doGetNextFrame()
//H264or5Fragmenter::doGetNextFrame() --->fInputSource->getNextFrame
//在 continuePlaying 步骤中,新 new 的H264or5Fragmenter 类型的对象中的 fInputSource 最终指向的对象类
//型为 H264VideoStreamFramer 类型。
//查看继承关系可知:H264VideoStreamFramer 继承自 H264or5VideoStreamFramer 继承自
//MPEGVideoStreamFramer
//继承自 FramedFilter 继承自 FramedSource 继承自 MediaSource 继承自 Medium
//getNextFrame 是基类FramedSource中的实现,被 MPEGVideoStreamFramer 继承,在 getNextFrame 中
//调用再次调用的 doGetNextFrame,则
//实际上调用的是 MPEGVideoStreamFramer中的实现
---> MPEGVideoStreamFramer::doGetNextFrame()
---> MPEGVideoStreamFramer::continueReadProcessing()
---> fParser->parse();
//由以上分析可知,fParser指向的对象中的成员 fInputSource 指向的对象类型为
//ByteStreamFileSource 类型。
//parse()为 MPEGVideoStreamParser 类中的纯虚函数,最终由子类 H264or5VideoStreamParser 实现
H264or5VideoStreamParser::parse()
--->test4Bytes() ---> ensureValidBytes() ---> ensureValidBytes1() ---> fInputSource->getNextFrame()
//此时的 getNextFrame 中调用的 doGetNextFrame ,则实际上调用的是 ByteStreamFileSource 类中的实现
parse 解析完之后,调用 afterGetting(FramedSource* source)
传入afsterGetting()的参数为this,指向的对象为 MPEGVideoStreamFramer 类型的对象
afterGetting() ---> *source->fAfterGettingFunc(),
// 此时 fAfterGettingFunc 的值为 H264or5Fragmenter类中,调用 fInputSource->getNextFrame 传入的:
afterGettingFrame
后续操作基本上均为重复调用getNextFrame然后产生sdp会话描述信息。至此,可以大概知道,如果需要实现
live555传输实时流,需要实现一下两个类:
1、H264VideoLiveServerMediaSubsession, 参考:H264VideoFileServerMediaSubsession
2、H264StreamLiveSource,参考:ByteStreamFileSource
核心在于实现 H264StreamLiveSource 类中的 doGetNextFrame 函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值