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;
_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<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);
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<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() {
_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<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++;
}
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<ModuleRtpRtcpImpl*>::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,

View File

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