zoukankan      html  css  js  c++  java
  • Darwin Streaming Server中RTSP会话流程解析(Darwin流媒体服务器解析1)

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

                                                      -->QTSServer::Initialize()

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

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

    具体函数在:

    QTSServer::CreateListeners()
    {
    …
                  newListenerArray[curPortIndex] = NEW RTSPListenerSocket();
                QTSS_Error err = newListenerArray[curPortIndex]->Initialize(thePortTrackers[count3].fIPAddr, thePortTrackers[count3].fPort);//fIPAddr为本地IP,fPort为配置端口号
    
    …
    }

    void QTSServer::StartTasks()
    {
        fRTCPTask = new RTCPTask();
        fStatsTask = new RTPStatsUpdaterTask();
    
        //
        // Start listening
        for (UInt32 x = 0; x < fNumListeners; x++)
            fListeners[x]->RequestEvent(EV_RE);
    }


    二、会话建立

    先看RTSPListenerSocket类:

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

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

    EventThread::Entry()
    {
    …
         EventContext* theContext = (EventContext*)ref->GetObject();
         theContext->ProcessEvent(theCurrentEvent.er_eventbits);
    …
    }

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

    	
        theTask = this->GetSessionTask(&theSocket);//创建RTSPSession
        if (theTask == NULL)
        {    //this should be a disconnect. do an ioctl call?
            close(osSocket);
            if (theSocket)
                theSocket->fState &= ~kConnected; // turn off connected state
        }
        else
        {   
            Assert(osSocket != EventContext::kInvalidFileDesc);
            
            //set options on the socket
            //we are a server, always disable nagle algorithm
            int one = 1;
            int err = ::setsockopt(osSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));
            AssertV(err == 0, OSThread::GetErrno());
            
            err = ::setsockopt(osSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(int));
            AssertV(err == 0, OSThread::GetErrno());
        
            int sndBufSize = 96L * 1024L;
            err = ::setsockopt(osSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sndBufSize, sizeof(int));
            AssertV(err == 0, OSThread::GetErrno());
        
            //setup the socket. When there is data on the socket,
            //theTask will get an kReadEvent event
            theSocket->Set(osSocket, &addr);
            theSocket->InitNonBlocking(osSocket);
            theSocket->SetTask(theTask);      //将处理Socket的类转入到RTSPSession
            theSocket->RequestEvent(EV_RE);   //将当前Socket加入select侦听队列
        }
      

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

    三、RTSP交互

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

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

    到EventContext中的ProcessEvent()函数:

    virtual void ProcessEvent(int /*eventBits*/) 
            {   
                if (EVENTCONTEXT_DEBUG)
                {
                    if (fTask== NULL)  
                        qtss_printf("EventContext::ProcessEvent context=%lu task=NULL\n",(UInt32) this); 
                    else 
                        qtss_printf("EventContext::ProcessEvent context=%lu task=%lu TaskName=%s\n",(UInt32)this,(UInt32) fTask, fTask->fTaskName); 
                }
    
                if (fTask != NULL)
                    fTask->Signal(Task::kReadEvent); 
            }

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

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

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

    ------------------------------------------------------------
    本文转自www.easydarwin.org,更多开源流媒体解决方案,请关注我们的微信:EasyDarwin 

  • 相关阅读:
    结构和联合
    字符串、字符和字节
    数组
    函数
    指针
    操作符和表达式
    语句
    数据
    TinyXML2 使用
    是否忘记了向源中添加“#include "StdAfx.h"”?
  • 原文地址:https://www.cnblogs.com/babosa/p/5904734.html
Copyright © 2011-2022 走看看