/* 设置好各种参数后发信号开始触发RTPSession和发送SR包.播放影片,下面是设置步骤:(1)记录并设置相应的播放时间;(2)设置播放状态,播放标志,更新播放的RTPSession总数;
(3)根据电影的平均比特率设置Client Windows size,重置过缓冲窗;(4)遍历RTPSession中的每个RTPStream,设置打薄参数,重置打薄延迟参数,清除上个Play中重传类的RTP包;(5)假如获得的movie
平均比特率>0,就灵活调整TCP RTSP Socket缓存大小以适应movie比特率,且介于预设的最大值和最小值之间;(6)发信号启动该RTP Session任务; */
QTSS_Error  RTPSession::Play(RTSPRequestInterface* request, QTSS_PlayFlags inFlags)
{
    //first setup the play associated session interface variables
    Assert(request != NULL);
	/* 假如没有Module数组,立即返回 */
    if (fModule == NULL)
        return QTSS_RequestFailed;//Can't play if there are no associated streams
    
    //what time is this play being issued(触发) at? 记录Play触发的时刻
	fLastBitRateUpdateTime = fNextSendPacketsTime = fPlayTime = OS::Milliseconds();
	/* 假如是第一次播放,同步当前播放时间 */
    if (fIsFirstPlay)
		fFirstPlayTime = fPlayTime;
	/* 获取当前播放时间戳和RTSP Request Header Range中的fStartTime的差值 */
    fAdjustedPlayTime = fPlayTime - ((SInt64)(request->GetStartTime() * 1000));
    //for RTCP SRs(RTCP发送方报告), we also need to store the play time in NTP
    fNTPPlayTime = OS::TimeMilli_To_1900Fixed64Secs(fPlayTime);
    
    //we are definitely playing now, so schedule(调度) the object!
    fState = qtssPlayingState;
    fIsFirstPlay = false;/* 现在不是第一次播放 */
    fPlayFlags = inFlags;/* 是生成SR包还是AppendServerInfo进SR包 */

	/* track how many sessions are playing,see QTSServerInterface.h,使fNumRTPPlayingSessions加1 */
    QTSServerInterface::GetServer()-> AlterRTPPlayingSessions(1);
    
	/* set Client window size according to bitrate,,参见RTPBandwidthTracker::SetWindowSize() */
	//根据电影的平均比特率设置Client Windows size
    UInt32 theWindowSize;
	/* 获取电影的平均比特率 */
    UInt32 bitRate = this->GetMovieAvgBitrate();
	/* 假如电影的平均比特率为0或超过1Mbps,就设置Windowsize 为64Kbytes */
	if ((bitRate == 0) || (bitRate > QTSServerInterface::GetServer()->GetPrefs()->GetWindowSizeMaxThreshold() * 1024))
        theWindowSize = 1024 * QTSServerInterface::GetServer()->GetPrefs()->GetLargeWindowSizeInK();
	/* 假如电影的平均比特率超过200kbps,就设置Windowsize 为48Kbytes */
	else if (bitRate > QTSServerInterface::GetServer()->GetPrefs()->GetWindowSizeThreshold() * 1024)
		theWindowSize = 1024 * QTSServerInterface::GetServer()->GetPrefs()->GetMediumWindowSizeInK();
	/* 否则,,就设置Windowsize 为24Kbytes */
    else
        theWindowSize = 1024 * QTSServerInterface::GetServer()->GetPrefs()->GetSmallWindowSizeInK();

    qtss_printf("bitrate = %d, window size = %d\n", bitRate, theWindowSize);

	/* 设置Client窗口大小,参见RTPBandwidthTracker::SetWindowSize() */
    this->GetBandwidthTracker()->SetWindowSize(theWindowSize);

	/* 重置过缓冲窗 */
	this->GetOverbufferWindow()->ResetOverBufferWindow();

    // Go through all the streams, setting their thinning params
    RTPStream** theStream = NULL;
    UInt32 theLen = 0;
    
	/* 遍历RTPSession中的每个RTPStream,设置打薄参数,重置打薄延迟参数,清除上个Play中重传类的RTP包 */
    for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++)
    {
        Assert(theStream != NULL);
        Assert(theLen == sizeof(RTPStream*));
        if (*theStream != NULL)
        {   /* 设置打薄参数 */
            (*theStream)->SetThinningParams();
 			(*theStream)->ResetThinningDelayParams();
            
            // If we are using reliable UDP, then make sure to clear all the packets from the previous play spurt out of the resender 
            (*theStream)->GetResender()->ClearOutstandingPackets();
        }
    }

    qtss_printf("movie bitrate = %d, window size = %d\n", this->GetMovieAvgBitrate(), theWindowSize);
    Assert(this->GetBandwidthTracker()->BytesInList() == 0);
    
    // Set the size of the RTSPSession's send buffer to an appropriate max size
    // based on the bitrate of the movie. This has 2 benefits:
    // 1) Each socket normally defaults to 32 K. A smaller buffer prevents the
    // system from getting buffer starved if lots of clients get flow-controlled
    //
    // 2) We may need to scale up buffer sizes for high-bandwidth movies in order
    // to maximize thruput, and we may need to scale down buffer sizes for low-bandwidth
    // movies to prevent us from buffering lots of data that the client can't use
    //
    // If we don't know any better, assume maximum buffer size.

	/* 获取服务器预设值来得到最大TCP缓冲区大小 */
    QTSServerPrefs* thePrefs = QTSServerInterface::GetServer()->GetPrefs();
    UInt32 theBufferSize = thePrefs->GetMaxTCPBufferSizeInBytes();
    
