Refactoring of the TMMBRSet class, giving it a reasonably tight interface.

The CL also fixes a number of line length and tab issues in touched files.

BUG=
TEST=

Review URL: https://webrtc-codereview.appspot.com/553005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2168 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
hta@webrtc.org 2012-05-03 14:07:23 +00:00
parent 3bc38c86e8
commit 54536bb6d4
7 changed files with 284 additions and 228 deletions

View File

@ -649,7 +649,7 @@ bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
if ((timeNow - receiveInfo->lastTimeReceived) > if ((timeNow - receiveInfo->lastTimeReceived) >
5 * RTCP_INTERVAL_AUDIO_MS) { 5 * RTCP_INTERVAL_AUDIO_MS) {
// no rtcp packet for the last five regular intervals, reset limitations // no rtcp packet for the last five regular intervals, reset limitations
receiveInfo->TmmbrSet.lengthOfSet = 0; receiveInfo->TmmbrSet.clearSet();
// prevent that we call this over and over again // prevent that we call this over and over again
receiveInfo->lastTimeReceived = 0; receiveInfo->lastTimeReceived = 0;
// send new TMMBN to all channels using the default codec // send new TMMBN to all channels using the default codec
@ -687,23 +687,22 @@ WebRtc_Word32 RTCPReceiver::BoundingSet(bool &tmmbrOwner,
__FUNCTION__); __FUNCTION__);
return -1; return -1;
} }
if (receiveInfo->TmmbnBoundingSet.lengthOfSet > 0) { if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
boundingSetRec->VerifyAndAllocateSet( boundingSetRec->VerifyAndAllocateSet(
receiveInfo->TmmbnBoundingSet.lengthOfSet + 1); receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet; i++) { for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
if(receiveInfo->TmmbnBoundingSet.ptrSsrcSet[i] == _SSRC) { i++) {
if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
// owner of bounding set // owner of bounding set
tmmbrOwner = true; tmmbrOwner = true;
} }
boundingSetRec->ptrTmmbrSet[i] = boundingSetRec->SetEntry(i,
receiveInfo->TmmbnBoundingSet.ptrTmmbrSet[i]; receiveInfo->TmmbnBoundingSet.Tmmbr(i),
boundingSetRec->ptrPacketOHSet[i] = receiveInfo->TmmbnBoundingSet.PacketOH(i),
receiveInfo->TmmbnBoundingSet.ptrPacketOHSet[i]; receiveInfo->TmmbnBoundingSet.Ssrc(i));
boundingSetRec->ptrSsrcSet[i] =
receiveInfo->TmmbnBoundingSet.ptrSsrcSet[i];
} }
} }
return receiveInfo->TmmbnBoundingSet.lengthOfSet; return receiveInfo->TmmbnBoundingSet.lengthOfSet();
} }
// no need for critsect we have _criticalSectionRTCPReceiver // no need for critsect we have _criticalSectionRTCPReceiver
@ -992,13 +991,10 @@ void
RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo, RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
const RTCPUtility::RTCPPacket& rtcpPacket) const RTCPUtility::RTCPPacket& rtcpPacket)
{ {
const unsigned int idx = receiveInfo.TmmbnBoundingSet.lengthOfSet; receiveInfo.TmmbnBoundingSet.AddEntry(
rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
receiveInfo.TmmbnBoundingSet.ptrTmmbrSet[idx] = rtcpPacket.TMMBNItem.MaxTotalMediaBitRate; rtcpPacket.TMMBNItem.MeasuredOverhead,
receiveInfo.TmmbnBoundingSet.ptrPacketOHSet[idx] = rtcpPacket.TMMBNItem.MeasuredOverhead; rtcpPacket.TMMBNItem.SSRC);
receiveInfo.TmmbnBoundingSet.ptrSsrcSet[idx] = rtcpPacket.TMMBNItem.SSRC;
++receiveInfo.TmmbnBoundingSet.lengthOfSet;
} }
// no need for critsect we have _criticalSectionRTCPReceiver // no need for critsect we have _criticalSectionRTCPReceiver
@ -1376,7 +1372,7 @@ WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
return 0; return 0;
} }
for (WebRtc_UWord32 i = 0; for (WebRtc_UWord32 i = 0;
(num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet); i++) { (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
if (receiveInfo->GetTMMBRSet(i, num, candidateSet, if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
_clock.GetTimeInMS()) == 0) { _clock.GetTimeInMS()) == 0) {
num++; num++;
@ -1393,7 +1389,7 @@ WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
__FUNCTION__); __FUNCTION__);
return -1; return -1;
} }
num += receiveInfo->TmmbrSet.lengthOfSet; num += receiveInfo->TmmbrSet.lengthOfSet();
receiveInfoIt++; receiveInfoIt++;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source * that can be found in the LICENSE file in the root of the source
@ -147,40 +147,26 @@ RTCPReceiveInformation::~RTCPReceiveInformation()
} }
} }
// don't use TmmbrSet.VerifyAndAllocate this version keeps the data // Increase size of TMMBRSet if needed, and also take care of
// the _tmmbrSetTimeouts array.
void void
RTCPReceiveInformation::VerifyAndAllocateTMMBRSet(const WebRtc_UWord32 minimumSize) RTCPReceiveInformation::VerifyAndAllocateTMMBRSet(const WebRtc_UWord32 minimumSize)
{ {
if(minimumSize > TmmbrSet.sizeOfSet) if(minimumSize > TmmbrSet.sizeOfSet())
{ {
TmmbrSet.VerifyAndAllocateSetKeepingData(minimumSize);
// make sure that our buffers are big enough // make sure that our buffers are big enough
WebRtc_UWord32* ptrTmmbrSet = new WebRtc_UWord32[minimumSize];
WebRtc_UWord32* ptrTmmbrPacketOHSet = new WebRtc_UWord32[minimumSize];
WebRtc_UWord32* ptrTmmbrSsrcSet = new WebRtc_UWord32[minimumSize];
WebRtc_UWord32* tmmbrSetTimeouts = new WebRtc_UWord32[minimumSize]; WebRtc_UWord32* tmmbrSetTimeouts = new WebRtc_UWord32[minimumSize];
if(TmmbrSet.lengthOfSet > 0) if(TmmbrSet.lengthOfSet() > 0)
{ {
// copy old values memcpy(tmmbrSetTimeouts, _tmmbrSetTimeouts,
memcpy(ptrTmmbrSet, TmmbrSet.ptrTmmbrSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet); sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet());
memcpy(ptrTmmbrPacketOHSet, TmmbrSet.ptrPacketOHSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
memcpy(ptrTmmbrSsrcSet, TmmbrSet.ptrSsrcSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
memcpy(tmmbrSetTimeouts, _tmmbrSetTimeouts, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet);
}
if(TmmbrSet.ptrTmmbrSet)
{
delete [] TmmbrSet.ptrTmmbrSet;
delete [] TmmbrSet.ptrPacketOHSet;
delete [] TmmbrSet.ptrSsrcSet;
} }
if(_tmmbrSetTimeouts) if(_tmmbrSetTimeouts)
{ {
delete [] _tmmbrSetTimeouts; delete [] _tmmbrSetTimeouts;
} }
TmmbrSet.ptrTmmbrSet = ptrTmmbrSet;
TmmbrSet.ptrPacketOHSet = ptrTmmbrPacketOHSet;
TmmbrSet.ptrSsrcSet = ptrTmmbrSsrcSet;
TmmbrSet.sizeOfSet = minimumSize;
_tmmbrSetTimeouts = tmmbrSetTimeouts; _tmmbrSetTimeouts = tmmbrSetTimeouts;
} }
} }
@ -191,26 +177,26 @@ RTCPReceiveInformation::InsertTMMBRItem(const WebRtc_UWord32 senderSSRC,
const WebRtc_UWord32 currentTimeMS) const WebRtc_UWord32 currentTimeMS)
{ {
// serach to see if we have it in our list // serach to see if we have it in our list
for(WebRtc_UWord32 i = 0; i < TmmbrSet.lengthOfSet; i++) for(WebRtc_UWord32 i = 0; i < TmmbrSet.lengthOfSet(); i++)
{ {
if(TmmbrSet.ptrSsrcSet[i] == senderSSRC) if(TmmbrSet.Ssrc(i) == senderSSRC)
{ {
// we already have this SSRC in our list // we already have this SSRC in our list
// update it // update it
TmmbrSet.ptrPacketOHSet[i] = TMMBRItem.MeasuredOverhead; TmmbrSet.SetEntry(i,
TmmbrSet.ptrTmmbrSet[i] = TMMBRItem.MaxTotalMediaBitRate; TMMBRItem.MaxTotalMediaBitRate,
TMMBRItem.MeasuredOverhead,
senderSSRC);
_tmmbrSetTimeouts[i] = currentTimeMS; _tmmbrSetTimeouts[i] = currentTimeMS;
return; return;
} }
} }
VerifyAndAllocateTMMBRSet(TmmbrSet.lengthOfSet+1); const WebRtc_UWord32 idx = TmmbrSet.lengthOfSet();
VerifyAndAllocateTMMBRSet(idx+1);
const WebRtc_UWord32 idx = TmmbrSet.lengthOfSet; TmmbrSet.AddEntry(TMMBRItem.MaxTotalMediaBitRate,
TmmbrSet.ptrPacketOHSet[idx] = TMMBRItem.MeasuredOverhead; TMMBRItem.MeasuredOverhead,
TmmbrSet.ptrTmmbrSet[idx] = TMMBRItem.MaxTotalMediaBitRate; senderSSRC);
TmmbrSet.ptrSsrcSet[idx] = senderSSRC;
_tmmbrSetTimeouts[idx] = currentTimeMS; _tmmbrSetTimeouts[idx] = currentTimeMS;
TmmbrSet.lengthOfSet++;
} }
WebRtc_Word32 WebRtc_Word32
@ -219,11 +205,11 @@ RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx,
TMMBRSet* candidateSet, TMMBRSet* candidateSet,
const WebRtc_UWord32 currentTimeMS) const WebRtc_UWord32 currentTimeMS)
{ {
if(sourceIdx >= TmmbrSet.lengthOfSet) if(sourceIdx >= TmmbrSet.lengthOfSet())
{ {
return -1; return -1;
} }
if(targetIdx >= candidateSet->sizeOfSet) if(targetIdx >= candidateSet->sizeOfSet())
{ {
return -1; return -1;
} }
@ -233,21 +219,17 @@ RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx,
if(timeNow - _tmmbrSetTimeouts[sourceIdx] > 5*RTCP_INTERVAL_AUDIO_MS) if(timeNow - _tmmbrSetTimeouts[sourceIdx] > 5*RTCP_INTERVAL_AUDIO_MS)
{ {
// value timed out // value timed out
const WebRtc_UWord32 move = TmmbrSet.lengthOfSet - (sourceIdx + 1); TmmbrSet.RemoveEntry(sourceIdx);
if(move > 0) const WebRtc_UWord32 move = TmmbrSet.lengthOfSet() - (sourceIdx + 1);
{ if (move > 0) {
memmove(&(TmmbrSet.ptrTmmbrSet[sourceIdx]), &(TmmbrSet.ptrTmmbrSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
memmove(&(TmmbrSet.ptrPacketOHSet[sourceIdx]),&(TmmbrSet.ptrPacketOHSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
memmove(&(TmmbrSet.ptrSsrcSet[sourceIdx]),&(TmmbrSet.ptrSsrcSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
memmove(&(_tmmbrSetTimeouts[sourceIdx]),&(_tmmbrSetTimeouts[sourceIdx+1]), move* sizeof(WebRtc_UWord32)); memmove(&(_tmmbrSetTimeouts[sourceIdx]),&(_tmmbrSetTimeouts[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
} }
TmmbrSet.lengthOfSet--;
return -1; return -1;
} }
candidateSet->SetEntry(targetIdx,
candidateSet->ptrTmmbrSet[targetIdx] = TmmbrSet.ptrTmmbrSet[sourceIdx]; TmmbrSet.Tmmbr(sourceIdx),
candidateSet->ptrPacketOHSet[targetIdx] = TmmbrSet.ptrPacketOHSet[sourceIdx]; TmmbrSet.PacketOH(sourceIdx),
candidateSet->ptrSsrcSet[targetIdx] = TmmbrSet.ptrSsrcSet[sourceIdx]; TmmbrSet.Ssrc(sourceIdx));
return 0; return 0;
} }

View File

@ -258,8 +258,8 @@ TEST_F(RtcpReceiverTest, TmmbrPacketAccepted) {
TMMBRSet candidate_set; TMMBRSet candidate_set;
candidate_set.VerifyAndAllocateSet(1); candidate_set.VerifyAndAllocateSet(1);
EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(1, 0, &candidate_set)); EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(1, 0, &candidate_set));
EXPECT_LT(0U, candidate_set.ptrTmmbrSet[0]); EXPECT_LT(0U, candidate_set.Tmmbr(0));
EXPECT_EQ(kMediaRecipientSsrc, candidate_set.ptrSsrcSet[0]); EXPECT_EQ(kMediaRecipientSsrc, candidate_set.Ssrc(0));
} }
TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) { TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) {
@ -328,7 +328,7 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) {
TMMBRSet candidate_set; TMMBRSet candidate_set;
candidate_set.VerifyAndAllocateSet(3); candidate_set.VerifyAndAllocateSet(3);
EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(3, 0, &candidate_set)); EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(3, 0, &candidate_set));
EXPECT_LT(0U, candidate_set.ptrTmmbrSet[0]); EXPECT_LT(0U, candidate_set.Tmmbr(0));
// We expect the timeout to be 25 seconds. Advance the clock by 12 // We expect the timeout to be 25 seconds. Advance the clock by 12
// seconds, timing out the first packet. // seconds, timing out the first packet.
system_clock_->AdvanceClock(12000); system_clock_->AdvanceClock(12000);
@ -336,7 +336,7 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) {
EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(0, 0, NULL)); EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(0, 0, NULL));
// Odd behaviour: There's only one left after timeout, not 2. // Odd behaviour: There's only one left after timeout, not 2.
EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(3, 0, &candidate_set)); EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(3, 0, &candidate_set));
EXPECT_EQ(kMediaRecipientSsrc + 2, candidate_set.ptrSsrcSet[0]); EXPECT_EQ(kMediaRecipientSsrc + 2, candidate_set.Ssrc(0));
} }

