基于EasyDarwin的实现无人机远程视频传输--RTSP初始化程序分析

来源:互联网 发布:广州茶楼你知多少钱 编辑:程序博客网 时间:2024/06/03 17:54

该文章整理于http://blog.csdn.net/longlong530 和 http://blog.csdn.net/longlong530/article/details/43194075
谢谢两位网友做的总结!
网上有很多大侠已经对Darwin做了详细的剖析,在下仅本着积累经验的目的,将Darwin的学习过程记录下来,同时与网友们交流学习,今天先来分析下Darwin如果根据配置文件监听RTSP连接的流程。

RTSP相关的代码主要是在QTSServer.cpp QTSServer.h 和RunServer.cpp文件中都在工程的Core文件夹中
RTSP建立侦听调用堆栈层次如下(函数参数默认省略,具体以代码为准):

–> 1. RunServer.cpp:StartServer()
–> 2. QTSServer::Initialize()
–> 3. QTSServer::CreateListeners()//函数根据本地xml配置文件中的rtsp_port和bind_ip_addr字段进行监听的建立.
UInt32* theIPAddrs = this->GetRTSPIPAddrs(inPrefs, &theNumAddrs);
UInt16* thePorts = GetRTSPPorts(inPrefs, &theNumPorts);

Bool16 QTSServer::CreateListeners(Bool16 startListeningNow, QTSServerPrefs* inPrefs, UInt16 inPortOverride){    struct PortTracking    {        PortTracking() : fPort(0), fIPAddr(0), fNeedsCreating(true) {}                UInt16 fPort;  //端口号        UInt32 fIPAddr;//地址        Bool16 fNeedsCreating;//是否需要创建RTSPListenerSocket,默认创建    };        PortTracking* thePortTrackers = NULL;       UInt32 theTotalPortTrackers = 0;        // Get the IP addresses from the pref 获取配置文件中用于监听RTSP连接的IP地址和端口号    UInt32 theNumAddrs = 0;    UInt32* theIPAddrs = this->GetRTSPIPAddrs(inPrefs, &theNumAddrs);       UInt32 index = 0;    //inPortOverride该参数为命令行参数传入,默认为0. -p XXX: Specify the default RTSP listening port of the server    if ( inPortOverride != 0)    {        theTotalPortTrackers = theNumAddrs; // one port tracking struct for each IP addr        thePortTrackers = NEW PortTracking[theTotalPortTrackers];        for (index = 0; index < theNumAddrs; index++)        {            thePortTrackers[index].fPort = inPortOverride;              thePortTrackers[index].fIPAddr = theIPAddrs[index];        }    }    else    {        UInt32 theNumPorts = 0;        UInt16* thePorts = GetRTSPPorts(inPrefs, &theNumPorts);  //根据xml配置文件中的获取端口号        theTotalPortTrackers = theNumAddrs * theNumPorts;        thePortTrackers = NEW PortTracking[theTotalPortTrackers];//一共需要监听的数量为:端口数 * IP地址数                UInt32 currentIndex  = 0;                for (index = 0; index < theNumAddrs; index++)        {            for (UInt32 portIndex = 0; portIndex < theNumPorts; portIndex++)            {                currentIndex = (theNumPorts * index) + portIndex;                                thePortTrackers[currentIndex].fPort = thePorts[portIndex];                thePortTrackers[currentIndex].fIPAddr = theIPAddrs[index];            }        }                                delete [] thePorts;    }            delete [] theIPAddrs;    //    // Now figure out which of these ports we are *already* listening on.    // If we already are listening on that port, just move the pointer to the    // listener over to the new array    TCPListenerSocket** newListenerArray = NEW TCPListenerSocket*[theTotalPortTrackers];    UInt32 curPortIndex = 0;        for (UInt32 count = 0; count < theTotalPortTrackers; count++)    {        for (UInt32 count2 = 0; count2 < fNumListeners; count2++) { if ((fListeners[count2]->GetLocalPort() == thePortTrackers[count].fPort) &&                (fListeners[count2]->GetLocalAddr() == thePortTrackers[count].fIPAddr))            {//如果fListeners监听列表中已经对该ip+port进行了监听,那么就不再监听;                thePortTrackers[count].fNeedsCreating = false;                newListenerArray[curPortIndex++] = fListeners[count2];                Assert(curPortIndex <= theTotalPortTrackers);                break;            }        }    }        //    // 创建为需要监听的IP+PORT创建RTSPListenerSocket    for (UInt32 count3 = 0; count3 < theTotalPortTrackers; count3++) { if (thePortTrackers[count3].fNeedsCreating) //不需要监听的已经在上一步把该字段置为false了. { //创建RTSP监听任务; newListenerArray[curPortIndex] = NEW RTSPListenerSocket(); QTSS_Error err = newListenerArray[curPortIndex]->Initialize(thePortTrackers[count3].fIPAddr, thePortTrackers[count3].fPort);            char thePortStr[20];            qtss_sprintf(thePortStr, "%hu", thePortTrackers[count3].fPort);                        //            // If there was an error creating this listener, destroy it and log an error            if ((startListeningNow) && (err != QTSS_NoErr))                delete newListenerArray[curPortIndex];            if (err == EADDRINUSE){                QTSSModuleUtils::LogError(qtssWarningVerbosity, qtssListenPortInUse, 0, thePortStr);}            else if (err == EACCES){QTSSModuleUtils::LogError(qtssWarningVerbosity, qtssListenPortAccessDenied, 0, thePortStr);}            else if (err != QTSS_NoErr){                QTSSModuleUtils::LogError(qtssWarningVerbosity, qtssListenPortError, 0, thePortStr);}            else            {//将第一个可用端口赋值给fOKPort,保存,后续通过GetOKPort()对外提供RTSP监听端口即为此端口;if(fOKPort == 0){fOKPort = thePortTrackers[count3].fPort;}                //                // This listener was successfully created.如果需要监听,则立即开始监听该socket上面的连接.                if (startListeningNow)                    newListenerArray[curPortIndex]->RequestEvent(EV_RE);                curPortIndex++;            }        }    }        //    //将fListeners监听列表中未在配置文件监听范围内的socket杀掉~    for (UInt32 count4 = 0; count4 < fNumListeners; count4++)    {        Bool16 deleteThisOne = true;                for (UInt32 count5 = 0; count5 < curPortIndex; count5++) { if (newListenerArray[count5] == fListeners[count4]) deleteThisOne = false; } if (deleteThisOne) fListeners[count4]->Signal(Task::kKillEvent);    }        //    // Finally, make our server attributes and fListener privy to the new...最后将监听列表赋给fListeners,监听数量赋给fNumListeners    fListeners = newListenerArray;    fNumListeners = curPortIndex;    UInt32 portIndex = 0;    //将监听的端口号列表保存起来,key值为qtssSvrRTSPPorts    for (UInt32 count6 = 0; count6 < fNumListeners; count6++) { if (fListeners[count6]->GetLocalAddr() != INADDR_LOOPBACK)        {            UInt16 thePort = fListeners[count6]->GetLocalPort();            (void)this->SetValue(qtssSvrRTSPPorts, portIndex, &thePort, sizeof(thePort), QTSSDictionary::kDontObeyReadOnly);            portIndex++;        }    }//设置端口列表的个数;    this->SetNumValues(qtssSvrRTSPPorts, portIndex);    delete [] thePortTrackers;    return (fNumListeners > 0);}

从配置文件中获取RTSP监听地址列表,即0配置项,系统默认是为0,该配置项在多网卡的服务器上可能需要用到,一般我们调试学习的时候可以不考虑。但是还是介绍下,也比较简单。

UInt32* QTSServer::GetRTSPIPAddrs(QTSServerPrefs* inPrefs, UInt32* outNumAddrsPtr){    UInt32 numAddrs = inPrefs->GetNumValues(qtssPrefsRTSPIPAddr);//获取配置文件中rtsp监听地址的数量;    UInt32* theIPAddrArray = NULL;        if (numAddrs == 0)//如果配置的监听地址数量为0,则设置为INADDR_ANY    {        *outNumAddrsPtr = 1;        theIPAddrArray = NEW UInt32[1];        theIPAddrArray[0] = INADDR_ANY;//INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。     }    else    {        theIPAddrArray = NEW UInt32[numAddrs + 1];        UInt32 arrIndex = 0;                for (UInt32 theIndex = 0; theIndex < numAddrs; theIndex++) { // Get the ip addr out of the prefs dictionary QTSS_Error theErr = QTSS_NoErr; char* theIPAddrStr = NULL; theErr = inPrefs->GetValueAsString(qtssPrefsRTSPIPAddr, theIndex, &theIPAddrStr);            if (theErr != QTSS_NoErr)            {                delete [] theIPAddrStr;                break;            }                        UInt32 theIPAddr = 0;            if (theIPAddrStr != NULL)            {//IP地址从字符串转换成整型,并从网络字节顺序转换为主机字节顺序                theIPAddr = SocketUtils::ConvertStringToAddr(theIPAddrStr);                delete [] theIPAddrStr;                                if (theIPAddr != 0)                    theIPAddrArray[arrIndex++] = theIPAddr;            }           }                if ((numAddrs == 1) && (arrIndex == 0))  //如果配置文件的IP地址数量为1,但是解析不到,则同样按照INADDR_ANY方式监听            theIPAddrArray[arrIndex++] = INADDR_ANY;        else            theIPAddrArray[arrIndex++] = INADDR_LOOPBACK; //INADDR_LOOPBACK, 也就是绑定地址LOOPBAC, 往往是127.0.0.1, 只能收到127.0.0.1上面的连接请求            *outNumAddrsPtr = arrIndex;    }        return theIPAddrArray;}
UInt16* QTSServer::GetRTSPPorts(QTSServerPrefs* inPrefs, UInt32* outNumPortsPtr){    *outNumPortsPtr = inPrefs->GetNumValues(qtssPrefsRTSPPorts); //获取qtssPrefsRTSPPorts对应的数组长度;        if (*outNumPortsPtr == 0)        return NULL;            UInt16* thePortArray = NEW UInt16[*outNumPortsPtr];    //获取监听端口号列表;    for (UInt32 theIndex = 0; theIndex < *outNumPortsPtr; theIndex++) { // Get the ip addr out of the prefs dictionary UInt32 theLen = sizeof(UInt16); QTSS_Error theErr = QTSS_NoErr; theErr = inPrefs->GetValue(qtssPrefsRTSPPorts, theIndex, &thePortArray[theIndex], &theLen);        Assert(theErr == QTSS_NoErr);       }        return thePortArray;}

如此根据配置文件的IP、port,即已将对应的Socket建立完成,且startListeningNow默认是false,需要在Runserver中调用sServer->StartTasks();方能开始监听

lo水印商标 更多详情请看:http://www.amovauto.com


0 0
原创粉丝点击