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:
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user