//监听rtsp服务端口
portNumBits rtspServerPortNum = 554
rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB)
setUpOurSocket(env, ourPort)【DynamicRTSPServer】
env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket, incomingConnectionHandler, this)【GenericMediaServer】
setBackgroundHandling(socketNum, SOCKET_READABLE, handlerProc, clientData);【BasicTaskScheduler】
fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData);
if (conditionSet&SOCKET_READABLE) FD_SET((unsigned)socketNum, &fReadSet);
if (conditionSet&SOCKET_WRITABLE) FD_SET((unsigned)socketNum, &fWriteSet);
if (conditionSet&SOCKET_EXCEPTION) FD_SET((unsigned)socketNum, &fExceptionSet);
//有客户端连接时,创建新的socket并处理
incomingConnectionHandler【GenericMediaServer】
incomingConnectionHandlerOnSocket【GenericMediaServer】
int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);
(void)createNewClientConnection(clientSocket, clientAddr);【RTSPServer】
return new RTSPClientConnection(*this, clientSocket, clientAddr);【RTSPServer】
envir().taskScheduler().setBackgroundHandling(fOurSocket, SOCKET_READABLE|SOCKET_EXCEPTION, incomingRequestHandler, this);【GenericMediaServer::ClientConnection】
//接收客户端发送的数据,根据cmdName的内容不同来调用不同的处理函数
incomingRequestHandler【GenericMediaServer::ClientConnection】
incomingRequestHandler【GenericMediaServer::ClientConnection】
int bytesRead = readSocket(envir(), fOurSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy);
recvfrom【GroupsockHelper.cpp】
handleRequestBytes(bytesRead);【RTSPServer::RTSPClientConnection】
parseRTSPRequestString((char*)fRequestBuffer, fLastCRLF+2 - fRequestBuffer,cmdName, sizeof cmdName...)
if (strcmp(cmdName, "OPTIONS") == 0)
handleCmd_OPTIONS();
if (strcmp(cmdName, "GET_PARAMETER") == 0)
handleCmd_SET_PARAMETER((char const*)fRequestBuffer);
if (strcmp(cmdName, "DESCRIBE") == 0)
handleCmd_DESCRIBE(urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
if (strcmp(cmdName, "SETUP") == 0)
clientSession->handleCmd_SETUP(this, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
playAfterSetup = clientSession->fStreamAfterSETUP;
if (strcmp(cmdName, "TEARDOWN") == 0
|| strcmp(cmdName, "PLAY") == 0
|| strcmp(cmdName, "PAUSE") == 0
|| strcmp(cmdName, "GET_PARAMETER") == 0
|| strcmp(cmdName, "SET_PARAMETER") == 0)
clientSession->handleCmd_withinSession(this, cmdName, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
handleCmd_DESCRIBE
ServerMediaSession*session = fOurServer.lookupServerMediaSession(urlTotalSuffix);【RTSPServer::RTSPClientConnection】
lookupServerMediaSession(char const* streamName, Boolean isFirstLookupInSession = True)【DynamicRTSPServer】//isFirstLookupInSession为true
ServerMediaSession* sms = RTSPServer::lookupServerMediaSession(streamName);【DynamicRTSPServer】//isFirstLookupInSession为true
//未找到MediaSession,创建一个
sms = createNewSMS(envir(), streamName, fid);
if (strcmp(extension, ".ts") == 0) 【ServerMediaSession】
NEW_SMS("MPEG Transport Stream");
sms = ServerMediaSession::createNew(env, fileName, fileName, descStr);
//ServerMediaSession中包含ServerMediaSubsession列表
sms->addSubsession(MPEG2TransportFileServerMediaSubsession::createNew(env, fileName, indexFileName, reuseSource));
if (strcmp(extension, ".264") == 0)
NEW_SMS("H.264 Video");
sms = ServerMediaSession::createNew(env, fileName, fileName, descStr);
sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));
addServerMediaSession(sms);【DynamicRTSPServer】
char const* sessionName = serverMediaSession->streamName();
//GenericMediaServer::HashTable* fServerMediaSessions( maps 'stream name' strings to "ServerMediaSession" objects)中包含一系列ServerMediaSession
fServerMediaSessions->Add(sessionName, (void*)serverMediaSession);
//获取sdp信息作为handleCmd_DESCRIBE的返回值
sdpDescription = session->generateSDPDescription();【ServerMediaSession】
ServerMediaSubsession* subsession;
for (subsession = fSubsessionsHead; subsession != NULL;subsession = subsession->fNext)//fSubsessionsHead subsession列表头
char const* sdpLines = subsession->sdpLines();【OnDemandServerMediaSubsession】
if (fSDPLines == NULL)
FramedSource* inputSource = createNewStreamSource(0, estBitrate);
//.264
ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName);
H264VideoStreamFramer::createNew(envir(), fileSource);
//.ts
ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(envir(), fFileName, inputDataChunkSize);
MPEG2TransportStreamFramer::createNew(envir(), fileSource);
RTPSink* dummyRTPSink = createNewRTPSink(dummyGroupsock, rtpPayloadType, inputSource);
//.264
H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
//.ts
SimpleRTPSink::createNew(envir(), rtpGroupsock,33, 90000, "video", "MP2T",1, True, False /*no 'M' bit*/);
setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate);
char const* auxSDPLine = getAuxSDPLine(rtpSink, inputSource);【H264VideoFileServerMediaSubsession:.264,OnDemandServerMediaSubsession:.ts】
//返回的sdp信息中包含了sdp中的m
char const* const sdpFmt ="m=%s %u RTP/AVP %d\r\n"
//.264获取sdp信息流程 ByteStreamFileSource为source,H264VideoRTPSink为sink
char const* auxSDPLine = getAuxSDPLine(rtpSink, inputSource);【H264VideoFileServerMediaSubsession:.264】
// Start reading the file:
fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);【MediaSink】
fAfterFunc = afterFunc;
fAfterClientData = afterClientData;
continuePlaying();【H264or5VideoRTPSink】
// Check whether the sink's 'auxSDPLine()' is ready:
checkForAuxSDPLine(this);
//taskScheduler socket网络事件轮询,如果收到网络事件,则调用对应的回调函数
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler)
env->taskScheduler().doEventLoop()【BasicTaskScheduler0】
for(;;)
SingleStep()【BasicTaskScheduler】
select(fMaxNumSockets, &readSet, &writeSet, &exceptionSet, &tv_timeToDelay);
HandlerIterator iter(*fHandlers);
HandlerDescriptor* handler;
(*handler->handlerProc)(handler->clientData, resultConditionSet);【BasicTaskScheduler】
DynamicRTSPServer->RTSPServerSupportingHTTPStreaming->RTSPServer->GenericMediaServer->Medium
BasicTaskScheduler->BasicTaskScheduler0->TaskScheduler
RTSPServer::RTSPClientSession->GenericMediaServer::ClientSession
ServerMediaSession->Medium
MPEG2TransportFileServerMediaSubsession->FileServerMediaSubsession->OnDemandServerMediaSubsession->ServerMediaSubsession->Medium
H264VideoFileServerMediaSubsession->FileServerMediaSubsession->OnDemandServerMediaSubsession->ServerMediaSubsession->Medium
ByteStreamFileSource->FramedFileSource->FramedSource->MediaSource->Medium //(h264,h265,ts的createNewStreamSource)
H264VideoRTPSink->H264or5VideoRTPSink->VideoRTPSink->MultiFramedRTPSink->RTPSink->MediaSink->Medium //(h264 的createNewRTPSink)
H265VideoRTPSink->H264or5VideoRTPSink->VideoRTPSink->MultiFramedRTPSink->RTPSink->MediaSink->Medium //(h265 的createNewRTPSink)
SimpleRTPSink->MultiFramedRTPSink->RTPSink->MediaSink->Medium//(ts 的createNewRTPSink)
注意
ServerMediaSession中包含ServerMediaSubsession列表。
GenericMediaServer中包含HashTable* fServerMediaSessions; // maps 'stream name' strings to "ServerMediaSession" objects