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:
parent
3bc38c86e8
commit
54536bb6d4
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user