live555 流程重要函数整理

live555 流程重要函数整理
2010-02-02 21:54
服务器启动
DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);
env->taskScheduler().doEventLoop()

有链接了!
select(fMaxNumSockets, &readSet, NULL, NULL,&tv_timeToDelay)

创建好了RTSPClientSession
void RTSPServer::RTSPClientSession::incomingRequestHandler(void* instance, int /*mask*/)
void RTSPServer::RTSPClientSession::incomingRequestHandler1()

重点在于 对 DESCRIBE 信令的处理:
void RTSPServer::RTSPClientSession::handleCmd_DESCRIBE(char const* cseq, char const* urlSuffix,
char const* fullRequestStr) 
需要一次 rtsp 会话了:
ServerMediaSession* session = fOurServer.lookupServerMediaSession(urlSuffix);
{
当前目录下检查文件
FILE* fid = fopen(streamName, "rb");

再看看对这个 streamName ,RTSPServer 是不是已经有 SMS
(ServerMediaSession*)(fServerMediaSessions->Lookup(streamName))

没有,就创建吧!
这里,还可以看出 RTSPClientSession 是标志一次 RSTP 会话,而 SMS 则是一种媒体会话
sms = createNewSMS(envir(), streamName, fid);

添加对应的 subsession
MPEG4VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource)
FileServerMediaSubsession(env, fileName, reuseFirstSource)
OnDemandServerMediaSubsession(env, reuseFirstSource) 
看到了吧,OnDemandServerMediaSubsession 与具体媒体文件无关的,很抽象的东东,但和 sdp 很有联系,它有很长的初始化列表 
ServerMediaSubsession(env),=>{
Medium(env), 
fIsSSM(isSSM),
fSubsessionsHead(NULL),
fSubsessionsTail(NULL), 
fSubsessionCounter(0),
fReferenceCount(0),
fDeleteWhenUnreferenced(False)
}//也是很长的初始化列表
fSDPLines(NULL), => 这个就是 SDP
fReuseFirstSource(reuseFirstSource),
fInitialPortNum(initialPortNum),
fLastStreamToken(NULL) 
}

以上都是为了获得 SDP
sdpDescription = session->generateSDPDescription()
这时,因为 subsession 是链表的原因,因此,遍历链表 ,得到每个 subsession 的 sdpLines
sdpLines = subsession->sdpLines()
用 float dur = duration() 获得播放的帧数 range ,还有等等
整个 sdp 构成就是:
fCreationTime.tv_sec, fCreationTime.tv_usec, // o= <session id>
1, // o= <version> // (needs to change if params are modified)
ipAddressStr, // o= <address>
fDescriptionSDPString, // s= <description>
fInfoSDPString, // i= <info>
libNameStr, libVersionStr, // a=tool:
sourceFilterLine, // a=source-filter: incl (if a SSM session)
rangeLine, // a=range: line
fDescriptionSDPString, // a=x-qt-text-nam: line
fInfoSDPString, // a=x-qt-text-inf: line
fMiscSDPLines,// miscellaneous session SDP lines (if any)
还有最重要的 每个subsession->sdpLines()
这个就是来源于 OnDemandServerMediaSubsession::sdpLines() 嗯嗯,一个和具体文件无关的 OnDemandServerMediaSubsession,,但是它里面却是通过 dummy 的FramedSource 和 RTPSink 在实际实现的时候,调用具体的实现,如 MPEG4ESVideoStreamFramer 等获取 sdpline。如下:

OnDemandServerMediaSubsession::sdpLines() {
把 媒体文件 二进制化成 ByteStreamFileSource ,再用它来创建 MPEG4VideoStreamFramer ,这个在另一篇博文中提过,是用来产生 头和帧 的。
但是,这个 estBitrate 倒是不懂怎么设定的??????
FramedSource* inputSource = createNewStreamSource(0, estBitrate);

unsigned char rtpPayloadType = 96 + trackNumber()-1; // if dynamic

这个是关于 Sink 的创建
RTPSink* dummyRTPSink  = createNewRTPSink(&dummyGroupsock, rtpPayloadType, inputSource);

用以上的信息产生 SDP
setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate);
如果说之前那些应该是整个会话的信息,而下面是对应媒体 subsession tarck信息:
mediaType, // m= <media>
fPortNumForSDP, // m= <port>
rtpPayloadType, // m= <fmt list>
ipAddressStr, // c= address
estBitrate, // b=AS:<bandwidth>
rtpmapLine, // a=rtpmap:... (if present)
rangeLine, // a=range:... (if present)
auxSDPLine, // optional extra SDP line
trackId()); // a=control:<track-id>
}