#if RTPSESSION_DEBUGGING
    qtss_printf("RTPSession GetMovieAvgBitrate %li\n",(SInt32)this->GetMovieAvgBitrate() );
#endif

	/* 假如获得的movie平均比特率>0,就灵活调整TCP Socket缓存大小以适应movie比特率,且介于预设的最大值和最小值之间 */
    if (this->GetMovieAvgBitrate() > 0)
    {
        // We have a bit rate... use it.
		/* 由电影比特率和预设的缓存秒数(0.5s),得到实际的缓存大小(字节) */
        Float32 realBufferSize = (Float32)this->GetMovieAvgBitrate() * thePrefs->GetTCPSecondsToBuffer();
        theBufferSize = (UInt32)realBufferSize;
        theBufferSize >>= 3; // Divide by 8 to convert from bits to bytes
        
        // Round down to the next lowest power of 2.
		/* 四舍五入到最接近的小于它的2的幂,该函数定义见下面 */
		/* 将入参变为2的幂的特殊算法:先将入参表示为十六进制,从第29bit位开始从高到底开始走,若遇到值为1的bit位,就返回该bit位值为1,其它31个bit位值全为0的数;若一直没有1,返回0 */
        theBufferSize = this->PowerOf2Floor(theBufferSize);
        
		//下面对缓存大小进行保护,使真实值务必介于预设的最大值和最小值之间

        // This is how much data we should buffer based on the scaling factor... if it is lower than the min, raise to min
        if (theBufferSize < thePrefs->GetMinTCPBufferSizeInBytes())
            theBufferSize = thePrefs->GetMinTCPBufferSizeInBytes();
            
        // Same deal for max buffer size
        if (theBufferSize > thePrefs->GetMaxTCPBufferSizeInBytes())
            theBufferSize = thePrefs->GetMaxTCPBufferSizeInBytes();
    }
