客户端使用RTP over RTSP方式推流(annouce-->setup-->play)给DSS 服务器进行流转发流程如下:
1. 当有RTSP请求消息到来时,相应的RTSPSession会被加入的TaskThread线程队列中等待执行,接着RTSPSession::Run()会被调用。
在RTSPSession::Run()状态机跳转中kReadingRequest状态时会调用RTSPRequestStream::ReadRequest()读取客户端发送来的数据。
数据读取完毕后 在kFilteringRequest状态时会判断接收的数据是否为RTP数据包,如果是RTP包则调用HandleIncomingDataPacket()进行处理
2.RTSPRequestStream::ReadRequest()读取客户端发送来的数据时,如果数据的第一个字节为$,后面的内容就作为RTP包数据读取。
3.RTSPSession::HandleIncomingDataPacket()首先调用RTPStream::ProcessIncomingInterleavedData解析RTP流数据;
然后将解析后的RTP包转发给注册了QTSS_RTSPIncomingData_Role角色的处理模块,QTSSReflectorModule注册了QTSS_RTSPIncomingData_Role并实现了相应的处理函数ProcessRTPData。当客户端使用RTSP方式推流(annouce-->setup-->play)给DSS 服务器进行流转发时就走的这个流程。
4.RTPStream::ProcessIncomingInterleavedData调用ProcessIncomingRTCPPacket只解析到来的是RTCP类型的数据包
5.QTSSReflectorModule调用ProcessRTPData处理接收到的RTP包。
QTSS_Error QTSSReflectorModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams)
{
switch (inRole)
{
case QTSS_Register_Role:
return Register(&inParams->regParams);
case QTSS_Initialize_Role:
return Initialize(&inParams->initParams);
case QTSS_RereadPrefs_Role:
return RereadPrefs();
case QTSS_RTSPRoute_Role:
return RedirectBroadcast(&inParams->rtspRouteParams);
case QTSS_RTSPPreProcessor_Role:
return ProcessRTSPRequest(&inParams->rtspRequestParams);
case QTSS_RTSPIncomingData_Role:
return ProcessRTPData(&inParams->rtspIncomingDataParams);
case QTSS_ClientSessionClosing_Role:
return DestroySession(&inParams->clientSessionClosingParams);
case QTSS_Shutdown_Role:
return Shutdown();
case QTSS_RTSPAuthorize_Role:
return ReflectorAuthorizeRTSPRequest(&inParams->rtspRequestParams);
case QTSS_Interval_Role:
return IntervalRole();
}
return QTSS_NoErr;
}
ProcessRTPData实现如下,通过PacketChannel对应的index在ReflectorSession取出相应的ReflectorStream,接着调用ReflectorStream::PushPacket将RTP放入到转发队列中去。
QTSS_Error ProcessRTPData(QTSS_IncomingData_Params* inParams)
{
......
UInt32 inIndex = packetChannel / 2; // one stream per every 2 channels rtcp channel handled below
if (inIndex < numStreams)
{
ReflectorStream* theStream = theSession->GetStreamByIndex(inIndex);
if (theStream == NULL) return QTSS_Unimplemented;
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);
//qtss_printf("QTSSReflectorModule.cpp:ProcessRTPData Send RTSP packet channel=%u to UDP localServerAddr=%" _U32BITARG_ " serverReceivePort=%" _U32BITARG_ " packetDataLen=%u \n", (UInt16) packetChannel, localServerAddr, serverReceivePort,packetDataLen);
}
}
......
}
6.
ReflectorStream::
PushPacket实现如下,ReflectorStream类中的成员变量fSocket是UDPSocketPair的实例,包含两个ReflectorSocket类型的成员变量,SocketA用来转发RTP包,SocketB用来转发RTCP包,调用ReflectorSocket::ProcessPacket会将包加入到发送队列里。
void ReflectorStream::PushPacket(char *packet, UInt32 packetLen, Bool16 isRTCP)
{
FU_Head *head = (FU_Head*)&packet[13];
if (packetLen > 0)
{
ReflectorPacket* thePacket = NULL;
if (isRTCP)
{
//qtss_printf("ReflectorStream::PushPacket RTCP packetlen = %" _U32BITARG_ "\n",packetLen);
thePacket = ((ReflectorSocket*)fSockets->GetSocketB())->GetPacket();
if (thePacket == NULL)
{
//qtss_printf("ReflectorStream::PushPacket RTCP GetPacket() is NULL\n");
return;
}
OSMutexLocker locker(((ReflectorSocket*)(fSockets->GetSocketB()))->GetDemuxer()->GetMutex());
thePacket->SetPacketData(packet, packetLen);
((ReflectorSocket*)fSockets->GetSocketB())->ProcessPacket(OS::Milliseconds(), thePacket, 0, 0);
((ReflectorSocket*)fSockets->GetSocketB())->Signal(Task::kIdleEvent);
}
else
{
//qtss_printf("ReflectorStream::PushPacket RTP packetlen = %" _U32BITARG_ "\n",packetLen);
thePacket = ((ReflectorSocket*)fSockets->GetSocketA())->GetPacket();
if (thePacket == NULL)
{
//qtss_printf("ReflectorStream::PushPacket GetPacket() is NULL\n");
return;
}
OSMutexLocker locker(((ReflectorSocket*)(fSockets->GetSocketA()))->GetDemuxer()->GetMutex());
thePacket->SetPacketData(packet, packetLen);
//if(this->fStreamInfo.fPayloadName.Equal("H264/90000"))
//{
// if(head->nalu_type != 0)
// {
// pkeyFrameCache->PutOnePacket(packet,packetLen,head->nalu_type,head->s);
// }
//}
((ReflectorSocket*)fSockets->GetSocketA())->ProcessPacket(OS::Milliseconds(), thePacket, 0, 0);
((ReflectorSocket*)fSockets->GetSocketA())->Signal(Task::kIdleEvent);
}
}
}
ReflectorSocket::ProcessPacket可以看出一个ReflectorSocket有一个ReflectorSender对应与其对应。最终数据包会被放入ReflectorSender的fPacketQueue队列里。
Bool16 ReflectorSocket::ProcessPacket(const SInt64& inMilliseconds, ReflectorPacket* thePacket, UInt32 theRemoteAddr, UInt16 theRemotePort)
{
......
// Find the appropriate ReflectorSender for this packet.
ReflectorSender* theSender = (ReflectorSender*)this->GetDemuxer()->GetTask(theRemoteAddr, 0);
// If there is a generic sender for this socket, use it.
if (theSender == NULL)
theSender = (ReflectorSender*)this->GetDemuxer()->GetTask(0, 0);
......
thePacket->fStreamCountID = ++(theSender->fStream->fPacketCount);
thePacket->fBucketsSeenThisPacket = 0;
thePacket->fTimeArrived = inMilliseconds;
theSender->fPacketQueue.EnQueue(&thePacket->fQueueElem);
......
}
SInt64 ReflectorSocket::Run()
{
//We want to make sure we can't get idle events WHILE we are inside
//this function. That will cause us to run the queues unnecessarily
//and just get all confused.
this->CancelTimeout();
Task::EventFlags theEvents = this->GetEvents();
//if we have been told to delete ourselves, do so.
if (theEvents & Task::kKillEvent)
return -1;
OSMutexLocker locker(this->GetDemuxer()->GetMutex());
SInt64 theMilliseconds = OS::Milliseconds();
//Only check for data on the socket if we've actually been notified to that effect
if (theEvents & Task::kReadEvent)
this->GetIncomingData(theMilliseconds);
#if DEBUG
//make sure that we haven't gotten here prematurely! This wouldn't mess
//anything up, but it would waste CPU.
if (theEvents & Task::kIdleEvent)
{
SInt32 temp = (SInt32)(fSleepTime - theMilliseconds);
char tempBuf[20];
qtss_sprintf(tempBuf, "%" _S32BITARG_ "", temp);
WarnV(fSleepTime <= theMilliseconds, tempBuf);
}
#endif
fSleepTime = 0;
//Now that we've gotten all available packets, have the streams reflect
for (OSQueueIter iter2(&fSenderQueue); !iter2.IsDone(); iter2.Next())
{
ReflectorSender* theSender2 = (ReflectorSender*)iter2.GetCurrent()->GetEnclosingObject();
if (theSender2 != NULL && theSender2->ShouldReflectNow(theMilliseconds, &fSleepTime))
theSender2->ReflectPackets(&fSleepTime, &fFreeQueue);
}
#if DEBUG
theMilliseconds = OS::Milliseconds();
#endif
//For smoothing purposes, the streams can mark when they want to wakeup.
if (fSleepTime > 0)
this->SetIdleTimer(fSleepTime);
#if DEBUG
//The debugging check above expects real time.
fSleepTime += theMilliseconds;
#endif
return 0;
}
在 ReflectorSocket::Run中会调用ReflectorSocket::ReflectPackets将可用的包转发,首先通过ReflectorStream找出ReflectorOutput对象,接着调用SendPacketsToOutput实现代码如下:
void ReflectorSender::ReflectPackets(SInt64* ioWakeupTime, OSQueue* inFreeQueue)
{
......
ReflectorOutput* theOutput = fStream->fOutputArray[bucketIndex][bucketMemberIndex];
if (theOutput != NULL)
{
if (false == theOutput->IsPlaying())
continue;
{
OSMutexLocker locker(&theOutput->fMutex);
OSQueueElem* packetElem = theOutput->GetBookMarkedPacket(&fPacketQueue);
if (packetElem == NULL) // should only be a new output
{
packetElem = fFirstPacketInQueueForNewOutput; // everybody starts at the oldest packet in the buffer delay or uses a bookmark
firstPacket = true;
theOutput->setNewFlag(false);
}
SInt64 bucketDelay = ReflectorStream::sBucketDelayInMsec * (SInt64)bucketIndex;
packetElem = this->SendPacketsToOutput(theOutput, packetElem, currentTime, bucketDelay, firstPacket);
if (packetElem)
{
OSQueueElem* newElem = NeedRelocateBookMark(packetElem);
ReflectorPacket* thePacket = (ReflectorPacket*)newElem->GetEnclosingObject();
thePacket->fNeededByOutput = true; // flag to prevent removal in RemoveOldPackets
(void)theOutput->SetBookMarkPacket(newElem); // store a reference to the packet
}
}
}
......
}
SendPacketsToOutput中接着调用ReflectorOutput::ReflectorOutput,由于该函数为纯虚函数,实际要调用的是RTPSessionOutput的ReflectorOutput
QTSS_Error RTPSessionOutput::WritePacket(StrPtrLen* inPacket, void* inStreamCookie, UInt32 inFlags, SInt64 packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr, Bool16 firstPacket)
{
......
//make sure all RTP streams with this ID see this packet
QTSS_RTPStreamObject *theStreamPtr = NULL;
for (UInt32 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&theStreamPtr, &theLen) == QTSS_NoErr; z++)
{
if (this->PacketMatchesStream(inStreamCookie, theStreamPtr))
{
......
writeErr = QTSS_Write(*theStreamPtr, &thePacket, inPacket->Len, NULL, inFlags | qtssWriteFlagsWriteBurstBegin);
......
}
......
}
RTPSessionOutput::
ReflectorOutput会获取请求该转发流的所有客户端对应的RTPStream,并通过调用QTSS_Write,该函数最终会调用RTPStream::write发送数据给请求的客户端。
RTPSessionOutput对象是在QTSSReflectorModule处理客户端 Setup请求建立的,并被加入到ReflectorSession。
ReflectorSession::AddOutput实际上调用ReflectorStream::AddOutput将RTPSessionOutput保存在fOutputArray中。
ReflectorSession,ReflectorStream是在推流端 Setup的时候建立的。详细请参照下面的链接
QTSSReflectorModule的Announce消息处理
QTSSReflectorModule的Describe消息处理
转载: http://blog.csdn.net/longlong530/article/details/43564747QTSSReflectorModule的Setup消息处理
转载: http://blog.csdn.net/longlong530/article/details/43667533