当前位置: > Linux服务器 >

Darwin Streaming Server中RTSP会话流程解析(Darwin流媒体服务器

时间:2014-09-17 12:17来源:linux.it.net.cn 作者:it

一、首先是本地监听的建立:StartServer() ->

                                                  -->QTSServer::Initialize()

                                                            --->QTSServer::CreateListeners() //函数中根据本地xml配置文件中的rtsp_port进行监听的建立                                   

                                                   -->QTSServer::StartTasks() //开启Socket读取

具体函数在:

[cpp] view plaincopy
  1. QTSServer::CreateListeners()  
  2. {  
  3. …  
  4.               newListenerArray[curPortIndex] = NEW RTSPListenerSocket();  
  5.             QTSS_Error err = newListenerArray[curPortIndex]->Initialize(thePortTrackers[count3].fIPAddr, thePortTrackers[count3].fPort);//fIPAddr为本地IP,fPort为配置端口号  
  6.   
  7. …  
  8. }  

[cpp] view plaincopy
  1. void QTSServer::StartTasks()  
  2. {  
  3.     fRTCPTask = new RTCPTask();  
  4.     fStatsTask = new RTPStatsUpdaterTask();  
  5.   
  6.     //  
  7.     // Start listening  
  8.     for (UInt32 x = 0; x < fNumListeners; x++)  
  9.         fListeners[x]->RequestEvent(EV_RE);  
  10. }  


二、会话建立

先看RTSPListenerSocket类:

Socket的读取统一归于EventContext类中的EventThread线程,具体到EventThread::Entry()中的select_waitevent()捕获。

EventThread::Entry()函数中查找EventThread::fRefTable,获取对应的EventContext。得到的是EventContext类型的派生类RTSPListenerSocket。

[cpp] view plaincopy
  1. EventThread::Entry()  
  2. {  
[cpp] view plaincopy
  1. …  
  2.      EventContext* theContext = (EventContext*)ref->GetObject();  
  3.      theContext->ProcessEvent(theCurrentEvent.er_eventbits);  
  4. …  
[cpp] view plaincopy
  1. }  

 

调用RTSPListenerSocket的ProcessEvent()函数,进而调用TCPListenerSocket::ProcessEvent(),在TCPListenerSocket::ProcessEvent()中accept Socket

[cpp] view plaincopy
  1. theTask = this->GetSessionTask(&theSocket);//创建RTSPSession  
  2. if (theTask == NULL)  
  3. {    //this should be a disconnect. do an ioctl call?  
  4.     close(osSocket);  
  5.     if (theSocket)  
  6.         theSocket->fState &= ~kConnected; // turn off connected state  
  7. }  
  8. else  
  9. {     
  10.     Assert(osSocket != EventContext::kInvalidFileDesc);  
  11.       
  12.     //set options on the socket  
  13.     //we are a server, always disable nagle algorithm  
  14.     int one = 1;  
  15.     int err = ::setsockopt(osSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));  
  16.     AssertV(err == 0, OSThread::GetErrno());  
  17.       
  18.     err = ::setsockopt(osSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(int));  
  19.     AssertV(err == 0, OSThread::GetErrno());  
  20.   
  21.     int sndBufSize = 96L * 1024L;  
  22.     err = ::setsockopt(osSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sndBufSize, sizeof(int));  
  23.     AssertV(err == 0, OSThread::GetErrno());  
  24.   
  25.     //setup the socket. When there is data on the socket,  
  26.     //theTask will get an kReadEvent event  
  27.     theSocket->Set(osSocket, &addr);  
  28.     theSocket->InitNonBlocking(osSocket);  
  29.     theSocket->SetTask(theTask);      //将处理Socket的类转入到RTSPSession  
  30.     theSocket->RequestEvent(EV_RE);   //将当前Socket加入select侦听队列  
  31. }  

将(TCPSocket*)theSocket加入到侦听队列中,从上以后就开始对该条已建立accept的(TCPSocket*)theSocket描述请求由此处所创建的(RTSPSession*)theTask进行处理。

三、RTSP交互

        同样Socket的读取统一归于EventContext类中的EventThread线程,具体到EventThread::Entry()中的select_waitevent()捕获。

EventThread::Entry()函数中查找EventThread::fRefTable,获取对应的EventContext。此时查找到第二部分中加入到侦听队列的Socket,进入

到EventContext中的ProcessEvent()函数:

[cpp] view plaincopy
  1. virtual void ProcessEvent(int /*eventBits*/)   
  2.         {     
  3.             if (EVENTCONTEXT_DEBUG)  
  4.             {  
  5.                 if (fTask== NULL)    
  6.                     qtss_printf("EventContext::ProcessEvent context=%lu task=NULL\n",(UInt32) this);   
  7.                 else   
  8.                     qtss_printf("EventContext::ProcessEvent context=%lu task=%lu TaskName=%s\n",(UInt32)this,(UInt32) fTask, fTask->fTaskName);   
  9.             }  
  10.   
  11.             if (fTask != NULL)  
  12.                 fTask->Signal(Task::kReadEvent);   
  13.         }  

激活第二部分中theSocket所映射的theTask,进行Socket读取。此处fTask就是RTSPSession类。把RTSPSession加入到TaskThread的队列等待RTSPSession::Run()被调用,

进而就是RTSPSession::Run()对具体的RTSP请求进行的处理。

 

好了,今天就简单推进到此处,下一部分将深入到RTSPSession中具体对报文如何解析,以及RTSPSession如何与其他模块&Task进行交互进行分析!

(责任编辑:IT)
------分隔线----------------------------
栏目列表
推荐内容