View File

@ -1134,18 +1134,21 @@ RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
// get current bounding set from RTCP receiver // get current bounding set from RTCP receiver
bool tmmbrOwner = false; bool tmmbrOwner = false;
TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet(); // store in candidateSet, allocates one extra slot // store in candidateSet, allocates one extra slot
TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
// holding _criticalSectionRTCPSender while calling RTCPreceiver which will accuire _criticalSectionRTCPReceiver // holding _criticalSectionRTCPSender while calling RTCPreceiver which
// is a potental deadlock but since RTCPreceiver is not doing the revese we should be fine // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
WebRtc_Word32 lengthOfBoundingSet = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet); // since RTCPreceiver is not doing the reverse we should be fine
WebRtc_Word32 lengthOfBoundingSet
= _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
if(lengthOfBoundingSet > 0) if(lengthOfBoundingSet > 0)
{ {
for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++) for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
{ {
if( candidateSet->ptrTmmbrSet[i] == _tmmbr_Send && if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
candidateSet->ptrPacketOHSet[i] == _packetOH_Send) candidateSet->PacketOH(i) == _packetOH_Send)
{ {
// do not send the same tuple // do not send the same tuple
return 0; return 0;
@ -1155,9 +1158,10 @@ RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
{ {
// use received bounding set as candidate set // use received bounding set as candidate set
// add current tuple // add current tuple
candidateSet->ptrTmmbrSet[lengthOfBoundingSet] = _tmmbr_Send; candidateSet->SetEntry(lengthOfBoundingSet,
candidateSet->ptrPacketOHSet[lengthOfBoundingSet] = _packetOH_Send; _tmmbr_Send,
candidateSet->ptrSsrcSet[lengthOfBoundingSet] = _SSRC; _packetOH_Send,
_SSRC);
int numCandidates = lengthOfBoundingSet+ 1; int numCandidates = lengthOfBoundingSet+ 1;
// find bounding set // find bounding set
@ -1236,7 +1240,7 @@ RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
return -1; return -1;
} }
// sanity // sanity
if(pos + 12 + boundingSet->lengthOfSet*8 >= IP_PACKET_SIZE) if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
{ {
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__); WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
return -2; return -2;
@ -1265,15 +1269,15 @@ RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
// Additional Feedback Control Information (FCI) // Additional Feedback Control Information (FCI)
int numBoundingSet = 0; int numBoundingSet = 0;
for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet; n++) for(WebRtc_UWord32 n=0; n< boundingSet->lengthOfSet(); n++)
{ {
if (boundingSet->ptrTmmbrSet[n] > 0) if (boundingSet->Tmmbr(n) > 0)
{ {
WebRtc_UWord32 tmmbrSSRC = boundingSet->ptrSsrcSet[n]; WebRtc_UWord32 tmmbrSSRC = boundingSet->Ssrc(n);
ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC); ModuleRTPUtility::AssignUWord32ToBuffer(rtcpbuffer+pos, tmmbrSSRC);
pos += 4; pos += 4;
WebRtc_UWord32 bitRate = boundingSet->ptrTmmbrSet[n] * 1000; WebRtc_UWord32 bitRate = boundingSet->Tmmbr(n) * 1000;
WebRtc_UWord32 mmbrExp = 0; WebRtc_UWord32 mmbrExp = 0;
for(int i=0; i<64; i++) for(int i=0; i<64; i++)
{ {
@ -1284,7 +1288,7 @@ RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
} }
} }
WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp); WebRtc_UWord32 mmbrMantissa = (bitRate >> mmbrExp);
WebRtc_UWord32 measuredOH = boundingSet->ptrPacketOHSet[n]; WebRtc_UWord32 measuredOH = boundingSet->PacketOH(n);
rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03)); rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7); rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);

