ProxyDemuxerTask* ProxyClientInfo::AddStream(QTSS_RTPStreamObject inStream) { // // Allocate some UDP sockets out of our pool to receive the UDP data from // the server. Demuxing is based on the origin server's (host's) IP addr, so // pass that to the socket pool so it can properly allocate a pair of UDP sockets. // We don't know what the remote port is yet (we only find out when we get the // SETUP response from the origin), so just pass in 0. UInt32 theHostAddr = fClient.GetSocket()->GetHostAddr(); UInt32 theLocalAddr = fClient.GetSocket()->GetLocalAddr(); UDPSocketPair* thePair = sSocketPool->GetUDPSocketPair(theLocalAddr, 0, theHostAddr, 0); fLastDemuxerTask = NEW ProxyDemuxerTask(inStream, thePair); fDemuxerTaskQueue.EnQueue(fLastDemuxerTask->GetQueueElem()); // // Tell the demuxers for these sockets to send any packets from this IP addr // to the ProxyDemuxerTask for this stream. This is how incoming UDP packets // will be routed to the proper QTSS_RTPStreamObject thePair->GetSocketA()->GetDemuxer()->RegisterTask(theHostAddr, 0, fLastDemuxerTask); thePair->GetSocketB()->GetDemuxer()->RegisterTask(theHostAddr, 0, fLastDemuxerTask); // // return the newly created ProxyDemuxerTask return fLastDemuxerTask; }
SInt64 ProxyTask::Run() { const UInt32 kMaxRTCPPacketSize = 2048; char thePacketBuffer[kMaxRTCPPacketSize]; QTSS_PacketStruct thePacketStruct; thePacketStruct.packetTransmitTime = QTSS_Milliseconds(); thePacketStruct.packetData = thePacketBuffer; (void)this->GetEvents(); OSMutexLocker locker(sSocketPool->GetMutex()); for (OSQueueIter iter(sSocketPool->GetSocketQueue()); !iter.IsDone(); iter.Next()) { UInt32 theRemoteAddr = 0; UInt16 theRemotePort = 0; UDPSocketPair* thePair = (UDPSocketPair*)iter.GetCurrent()->GetEnclosingObject(); Assert(thePair != NULL); for (UInt32 x = 0; x < 2; x++) { QTSS_WriteFlags theFlags = qtssWriteFlagsNoFlags; UDPSocket* theSocket = NULL; if (x == 0) { theFlags = qtssWriteFlagsIsRTP; theSocket = thePair->GetSocketA(); } else { theFlags = qtssWriteFlagsIsRTCP; theSocket = thePair->GetSocketB(); } Assert(theSocket->GetDemuxer() != NULL); OSMutexLocker locker(theSocket->GetDemuxer()->GetMutex()); //get all the outstanding packets for this socket while (true) { UInt32 thePacketLen = 0; theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacketStruct.packetData, kMaxRTCPPacketSize, &thePacketLen); if (thePacketLen == 0) break;//no more packets on this socket! ProxyDemuxerTask* theDemuxerTask = (ProxyDemuxerTask*)theSocket->GetDemuxer()->GetTask(theRemoteAddr, 0); if (theDemuxerTask != NULL) { QTSS_RTPStreamObject theStream = theDemuxerTask->GetStream(); (void)QTSS_Write(theStream, &thePacketStruct, thePacketLen, NULL, theFlags); } } } } return kProxyTaskPollIntervalMsec; }
ProxyClientInfo::~ProxyClientInfo() { UInt32 theHostAddr = fClient.GetSocket()->GetHostAddr(); for (OSQueueIter iter(&fDemuxerTaskQueue); !iter.IsDone(); ) { OSQueueElem* theElem = iter.GetCurrent(); ProxyDemuxerTask* theTask = (ProxyDemuxerTask*)theElem->GetEnclosingObject(); // // Move onto the next element becase we are going to be deleting this one iter.Next(); theElem->Remove(); // Get off the queue before deleting // // Clean up UDPSocketPair* thePair = theTask->GetSockets(); thePair->GetSocketA()->GetDemuxer()->UnregisterTask(theHostAddr, 0, theTask); thePair->GetSocketB()->GetDemuxer()->UnregisterTask(theHostAddr, 0, theTask); delete theTask; sSocketPool->ReleaseUDPSocketPair(thePair); } }
int QTFileBroadcaster::SetUp(PLBroadcastDef *broadcastDefPtr, bool *quitImmediatePtr) { int result = -1; int numStreams = 0; fQuitImmediatePtr = quitImmediatePtr; PlayListUtils::Initialize(); do { if (! broadcastDefPtr) { result = eParam; break; }; if (!broadcastDefPtr->mSDPFile || 0 == broadcastDefPtr->mSDPFile[0] ) { result = eSDPFileInvalidName; break; }; int nameLen = strlen(broadcastDefPtr->mSDPFile); if (nameLen > 255) { result = eSDPFileInvalidName; break; }; if (0 == nameLen) { result = eSDPFileInvalidName; break; }; if (broadcastDefPtr->mTheSession) { if (!broadcastDefPtr->mDestSDPFile) { result = eNetworkSDPFileNameInvalidMissing; break; }; if (!broadcastDefPtr->mDestSDPFile[0]) { result = eNetworkSDPFileNameInvalidMissing; break; }; if (!::strcmp(broadcastDefPtr->mDestSDPFile, "no_name")) { result = eNetworkSDPFileNameInvalidMissing; break; }; // if ('/' == broadcastDefPtr->mDestSDPFile[0]) // { result = eNetworkSDPFileNameInvalidBadPath; break; }; } result = fStreamSDPParser.ReadSDP(broadcastDefPtr->mSDPFile); if (result != 0) { if (result < 0) { result = eSDPFileNotFound; break; }; if (result > 0) { result = eSDPFileInvalid; break; }; } fBroadcastDefPtr = broadcastDefPtr; if (broadcastDefPtr->mTheSession == NULL) { if (!broadcastDefPtr->mBasePort) { result = eSDPFileNoPorts; break; }; int portLen = strlen(broadcastDefPtr->mBasePort); if (0 == portLen) { result = eDescriptionInvalidDestPort; break; }; if (portLen > 5 ) { result = eDescriptionInvalidDestPort; break; }; int basePort = atoi(broadcastDefPtr->mBasePort); if ( basePort > 65531 ) { result = eDescriptionInvalidDestPort; break; }; if ( basePort < 5004 ) { result = eDescriptionInvalidDestPort; break; }; } numStreams = fStreamSDPParser.GetNumTracks(); if (numStreams == 0) { result = eSDPFileNoMedia; break; }; UDPSocketPair *socketArrayPtr = fSocketlist.SetSize(numStreams); if (socketArrayPtr == NULL) { result = eMem; break; }; // Bind SDP file defined ports to active stream ports { UInt16 streamIndex = 0; UInt16 rtpPort = 0; UInt16 rtcpPort = 0; TypeMap* mediaTypePtr; char sdpIPAddress[32]; SimpleString* ipStringPtr = fStreamSDPParser.GetIPString(); if ( (NULL == ipStringPtr) || (ipStringPtr->fLen >= 32) ) { result = eSDPFileInvalid; break; } memcpy(sdpIPAddress,ipStringPtr->fTheString,ipStringPtr->fLen); sdpIPAddress[ipStringPtr->fLen] = '\0'; UDPSocketPair *aSocketPair = fSocketlist.Begin(); Bool16 setupUDP = true; while (aSocketPair != NULL) { mediaTypePtr = fStreamSDPParser.fSDPMediaList.SetPos(streamIndex); if (mediaTypePtr == NULL) { result = eSDPFileInvalid; break; } if (broadcastDefPtr->mTheSession != NULL) { mediaTypePtr->fPort = broadcastDefPtr->mTheSession->GetStreamDestPort(streamIndex); //qtss_printf("QTFileBroadcaster::SetUp streamIndex=%u port=%d\n",streamIndex,mediaTypePtr->fPort); if (BroadcasterSession::kTCPTransportType == broadcastDefPtr->mTheSession->GetTransportType()) { aSocketPair->SetRTSPSession(broadcastDefPtr->mTheSession, (UInt8) streamIndex * 2); setupUDP = false; } else { setupUDP = true; } } if (setupUDP) { SInt16 ttl = (SInt16) atoi(broadcastDefPtr->mTTL); if ( ( ttl > 255 ) || ( ttl < 1 ) ) { result = eSDPFileInvalidTTL; break; }; if (mediaTypePtr->fPort == 0) { result = eSDPFileInvalidPort; break; } rtpPort = mediaTypePtr->fPort; rtcpPort = rtpPort + 1; result = aSocketPair->OpenAndBind(rtpPort,rtcpPort,sdpIPAddress); if (result != 0) { result = eFailedBind; break; } (void) aSocketPair->SetMultiCastOptions(ttl); } aSocketPair = fSocketlist.Next(); streamIndex++; } if (result != 0) break; } MediaStream *mediaArrayPtr = fMediaStreamList.SetSize(numStreams); if (mediaArrayPtr == NULL) { result = eMem; break; } for (int i = 0; i < numStreams; i ++) { UDPSocketPair *socketPairPtr = fSocketlist.SetPos(i); MediaStream *mediaStreamPtr = fMediaStreamList.SetPos(i); TypeMap *streamMediaTypePtr = fStreamSDPParser.fSDPMediaList.SetPos(i); if (socketPairPtr && mediaStreamPtr && streamMediaTypePtr) { mediaStreamPtr->fData.fSocketPair = socketPairPtr; streamMediaTypePtr->fMediaStreamPtr = mediaStreamPtr; mediaStreamPtr->fData.fStreamMediaTypePtr = streamMediaTypePtr; } else { result = eMem; break; } } fMediaStreamList.SetUpStreamSSRCs(); fStreamStartTime = PlayListUtils::Milliseconds(); fMediaStreamList.StreamStarted(fStreamStartTime); result = 0; LogFileOpen(); } while (false); return result; }
SInt64 RTCPTask::Run() { const UInt32 kMaxRTCPPacketSize = 2048; char thePacketBuffer[kMaxRTCPPacketSize]; StrPtrLen thePacket(thePacketBuffer, 0); QTSServerInterface* theServer = QTSServerInterface::GetServer(); //This task goes through all the UDPSockets in the RTPSocketPool, checking to see //if they have data. If they do, it demuxes the packets and sends the packet onto //the proper RTP session. EventFlags events = this->GetEvents(); // get and clear events if ( (events & Task::kReadEvent) || (events & Task::kIdleEvent) ) { //Must be done atomically wrt the socket pool. OSMutexLocker locker(theServer->GetSocketPool()->GetMutex()); for (OSQueueIter iter(theServer->GetSocketPool()->GetSocketQueue()); !iter.IsDone(); iter.Next()) { UInt32 theRemoteAddr = 0; UInt16 theRemotePort = 0; UDPSocketPair* thePair = (UDPSocketPair*)iter.GetCurrent()->GetEnclosingObject(); Assert(thePair != NULL); for (UInt32 x = 0; x < 2; x++) { UDPSocket* theSocket = NULL; if (x == 0) theSocket = thePair->GetSocketA(); else theSocket = thePair->GetSocketB(); UDPDemuxer* theDemuxer = theSocket->GetDemuxer(); if (theDemuxer == NULL) continue; else { theDemuxer->GetMutex()->Lock(); while (true) //get all the outstanding packets for this socket { thePacket.Len = 0; theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacket.Ptr, kMaxRTCPPacketSize, &thePacket.Len); if (thePacket.Len == 0) { theSocket->RequestEvent(EV_RE); break;//no more packets on this socket! } //if this socket has a demuxer, find the target RTPStream if (theDemuxer != NULL) { RTPStream* theStream = (RTPStream*)theDemuxer->GetTask(theRemoteAddr, theRemotePort); if (theStream != NULL) theStream->ProcessIncomingRTCPPacket(&thePacket); } } theDemuxer->GetMutex()->Unlock(); } } } } return 0; /* Fix for 4004432 */ /* SInt64 result = 0; if (theServer->GetNumRTPSessions() > 0) result = theServer->GetPrefs()->GetRTCPPollIntervalInMsec(); return result; */ }