备注:如果你要做 264 的话,要注意264 在 Sink 的初始化的时候,和 Mpeg4 不同
264 设了 unsigned profile_level_id, char const* sprop_parameter_sets_str ,其实这两个参数我现在还不是很懂,要查下 码流 才能确定
》》》》》求助《《《《《《《《《 如果有知道的,希望能留言告诉我。

auxSDPLine, // optional extra SDP line 这一行的 auxSDPLine 就是 调用OnDemandServerMediaSubsession::getAuxSDPLine 得到的,而它的信息来自于 sink 的getAuxSDPLine ,而这个东东,对应于264 ,就是上面两个参数,所以很重要的。

》》》》》求助《《《《《《《《《这两个参数有多重要,希望知道的各位大虾能留言给我

ok ,到此为止 DESCRIBE 分析完毕
接着就是 handleCmd_SETUP
fStreamStates = new struct streamState[fNumStreamStates];
记录 SMS 下的subsession 的信息 ,这里为什么要记录? 我认为是这样的:Server 对每个 streamName 有且仅有维持一个 SMS ,那对每个 Client 如何记录状态呢,就是靠这个 fStreamStates 。
而且感觉这个是整个 SETUP 的重点,同时,它从 subsession 中取信息 ,
subsession->getStreamParameters(fOurSessionId, fClientAddr.sin_addr.s_addr,
clientRTPPort, clientRTCPPort,
tcpSocketNum, rtpChannelId, rtcpChannelId,
destinationAddress, destinationTTL, fIsMulticast,
serverRTPPort, serverRTCPPort,
fStreamStates[streamNum].streamToken);
获取流媒体发送传输参数。将这些参数组 装成响应消息,返回给客户端

获取发送传输参数的过程:调用子会话(如具体实现类MPEG1or2DemuxedServerMediaSubsession)的 createNewStreamSource(...)创建MPEG1or2VideoStreamFramer,选择发送传输参数,并调用子会话的 createNewRTPSink(...)创建MPEG1or2VideoRTPSink。同时将这些信息保存在StreamState类对象中,用于 记录流的状态 ( A class that represents the state of an ongoing stream)。
从 StreamState 的成员变量都可以看出一些端倪:
{
OnDemandServerMediaSubsession& fMaster;
Boolean fAreCurrentlyPlaying;
unsigned fReferenceCount;
Port fServerRTPPort, fServerRTCPPort;
RTPSink* fRTPSink;
BasicUDPSink* fUDPSink;
float fStreamDuration;
unsigned fTotalBW; RTCPInstance* fRTCPInstance;
FramedSource* fMediaSource;
Groupsock* fRTPgs; Groupsock* fRTCPgs;
}

PLAY
fStreamStates[i].subsession->startStream(fOurSessionId,
fStreamStates[i].streamToken,
(TaskFunc*)noteClientLiveness,
this,
rtpSeqNum,
rtpTimestamp);
MediaSink::startPlaying(...)
MultiFramedRTPSink::continuePlaying()
MultiFramedRTPSink::buildAndSendPacket(...){
buildAndSendPacke内部先设置RTP包头, 内部再调用MultiFramedRTPSink::packFrame()填充编码帧数据{
FramedSource::getNextFrame()
MPEGVideoStreamFramer::doGetNextFrame()
MPEGVideoStreamFramer::continueReadProcessing()
FramedSource::afterGetting(...)
MultiFramedRTPSink::afterGettingFrame(...),
MultiFramedRTPSink::afterGettingFrame1(...)
...
MultiFramedRTPSink::sendPacketIfNecessary(),
}
}
然后是计算下一个数据包发送时间,把MultiFramedRTPSink::sendNext(...)函数句柄传给任务调度器,作为一个延时事件调度。在主循环中,当MultiFramedRTPSink::sendNext()被调度时,又开始调用 MultiFramedRTPSink::buildAndSendPacket(...)开始新的发送数据过程,这样客户端可以源源不断的收到服务器传来的RTP包了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值