Calculate the available bandwidth before sending a TMMBR

Also changed the way TMMBR was processed since it did not match the new bandwidth estimator.

Review URL: http://webrtc-codereview.appspot.com/270003
Patch from pwestin1 <pwestin@webrtc.org>.

git-svn-id: http://webrtc.googlecode.com/svn/trunk@925 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mflodman@webrtc.org
2011-11-10 12:54:46 +00:00
parent 637a59e68e
commit 7a4eb2837a
2 changed files with 107 additions and 129 deletions

View File

@ -442,6 +442,10 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process()
{ {
WebRtc_UWord16 RTT = 0; WebRtc_UWord16 RTT = 0;
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL);
if (TMMBR())
{
_rtcpSender.CalculateNewTargetBitrate(RTT);
}
_rtcpSender.SendRTCP(kRtcpReport, 0, 0, RTT); _rtcpSender.SendRTCP(kRtcpReport, 0, 0, RTT);
} }
if(_rtpSender.RTPKeepalive()) if(_rtpSender.RTPKeepalive())
@ -2489,7 +2493,7 @@ RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate(
bool firstOverUse = false; bool firstOverUse = false;
RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput, RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput,
firstOverUse); firstOverUse);
if (firstOverUse && _rtcpSender.Status() == kRtcpNonCompound) { if (firstOverUse) {
// Send TMMBR immediately // Send TMMBR immediately
WebRtc_UWord16 RTT = 0; WebRtc_UWord16 RTT = 0;
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL);
@ -2625,15 +2629,13 @@ void ModuleRtpRtcpImpl::OnReceivedReferencePictureSelectionIndication(
void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate( void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
const WebRtc_UWord16 bwEstimateKbit) { const WebRtc_UWord16 bwEstimateKbit) {
// We received a TMMBR // We received a TMMBR
if (_defaultModule) { const bool defaultInstance(_childModules.empty() ? false : true);
CriticalSectionScoped lock(_criticalSectionModulePtrs); if (defaultInstance) {
if (_defaultModule) { ProcessDefaultModuleBandwidth();
// if we use a default module pass this info to the default module
_defaultModule->OnReceivedBandwidthEstimateUpdate(bwEstimateKbit);
return; return;
} }
}
if (_audio) { if (_audio) {
_rtcpReceiver.UpdateBandwidthEstimate(bwEstimateKbit); _rtcpReceiver.UpdateBandwidthEstimate(bwEstimateKbit);
} else { } else {
@ -2644,17 +2646,27 @@ void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(
&newBitrate, &newBitrate,
&fractionLost, &fractionLost,
&roundTripTime) == 0) { &roundTripTime) == 0) {
// video callback if (!_defaultModule) {
// No default module check if we should trigger OnNetworkChanged
// via video callback
_rtpReceiver.UpdateBandwidthManagement(newBitrate, _rtpReceiver.UpdateBandwidthManagement(newBitrate,
fractionLost, fractionLost,
roundTripTime); roundTripTime);
const bool defaultInstance = !_childModules.empty(); }
if ((newBitrate > 0) && !defaultInstance) { if (newBitrate > 0) {
// update bitrate // update bitrate
_rtpSender.SetTargetSendBitrate(newBitrate); _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 // bw estimation
@ -2708,39 +2720,7 @@ void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate(
roundTripTime); roundTripTime);
} else { } else {
if (!_simulcast) { if (!_simulcast) {
WebRtc_UWord32 minBitrateBps = 0xffffffff; ProcessDefaultModuleBandwidth();
WebRtc_UWord32 maxBitrateBps = 0;
{
// get min and max for the sending channels
CriticalSectionScoped lock(_criticalSectionModulePtrs);
std::list<ModuleRtpRtcpImpl*>::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);
} else { } else {
// default and simulcast // default and simulcast
WebRtc_UWord32 newBitrate = 0; 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<ModuleRtpRtcpImpl*>::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() { void ModuleRtpRtcpImpl::OnRequestSendReport() {
_rtcpSender.SendRTCP(kRtcpSr); _rtcpSender.SendRTCP(kRtcpSr);
} }
@ -2864,56 +2901,13 @@ WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() {
WebRtc_Word32 newBitrates = 0; WebRtc_Word32 newBitrates = 0;
WebRtc_UWord32 minBitrateKbit = 0; WebRtc_UWord32 minBitrateKbit = 0;
WebRtc_UWord32 maxBitrateKbit = 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; WebRtc_UWord32 accNumCandidates = 0;
// Find candidate set
if (!_childModules.empty()) { if (!_childModules.empty()) {
CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); // Default module should not handle this
// this module is the default module
// loop over all modules using the default codec
WebRtc_UWord32 size = 0;
std::list<ModuleRtpRtcpImpl*>::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++;
}
TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
if (candidateSet == NULL) {
return -1; 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++;
}
} else {
// this module don't use the default module and is not the
// default module
WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0, 0, NULL); WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0, 0, NULL);
if (size > 0) { if (size > 0) {
TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size); TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
@ -2925,7 +2919,6 @@ WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() {
// candidate set empty // candidate set empty
VerifyAndAllocateCandidateSet(0); // resets candidate set VerifyAndAllocateCandidateSet(0); // resets candidate set
} }
}
// Find bounding set // Find bounding set
TMMBRSet* boundingSet = NULL; TMMBRSet* boundingSet = NULL;
numBoundingSet = FindTMMBRBoundingSet(boundingSet); numBoundingSet = FindTMMBRBoundingSet(boundingSet);
@ -2936,33 +2929,17 @@ WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() {
"Failed to find TMMBR bounding set."); "Failed to find TMMBR bounding set.");
return -1; return -1;
} }
// Set bounding set // Set bounding set
// Inform remote clients about the new bandwidth // Inform remote clients about the new bandwidth
if (_childModules.empty()) {
// inform the remote client // inform the remote client
_rtcpSender.SetTMMBN(boundingSet, _rtcpSender.SetTMMBN(boundingSet,
_rtpSender.MaxConfiguredBitrateVideo()/1000); _rtpSender.MaxConfiguredBitrateVideo()/1000);
// might trigger a TMMBN // might trigger a TMMBN
} else {
// inform child modules using the default codec
CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);
std::list<ModuleRtpRtcpImpl*>::iterator it = _childModules.begin();
while (it != _childModules.end()) {
ModuleRtpRtcpImpl* module = *it;
if (module) {
module->SetTMMBN(boundingSet,
_rtpSender.MaxConfiguredBitrateVideo()/1000);
}
it++;
}
}
if (numBoundingSet == 0) { if (numBoundingSet == 0) {
// owner of max bitrate request has timed out // owner of max bitrate request has timed out
// empty bounding set has been sent // empty bounding set has been sent
return 0; return 0;
} }
// Get net bitrate from bounding set depending on sent packet rate // Get net bitrate from bounding set depending on sent packet rate
newBitrates = CalcMinMaxBitRate(_rtpSender.PacketRate(), newBitrates = CalcMinMaxBitRate(_rtpSender.PacketRate(),
(WebRtc_UWord32)numBoundingSet, (WebRtc_UWord32)numBoundingSet,

View File

@ -532,6 +532,7 @@ protected:
RTCPReceiver _rtcpReceiver; RTCPReceiver _rtcpReceiver;
private: private:
void SendKeyFrame(); void SendKeyFrame();
void ProcessDefaultModuleBandwidth();
WebRtc_Word32 _id; WebRtc_Word32 _id;
const bool _audio; const bool _audio;