View File

@ -204,13 +204,8 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) {
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound)); EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
TMMBRSet bounding_set; TMMBRSet bounding_set;
bounding_set.VerifyAndAllocateSet(1); bounding_set.VerifyAndAllocateSet(1);
const WebRtc_UWord32 idx = bounding_set.lengthOfSet;
// TODO(hta): Make an accessor on TMMBRSet to do this insertion.
const WebRtc_UWord32 kSourceSsrc = 12345; const WebRtc_UWord32 kSourceSsrc = 12345;
bounding_set.ptrPacketOHSet[idx] = 0; bounding_set.AddEntry(32768, 0, kSourceSsrc);
bounding_set.ptrTmmbrSet[idx] = 32768; // bits per second
bounding_set.ptrSsrcSet[idx] = kSourceSsrc;
bounding_set.lengthOfSet++;
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3)); EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3));
ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags); ASSERT_EQ(0U, test_transport_->rtcp_packet_info_.rtcpPacketTypeFlags);
@ -224,6 +219,6 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) {
// We expect 1 member of the incoming set. // We expect 1 member of the incoming set.
EXPECT_EQ(1, test_transport_->rtcp_receiver_->BoundingSet(owner, EXPECT_EQ(1, test_transport_->rtcp_receiver_->BoundingSet(owner,
&incoming_set)); &incoming_set));
EXPECT_EQ(kSourceSsrc, incoming_set.ptrSsrcSet[0]); EXPECT_EQ(kSourceSsrc, incoming_set.Ssrc(0));
} }
} // namespace webrtc } // namespace webrtc

