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) >
5 * RTCP_INTERVAL_AUDIO_MS) {
// 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
receiveInfo->lastTimeReceived = 0;
// send new TMMBN to all channels using the default codec
@ -687,23 +687,22 @@ WebRtc_Word32 RTCPReceiver::BoundingSet(bool &tmmbrOwner,
__FUNCTION__);
return -1;
}
if (receiveInfo->TmmbnBoundingSet.lengthOfSet > 0) {
if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
boundingSetRec->VerifyAndAllocateSet(
receiveInfo->TmmbnBoundingSet.lengthOfSet + 1);
for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet; i++) {
if(receiveInfo->TmmbnBoundingSet.ptrSsrcSet[i] == _SSRC) {
receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
for(WebRtc_UWord32 i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
i++) {
if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
// owner of bounding set
tmmbrOwner = true;
}
boundingSetRec->ptrTmmbrSet[i] =
receiveInfo->TmmbnBoundingSet.ptrTmmbrSet[i];
boundingSetRec->ptrPacketOHSet[i] =
receiveInfo->TmmbnBoundingSet.ptrPacketOHSet[i];
boundingSetRec->ptrSsrcSet[i] =
receiveInfo->TmmbnBoundingSet.ptrSsrcSet[i];
boundingSetRec->SetEntry(i,
receiveInfo->TmmbnBoundingSet.Tmmbr(i),
receiveInfo->TmmbnBoundingSet.PacketOH(i),
receiveInfo->TmmbnBoundingSet.Ssrc(i));
}
}
return receiveInfo->TmmbnBoundingSet.lengthOfSet;
return receiveInfo->TmmbnBoundingSet.lengthOfSet();
}
// no need for critsect we have _criticalSectionRTCPReceiver
@ -992,13 +991,10 @@ void
RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
const RTCPUtility::RTCPPacket& rtcpPacket)
{
const unsigned int idx = receiveInfo.TmmbnBoundingSet.lengthOfSet;
receiveInfo.TmmbnBoundingSet.ptrTmmbrSet[idx] = rtcpPacket.TMMBNItem.MaxTotalMediaBitRate;
receiveInfo.TmmbnBoundingSet.ptrPacketOHSet[idx] = rtcpPacket.TMMBNItem.MeasuredOverhead;
receiveInfo.TmmbnBoundingSet.ptrSsrcSet[idx] = rtcpPacket.TMMBNItem.SSRC;
++receiveInfo.TmmbnBoundingSet.lengthOfSet;
receiveInfo.TmmbnBoundingSet.AddEntry(
rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
rtcpPacket.TMMBNItem.MeasuredOverhead,
rtcpPacket.TMMBNItem.SSRC);
}
// no need for critsect we have _criticalSectionRTCPReceiver
@ -1376,7 +1372,7 @@ WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
return 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,
_clock.GetTimeInMS()) == 0) {
num++;
@ -1393,7 +1389,7 @@ WebRtc_Word32 RTCPReceiver::TMMBRReceived(const WebRtc_UWord32 size,
__FUNCTION__);
return -1;
}
num += receiveInfo->TmmbrSet.lengthOfSet;
num += receiveInfo->TmmbrSet.lengthOfSet();
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
* 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
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
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];
if(TmmbrSet.lengthOfSet > 0)
if(TmmbrSet.lengthOfSet() > 0)
{
// copy old values
memcpy(ptrTmmbrSet, TmmbrSet.ptrTmmbrSet, 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;
memcpy(tmmbrSetTimeouts, _tmmbrSetTimeouts,
sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet());
}
if(_tmmbrSetTimeouts)
{
delete [] _tmmbrSetTimeouts;
}
TmmbrSet.ptrTmmbrSet = ptrTmmbrSet;
TmmbrSet.ptrPacketOHSet = ptrTmmbrPacketOHSet;
TmmbrSet.ptrSsrcSet = ptrTmmbrSsrcSet;
TmmbrSet.sizeOfSet = minimumSize;
_tmmbrSetTimeouts = tmmbrSetTimeouts;
}
}
@ -191,26 +177,26 @@ RTCPReceiveInformation::InsertTMMBRItem(const WebRtc_UWord32 senderSSRC,
const WebRtc_UWord32 currentTimeMS)
{
// 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
// update it
TmmbrSet.ptrPacketOHSet[i] = TMMBRItem.MeasuredOverhead;
TmmbrSet.ptrTmmbrSet[i] = TMMBRItem.MaxTotalMediaBitRate;
TmmbrSet.SetEntry(i,
TMMBRItem.MaxTotalMediaBitRate,
TMMBRItem.MeasuredOverhead,
senderSSRC);
_tmmbrSetTimeouts[i] = currentTimeMS;
return;
}
}
VerifyAndAllocateTMMBRSet(TmmbrSet.lengthOfSet+1);
const WebRtc_UWord32 idx = TmmbrSet.lengthOfSet;
TmmbrSet.ptrPacketOHSet[idx] = TMMBRItem.MeasuredOverhead;
TmmbrSet.ptrTmmbrSet[idx] = TMMBRItem.MaxTotalMediaBitRate;
TmmbrSet.ptrSsrcSet[idx] = senderSSRC;
const WebRtc_UWord32 idx = TmmbrSet.lengthOfSet();
VerifyAndAllocateTMMBRSet(idx+1);
TmmbrSet.AddEntry(TMMBRItem.MaxTotalMediaBitRate,
TMMBRItem.MeasuredOverhead,
senderSSRC);
_tmmbrSetTimeouts[idx] = currentTimeMS;
TmmbrSet.lengthOfSet++;
}
WebRtc_Word32
@ -219,11 +205,11 @@ RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx,
TMMBRSet* candidateSet,
const WebRtc_UWord32 currentTimeMS)
{
if(sourceIdx >= TmmbrSet.lengthOfSet)
if(sourceIdx >= TmmbrSet.lengthOfSet())
{
return -1;
}
if(targetIdx >= candidateSet->sizeOfSet)
if(targetIdx >= candidateSet->sizeOfSet())
{
return -1;
}
@ -233,21 +219,17 @@ RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx,
if(timeNow - _tmmbrSetTimeouts[sourceIdx] > 5*RTCP_INTERVAL_AUDIO_MS)
{
// value timed out
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));
TmmbrSet.RemoveEntry(sourceIdx);
const WebRtc_UWord32 move = TmmbrSet.lengthOfSet() - (sourceIdx + 1);
if (move > 0) {
memmove(&(_tmmbrSetTimeouts[sourceIdx]),&(_tmmbrSetTimeouts[sourceIdx+1]), move* sizeof(WebRtc_UWord32));
}
TmmbrSet.lengthOfSet--;
return -1;
}
candidateSet->ptrTmmbrSet[targetIdx] = TmmbrSet.ptrTmmbrSet[sourceIdx];
candidateSet->ptrPacketOHSet[targetIdx] = TmmbrSet.ptrPacketOHSet[sourceIdx];
candidateSet->ptrSsrcSet[targetIdx] = TmmbrSet.ptrSsrcSet[sourceIdx];
candidateSet->SetEntry(targetIdx,
TmmbrSet.Tmmbr(sourceIdx),
TmmbrSet.PacketOH(sourceIdx),
TmmbrSet.Ssrc(sourceIdx));
return 0;
}

