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;
}