live555 流程重要函数整理
2012-04-09 14:09
253 查看
http://hi.baidu.com/amixyue/blog/item/df5d0a37a87f96305ab5f50e.html
live555 流程重要函数整理
2010-02-02 21:54
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包了。 |
相关文章推荐
- live555 流程重要函数整理
- live555 流程重要函数整理
- live555 流程重要函数整理
- live555 流程重要函数整理
- Python的机器学习库Sklearn中重要模块及其常用函数整理
- 安卓自定义View进阶-流程与重要的函数
- ORACLE调用接口(OCI)简介及重要函数流程介绍
- nginx configure location 流程以及重要函数分析
- 整理 live555 rtsp ffmpeg 客户端解码流程
- Linux基础-shell脚本知识整理和脚本编写----------变量、运算符、流程控制、函数、计划任务(发送邮件)
- 使用ffmpeg进行解码的基本流程 和几个重要函数
- Binder 机制详解—重要函数调用流程分析
- 整理一些PHP函数,这些函数用的不是非常多,但是又非常重要,如果适当的用起来,有可以提升性能
- linux文件系统启动流程 ---笔记整理
- mfc分析和整理--全局函数
- 面试准备 -- 程序员面试宝典 -- 重要知识点整理
- 【转】LR常用函数整理
- app上架流程的整理
- R语言实用函数整理
- sprintf函数使用详解【整理】