View File

@ -10,56 +10,91 @@
#include "tmmbr_help.h" #include "tmmbr_help.h"
#include <assert.h>
#include <limits> #include <limits>
#include <string.h>
#include "rtp_rtcp_config.h" #include "rtp_rtcp_config.h"
namespace webrtc { namespace webrtc {
TMMBRSet::TMMBRSet() : TMMBRSet::TMMBRSet() :
ptrTmmbrSet(0), _sizeOfSet(0),
ptrPacketOHSet(0), _lengthOfSet(0)
ptrSsrcSet(0),
sizeOfSet(0),
lengthOfSet(0)
{ {
} }
TMMBRSet::~TMMBRSet() TMMBRSet::~TMMBRSet()
{ {
delete [] ptrTmmbrSet; _sizeOfSet = 0;
delete [] ptrPacketOHSet; _lengthOfSet = 0;
delete [] ptrSsrcSet;
ptrTmmbrSet = 0;
ptrPacketOHSet = 0;
ptrSsrcSet = 0;
sizeOfSet = 0;
lengthOfSet = 0;
} }
void void
TMMBRSet::VerifyAndAllocateSet(WebRtc_UWord32 minimumSize) TMMBRSet::VerifyAndAllocateSet(WebRtc_UWord32 minimumSize)
{ {
if(minimumSize > sizeOfSet) if(minimumSize > _sizeOfSet)
{ {
// make sure that our buffers are big enough // make sure that our buffers are big enough
if(ptrTmmbrSet) _data.resize(minimumSize);
{ _sizeOfSet = minimumSize;
delete [] ptrTmmbrSet;
delete [] ptrPacketOHSet;
delete [] ptrSsrcSet;
}
ptrTmmbrSet = new WebRtc_UWord32[minimumSize];
ptrPacketOHSet = new WebRtc_UWord32[minimumSize];
ptrSsrcSet = new WebRtc_UWord32[minimumSize];
sizeOfSet = minimumSize;
} }
// reset memory // reset memory
for(WebRtc_UWord32 i = 0; i < sizeOfSet; i++) for(WebRtc_UWord32 i = 0; i < _sizeOfSet; i++)
{ {
ptrTmmbrSet[i] = 0; _data.at(i).tmmbr = 0;
ptrPacketOHSet[i] = 0; _data.at(i).packet_oh = 0;
ptrSsrcSet[i] = 0; _data.at(i).ssrc = 0;
} }
lengthOfSet = 0; _lengthOfSet = 0;
}
void
TMMBRSet::VerifyAndAllocateSetKeepingData(WebRtc_UWord32 minimumSize)
{
if(minimumSize > _sizeOfSet)
{
{
_data.resize(minimumSize);
}
_sizeOfSet = minimumSize;
}
}
void TMMBRSet::SetEntry(unsigned int i,
WebRtc_UWord32 tmmbrSet,
WebRtc_UWord32 packetOHSet,
WebRtc_UWord32 ssrcSet) {
assert(i < _sizeOfSet);
_data.at(i).tmmbr = tmmbrSet;
_data.at(i).packet_oh = packetOHSet;
_data.at(i).ssrc = ssrcSet;
if (i >= _lengthOfSet) {
_lengthOfSet = i + 1;
}
}
void TMMBRSet::AddEntry(WebRtc_UWord32 tmmbrSet,
WebRtc_UWord32 packetOHSet,
WebRtc_UWord32 ssrcSet) {
assert(_lengthOfSet < _sizeOfSet);
SetEntry(_lengthOfSet, tmmbrSet, packetOHSet, ssrcSet);
}
void TMMBRSet::RemoveEntry(WebRtc_UWord32 sourceIdx) {
assert(sourceIdx < _lengthOfSet);
_data.erase(_data.begin() + sourceIdx);
_lengthOfSet--;
_data.resize(_sizeOfSet); // Ensure that size remains the same.
}
void TMMBRSet::SwapEntries(WebRtc_UWord32 i, WebRtc_UWord32 j) {
SetElement temp;
temp = _data[i];
_data[i] = _data[j];
_data[j] = temp;
}
void TMMBRSet::ClearEntry(WebRtc_UWord32 idx) {
SetEntry(idx, 0, 0, 0);
} }
TMMBRHelp::TMMBRHelp() TMMBRHelp::TMMBRHelp()
@ -84,7 +119,7 @@ TMMBRHelp::VerifyAndAllocateBoundingSet(WebRtc_UWord32 minimumSize)
{ {
CriticalSectionScoped lock(_criticalSection); CriticalSectionScoped lock(_criticalSection);
if(minimumSize > _boundingSet.sizeOfSet) if(minimumSize > _boundingSet.sizeOfSet())
{ {
// make sure that our buffers are big enough // make sure that our buffers are big enough
if(_ptrIntersectionBoundingSet) if(_ptrIntersectionBoundingSet)
@ -111,16 +146,16 @@ TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
if (boundingSetToSend == NULL) if (boundingSetToSend == NULL)
{ {
_boundingSetToSend.lengthOfSet = 0; _boundingSetToSend.clearSet();
return 0; return 0;
} }
VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet); VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet());
_boundingSetToSend.clearSet();
for (WebRtc_UWord32 i = 0; i < boundingSetToSend->lengthOfSet; i++) for (WebRtc_UWord32 i = 0; i < boundingSetToSend->lengthOfSet(); i++)
{ {
// cap at our configured max bitrate // cap at our configured max bitrate
WebRtc_UWord32 bitrate = boundingSetToSend->ptrTmmbrSet[i]; WebRtc_UWord32 bitrate = boundingSetToSend->Tmmbr(i);
if(maxBitrateKbit) if(maxBitrateKbit)
{ {
// do we have a configured max bitrate? // do we have a configured max bitrate?
@ -129,12 +164,10 @@ TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
bitrate = maxBitrateKbit; bitrate = maxBitrateKbit;
} }
} }
_boundingSetToSend.SetEntry(i, bitrate,
_boundingSetToSend.ptrTmmbrSet[i] = bitrate; boundingSetToSend->PacketOH(i),
_boundingSetToSend.ptrPacketOHSet[i] = boundingSetToSend->ptrPacketOHSet[i]; boundingSetToSend->Ssrc(i));
_boundingSetToSend.ptrSsrcSet[i] = boundingSetToSend->ptrSsrcSet[i];
} }
_boundingSetToSend.lengthOfSet = boundingSetToSend->lengthOfSet;
return 0; return 0;
} }
@ -175,33 +208,34 @@ TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet)
// Work on local variable, will be modified // Work on local variable, will be modified
TMMBRSet candidateSet; TMMBRSet candidateSet;
candidateSet.VerifyAndAllocateSet(_candidateSet.sizeOfSet); candidateSet.VerifyAndAllocateSet(_candidateSet.sizeOfSet());
// Number of set candidates // TODO(hta) Figure out if this should be lengthOfSet instead.
WebRtc_Word32 numSetCandidates = 0; for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet(); i++)
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; i++)
{ {
if(_candidateSet.ptrTmmbrSet[i]) if(_candidateSet.Tmmbr(i))
{ {
numSetCandidates++; candidateSet.AddEntry(_candidateSet.Tmmbr(i),
candidateSet.ptrTmmbrSet[i] = _candidateSet.ptrTmmbrSet[i]; _candidateSet.PacketOH(i),
candidateSet.ptrPacketOHSet[i] = _candidateSet.ptrPacketOHSet[i]; _candidateSet.Ssrc(i));
candidateSet.ptrSsrcSet[i] = _candidateSet.ptrSsrcSet[i];
} }
else else
{ {
// make sure this is zero if tmmbr = 0 // make sure this is zero if tmmbr = 0
_candidateSet.ptrPacketOHSet[i] = 0; assert(_candidateSet.PacketOH(i) == 0);
// Old code:
// _candidateSet.ptrPacketOHSet[i] = 0;
} }
} }
candidateSet.lengthOfSet = numSetCandidates;
// Number of set candidates
WebRtc_Word32 numSetCandidates = candidateSet.lengthOfSet();
// Find bounding set // Find bounding set
WebRtc_UWord32 numBoundingSet = 0; WebRtc_UWord32 numBoundingSet = 0;
if (numSetCandidates > 0) if (numSetCandidates > 0)
{ {
numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet); numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet);
if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.sizeOfSet)) if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.sizeOfSet()))
{ {
return -1; return -1;
} }
@ -217,17 +251,18 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
CriticalSectionScoped lock(_criticalSection); CriticalSectionScoped lock(_criticalSection);
WebRtc_UWord32 numBoundingSet = 0; WebRtc_UWord32 numBoundingSet = 0;
VerifyAndAllocateBoundingSet(candidateSet.sizeOfSet); VerifyAndAllocateBoundingSet(candidateSet.sizeOfSet());
if (numCandidates == 1) if (numCandidates == 1)
{ {
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++) // TODO(hta): lengthOfSet instead of sizeOfSet?
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet(); i++)
{ {
if(candidateSet.ptrTmmbrSet[i] > 0) if (candidateSet.Tmmbr(i) > 0)
{ {
_boundingSet.ptrTmmbrSet[numBoundingSet] = candidateSet.ptrTmmbrSet[i]; _boundingSet.AddEntry(candidateSet.Tmmbr(i),
_boundingSet.ptrPacketOHSet[numBoundingSet] = candidateSet.ptrPacketOHSet[i]; candidateSet.PacketOH(i),
_boundingSet.ptrSsrcSet[numBoundingSet] = candidateSet.ptrSsrcSet[i]; candidateSet.Ssrc(i));
numBoundingSet++; numBoundingSet++;
} }
} }
@ -238,110 +273,103 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
} else } else
{ {
// 1. Sort by increasing packetOH // 1. Sort by increasing packetOH
WebRtc_UWord32 temp; for (int i = candidateSet.sizeOfSet() - 1; i >= 0; i--)
for (int i = candidateSet.sizeOfSet - 1; i >= 0; i--)
{ {
for (int j = 1; j <= i; j++) for (int j = 1; j <= i; j++)
{ {
if (candidateSet.ptrPacketOHSet[j-1] > candidateSet.ptrPacketOHSet[j]) if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j))
{ {
temp = candidateSet.ptrPacketOHSet[j-1]; candidateSet.SwapEntries(j-1, j);
candidateSet.ptrPacketOHSet[j-1] = candidateSet.ptrPacketOHSet[j];
candidateSet.ptrPacketOHSet[j] = temp;
temp = candidateSet.ptrTmmbrSet[j-1];
candidateSet.ptrTmmbrSet[j-1] = candidateSet.ptrTmmbrSet[j];
candidateSet.ptrTmmbrSet[j] = temp;
temp = candidateSet.ptrSsrcSet[j-1];
candidateSet.ptrSsrcSet[j-1] = candidateSet.ptrSsrcSet[j];
candidateSet.ptrSsrcSet[j] = temp;
} }
} }
} }
// 2. For tuples with same OH, keep the one w/ the lowest bitrate // 2. For tuples with same OH, keep the one w/ the lowest bitrate
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++) for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet(); i++)
{ {
if (candidateSet.ptrTmmbrSet[i] > 0) if (candidateSet.Tmmbr(i) > 0)
{ {
// get min bitrate for packets w/ same OH // get min bitrate for packets w/ same OH
WebRtc_UWord32 currentPacketOH = candidateSet.ptrPacketOHSet[i]; WebRtc_UWord32 currentPacketOH = candidateSet.PacketOH(i);
WebRtc_UWord32 currentMinTMMBR = candidateSet.ptrTmmbrSet[i]; WebRtc_UWord32 currentMinTMMBR = candidateSet.Tmmbr(i);
WebRtc_UWord32 currentMinIndexTMMBR = i; WebRtc_UWord32 currentMinIndexTMMBR = i;
for (WebRtc_UWord32 j = i+1; j < candidateSet.sizeOfSet; j++) for (WebRtc_UWord32 j = i+1; j < candidateSet.sizeOfSet(); j++)
{ {
if(candidateSet.ptrPacketOHSet[j] == currentPacketOH) if(candidateSet.PacketOH(j) == currentPacketOH)
{ {
if(candidateSet.ptrTmmbrSet[j] < currentMinTMMBR) if(candidateSet.Tmmbr(j) < currentMinTMMBR)
{ {
currentMinTMMBR = candidateSet.ptrTmmbrSet[j]; currentMinTMMBR = candidateSet.Tmmbr(j);
currentMinIndexTMMBR = j; currentMinIndexTMMBR = j;
} }
} }
} }
// keep lowest bitrate // keep lowest bitrate
for (WebRtc_UWord32 j = 0; j < candidateSet.sizeOfSet; j++) for (WebRtc_UWord32 j = 0; j < candidateSet.sizeOfSet(); j++)
{ {
if(candidateSet.ptrPacketOHSet[j] == currentPacketOH && j != currentMinIndexTMMBR) if(candidateSet.PacketOH(j) == currentPacketOH
&& j != currentMinIndexTMMBR)
{ {
candidateSet.ptrTmmbrSet[j] = 0; candidateSet.ClearEntry(j);
candidateSet.ptrPacketOHSet[j] = 0;
candidateSet.ptrSsrcSet[j] = 0;
numCandidates--;
} }
} }
} }
} }
// 3. Select and remove tuple w/ lowest tmmbr. (If more than 1, choose the one w/ highest OH). // 3. Select and remove tuple w/ lowest tmmbr.
// (If more than 1, choose the one w/ highest OH).
WebRtc_UWord32 minTMMBR = 0; WebRtc_UWord32 minTMMBR = 0;
WebRtc_UWord32 minIndexTMMBR = 0; WebRtc_UWord32 minIndexTMMBR = 0;
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++) for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet(); i++)
{ {
if (candidateSet.ptrTmmbrSet[i] > 0) if (candidateSet.Tmmbr(i) > 0)
{ {
minTMMBR = candidateSet.ptrTmmbrSet[i]; minTMMBR = candidateSet.Tmmbr(i);
minIndexTMMBR = i; minIndexTMMBR = i;
break; break;
} }
} }
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++) for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet(); i++)
{ {
if (candidateSet.ptrTmmbrSet[i] > 0 && candidateSet.ptrTmmbrSet[i] <= minTMMBR) if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR)
{ {
// get min bitrate // get min bitrate
minTMMBR = candidateSet.ptrTmmbrSet[i]; minTMMBR = candidateSet.Tmmbr(i);
minIndexTMMBR = i; minIndexTMMBR = i;
} }
} }
// first member of selected list // first member of selected list
_boundingSet.ptrTmmbrSet[numBoundingSet] = candidateSet.ptrTmmbrSet[minIndexTMMBR]; _boundingSet.SetEntry(numBoundingSet,
_boundingSet.ptrPacketOHSet[numBoundingSet] = candidateSet.ptrPacketOHSet[minIndexTMMBR]; candidateSet.Tmmbr(minIndexTMMBR),
_boundingSet.ptrSsrcSet[numBoundingSet] = candidateSet.ptrSsrcSet[minIndexTMMBR]; candidateSet.PacketOH(minIndexTMMBR),
candidateSet.Ssrc(minIndexTMMBR));
// set intersection value // set intersection value
_ptrIntersectionBoundingSet[numBoundingSet] = 0; _ptrIntersectionBoundingSet[numBoundingSet] = 0;
// calculate its maximum packet rate (where its line crosses x-axis) // calculate its maximum packet rate (where its line crosses x-axis)
_ptrMaxPRBoundingSet[numBoundingSet] = _boundingSet.ptrTmmbrSet[numBoundingSet]*1000 / float(8*_boundingSet.ptrPacketOHSet[numBoundingSet]); _ptrMaxPRBoundingSet[numBoundingSet]
= _boundingSet.Tmmbr(numBoundingSet) * 1000
/ float(8 * _boundingSet.PacketOH(numBoundingSet));
numBoundingSet++; numBoundingSet++;
// remove from candidate list // remove from candidate list
candidateSet.ptrTmmbrSet[minIndexTMMBR] = 0; candidateSet.ClearEntry(minIndexTMMBR);
candidateSet.ptrPacketOHSet[minIndexTMMBR] = 0;
candidateSet.ptrSsrcSet[minIndexTMMBR] = 0;
numCandidates--; numCandidates--;
// 4. Discard from candidate list all tuple w/ lower OH (next tuple must be steeper) // 4. Discard from candidate list all tuple w/ lower OH
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++) // (next tuple must be steeper)
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet(); i++)
{ {
if(candidateSet.ptrTmmbrSet[i] > 0 && candidateSet.ptrPacketOHSet[i] < _boundingSet.ptrPacketOHSet[0]) if(candidateSet.Tmmbr(i) > 0
&& candidateSet.PacketOH(i) < _boundingSet.PacketOH(0))
{ {
candidateSet.ptrTmmbrSet[i] = 0; candidateSet.ClearEntry(i);
candidateSet.ptrPacketOHSet[i] = 0;
candidateSet.ptrSsrcSet[i] = 0;
numCandidates--; numCandidates--;
} }
} }
if (numCandidates == 0) if (numCandidates == 0)
{ {
_boundingSet.lengthOfSet = numBoundingSet; // Should be true already:_boundingSet.lengthOfSet = numBoundingSet;
assert(_boundingSet.lengthOfSet() == numBoundingSet);
return numBoundingSet; return numBoundingSet;
} }
@ -355,47 +383,54 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
if (getNewCandidate) if (getNewCandidate)
{ {
// 5. Remove first remaining tuple from candidate list // 5. Remove first remaining tuple from candidate list
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++) for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet(); i++)
{ {
if (candidateSet.ptrTmmbrSet[i] > 0) if (candidateSet.Tmmbr(i) > 0)
{ {
curCandidateTMMBR = candidateSet.ptrTmmbrSet[i]; curCandidateTMMBR = candidateSet.Tmmbr(i);
curCandidatePacketOH = candidateSet.ptrPacketOHSet[i]; curCandidatePacketOH = candidateSet.PacketOH(i);
curCandidateSSRC = candidateSet.ptrSsrcSet[i]; curCandidateSSRC = candidateSet.Ssrc(i);
curCandidateIndex = i; curCandidateIndex = i;
candidateSet.ptrTmmbrSet[curCandidateIndex] = 0; candidateSet.ClearEntry(curCandidateIndex);
candidateSet.ptrPacketOHSet[curCandidateIndex] = 0;
candidateSet.ptrSsrcSet[curCandidateIndex] = 0;
break; break;
} }
} }
} }
// 6. Calculate packet rate and intersection of the current line with line of last tuple in selected list // 6. Calculate packet rate and intersection of the current
float packetRate = float(curCandidateTMMBR - _boundingSet.ptrTmmbrSet[numBoundingSet-1])*1000 / (8*(curCandidatePacketOH - _boundingSet.ptrPacketOHSet[numBoundingSet-1])); // line with line of last tuple in selected list
float packetRate
= float(curCandidateTMMBR
- _boundingSet.Tmmbr(numBoundingSet-1))*1000
/ (8*(curCandidatePacketOH
- _boundingSet.PacketOH(numBoundingSet-1)));
// 7. If the packet rate is equal or lower than intersection of last tuple in selected list, // 7. If the packet rate is equal or lower than intersection of
// last tuple in selected list,
// remove last tuple in selected list & go back to step 6 // remove last tuple in selected list & go back to step 6
if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1]) if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1])
{ {
// remove last tuple and goto step 6 // remove last tuple and goto step 6
numBoundingSet--; numBoundingSet--;
_boundingSet.ptrTmmbrSet[numBoundingSet] = 0; _boundingSet.ClearEntry(numBoundingSet);
_boundingSet.ptrPacketOHSet[numBoundingSet] = 0;
_boundingSet.ptrSsrcSet[numBoundingSet] = 0;
_ptrIntersectionBoundingSet[numBoundingSet] = 0; _ptrIntersectionBoundingSet[numBoundingSet] = 0;
_ptrMaxPRBoundingSet[numBoundingSet] = 0; _ptrMaxPRBoundingSet[numBoundingSet] = 0;
getNewCandidate = false; getNewCandidate = false;
} else } else
{ {
// 8. If packet rate is lower than maximum packet rate of last tuple in selected list, add current tuple to selected list // 8. If packet rate is lower than maximum packet rate of
// last tuple in selected list, add current tuple to selected
// list
if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1]) if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1])
{ {
_boundingSet.ptrTmmbrSet[numBoundingSet] = curCandidateTMMBR; _boundingSet.SetEntry(numBoundingSet,
_boundingSet.ptrPacketOHSet[numBoundingSet] = curCandidatePacketOH; curCandidateTMMBR,
_boundingSet.ptrSsrcSet[numBoundingSet] = curCandidateSSRC; curCandidatePacketOH,
curCandidateSSRC);
_ptrIntersectionBoundingSet[numBoundingSet] = packetRate; _ptrIntersectionBoundingSet[numBoundingSet] = packetRate;
_ptrMaxPRBoundingSet[numBoundingSet] = _boundingSet.ptrTmmbrSet[numBoundingSet]*1000 / float(8*_boundingSet.ptrPacketOHSet[numBoundingSet]); _ptrMaxPRBoundingSet[numBoundingSet]
= _boundingSet.Tmmbr(numBoundingSet)*1000
/ float(8*_boundingSet.PacketOH(numBoundingSet));
numBoundingSet++; numBoundingSet++;
} }
numCandidates--; numCandidates--;
@ -405,7 +440,6 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
// 9. Go back to step 5 if any tuple remains in candidate list // 9. Go back to step 5 if any tuple remains in candidate list
} while (numCandidates > 0); } while (numCandidates > 0);
} }
_boundingSet.lengthOfSet = numBoundingSet;
return numBoundingSet; return numBoundingSet;
} }
@ -417,8 +451,9 @@ bool TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
// Empty bounding set. // Empty bounding set.
return false; return false;
} }
for(WebRtc_UWord32 i = 0; (i < length) && (i < _boundingSet.sizeOfSet); ++i) { for(WebRtc_UWord32 i = 0;
if(_boundingSet.ptrSsrcSet[i] == ssrc) { (i < length) && (i < _boundingSet.sizeOfSet()); ++i) {
if(_boundingSet.Ssrc(i) == ssrc) {
return true; return true;
} }
} }
@ -428,14 +463,14 @@ bool TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
bool TMMBRHelp::CalcMinBitRate( WebRtc_UWord32* minBitrateKbit) const { bool TMMBRHelp::CalcMinBitRate( WebRtc_UWord32* minBitrateKbit) const {
CriticalSectionScoped lock(_criticalSection); CriticalSectionScoped lock(_criticalSection);
if (_candidateSet.sizeOfSet == 0) { if (_candidateSet.sizeOfSet() == 0) {
// Empty bounding set. // Empty bounding set.
return false; return false;
} }
*minBitrateKbit = std::numeric_limits<uint32_t>::max(); *minBitrateKbit = std::numeric_limits<uint32_t>::max();
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; ++i) { for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet(); ++i) {
WebRtc_UWord32 curNetBitRateKbit = _candidateSet.ptrTmmbrSet[i]; WebRtc_UWord32 curNetBitRateKbit = _candidateSet.Tmmbr(i);
if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) { if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE; curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
} }