View File

@ -258,8 +258,8 @@ TEST_F(RtcpReceiverTest, TmmbrPacketAccepted) {
TMMBRSet candidate_set;
candidate_set.VerifyAndAllocateSet(1);
EXPECT_EQ(1, rtcp_receiver_->TMMBRReceived(1, 0, &candidate_set));
EXPECT_LT(0U, candidate_set.ptrTmmbrSet[0]);
EXPECT_EQ(kMediaRecipientSsrc, candidate_set.ptrSsrcSet[0]);
EXPECT_LT(0U, candidate_set.Tmmbr(0));
EXPECT_EQ(kMediaRecipientSsrc, candidate_set.Ssrc(0));
}
TEST_F(RtcpReceiverTest, TmmbrPacketNotForUsIgnored) {
@ -328,7 +328,7 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) {
TMMBRSet candidate_set;
candidate_set.VerifyAndAllocateSet(3);
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
// seconds, timing out the first packet.
system_clock_->AdvanceClock(12000);
@ -336,7 +336,7 @@ TEST_F(RtcpReceiverTest, TmmbrThreeConstraintsTimeOut) {
EXPECT_EQ(3, rtcp_receiver_->TMMBRReceived(0, 0, NULL));
// Odd behaviour: There's only one left after timeout, not 2.
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
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
// is a potental deadlock but since RTCPreceiver is not doing the revese we should be fine
WebRtc_Word32 lengthOfBoundingSet = _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
// holding _criticalSectionRTCPSender while calling RTCPreceiver which
// will accuire _criticalSectionRTCPReceiver is a potental deadlock but
// since RTCPreceiver is not doing the reverse we should be fine
WebRtc_Word32 lengthOfBoundingSet
= _rtpRtcp.BoundingSet(tmmbrOwner, candidateSet);
if(lengthOfBoundingSet > 0)
{
for (WebRtc_Word32 i = 0; i < lengthOfBoundingSet; i++)
{
if( candidateSet->ptrTmmbrSet[i] == _tmmbr_Send &&
candidateSet->ptrPacketOHSet[i] == _packetOH_Send)
if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
candidateSet->PacketOH(i) == _packetOH_Send)
{
// do not send the same tuple
return 0;
@ -1155,9 +1158,10 @@ RTCPSender::BuildTMMBR(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
{
// use received bounding set as candidate set
// add current tuple
candidateSet->ptrTmmbrSet[lengthOfBoundingSet] = _tmmbr_Send;
candidateSet->ptrPacketOHSet[lengthOfBoundingSet] = _packetOH_Send;
candidateSet->ptrSsrcSet[lengthOfBoundingSet] = _SSRC;
candidateSet->SetEntry(lengthOfBoundingSet,
_tmmbr_Send,
_packetOH_Send,
_SSRC);
int numCandidates = lengthOfBoundingSet+ 1;
// find bounding set
@ -1236,7 +1240,7 @@ RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
return -1;
}
// 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__);
return -2;
@ -1265,15 +1269,15 @@ RTCPSender::BuildTMMBN(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
// Additional Feedback Control Information (FCI)
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);
pos += 4;
WebRtc_UWord32 bitRate = boundingSet->ptrTmmbrSet[n] * 1000;
WebRtc_UWord32 bitRate = boundingSet->Tmmbr(n) * 1000;
WebRtc_UWord32 mmbrExp = 0;
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 measuredOH = boundingSet->ptrPacketOHSet[n];
WebRtc_UWord32 measuredOH = boundingSet->PacketOH(n);
rtcpbuffer[pos++]=(WebRtc_UWord8)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
rtcpbuffer[pos++]=(WebRtc_UWord8)(mmbrMantissa >> 7);

View File

@ -204,13 +204,8 @@ TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndValid) {
EXPECT_EQ(0, rtcp_sender_->SetRTCPStatus(kRtcpCompound));
TMMBRSet bounding_set;
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;
bounding_set.ptrPacketOHSet[idx] = 0;
bounding_set.ptrTmmbrSet[idx] = 32768; // bits per second
bounding_set.ptrSsrcSet[idx] = kSourceSsrc;
bounding_set.lengthOfSet++;
bounding_set.AddEntry(32768, 0, kSourceSsrc);
EXPECT_EQ(0, rtcp_sender_->SetTMMBN(&bounding_set, 3));
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.
EXPECT_EQ(1, test_transport_->rtcp_receiver_->BoundingSet(owner,
&incoming_set));
EXPECT_EQ(kSourceSsrc, incoming_set.ptrSsrcSet[0]);
EXPECT_EQ(kSourceSsrc, incoming_set.Ssrc(0));
}
} // namespace webrtc

View File

@ -10,56 +10,91 @@
#include "tmmbr_help.h"
#include <assert.h>
#include <limits>
#include <string.h>
#include "rtp_rtcp_config.h"
namespace webrtc {
TMMBRSet::TMMBRSet() :
ptrTmmbrSet(0),
ptrPacketOHSet(0),
ptrSsrcSet(0),
sizeOfSet(0),
lengthOfSet(0)
_sizeOfSet(0),
_lengthOfSet(0)
{
}
TMMBRSet::~TMMBRSet()
{
delete [] ptrTmmbrSet;
delete [] ptrPacketOHSet;
delete [] ptrSsrcSet;
ptrTmmbrSet = 0;
ptrPacketOHSet = 0;
ptrSsrcSet = 0;
sizeOfSet = 0;
lengthOfSet = 0;
_sizeOfSet = 0;
_lengthOfSet = 0;
}
void
TMMBRSet::VerifyAndAllocateSet(WebRtc_UWord32 minimumSize)
{
if(minimumSize > sizeOfSet)
if(minimumSize > _sizeOfSet)
{
// make sure that our buffers are big enough
if(ptrTmmbrSet)
{
delete [] ptrTmmbrSet;
delete [] ptrPacketOHSet;
delete [] ptrSsrcSet;
}
ptrTmmbrSet = new WebRtc_UWord32[minimumSize];
ptrPacketOHSet = new WebRtc_UWord32[minimumSize];
ptrSsrcSet = new WebRtc_UWord32[minimumSize];
sizeOfSet = minimumSize;
_data.resize(minimumSize);
_sizeOfSet = minimumSize;
}
// reset memory
for(WebRtc_UWord32 i = 0; i < sizeOfSet; i++)
for(WebRtc_UWord32 i = 0; i < _sizeOfSet; i++)
{
ptrTmmbrSet[i] = 0;
ptrPacketOHSet[i] = 0;
ptrSsrcSet[i] = 0;
_data.at(i).tmmbr = 0;
_data.at(i).packet_oh = 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()
@ -84,7 +119,7 @@ TMMBRHelp::VerifyAndAllocateBoundingSet(WebRtc_UWord32 minimumSize)
{
CriticalSectionScoped lock(_criticalSection);
if(minimumSize > _boundingSet.sizeOfSet)
if(minimumSize > _boundingSet.sizeOfSet())
{
// make sure that our buffers are big enough
if(_ptrIntersectionBoundingSet)
@ -111,16 +146,16 @@ TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
if (boundingSetToSend == NULL)
{
_boundingSetToSend.lengthOfSet = 0;
_boundingSetToSend.clearSet();
return 0;
}
VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet);
for (WebRtc_UWord32 i = 0; i < boundingSetToSend->lengthOfSet; i++)
VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet());
_boundingSetToSend.clearSet();
for (WebRtc_UWord32 i = 0; i < boundingSetToSend->lengthOfSet(); i++)
{
// cap at our configured max bitrate
WebRtc_UWord32 bitrate = boundingSetToSend->ptrTmmbrSet[i];
WebRtc_UWord32 bitrate = boundingSetToSend->Tmmbr(i);
if(maxBitrateKbit)
{
// do we have a configured max bitrate?
@ -129,12 +164,10 @@ TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
bitrate = maxBitrateKbit;
}
}
_boundingSetToSend.ptrTmmbrSet[i] = bitrate;
_boundingSetToSend.ptrPacketOHSet[i] = boundingSetToSend->ptrPacketOHSet[i];
_boundingSetToSend.ptrSsrcSet[i] = boundingSetToSend->ptrSsrcSet[i];
_boundingSetToSend.SetEntry(i, bitrate,
boundingSetToSend->PacketOH(i),
boundingSetToSend->Ssrc(i));
}
_boundingSetToSend.lengthOfSet = boundingSetToSend->lengthOfSet;
return 0;
}
@ -175,33 +208,34 @@ TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet)
// Work on local variable, will be modified
TMMBRSet candidateSet;
candidateSet.VerifyAndAllocateSet(_candidateSet.sizeOfSet);
candidateSet.VerifyAndAllocateSet(_candidateSet.sizeOfSet());
// Number of set candidates
WebRtc_Word32 numSetCandidates = 0;
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; i++)
// TODO(hta) Figure out if this should be lengthOfSet instead.
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet(); i++)
{
if(_candidateSet.ptrTmmbrSet[i])
if(_candidateSet.Tmmbr(i))
{
numSetCandidates++;
candidateSet.ptrTmmbrSet[i] = _candidateSet.ptrTmmbrSet[i];
candidateSet.ptrPacketOHSet[i] = _candidateSet.ptrPacketOHSet[i];
candidateSet.ptrSsrcSet[i] = _candidateSet.ptrSsrcSet[i];
candidateSet.AddEntry(_candidateSet.Tmmbr(i),
_candidateSet.PacketOH(i),
_candidateSet.Ssrc(i));
}
else
{
// 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
WebRtc_UWord32 numBoundingSet = 0;
if (numSetCandidates > 0)
{
numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet);
if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.sizeOfSet))
if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.sizeOfSet()))
{
return -1;
}
@ -217,17 +251,18 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
CriticalSectionScoped lock(_criticalSection);
WebRtc_UWord32 numBoundingSet = 0;
VerifyAndAllocateBoundingSet(candidateSet.sizeOfSet);
VerifyAndAllocateBoundingSet(candidateSet.sizeOfSet());
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.ptrPacketOHSet[numBoundingSet] = candidateSet.ptrPacketOHSet[i];
_boundingSet.ptrSsrcSet[numBoundingSet] = candidateSet.ptrSsrcSet[i];
_boundingSet.AddEntry(candidateSet.Tmmbr(i),
candidateSet.PacketOH(i),
candidateSet.Ssrc(i));
numBoundingSet++;
}
}
@ -238,110 +273,103 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
} else
{
// 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++)
{
if (candidateSet.ptrPacketOHSet[j-1] > candidateSet.ptrPacketOHSet[j])
if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j))
{
temp = candidateSet.ptrPacketOHSet[j-1];
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;
candidateSet.SwapEntries(j-1, j);
}
}
}
// 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
WebRtc_UWord32 currentPacketOH = candidateSet.ptrPacketOHSet[i];
WebRtc_UWord32 currentMinTMMBR = candidateSet.ptrTmmbrSet[i];
WebRtc_UWord32 currentPacketOH = candidateSet.PacketOH(i);
WebRtc_UWord32 currentMinTMMBR = candidateSet.Tmmbr(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;
}
}
}
// 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.ptrPacketOHSet[j] = 0;
candidateSet.ptrSsrcSet[j] = 0;
numCandidates--;
candidateSet.ClearEntry(j);
}
}
}
}
// 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 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;
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
minTMMBR = candidateSet.ptrTmmbrSet[i];
minTMMBR = candidateSet.Tmmbr(i);
minIndexTMMBR = i;
}
}
// first member of selected list
_boundingSet.ptrTmmbrSet[numBoundingSet] = candidateSet.ptrTmmbrSet[minIndexTMMBR];
_boundingSet.ptrPacketOHSet[numBoundingSet] = candidateSet.ptrPacketOHSet[minIndexTMMBR];
_boundingSet.ptrSsrcSet[numBoundingSet] = candidateSet.ptrSsrcSet[minIndexTMMBR];
_boundingSet.SetEntry(numBoundingSet,
candidateSet.Tmmbr(minIndexTMMBR),
candidateSet.PacketOH(minIndexTMMBR),
candidateSet.Ssrc(minIndexTMMBR));
// set intersection value
_ptrIntersectionBoundingSet[numBoundingSet] = 0;
// 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++;
// remove from candidate list
candidateSet.ptrTmmbrSet[minIndexTMMBR] = 0;
candidateSet.ptrPacketOHSet[minIndexTMMBR] = 0;
candidateSet.ptrSsrcSet[minIndexTMMBR] = 0;
candidateSet.ClearEntry(minIndexTMMBR);
numCandidates--;
// 4. Discard from candidate list all tuple w/ lower OH (next tuple must be steeper)
for (WebRtc_UWord32 i = 0; i < candidateSet.sizeOfSet; i++)
// 4. Discard from candidate list all tuple w/ lower OH
// (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.ptrPacketOHSet[i] = 0;
candidateSet.ptrSsrcSet[i] = 0;
candidateSet.ClearEntry(i);
numCandidates--;
}
}
if (numCandidates == 0)
{
_boundingSet.lengthOfSet = numBoundingSet;
// Should be true already:_boundingSet.lengthOfSet = numBoundingSet;
assert(_boundingSet.lengthOfSet() == numBoundingSet);
return numBoundingSet;
}
@ -355,47 +383,54 @@ TMMBRHelp::FindTMMBRBoundingSet(WebRtc_Word32 numCandidates, TMMBRSet& candidate
if (getNewCandidate)
{
// 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];
curCandidatePacketOH = candidateSet.ptrPacketOHSet[i];
curCandidateSSRC = candidateSet.ptrSsrcSet[i];
curCandidateTMMBR = candidateSet.Tmmbr(i);
curCandidatePacketOH = candidateSet.PacketOH(i);
curCandidateSSRC = candidateSet.Ssrc(i);
curCandidateIndex = i;
candidateSet.ptrTmmbrSet[curCandidateIndex] = 0;
candidateSet.ptrPacketOHSet[curCandidateIndex] = 0;
candidateSet.ptrSsrcSet[curCandidateIndex] = 0;
candidateSet.ClearEntry(curCandidateIndex);
break;
}
}
}
// 6. Calculate packet rate and intersection of the current line with line of last tuple in selected list
float packetRate = float(curCandidateTMMBR - _boundingSet.ptrTmmbrSet[numBoundingSet-1])*1000 / (8*(curCandidatePacketOH - _boundingSet.ptrPacketOHSet[numBoundingSet-1]));
// 6. Calculate packet rate and intersection of the current
// 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
if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1])
{
// remove last tuple and goto step 6
numBoundingSet--;
_boundingSet.ptrTmmbrSet[numBoundingSet] = 0;
_boundingSet.ptrPacketOHSet[numBoundingSet] = 0;
_boundingSet.ptrSsrcSet[numBoundingSet] = 0;
_boundingSet.ClearEntry(numBoundingSet);
_ptrIntersectionBoundingSet[numBoundingSet] = 0;
_ptrMaxPRBoundingSet[numBoundingSet] = 0;
getNewCandidate = false;
} 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])
{
_boundingSet.ptrTmmbrSet[numBoundingSet] = curCandidateTMMBR;
_boundingSet.ptrPacketOHSet[numBoundingSet] = curCandidatePacketOH;
_boundingSet.ptrSsrcSet[numBoundingSet] = curCandidateSSRC;
_boundingSet.SetEntry(numBoundingSet,
curCandidateTMMBR,
curCandidatePacketOH,
curCandidateSSRC);
_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++;
}
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
} while (numCandidates > 0);
}
_boundingSet.lengthOfSet = numBoundingSet;
return numBoundingSet;
}
@ -417,8 +451,9 @@ bool TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
// Empty bounding set.
return false;
}
for(WebRtc_UWord32 i = 0; (i < length) && (i < _boundingSet.sizeOfSet); ++i) {
if(_boundingSet.ptrSsrcSet[i] == ssrc) {
for(WebRtc_UWord32 i = 0;
(i < length) && (i < _boundingSet.sizeOfSet()); ++i) {
if(_boundingSet.Ssrc(i) == ssrc) {
return true;
}
}
@ -428,14 +463,14 @@ bool TMMBRHelp::IsOwner(const WebRtc_UWord32 ssrc,
bool TMMBRHelp::CalcMinBitRate( WebRtc_UWord32* minBitrateKbit) const {
CriticalSectionScoped lock(_criticalSection);
if (_candidateSet.sizeOfSet == 0) {
if (_candidateSet.sizeOfSet() == 0) {
// Empty bounding set.
return false;
}
*minBitrateKbit = std::numeric_limits<uint32_t>::max();
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet; ++i) {
WebRtc_UWord32 curNetBitRateKbit = _candidateSet.ptrTmmbrSet[i];
for (WebRtc_UWord32 i = 0; i < _candidateSet.sizeOfSet(); ++i) {
WebRtc_UWord32 curNetBitRateKbit = _candidateSet.Tmmbr(i);
if (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_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_
#include <vector>
#include "typedefs.h"
#include "critical_section_wrapper.h"
@ -27,12 +28,55 @@ public:
~TMMBRSet();
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;
WebRtc_UWord32* ptrPacketOHSet;
WebRtc_UWord32* ptrSsrcSet;
WebRtc_UWord32 sizeOfSet;
WebRtc_UWord32 lengthOfSet;
void AddEntry(WebRtc_UWord32 tmmbrSet,
WebRtc_UWord32 packetOHSet,
WebRtc_UWord32 ssrcSet);
// 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