1. 程式人生 > >用Darwin開發RTSP級聯伺服器(拉模式轉發)(附原始碼)

用Darwin開發RTSP級聯伺服器(拉模式轉發)(附原始碼)

QTSS_Error DoDescribe(QTSS_StandardRTSP_Params* inParams)
{
	char* theUriStr = NULL;
    QTSS_Error err = QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqFileName, 0, &theUriStr);
    Assert(err == QTSS_NoErr);
    if(err != QTSS_NoErr)
		return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest, 0);
    QTSSCharArrayDeleter theUriStrDeleter(theUriStr);

	// 查詢配置表,獲取攝像機資訊結構體
	DeviceInfo* pDeviceInfo = parseDevice->GetDeviceInfoByIdName(theUriStr);

	if(pDeviceInfo == NULL)
	{
		// 對映表中沒有查到相關資訊,返回,RTSP請求交給其他模組處理
		return QTSS_RequestFailed;
	}

	// 對映資訊存在rtsp://218.204.223.237:554/live/1/66251FC11353191F/e7ooqwcfbqjoo80j.sdp
	RTSPClientSession* clientSes = NULL;
	// 首先查詢RTSPClientSession Hash表是否已經建立了對應攝像機的RTSPClientSession
	StrPtrLen streamName(theUriStr);
	OSRef* clientSesRef = sClientSessionMap->Resolve(&streamName);
	if(clientSesRef != NULL)
	{
		clientSes = (RTSPClientSession*)clientSesRef->GetObject();
	}
	else
	{
		// 初次建立伺服器與攝像機間的互動RTSPClientSession
		clientSes = NEW RTSPClientSession(
									SocketUtils::ConvertStringToAddr(pDeviceInfo->m_szIP),
									pDeviceInfo->m_nPort,
									pDeviceInfo->m_szSourceUrl,
									1,
									rtcpInterval,
									0,
									theReadInterval,
									sockRcvBuf,
									speed,
									packetPlayHeader,
									overbufferwindowInK,
									sendOptions,
									pDeviceInfo->m_szUser,
									pDeviceInfo->m_szPassword,
									theUriStr);

		// 向攝像機源端傳送Describe請求
		OS_Error theErr = clientSes->SendDescribe();

		if(theErr == QTSS_NoErr){
			// 將成功建立的RTSPClientSession註冊到sClientSessionMap表中
			OS_Error theErr = sClientSessionMap->Register(clientSes->GetRef());
			Assert(theErr == QTSS_NoErr);
		}
		else{
			clientSes->Signal(Task::kKillEvent);
			return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientNotFound, 0); 
		}

		//增加一次對RTSPClientSession的無效引用,後面會統一釋放
		OSRef* debug = sClientSessionMap->Resolve(&streamName);
		Assert(debug == clientSes->GetRef());
	}

	// 建立轉發所用的ReflectorSession,後續流程與QTSSReflectorModule類似
	ReflectorSession* theSession = SetupProxySession(inParams, clientSes);
    
    if (theSession == NULL)
	{
		sClientSessionMap->Release(clientSes->GetRef());
        return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssServerNotImplemented, 0);
	}
}

      這裡我們用到了兩個Hash Map,一個是儲存RTSPClientSession的sClientSessionMap、一個儲存ReflectorSession的sSessionMap。