View File

@ -11,6 +11,7 @@
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_
#include <vector>
#include "typedefs.h" #include "typedefs.h"
#include "critical_section_wrapper.h" #include "critical_section_wrapper.h"
@ -27,12 +28,55 @@ public:
~TMMBRSet(); ~TMMBRSet();
void VerifyAndAllocateSet(WebRtc_UWord32 minimumSize); void VerifyAndAllocateSet(WebRtc_UWord32 minimumSize);
void VerifyAndAllocateSetKeepingData(WebRtc_UWord32 minimumSize);
// Number of valid data items in set.
WebRtc_UWord32 lengthOfSet() const { return _lengthOfSet; }
// Presently allocated max size of set.
WebRtc_UWord32 sizeOfSet() const { return _sizeOfSet; }
void clearSet() {
_lengthOfSet = 0;
}
WebRtc_UWord32 Tmmbr(int i) const {
return _data.at(i).tmmbr;
}
WebRtc_UWord32 PacketOH(int i) const {
return _data.at(i).packet_oh;
}
WebRtc_UWord32 Ssrc(int i) const {
return _data.at(i).ssrc;
}
void SetEntry(unsigned int i,
WebRtc_UWord32 tmmbrSet,
WebRtc_UWord32 packetOHSet,
WebRtc_UWord32 ssrcSet);
WebRtc_UWord32* ptrTmmbrSet; void AddEntry(WebRtc_UWord32 tmmbrSet,
WebRtc_UWord32* ptrPacketOHSet; WebRtc_UWord32 packetOHSet,
WebRtc_UWord32* ptrSsrcSet; WebRtc_UWord32 ssrcSet);
WebRtc_UWord32 sizeOfSet;
WebRtc_UWord32 lengthOfSet; // Remove one entry from table, and move all others down.
void RemoveEntry(WebRtc_UWord32 sourceIdx);
void SwapEntries(WebRtc_UWord32 firstIdx,
WebRtc_UWord32 secondIdx);
// Set entry data to zero, but keep it in table.
void ClearEntry(WebRtc_UWord32 idx);
private:
class SetElement {
public:
SetElement() : tmmbr(0), packet_oh(0), ssrc(0) {}
WebRtc_UWord32 tmmbr;
WebRtc_UWord32 packet_oh;
WebRtc_UWord32 ssrc;
};
std::vector<SetElement> _data;
// Number of places allocated.
WebRtc_UWord32 _sizeOfSet;
// NUmber of places currently in use.
WebRtc_UWord32 _lengthOfSet;
}; };
class TMMBRHelp class TMMBRHelp