简单控制流

  • 格式:pdf
  • 大小:94.46 KB
  • 文档页数:5

简单消息处理过程:1.Describe:handleCmd_DESCRIBE-|sdpLines--|createNewStreamSource---|ByteStreamFileSource---|H264VideoStreamFramer----|H264or5VideoStreamFramer-----|H264or5VideoStreamParser------|MPEGVideoStreamParser:: StreamParser(inputSource, FramedSource::handleClosure, usingSource,&MPEGVideoStreamFramer::continueReadProcessing, usingSource), -------|continueReadProcessing--------|parse--|createGroupsock--|createNewRTPSink(dummyGroupsock, rtpPayloadType, inputSource)---|H264or5VideoRTPSink----|VideoRTPSink-----|MultiFramedRTPSink--|setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate)---|getAuxSDPLine----|checkForAuxSDPLine-----|checkForAuxSDPLine1{nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay, (TaskFunc*)checkForAuxSDPLine, this);/*添加到任务调度中,固定时间就会调用checkForAuxSDPLine来查找sdp*/ }播放过程:3.PlayhandleCmd_PLAY-|startStream--|StreamState::startPlaying{fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);}//播放完成之后会执行该函数来关闭---|MediaSink::startPlaying(之前笔记之中缺少了一个环节,注意startPlaying中参数,func对应函数应该是在播放完成之后需要调用来关闭播放的.)----|H264or5VideoRTPSink::continuePlaying()-----|MultiFramedRTPSink::continuePlaying()------|buildAndSendPacket(大循环,源源不断获取数据)-------|packFrame{fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(), afterGettingFrame, this, ourHandleClosure, this);}--------|H264or5Fragmenter::doGetNextFrame(){if (fNumValidDataBytes == 1) {fInputSource->getNextFrame(&fInputBuffer[1], fInputBufferSize - 1,afterGettingFrame, this,FramedSource::handleClosure, this);}else{case1; case2; case3. //根据帧数据大小和可发送最大长度比较,分片处理FramedSource::afterGetting(this); //发送数据}}--------|MPEGVideoStreamFramer::doGetNextFrame()---------|continueReadProcessing{unsigned acquiredFrameSize = fParser->parse();if (acquiredFrameSize > 0) {afterGetting(this); //在doGetNextFrame中有进行发送数据,这块作用??}}----------| H264or5VideoStreamParser::parse(){test4Bytes() //用来获取字节数据}-----------| u_int32_t test4Bytes()------------|StreamParser::ensureValidBytes1(unsigned numBytesNeeded) {fInputSource->getNextFrame(&curBank()[fTotNumValidBytes], maxNumBytesToRead,afterGettingBytes, this,onInputClosure, this);// 这里的fInputSource应该是前面创建的ByteStreamFileSource文件}-------------|ByteStreamFileSource::doGetNextFrame()--------------| ByteStreamFileSource::doReadFromFile() {fFrameSize = fread(fTo, 1, fMaxSize, fFid); //找不到定义,原来是系统函数size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); }---------|FramedSource::afterGetting(FramedSource* source)//数据已获取,发送数据----------|MultiFramedRTPSink::afterGettingFrame1-----------|sendPacketIfNecessary{(1)fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize());//发送数据(2)nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo,(TaskFunc*)sendNext, this); //获取下一帧数据}------------|(1)RTPInterface::sendPacket-------------|sendRTPorRTCPPacketOverTCP(packet, packetSize,stream->fStreamSocketNum, stream->fStreamChannelId)--------------|sendDataOverTCP(socketNum, packet, packetSize, True)---------------|send(socketNum, (char const*)data, dataSize, 0/*flags*/)//调用系统函数------------|(2)void MultiFramedRTPSink::sendNext(void* firstArg) {sink->buildAndSendPacket(False); //所以说buildAndSendPacket 是大循环}source文件分析:RTSPServer::RTSPClientConnection::handleCmd_DESCRIBE(char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr) {(1)session = fOurServer.lookupServerMediaSession(urlTotalSuffix); //查找并建立会话(2)sdpDescription = session->generateSDPDescription(); //获取文件sdp内容,并ByteStreamFileSource和createNewRTPSink,并对ByteStreamFileSource实例化} --|(1)ServerMediaSession* DynamicRTSPServer::lookupServerMediaSession(char const* streamName, Boolean isFirstLookupInSession) {FILE* fid = fopen(streamName, "rb");ServerMediaSession* sms =RTSPServer::lookupServerMediaSession(streamName);//查找是否存在该会话if (sms == NULL) {sms = createNewSMS(envir(), streamName, fid); //不存在该会话时则建立会话addServerMediaSession(sms);}}---|ServerMediaSession* createNewSMS(UsageEnvironment& env,char const* fileName, FILE* /*fid*/) {else if (strcmp(extension, ".264") == 0) {// Assumed to be a H.264 Video Elementary Stream file:NEW_SMS("H.264 Video");OutPacketBuffer::maxSize = 100000; // allow for some possibly large H.264 framessms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));}----|H264VideoFileServerMediaSubsession::H264VideoFileServerMediaSubsession(UsageEnvironment& env,char const* fileName, Boolean reuseFirstSource) : FileServerMediaSubsession(env, fileName, reuseFirstSource),fAuxSDPLine(NULL), fDoneFlag(0), fDummyRTPSink(NULL) {}-----|FileServerMediaSubsession::FileServerMediaSubsession(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource): OnDemandServerMediaSubsession(env, reuseFirstSource),fFileSize(0) {fFileName = strDup(fileName); //fFileName在这里被指定之后,之后要用它来实例化ByteStreamFileSource}}到目前为止,会话已经建立好了,并且该会话所对应的fFileName的内容也已经是客户端需求文件的路径.可以说,该会话已经与该文件绑定在一起了.这样,在后面试了实例化ByteStreamFileSource 时,对应的文件路径就是fFileName内容,这样就很明确了.--|ServerMediaSession::generateSDPDescription()---|OnDemandServerMediaSubsession::sdpLines() {FramedSource* inputSource = createNewStreamSource(0, estBitrate);//实例化sourceGroupsock* dummyGroupsock = createGroupsock(dummyAddr, 0);RTPSink* dummyRTPSink = createNewRTPSink(dummyGroupsock, rtpPayloadType, inputSource); //将source和groupsock传参,实例化sink setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate);//取sdp内容}----|H264VideoFileServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {ByteStreamFileSource*fileSource = ByteStreamFileSource::createNew(envir(), fFileName);/*fFileName就是在上面创建会话时指定的对应的文件路径.故是从ByteStreamFileSource对应的source上来取数据*/return H264VideoStreamFramer::createNew(envir(),fileSource);/*一层层跟踪下去,会发现,创建了一个StreamParser::StreamParser,并且类成员fInputSource(inputSource),该inputSource的本来面目其实就是上面传入的fileSource,所以,在真正取数据的parse->..->StreamParser::ensureValidBytes1里面所对应的fInputSource就是在这块创建的ByteStreamFileSource对象*/}-----|StreamParser::ensureValidBytes1(unsigned numBytesNeeded) { fInputSource->getNextFrame(&curBank()[fTotNumValidBytes],maxNumBytesToRead,afterGettingBytes, this,onInputClosure, this); //该fInputSource指的就是ByteStreamFileSource,故,doGetNextFrame对应的就是ByteStreamFileSource中相应操作,真正获取数据}如果想要让自定义的h264文件数据被读取,从而发送显示到客户端, 就需要让供应数据的ByteStreamFileSource对象中的数据源文件路径为自定义路径=>需要修改fFileName内容为自定义文件路径内容=>就需要替换handleCmd_DESCRIBE传入的urlTotalSuffix=>也就是需要将客户端请求消息中的urlTotalSuffix内容改为自定义文件路径按照现在的理解,可能就需要砍掉option,以及describe消息请求及处理相关操作.去掉客户端describe消息请求即可,直接上层控制开始数据传送就发送数据1.建立与客户端会话,使得文件路径就是inputSource(存放h264数据文件).后期需要做成,该文件中数据内容也是在不断输入的.编码后数据的输入.2.直接由上层控制是否开始发送数据,一旦开始发送数据,则思考:为什么要取出每个会话中的sdp???? 因为是分别取出audio和video的.char* ServerMediaSession::generateSDPDescription() {for (subsession = fSubsessionsHead; subsession != NULL;subsession = subsession->fNext) {char const* sdpLines = subsession->sdpLines();if (sdpLines == NULL) continue; // the media's not availablesdpLength += strlen(sdpLines);}}获取SDP字符串,在函数内会依次获取每个ServerMediaSubSession(video & audio ..)的字符串然连接起来。