diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 4a19767823..f420ceb4f5 100644 --- a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -442,6 +442,10 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() { WebRtc_UWord16 RTT = 0; _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); + if (TMMBR()) + { + _rtcpSender.CalculateNewTargetBitrate(RTT); + } _rtcpSender.SendRTCP(kRtcpReport, 0, 0, RTT); } if(_rtpSender.RTPKeepalive()) @@ -2489,7 +2493,7 @@ RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate( bool firstOverUse = false; RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput, firstOverUse); - if (firstOverUse && _rtcpSender.Status() == kRtcpNonCompound) { + if (firstOverUse) { // Send TMMBR immediately WebRtc_UWord16 RTT = 0; _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); @@ -2625,14 +2629,12 @@ void ModuleRtpRtcpImpl::OnReceivedReferencePictureSelectionIndication( void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate( const WebRtc_UWord16 bwEstimateKbit) { + // We received a TMMBR - if (_defaultModule) { - CriticalSectionScoped lock(_criticalSectionModulePtrs); - if (_defaultModule) { - // if we use a default module pass this info to the default module - _defaultModule->OnReceivedBandwidthEstimateUpdate(bwEstimateKbit); - return; - } + const bool defaultInstance(_childModules.empty() ? false : true); + if (defaultInstance) { + ProcessDefaultModuleBandwidth(); + return; } if (_audio) { _rtcpReceiver.UpdateBandwidthEstimate(bwEstimateKbit); @@ -2644,17 +2646,27 @@ void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate( &newBitrate, &fractionLost, &roundTripTime) == 0) { - // video callback - _rtpReceiver.UpdateBandwidthManagement(newBitrate, - fractionLost, - roundTripTime); - const bool defaultInstance = !_childModules.empty(); - if ((newBitrate > 0) && !defaultInstance) { + if (!_defaultModule) { + // No default module check if we should trigger OnNetworkChanged + // via video callback + _rtpReceiver.UpdateBandwidthManagement(newBitrate, + fractionLost, + roundTripTime); + } + if (newBitrate > 0) { // update bitrate _rtpSender.SetTargetSendBitrate(newBitrate); } } } + if (_defaultModule) { + CriticalSectionScoped lock(_criticalSectionModulePtrs); + if (_defaultModule) { + // if we use a default module pass this info to the default module + _defaultModule->OnReceivedBandwidthEstimateUpdate(bwEstimateKbit); + return; + } + } } // bw estimation @@ -2708,39 +2720,7 @@ void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate( roundTripTime); } else { if (!_simulcast) { - WebRtc_UWord32 minBitrateBps = 0xffffffff; - WebRtc_UWord32 maxBitrateBps = 0; - { - // get min and max for the sending channels - CriticalSectionScoped lock(_criticalSectionModulePtrs); - - std::list::iterator it = - _childModules.begin(); - while (it != _childModules.end()) { - // Get child RTP sender and ask for bitrate estimate - ModuleRtpRtcpImpl* childModule = *it; - if (childModule->Sending()) { - RTPSender& childRtpSender = (*it)->_rtpSender; - const WebRtc_UWord32 childEstimateBps = - 1000 * childRtpSender.TargetSendBitrateKbit(); - if (childEstimateBps < minBitrateBps) { - minBitrateBps = childEstimateBps; - } - if (childEstimateBps > maxBitrateBps) { - maxBitrateBps = childEstimateBps; - } - } - it++; - } - } // end critsect - _bandwidthManagement.SetSendBitrate(minBitrateBps, 0, 0); - // Update default module bitrate. Don't care about min max. - // Check if we should trigger OnNetworkChanged via video callback - // TODO(pwestin) for this to work better fractionLost shoudl be the - // weighted average loss from all childs - _rtpReceiver.UpdateBandwidthManagement(minBitrateBps, - fractionLost, - roundTripTime); + ProcessDefaultModuleBandwidth(); } else { // default and simulcast WebRtc_UWord32 newBitrate = 0; @@ -2799,6 +2779,63 @@ void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate( } } +void ModuleRtpRtcpImpl::ProcessDefaultModuleBandwidth() { + WebRtc_UWord32 minBitrateBps = 0xffffffff; + WebRtc_UWord32 maxBitrateBps = 0; + WebRtc_UWord32 count = 0; + WebRtc_UWord32 fractionLostAcc = 0; + WebRtc_UWord16 maxRoundTripTime = 0; + { + // get min and max for the sending channels + CriticalSectionScoped lock(_criticalSectionModulePtrs); + + std::list::iterator it = + _childModules.begin(); + while (it != _childModules.end()) { + // Get child RTP sender and ask for bitrate estimate + ModuleRtpRtcpImpl* childModule = *it; + if (childModule->Sending()) { + count++; + RTPSender& childRtpSender = (*it)->_rtpSender; + const WebRtc_UWord32 childEstimateBps = + 1000 * childRtpSender.TargetSendBitrateKbit(); + if (childEstimateBps < minBitrateBps) { + minBitrateBps = childEstimateBps; + } + if (childEstimateBps > maxBitrateBps) { + maxBitrateBps = childEstimateBps; + } + WebRtc_UWord16 RTT = 0; + WebRtc_UWord8 fractionLost = 0; + RTPReceiver& childRtpReceiver = (*it)->_rtpReceiver; + RTCPReceiver& childRtcpReceiver = (*it)->_rtcpReceiver; + childRtpReceiver.Statistics(&fractionLost, + NULL, + NULL, + NULL, + NULL, + false); + fractionLostAcc += fractionLost; + childRtcpReceiver.RTT(childRtpReceiver.SSRC(), + &RTT, + NULL, + NULL, + NULL); + maxRoundTripTime = + (RTT > maxRoundTripTime) ? RTT : maxRoundTripTime; + } + it++; + } + } // end critsect + _bandwidthManagement.SetSendBitrate(minBitrateBps, 0, 0); + // Update default module bitrate. Don't care about min max. + // Check if we should trigger OnNetworkChanged via video callback + WebRtc_UWord8 fractionLostAvg = WebRtc_UWord8(fractionLostAcc / count); + _rtpReceiver.UpdateBandwidthManagement(minBitrateBps, + fractionLostAvg , + maxRoundTripTime); +} + void ModuleRtpRtcpImpl::OnRequestSendReport() { _rtcpSender.SendRTCP(kRtcpSr); } @@ -2864,67 +2901,23 @@ WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() { WebRtc_Word32 newBitrates = 0; WebRtc_UWord32 minBitrateKbit = 0; WebRtc_UWord32 maxBitrateKbit = 0; - - if (_defaultModule) { - CriticalSectionScoped lock(_criticalSectionModulePtrs); - - // no callbacks allowed inside here - if (_defaultModule) { - // let the default module do the update - return _defaultModule->UpdateTMMBR(); - } - } - WebRtc_UWord32 accNumCandidates = 0; - // Find candidate set - if (!_childModules.empty()) { - CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); + if (!_childModules.empty()) { + // Default module should not handle this + return -1; + } - // this module is the default module - // loop over all modules using the default codec - WebRtc_UWord32 size = 0; - std::list::iterator it = _childModules.begin(); - while (it != _childModules.end()) { - ModuleRtpRtcpImpl* module = *it; - WebRtc_Word32 tmpSize = module->TMMBRReceived(0, 0, NULL); - if (tmpSize > 0) { - size += tmpSize; - } - it++; - } + WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0, 0, NULL); + if (size > 0) { TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size); - if (candidateSet == NULL) { - return -1; - } - - it = _childModules.begin(); - while (it != _childModules.end()) { - ModuleRtpRtcpImpl* module = *it; - if (size > accNumCandidates && module) { - WebRtc_Word32 accSize = module->TMMBRReceived(size, - accNumCandidates, - candidateSet); - if (accSize > 0) { - accNumCandidates = accSize; - } - } - it++; - } + // get candidate set from receiver + accNumCandidates = _rtcpReceiver.TMMBRReceived(size, + accNumCandidates, + candidateSet); } else { - // this module don't use the default module and is not the - // default module - WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0, 0, NULL); - if (size > 0) { - TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size); - // get candidate set from receiver - accNumCandidates = _rtcpReceiver.TMMBRReceived(size, - accNumCandidates, - candidateSet); - } else { - // candidate set empty - VerifyAndAllocateCandidateSet(0); // resets candidate set - } + // candidate set empty + VerifyAndAllocateCandidateSet(0); // resets candidate set } // Find bounding set TMMBRSet* boundingSet = NULL; @@ -2936,33 +2929,17 @@ WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() { "Failed to find TMMBR bounding set."); return -1; } - // Set bounding set // Inform remote clients about the new bandwidth - if (_childModules.empty()) { - // inform the remote client - _rtcpSender.SetTMMBN(boundingSet, - _rtpSender.MaxConfiguredBitrateVideo()/1000); - // might trigger a TMMBN - } else { - // inform child modules using the default codec - CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); - std::list::iterator it = _childModules.begin(); - while (it != _childModules.end()) { - ModuleRtpRtcpImpl* module = *it; - if (module) { - module->SetTMMBN(boundingSet, - _rtpSender.MaxConfiguredBitrateVideo()/1000); - } - it++; - } - } + // inform the remote client + _rtcpSender.SetTMMBN(boundingSet, + _rtpSender.MaxConfiguredBitrateVideo()/1000); + // might trigger a TMMBN if (numBoundingSet == 0) { // owner of max bitrate request has timed out // empty bounding set has been sent return 0; } - // Get net bitrate from bounding set depending on sent packet rate newBitrates = CalcMinMaxBitRate(_rtpSender.PacketRate(), (WebRtc_UWord32)numBoundingSet, diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h index a11d54c8a7..462a66521d 100644 --- a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -284,14 +284,14 @@ public: // statistics of the amount of data sent and received virtual WebRtc_Word32 DataCountersRTP(WebRtc_UWord32 *bytesSent, - WebRtc_UWord32 *packetsSent, - WebRtc_UWord32 *bytesReceived, - WebRtc_UWord32 *packetsReceived) const; + WebRtc_UWord32 *packetsSent, + WebRtc_UWord32 *bytesReceived, + WebRtc_UWord32 *packetsReceived) const; virtual WebRtc_Word32 ReportBlockStatistics(WebRtc_UWord8 *fraction_lost, - WebRtc_UWord32 *cum_lost, - WebRtc_UWord32 *ext_max, - WebRtc_UWord32 *jitter); + WebRtc_UWord32 *cum_lost, + WebRtc_UWord32 *ext_max, + WebRtc_UWord32 *jitter); // Get received RTCP report, sender info virtual WebRtc_Word32 RemoteRTCPStat( RTCPSenderInfo* senderInfo); @@ -532,6 +532,7 @@ protected: RTCPReceiver _rtcpReceiver; private: void SendKeyFrame(); + void ProcessDefaultModuleBandwidth(); WebRtc_Word32 _id; const bool _audio;