Solves two bandwidth estimation issues and measures the sent video bitrate.

Issues solved:
1. Possible overflow when reducing the bandwidth estimate at the send-side
2. A burst of loss reports could make us reduce the rate way too far since
   we reduced the rate relative the current estimate and not the actual
   rate sent.

BUG=
TEST=

Review URL: http://webrtc-codereview.appspot.com/244011

git-svn-id: http://webrtc.googlecode.com/svn/trunk@822 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2011-10-27 16:08:29 +00:00
parent 7e4269e9ee
commit fbea4e555d
16 changed files with 105 additions and 20 deletions

View File

@ -496,6 +496,7 @@ public:
* get sent bitrate in Kbit/s
*/
virtual void BitrateSent(WebRtc_UWord32* totalRate,
WebRtc_UWord32* videoRate,
WebRtc_UWord32* fecRate,
WebRtc_UWord32* nackRate) const = 0;

View File

@ -104,6 +104,7 @@ BandwidthManagement::UpdateBandwidthEstimate(const WebRtc_UWord16 bandWidthKbit,
WebRtc_Word32 BandwidthManagement::UpdatePacketLoss(
const WebRtc_UWord32 lastReceivedExtendedHighSeqNum,
WebRtc_UWord32 sentBitrate,
const WebRtc_UWord16 rtt,
WebRtc_UWord8* loss,
WebRtc_UWord32* newBitrate)
@ -168,7 +169,7 @@ WebRtc_Word32 BandwidthManagement::UpdatePacketLoss(
// Remember the sequence number until next time
_lastPacketLossExtendedHighSeqNum = lastReceivedExtendedHighSeqNum;
WebRtc_UWord32 bitRate = ShapeSimple(*loss, rtt);
WebRtc_UWord32 bitRate = ShapeSimple(*loss, rtt, sentBitrate);
if (bitRate == 0)
{
// no change
@ -211,7 +212,8 @@ WebRtc_Word32 BandwidthManagement::CalcTFRCbps(WebRtc_Word16 avgPackSizeBytes,
*/
// protected
WebRtc_UWord32 BandwidthManagement::ShapeSimple(WebRtc_Word32 packetLoss,
WebRtc_Word32 rtt)
WebRtc_Word32 rtt,
WebRtc_UWord32 sentBitrate)
{
WebRtc_UWord32 newBitRate = 0;
bool reducing = false;
@ -226,7 +228,8 @@ WebRtc_UWord32 BandwidthManagement::ShapeSimple(WebRtc_Word32 packetLoss,
// 26/256 ~= 10%
// reduce rate: newRate = rate * (1 - 0.5*lossRate)
// packetLoss = 256*lossRate
newBitRate = (_bitRate * (512 - packetLoss)) / 512;
newBitRate = static_cast<WebRtc_UWord32>(
(sentBitrate * static_cast<double>(512 - packetLoss)) / 512.0);
reducing = true;
}
else

View File

@ -35,6 +35,7 @@ public:
// Call when we receive a RTCP message with a ReceiveBlock
WebRtc_Word32 UpdatePacketLoss(
const WebRtc_UWord32 lastReceivedExtendedHighSeqNum,
WebRtc_UWord32 sentBitrate,
const WebRtc_UWord16 rtt,
WebRtc_UWord8* loss,
WebRtc_UWord32* newBitrate);
@ -48,7 +49,9 @@ public:
WebRtc_Word32 MaxConfiguredBitrate(WebRtc_UWord16* maxBitrateKbit);
protected:
WebRtc_UWord32 ShapeSimple(WebRtc_Word32 packetLoss, WebRtc_Word32 rtt);
WebRtc_UWord32 ShapeSimple(WebRtc_Word32 packetLoss,
WebRtc_Word32 rtt,
WebRtc_UWord32 sentBitrate);
WebRtc_Word32 CalcTFRCbps(WebRtc_Word16 avgPackSizeBytes,
WebRtc_Word32 rttMs,

View File

@ -1694,9 +1694,11 @@ RTCPSender::SendRTCP(const WebRtc_UWord32 packetTypeFlags,
{
// calc bw for video 360/sendBW in kbit/s
WebRtc_UWord32 sendBitrateKbit = 0;
WebRtc_UWord32 videoRate = 0;
WebRtc_UWord32 fecRate = 0;
WebRtc_UWord32 nackRate = 0;
_rtpRtcp.BitrateSent(&sendBitrateKbit,
&videoRate,
&fecRate,
&nackRate);
sendBitrateKbit /= 1000;

View File

@ -2340,8 +2340,9 @@ WebRtc_UWord32 ModuleRtpRtcpImpl::BitrateReceivedNow() const {
}
void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
WebRtc_UWord32* fecRate,
WebRtc_UWord32* nackRate) const {
WebRtc_UWord32* videoRate,
WebRtc_UWord32* fecRate,
WebRtc_UWord32* nackRate) const {
const bool defaultInstance(_childModules.empty() ? false : true);
if (defaultInstance) {
@ -2354,9 +2355,11 @@ void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
RtpRtcp* module = *it;
if (module) {
WebRtc_UWord32 childTotalRate = 0;
WebRtc_UWord32 childVideoRate = 0;
WebRtc_UWord32 childFecRate = 0;
WebRtc_UWord32 childNackRate = 0;
module->BitrateSent(&childTotalRate,
&childVideoRate,
&childFecRate,
&childNackRate);
if (totalRate != NULL && childTotalRate > *totalRate)
@ -2372,6 +2375,8 @@ void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
}
if (totalRate != NULL)
*totalRate = _rtpSender.BitrateLast();
if (videoRate != NULL)
*videoRate = _rtpSender.VideoBitrateSent();
if (fecRate != NULL)
*fecRate = _rtpSender.FecOverheadRate();
if (nackRate != NULL)
@ -2663,8 +2668,13 @@ void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate(
if (!defaultInstance) {
WebRtc_UWord32 newBitrate = 0;
WebRtc_UWord8 loss = fractionLost; // local copy since it can change
WebRtc_UWord32 videoRate = 0;
WebRtc_UWord32 fecRate = 0;
WebRtc_UWord32 nackRate = 0;
BitrateSent(NULL, &videoRate, &fecRate, &nackRate);
if (_bandwidthManagement.UpdatePacketLoss(
lastReceivedExtendedHighSeqNum,
videoRate + fecRate + nackRate,
roundTripTime,
&loss,
&newBitrate) != 0) {
@ -2735,10 +2745,15 @@ void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate(
// default and simulcast
WebRtc_UWord32 newBitrate = 0;
WebRtc_UWord8 loss = fractionLost; // local copy
WebRtc_UWord32 videoRate = 0;
WebRtc_UWord32 fecRate = 0;
WebRtc_UWord32 nackRate = 0;
BitrateSent(NULL, &videoRate, &fecRate, &nackRate);
if (_bandwidthManagement.UpdatePacketLoss(0, // we can't use this
roundTripTime,
&loss,
&newBitrate) != 0) {
videoRate + fecRate + nackRate,
roundTripTime,
&loss,
&newBitrate) != 0) {
// ignore this update
return;
}

View File

@ -460,6 +460,7 @@ public:
TMMBRSet*& boundingSetRec);
virtual void BitrateSent(WebRtc_UWord32* totalRate,
WebRtc_UWord32* videoRate,
WebRtc_UWord32* fecRate,
WebRtc_UWord32* nackRate) const;

View File

@ -241,9 +241,20 @@ RTPSender::ActualSendBitrateKbit() const
return (WebRtc_UWord16) (Bitrate::BitrateNow()/1000);
}
WebRtc_UWord32
RTPSender::VideoBitrateSent() const {
if (_video)
return _video->VideoBitrateSent();
else
return 0;
}
WebRtc_UWord32
RTPSender::FecOverheadRate() const {
return _video->FecOverheadRate();
if (_video)
return _video->FecOverheadRate();
else
return 0;
}
WebRtc_UWord32

View File

@ -73,6 +73,7 @@ public:
WebRtc_UWord16 TargetSendBitrateKbit() const;
WebRtc_UWord16 ActualSendBitrateKbit() const;
WebRtc_UWord32 VideoBitrateSent() const;
WebRtc_UWord32 FecOverheadRate() const;
WebRtc_UWord32 NackOverheadRate() const;

View File

@ -157,7 +157,6 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
const WebRtc_UWord16 payloadLength,
const WebRtc_UWord16 rtpHeaderLength)
{
int fecOverheadSent = 0;
if(_fecEnabled)
{
WebRtc_Word32 retVal = 0;
@ -209,6 +208,10 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
_numberFirstPartition,
_fecUseUepProtection,
fecPacketList);
int fecOverheadSent = 0;
int videoSent = 0;
while(!_rtpPacketListFec.Empty())
{
WebRtc_UWord8 newDataBuffer[IP_PACKET_SIZE];
@ -218,6 +221,10 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
RtpPacket* packetToSend =
static_cast<RtpPacket*>(item->GetItem());
item = _mediaPacketListFec.First();
ForwardErrorCorrection::Packet* mediaPacket =
static_cast<ForwardErrorCorrection::Packet*>(item->GetItem());
// Copy RTP header
memcpy(newDataBuffer, packetToSend->pkt->data,
packetToSend->rtpHeaderLength);
@ -244,13 +251,24 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
_mediaPacketListFec.PopFront();
// Send normal packet with RED header
retVal |= _rtpSender.SendToNetwork(
int packetSuccess = _rtpSender.SendToNetwork(
newDataBuffer,
packetToSend->pkt->length -
packetToSend->rtpHeaderLength +
REDForFECHeaderLength,
packetToSend->rtpHeaderLength);
retVal |= packetSuccess;
if (packetSuccess == 0)
{
videoSent += mediaPacket->length;
fecOverheadSent += (packetToSend->pkt->length -
mediaPacket->length +
packetToSend->rtpHeaderLength +
REDForFECHeaderLength);
}
delete packetToSend->pkt;
delete packetToSend;
packetToSend = NULL;
@ -295,24 +313,32 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
// No marker bit on FEC packets, last media packet have the
// marker send FEC packet with RED header
retVal |= _rtpSender.SendToNetwork(
int packetSuccess = _rtpSender.SendToNetwork(
newDataBuffer,
packetToSend->length + REDForFECHeaderLength,
lastMediaRtpHeader.length);
if (retVal == 0)
retVal |= packetSuccess;
if (packetSuccess == 0)
{
fecOverheadSent += packetToSend->length +
REDForFECHeaderLength;
REDForFECHeaderLength + lastMediaRtpHeader.length;
}
}
_videoBitrate.Update(videoSent);
_fecOverheadRate.Update(fecOverheadSent);
}
_fecOverheadRate.Update(fecOverheadSent);
return retVal;
}
return _rtpSender.SendToNetwork(dataBuffer,
payloadLength,
rtpHeaderLength);
int retVal = _rtpSender.SendToNetwork(dataBuffer,
payloadLength,
rtpHeaderLength);
if (retVal == 0)
{
_videoBitrate.Update(payloadLength + rtpHeaderLength);
}
return retVal;
}
WebRtc_Word32
@ -1283,9 +1309,14 @@ RTPSenderVideo::SendVP8(const FrameType frameType,
}
void RTPSenderVideo::ProcessBitrate() {
_videoBitrate.Process();
_fecOverheadRate.Process();
}
WebRtc_UWord32 RTPSenderVideo::VideoBitrateSent() const {
return _videoBitrate.BitrateLast();
}
WebRtc_UWord32 RTPSenderVideo::FecOverheadRate() const {
return _fecOverheadRate.BitrateLast();
}

View File

@ -87,6 +87,7 @@ public:
void ProcessBitrate();
WebRtc_UWord32 VideoBitrateSent() const;
WebRtc_UWord32 FecOverheadRate() const;
protected:
@ -167,7 +168,11 @@ private:
int _numberFirstPartition;
ListWrapper _mediaPacketListFec;
ListWrapper _rtpPacketListFec;
// Bitrate used for FEC payload, RED headers, RTP headers for FEC packets
// and any padding overhead.
Bitrate _fecOverheadRate;
// Bitrate used for video payload and RTP headers
Bitrate _videoBitrate;
// H263
WebRtc_UWord8 _savedByte;

View File

@ -245,6 +245,7 @@ public:
// bits/s.
virtual int GetBandwidthUsage(const int videoChannel,
unsigned int& totalBitrateSent,
unsigned int& videoBitrateSent,
unsigned int& fecBitrateSent,
unsigned int& nackBitrateSent) const = 0;

View File

@ -1452,6 +1452,7 @@ WebRtc_Word32 ViEChannel::GetRtpStatistics(
}
void ViEChannel::GetBandwidthUsage(WebRtc_UWord32& totalBitrateSent,
WebRtc_UWord32& videoBitrateSent,
WebRtc_UWord32& fecBitrateSent,
WebRtc_UWord32& nackBitrateSent) const {
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
@ -1459,15 +1460,17 @@ void ViEChannel::GetBandwidthUsage(WebRtc_UWord32& totalBitrateSent,
"%s", __FUNCTION__);
_rtpRtcp.BitrateSent(&totalBitrateSent,
&videoBitrateSent,
&fecBitrateSent,
&nackBitrateSent);
for (std::list<RtpRtcp*>::const_iterator it = _simulcastRtpRtcp.begin();
it != _simulcastRtpRtcp.end(); it++) {
WebRtc_UWord32 streamRate = 0;
WebRtc_UWord32 videoRate = 0;
WebRtc_UWord32 fecRate = 0;
WebRtc_UWord32 nackRate = 0;
RtpRtcp* rtpRtcp = *it;
rtpRtcp->BitrateSent(&streamRate, &fecRate, &nackRate);
rtpRtcp->BitrateSent(&streamRate, &videoRate, &fecRate, &nackRate);
totalBitrateSent += streamRate;
fecBitrateSent += fecRate;
nackBitrateSent += nackRate;

View File

@ -172,6 +172,7 @@ public:
WebRtc_UWord32& packetsReceived) const;
void GetBandwidthUsage(WebRtc_UWord32& totalBitrateSent,
WebRtc_UWord32& videoBitrateSent,
WebRtc_UWord32& fecBitrateSent,
WebRtc_UWord32& nackBitrateSent) const;

View File

@ -972,6 +972,7 @@ int ViERTP_RTCPImpl::GetRTPStatistics(const int videoChannel,
// The function gets bandwidth usage statistics from the sent RTP streams.
int ViERTP_RTCPImpl::GetBandwidthUsage(const int videoChannel,
unsigned int& totalBitrateSent,
unsigned int& videoBitrateSent,
unsigned int& fecBitrateSent,
unsigned int& nackBitrateSent) const {
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
@ -992,6 +993,7 @@ int ViERTP_RTCPImpl::GetBandwidthUsage(const int videoChannel,
ptrViEChannel->GetBandwidthUsage(
static_cast<WebRtc_UWord32&>(totalBitrateSent),
static_cast<WebRtc_UWord32&>(videoBitrateSent),
static_cast<WebRtc_UWord32&>(fecBitrateSent),
static_cast<WebRtc_UWord32&>(nackBitrateSent));
return 0;

View File

@ -112,6 +112,7 @@ public:
virtual int GetBandwidthUsage(const int videoChannel,
unsigned int& totalBitrateSent,
unsigned int& videoBitrateSent,
unsigned int& fecBitrateSent,
unsigned int& nackBitrateSent) const;

View File

@ -233,11 +233,13 @@ int ViEAutoTest::ViERtpRtcpStandardTest()
int recRttMs = 0;
unsigned int sentTotalBitrate = 0;
unsigned int sentVideoBitrate = 0;
unsigned int sentFecBitrate = 0;
unsigned int sentNackBitrate = 0;
error = ViE.ptrViERtpRtcp->GetBandwidthUsage(tbChannel.videoChannel,
sentTotalBitrate,
sentVideoBitrate,
sentFecBitrate,
sentNackBitrate);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
@ -311,6 +313,7 @@ int ViEAutoTest::ViERtpRtcpStandardTest()
error = ViE.ptrViERtpRtcp->GetBandwidthUsage(tbChannel.videoChannel,
sentTotalBitrate,
sentVideoBitrate,
sentFecBitrate,
sentNackBitrate);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
@ -340,6 +343,7 @@ int ViEAutoTest::ViERtpRtcpStandardTest()
error = ViE.ptrViERtpRtcp->GetBandwidthUsage(tbChannel.videoChannel,
sentTotalBitrate,
sentVideoBitrate,
sentFecBitrate,
sentNackBitrate);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",