QTSS_Error DoPlay(QTSS_StandardRTSP_Params* inParams, ReflectorSession* inSession) { QTSS_Error theErr = QTSS_NoErr; UInt32 flags = 0; UInt32 theLen = 0; if (inSession == NULL) // it is a broadcast session so store the broadcast session. return QTSS_RequestFailed; else { UInt32 bitsPerSecond = inSession->GetBitRate(); (void)QTSS_SetValue(inParams->inClientSession, qtssCliSesMovieAverageBitRate, 0, &bitsPerSecond, sizeof(bitsPerSecond)); QTSS_Error theErr = QTSS_Play(inParams->inClientSession, inParams->inRTSPRequest, qtssPlayFlagsAppendServerInfo); if (theErr != QTSS_NoErr) return theErr; } OSRef* theRelaySessionRef = sClientSessionMap->Resolve(inSession->GetRef()->GetString()); if(theRelaySessionRef != NULL) { RTSPRelaySession* relaySes = (RTSPRelaySession*)theRelaySessionRef->GetObject(); QTSS_Error err = relaySes->Start(); sClientSessionMap->Release(theRelaySessionRef); } else { return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssServerInternal, 0); } (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, flags); return QTSS_NoErr; }
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); //从接口获取信息结构体 //信息存在rtsp://59.46.115.84:8554/h264/ch1/sub/av_stream RTSPRelaySession* clientSes = NULL; //首先查找Map里面是否已经有了对应的流 StrPtrLen streamName(theUriStr); OSRef* clientSesRef = sRelaySessionMap->Resolve(&streamName); if(clientSesRef != NULL) { clientSes = (RTSPRelaySession*)clientSesRef->GetObject(); } else { clientSes = NEW RTSPRelaySession("rtsp://*****:*****@192.168.66.189/", RTSPRelaySession::kRTSPTCPClientType, theUriStr); QTSS_Error theErr = clientSes->SendDescribe(); if(theErr == QTSS_NoErr) { OS_Error theErr = sRelaySessionMap->Register(clientSes->GetRef()); Assert(theErr == QTSS_NoErr); } else { clientSes->Signal(Task::kKillEvent); return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientNotFound, 0); } //增加一次对RelaySession的无效引用,后面会统一释放 OSRef* debug = sRelaySessionMap->Resolve(&streamName); Assert(debug == clientSes->GetRef()); } return QTSS_NoErr; }
QTSS_Error ProcessRelayRTPData(QTSS_RelayingData_Params* inParams) { ReflectorSession* theSession = NULL; RTSPRelaySession* relaySes = (RTSPRelaySession*)inParams->inRTSPSession; theSession = relaySes->GetReflectorSession(); if (theSession == NULL) return QTSS_NoErr; SourceInfo* theSoureInfo = theSession->GetSourceInfo(); Assert(theSoureInfo != NULL); if (theSoureInfo == NULL) return QTSS_NoErr; UInt32 numStreams = theSession->GetNumStreams(); char* packetData= inParams->inPacketData; UInt8 packetChannel = inParams->inChannel; UInt16 packetDataLen = inParams->inPacketLen; char* rtpPacket = &packetData[0]; { UInt32 inIndex = packetChannel / 2; ReflectorStream* theStream = NULL; if (inIndex < numStreams) { theStream = theSession->GetStreamByIndex(inIndex); SourceInfo::StreamInfo* theStreamInfo =theStream->GetStreamInfo(); UInt16 serverReceivePort =theStreamInfo->fPort; Bool16 isRTCP =false; if (theStream != NULL) { if (packetChannel & 1) { serverReceivePort ++; isRTCP = true; } theStream->PushPacket(rtpPacket,packetDataLen, isRTCP); } } } return QTSS_NoErr; }
void RemoveOutput(ReflectorOutput* inOutput, ReflectorSession* inSession, Bool16 killClients) { //This function removes the output from the ReflectorSession, then Assert(inSession); if (inSession != NULL) { if (inOutput != NULL) { inSession->RemoveOutput(inOutput,true); //qtss_printf("QTSSReflectorModule.cpp:RemoveOutput it is a client session\n"); } else { // it is a Broadcaster session //qtss_printf("QTSSReflectorModule.cpp:RemoveOutput it is a broadcaster session\n"); //SourceInfo* theInfo = inSession->GetSourceInfo(); //Assert(theInfo); // //if (theInfo->IsRTSPControlled()) //{ // FileDeleter(inSession->GetSourcePath()); //} // //if (killClients || 1) //{ inSession->TearDownAllOutputs(); //} } //qtss_printf("QTSSReflectorModule.cpp:RemoveOutput refcount =%lu\n", inSession->GetRef()->GetRefCount()); //check if the ReflectorSession should be deleted //(it should if its ref count has dropped to 0) OSMutexLocker locker (sSessionMap->GetMutex()); OSRef* theSessionRef = inSession->GetRef(); if (theSessionRef != NULL) { if (theSessionRef->GetRefCount() == 0) { RTSPRelaySession* proxySession = (RTSPRelaySession*)inSession->GetRTSPRelaySession(); if(proxySession != NULL) { proxySession->SetReflectorSession(NULL); sClientSessionMap->UnRegister(proxySession->GetRef()); proxySession->Signal(Task::kKillEvent); } inSession->SetRTSPRelaySession(NULL); sSessionMap->UnRegister(theSessionRef); delete inSession; } //else if (theSessionRef->GetRefCount() == 1) //{ // //qtss_printf("QTSSReflector.cpp:RemoveOutput Delete SESSION=%lu\n",(UInt32)inSession); // RTSPRelaySession* proxySession = (RTSPRelaySession*)inSession->GetRelaySession(); // if(proxySession != NULL) // { // proxySession->SetReflectorSession(NULL); // sClientSessionMap->UnRegister(proxySession->GetRef()); // proxySession->Signal(Task::kKillEvent); // } // inSession->SetRelaySession(NULL); // sSessionMap->UnRegister(theSessionRef); // delete inSession; //} else { qtss_printf("QTSSReflector.cpp:RemoveOutput Release SESSION=%lu RefCount=%d\n",(UInt64)inSession,theSessionRef->GetRefCount()); sSessionMap->Release(theSessionRef); // one of the sessions on the ref is ending just decrement the count } } } delete inOutput; }
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); //从接口获取信息结构体 //TODO: DeviceInfo* pDeviceInfo = parseDevice->GetDeviceInfoByIdName(theUriStr); if(pDeviceInfo == NULL) { qtss_printf("ID:%s Not Found\n",theUriStr); return QTSS_RequestFailed; } //信息存在rtsp://59.46.115.84:8554/h264/ch1/sub/av_stream RTSPRelaySession* clientSes = NULL; //首先查找Map里面是否已经有了对应的流 StrPtrLen streamName(theUriStr); OSRef* clientSesRef = sClientSessionMap->Resolve(&streamName); if(clientSesRef != NULL) { clientSes = (RTSPRelaySession*)clientSesRef->GetObject(); } else { clientSes = NEW RTSPRelaySession( 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); OS_Error theErr = clientSes->SendDescribe(); if(theErr == QTSS_NoErr) { OS_Error theErr = sClientSessionMap->Register(clientSes->GetRef()); Assert(theErr == QTSS_NoErr); } else { clientSes->Signal(Task::kKillEvent); return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientNotFound, 0); } //增加一次对RelaySession的无效引用,后面会统一释放 OSRef* debug = sClientSessionMap->Resolve(&streamName); Assert(debug == clientSes->GetRef()); } ReflectorSession* theSession = SetupProxySession(inParams, clientSes); if (theSession == NULL) { sClientSessionMap->Release(clientSes->GetRef()); return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssServerNotImplemented, 0); } QTSS_Error Err = QTSS_SetValue(inParams->inRTSPSession, sRTSPBroadcastSessionAttr, 0, &theSession, sizeof(theSession)); Assert(Err == QTSS_NoErr); clientSes->SetReflectorSession(theSession); theSession->SetRTSPRelaySession((void*)clientSes); sClientSessionMap->Release(clientSes->GetRef()); iovec theDescribeVec[3] = { {0 }}; Assert(theSession->GetLocalSDP()->Ptr != NULL); StrPtrLen theFileData; QTSS_TimeVal outModDate = 0; QTSS_TimeVal inModDate = -1; theFileData.Ptr = theSession->GetLocalSDP()->Ptr; theFileData.Len = theSession->GetLocalSDP()->Len; // -------------- process SDP to remove connection info and add track IDs, port info, and default c= line StrPtrLen theSDPData; SDPSourceInfo tempSDPSourceInfo(theFileData.Ptr, theFileData.Len); // will make a copy and delete in destructor theSDPData.Ptr = tempSDPSourceInfo.GetLocalSDP(&theSDPData.Len); // returns a new buffer with processed sdp OSCharArrayDeleter sdpDeleter(theSDPData.Ptr); // delete the temp sdp source info buffer returned by GetLocalSDP if (theSDPData.Len <= 0) // can't find it on disk or it failed to parse just use the one in the session. { theSDPData.Ptr = theSession->GetLocalSDP()->Ptr; // this sdp isn't ours it must not be deleted theSDPData.Len = theSession->GetLocalSDP()->Len; } // ------------ Clean up missing required SDP lines ResizeableStringFormatter editedSDP(NULL,0); DoDescribeAddRequiredSDPLines2(inParams, theSession, outModDate, &editedSDP, &theSDPData); StrPtrLen editedSDPSPL(editedSDP.GetBufPtr(),editedSDP.GetBytesWritten()); // ------------ Check the headers SDPContainer checkedSDPContainer; checkedSDPContainer.SetSDPBuffer( &editedSDPSPL ); if (!checkedSDPContainer.IsSDPBufferValid()) { return QTSSModuleUtils::SendErrorResponseWithMessage(inParams->inRTSPRequest, qtssUnsupportedMediaType, &sSDPNotValidMessage); } // ------------ Put SDP header lines in correct order Float32 adjustMediaBandwidthPercent = 1.0; Bool16 adjustMediaBandwidth = false; SDPLineSorter sortedSDP(&checkedSDPContainer,adjustMediaBandwidthPercent); // ------------ Write the SDP UInt32 sessLen = sortedSDP.GetSessionHeaders()->Len; UInt32 mediaLen = sortedSDP.GetMediaHeaders()->Len; theDescribeVec[1].iov_base = sortedSDP.GetSessionHeaders()->Ptr; theDescribeVec[1].iov_len = sortedSDP.GetSessionHeaders()->Len; theDescribeVec[2].iov_base = sortedSDP.GetMediaHeaders()->Ptr; theDescribeVec[2].iov_len = sortedSDP.GetMediaHeaders()->Len; (void)QTSS_AppendRTSPHeader(inParams->inRTSPRequest, qtssCacheControlHeader, kCacheControlHeader.Ptr, kCacheControlHeader.Len); QTSSModuleUtils::SendDescribeResponse(inParams->inRTSPRequest, inParams->inClientSession, &theDescribeVec[0], 3, sessLen + mediaLen ); return QTSS_NoErr; }