QTSS_Error  RTPSession::Play(RTSPRequestInterface* request, QTSS_PlayFlags inFlags)
{
    //first setup the play associated session interface variables
    Assert(request != NULL);
    if (fModule == NULL)
        return QTSS_RequestFailed;//Can't play if there are no associated streams
    
    //what time is this play being issued at?
	fLastBitRateUpdateTime = fNextSendPacketsTime = fPlayTime = OS::Milliseconds();
    if (fIsFirstPlay)
		fFirstPlayTime = fPlayTime;
    fAdjustedPlayTime = fPlayTime - ((SInt64)(request->GetStartTime() * 1000));

    //for RTCP SRs, we also need to store the play time in NTP
    fNTPPlayTime = OS::TimeMilli_To_1900Fixed64Secs(fPlayTime);
    
    //we are definitely playing now, so schedule the object!
    fState = qtssPlayingState;
    fIsFirstPlay = false;
    fPlayFlags = inFlags;
    QTSServerInterface::GetServer()-> AlterRTPPlayingSessions(1);
    
    UInt32 theWindowSize;
    UInt32 bitRate = this->GetMovieAvgBitrate();
	if ((bitRate == 0) || (bitRate > QTSServerInterface::GetServer()->GetPrefs()->GetWindowSizeMaxThreshold() * 1024))
        theWindowSize = 1024 * QTSServerInterface::GetServer()->GetPrefs()->GetLargeWindowSizeInK();
	else if (bitRate > QTSServerInterface::GetServer()->GetPrefs()->GetWindowSizeThreshold() * 1024)
		theWindowSize = 1024 * QTSServerInterface::GetServer()->GetPrefs()->GetMediumWindowSizeInK();		
    else
        theWindowSize = 1024 * QTSServerInterface::GetServer()->GetPrefs()->GetSmallWindowSizeInK();

//  qtss_printf("bitrate = %d, window size = %d\n", bitRate, theWindowSize);
    this->GetBandwidthTracker()->SetWindowSize(theWindowSize);
	this->GetOverbufferWindow()->ResetOverBufferWindow();

    //
    // Go through all the streams, setting their thinning params
    RTPStream** theStream = NULL;
    UInt32 theLen = 0;
    
    for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++)
    {
        Assert(theStream != NULL);
        Assert(theLen == sizeof(RTPStream*));
        if (*theStream != NULL)
        {
            (*theStream)->SetThinningParams();
 			(*theStream)->ResetThinningDelayParams();
            //
            // If we are using reliable UDP, then make sure to clear all the packets
            // from the previous play spurt out of the resender
            (*theStream)->GetResender()->ClearOutstandingPackets();
        }
    }

//  qtss_printf("movie bitrate = %d, window size = %d\n", this->GetMovieAvgBitrate(), theWindowSize);
    Assert(this->GetBandwidthTracker()->BytesInList() == 0);
    
    // Set the size of the RTSPSession's send buffer to an appropriate max size
    // based on the bitrate of the movie. This has 2 benefits:
    // 1) Each socket normally defaults to 32 K. A smaller buffer prevents the
    // system from getting buffer starved if lots of clients get flow-controlled
    //
    // 2) We may need to scale up buffer sizes for high-bandwidth movies in order
    // to maximize thruput, and we may need to scale down buffer sizes for low-bandwidth
    // movies to prevent us from buffering lots of data that the client can't use
    
    // If we don't know any better, assume maximum buffer size.
    QTSServerPrefs* thePrefs = QTSServerInterface::GetServer()->GetPrefs();
    UInt32 theBufferSize = thePrefs->GetMaxTCPBufferSizeInBytes();
    
#if RTPSESSION_DEBUGGING
    qtss_printf("RTPSession GetMovieAvgBitrate %li\n",(SInt32)this->GetMovieAvgBitrate() );
#endif

    if (this->GetMovieAvgBitrate() > 0)
    {
        // We have a bit rate... use it.
        Float32 realBufferSize = (Float32)this->GetMovieAvgBitrate() * thePrefs->GetTCPSecondsToBuffer();
        theBufferSize = (UInt32)realBufferSize;
        theBufferSize >>= 3; // Divide by 8 to convert from bits to bytes
        
        // Round down to the next lowest power of 2.
        theBufferSize = this->PowerOf2Floor(theBufferSize);
        
        // This is how much data we should buffer based on the scaling factor... if it is
        // lower than the min, raise to min
        if (theBufferSize < thePrefs->GetMinTCPBufferSizeInBytes())
            theBufferSize = thePrefs->GetMinTCPBufferSizeInBytes();
            
        // Same deal for max buffer size
        if (theBufferSize > thePrefs->GetMaxTCPBufferSizeInBytes())
            theBufferSize = thePrefs->GetMaxTCPBufferSizeInBytes();
    }