/* 设置好各种参数后发信号开始触发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(); }