blob: 5bd6221425be312740a256384c91bc9c145951f2 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "tmmbr_help.h"
12
hta@webrtc.org54536bb2012-05-03 14:07:23 +000013#include <assert.h>
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000014#include <limits>
hta@webrtc.org54536bb2012-05-03 14:07:23 +000015#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000016#include "rtp_rtcp_config.h"
17
18namespace webrtc {
19TMMBRSet::TMMBRSet() :
hta@webrtc.org54536bb2012-05-03 14:07:23 +000020 _sizeOfSet(0),
21 _lengthOfSet(0)
niklase@google.com470e71d2011-07-07 08:21:25 +000022{
23}
24
25TMMBRSet::~TMMBRSet()
26{
hta@webrtc.org54536bb2012-05-03 14:07:23 +000027 _sizeOfSet = 0;
28 _lengthOfSet = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000029}
30
31void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000032TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +000033{
hta@webrtc.org54536bb2012-05-03 14:07:23 +000034 if(minimumSize > _sizeOfSet)
niklase@google.com470e71d2011-07-07 08:21:25 +000035 {
36 // make sure that our buffers are big enough
hta@webrtc.org54536bb2012-05-03 14:07:23 +000037 _data.resize(minimumSize);
38 _sizeOfSet = minimumSize;
niklase@google.com470e71d2011-07-07 08:21:25 +000039 }
40 // reset memory
pbos@webrtc.org2f446732013-04-08 11:08:41 +000041 for(uint32_t i = 0; i < _sizeOfSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +000042 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000043 _data.at(i).tmmbr = 0;
44 _data.at(i).packet_oh = 0;
45 _data.at(i).ssrc = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000046 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +000047 _lengthOfSet = 0;
48}
49
50void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000051TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize)
hta@webrtc.org54536bb2012-05-03 14:07:23 +000052{
53 if(minimumSize > _sizeOfSet)
54 {
55 {
56 _data.resize(minimumSize);
57 }
58 _sizeOfSet = minimumSize;
59 }
60}
61
62void TMMBRSet::SetEntry(unsigned int i,
pbos@webrtc.org2f446732013-04-08 11:08:41 +000063 uint32_t tmmbrSet,
64 uint32_t packetOHSet,
65 uint32_t ssrcSet) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000066 assert(i < _sizeOfSet);
67 _data.at(i).tmmbr = tmmbrSet;
68 _data.at(i).packet_oh = packetOHSet;
69 _data.at(i).ssrc = ssrcSet;
70 if (i >= _lengthOfSet) {
71 _lengthOfSet = i + 1;
72 }
73}
74
pbos@webrtc.org2f446732013-04-08 11:08:41 +000075void TMMBRSet::AddEntry(uint32_t tmmbrSet,
76 uint32_t packetOHSet,
77 uint32_t ssrcSet) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000078 assert(_lengthOfSet < _sizeOfSet);
79 SetEntry(_lengthOfSet, tmmbrSet, packetOHSet, ssrcSet);
80}
81
pbos@webrtc.org2f446732013-04-08 11:08:41 +000082void TMMBRSet::RemoveEntry(uint32_t sourceIdx) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000083 assert(sourceIdx < _lengthOfSet);
84 _data.erase(_data.begin() + sourceIdx);
85 _lengthOfSet--;
86 _data.resize(_sizeOfSet); // Ensure that size remains the same.
87}
88
pbos@webrtc.org2f446732013-04-08 11:08:41 +000089void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000090 SetElement temp;
91 temp = _data[i];
92 _data[i] = _data[j];
93 _data[j] = temp;
94}
95
pbos@webrtc.org2f446732013-04-08 11:08:41 +000096void TMMBRSet::ClearEntry(uint32_t idx) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000097 SetEntry(idx, 0, 0, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +000098}
99
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000100TMMBRHelp::TMMBRHelp()
101 : _criticalSection(CriticalSectionWrapper::CreateCriticalSection()),
102 _candidateSet(),
103 _boundingSet(),
104 _boundingSetToSend(),
105 _ptrIntersectionBoundingSet(NULL),
106 _ptrMaxPRBoundingSet(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000107}
108
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000109TMMBRHelp::~TMMBRHelp() {
110 delete [] _ptrIntersectionBoundingSet;
111 delete [] _ptrMaxPRBoundingSet;
112 _ptrIntersectionBoundingSet = 0;
113 _ptrMaxPRBoundingSet = 0;
114 delete _criticalSection;
niklase@google.com470e71d2011-07-07 08:21:25 +0000115}
116
117TMMBRSet*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000118TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000119{
120 CriticalSectionScoped lock(_criticalSection);
121
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000122 if(minimumSize > _boundingSet.sizeOfSet())
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 {
124 // make sure that our buffers are big enough
125 if(_ptrIntersectionBoundingSet)
126 {
127 delete [] _ptrIntersectionBoundingSet;
128 delete [] _ptrMaxPRBoundingSet;
129 }
130 _ptrIntersectionBoundingSet = new float[minimumSize];
131 _ptrMaxPRBoundingSet = new float[minimumSize];
132 }
133 _boundingSet.VerifyAndAllocateSet(minimumSize);
134 return &_boundingSet;
135}
136
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000137TMMBRSet* TMMBRHelp::BoundingSet() {
138 return &_boundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000139}
140
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000141int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000142TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000143 const uint32_t maxBitrateKbit)
niklase@google.com470e71d2011-07-07 08:21:25 +0000144{
145 CriticalSectionScoped lock(_criticalSection);
146
147 if (boundingSetToSend == NULL)
148 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000149 _boundingSetToSend.clearSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 return 0;
151 }
152
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000153 VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet());
154 _boundingSetToSend.clearSet();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000155 for (uint32_t i = 0; i < boundingSetToSend->lengthOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 {
157 // cap at our configured max bitrate
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000158 uint32_t bitrate = boundingSetToSend->Tmmbr(i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000159 if(maxBitrateKbit)
160 {
161 // do we have a configured max bitrate?
162 if(bitrate > maxBitrateKbit)
163 {
164 bitrate = maxBitrateKbit;
165 }
166 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000167 _boundingSetToSend.SetEntry(i, bitrate,
168 boundingSetToSend->PacketOH(i),
169 boundingSetToSend->Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000170 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 return 0;
172}
173
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000174int32_t
175TMMBRHelp::VerifyAndAllocateBoundingSetToSend(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000176{
177 CriticalSectionScoped lock(_criticalSection);
178
179 _boundingSetToSend.VerifyAndAllocateSet(minimumSize);
180 return 0;
181}
182
183TMMBRSet*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000184TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000185{
186 CriticalSectionScoped lock(_criticalSection);
187
188 _candidateSet.VerifyAndAllocateSet(minimumSize);
189 return &_candidateSet;
190}
191
192TMMBRSet*
193TMMBRHelp::CandidateSet()
194{
195 return &_candidateSet;
196}
197
198TMMBRSet*
199TMMBRHelp::BoundingSetToSend()
200{
201 return &_boundingSetToSend;
202}
203
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000204int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000205TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet)
206{
207 CriticalSectionScoped lock(_criticalSection);
208
209 // Work on local variable, will be modified
210 TMMBRSet candidateSet;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000211 candidateSet.VerifyAndAllocateSet(_candidateSet.sizeOfSet());
niklase@google.com470e71d2011-07-07 08:21:25 +0000212
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000213 // TODO(hta) Figure out if this should be lengthOfSet instead.
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000214 for (uint32_t i = 0; i < _candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000215 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000216 if(_candidateSet.Tmmbr(i))
niklase@google.com470e71d2011-07-07 08:21:25 +0000217 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000218 candidateSet.AddEntry(_candidateSet.Tmmbr(i),
219 _candidateSet.PacketOH(i),
220 _candidateSet.Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 }
222 else
223 {
224 // make sure this is zero if tmmbr = 0
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000225 assert(_candidateSet.PacketOH(i) == 0);
226 // Old code:
227 // _candidateSet.ptrPacketOHSet[i] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 }
229 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000230
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000231 // Number of set candidates
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000232 int32_t numSetCandidates = candidateSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000233 // Find bounding set
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000234 uint32_t numBoundingSet = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 if (numSetCandidates > 0)
236 {
237 numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet);
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000238 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.sizeOfSet()))
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 {
240 return -1;
241 }
242 boundingSet = &_boundingSet;
243 }
244 return numBoundingSet;
245}
246
247
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000248int32_t
249TMMBRHelp::FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet)
niklase@google.com470e71d2011-07-07 08:21:25 +0000250{
251 CriticalSectionScoped lock(_criticalSection);
252
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000253 uint32_t numBoundingSet = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000254 VerifyAndAllocateBoundingSet(candidateSet.sizeOfSet());
niklase@google.com470e71d2011-07-07 08:21:25 +0000255
256 if (numCandidates == 1)
257 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000258 // TODO(hta): lengthOfSet instead of sizeOfSet?
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000259 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000260 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000261 if (candidateSet.Tmmbr(i) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000262 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000263 _boundingSet.AddEntry(candidateSet.Tmmbr(i),
264 candidateSet.PacketOH(i),
265 candidateSet.Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 numBoundingSet++;
267 }
268 }
269 if (numBoundingSet != 1)
270 {
271 numBoundingSet = -1;
272 }
273 } else
274 {
275 // 1. Sort by increasing packetOH
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000276 for (int i = candidateSet.sizeOfSet() - 1; i >= 0; i--)
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 {
278 for (int j = 1; j <= i; j++)
279 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000280 if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j))
niklase@google.com470e71d2011-07-07 08:21:25 +0000281 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000282 candidateSet.SwapEntries(j-1, j);
niklase@google.com470e71d2011-07-07 08:21:25 +0000283 }
284 }
285 }
286 // 2. For tuples with same OH, keep the one w/ the lowest bitrate
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000287 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000288 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000289 if (candidateSet.Tmmbr(i) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 {
291 // get min bitrate for packets w/ same OH
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000292 uint32_t currentPacketOH = candidateSet.PacketOH(i);
293 uint32_t currentMinTMMBR = candidateSet.Tmmbr(i);
294 uint32_t currentMinIndexTMMBR = i;
295 for (uint32_t j = i+1; j < candidateSet.sizeOfSet(); j++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000296 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000297 if(candidateSet.PacketOH(j) == currentPacketOH)
niklase@google.com470e71d2011-07-07 08:21:25 +0000298 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000299 if(candidateSet.Tmmbr(j) < currentMinTMMBR)
niklase@google.com470e71d2011-07-07 08:21:25 +0000300 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000301 currentMinTMMBR = candidateSet.Tmmbr(j);
niklase@google.com470e71d2011-07-07 08:21:25 +0000302 currentMinIndexTMMBR = j;
303 }
304 }
305 }
306 // keep lowest bitrate
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000307 for (uint32_t j = 0; j < candidateSet.sizeOfSet(); j++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000309 if(candidateSet.PacketOH(j) == currentPacketOH
310 && j != currentMinIndexTMMBR)
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000312 candidateSet.ClearEntry(j);
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 }
314 }
315 }
316 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000317 // 3. Select and remove tuple w/ lowest tmmbr.
318 // (If more than 1, choose the one w/ highest OH).
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000319 uint32_t minTMMBR = 0;
320 uint32_t minIndexTMMBR = 0;
321 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000322 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000323 if (candidateSet.Tmmbr(i) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000324 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000325 minTMMBR = candidateSet.Tmmbr(i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000326 minIndexTMMBR = i;
327 break;
328 }
329 }
330
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000331 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000332 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000333 if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR)
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 {
335 // get min bitrate
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000336 minTMMBR = candidateSet.Tmmbr(i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000337 minIndexTMMBR = i;
338 }
339 }
340 // first member of selected list
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000341 _boundingSet.SetEntry(numBoundingSet,
342 candidateSet.Tmmbr(minIndexTMMBR),
343 candidateSet.PacketOH(minIndexTMMBR),
344 candidateSet.Ssrc(minIndexTMMBR));
345
niklase@google.com470e71d2011-07-07 08:21:25 +0000346 // set intersection value
347 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
348 // calculate its maximum packet rate (where its line crosses x-axis)
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000349 _ptrMaxPRBoundingSet[numBoundingSet]
350 = _boundingSet.Tmmbr(numBoundingSet) * 1000
351 / float(8 * _boundingSet.PacketOH(numBoundingSet));
niklase@google.com470e71d2011-07-07 08:21:25 +0000352 numBoundingSet++;
353 // remove from candidate list
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000354 candidateSet.ClearEntry(minIndexTMMBR);
niklase@google.com470e71d2011-07-07 08:21:25 +0000355 numCandidates--;
356
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000357 // 4. Discard from candidate list all tuple w/ lower OH
358 // (next tuple must be steeper)
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000359 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000360 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000361 if(candidateSet.Tmmbr(i) > 0
362 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0))
niklase@google.com470e71d2011-07-07 08:21:25 +0000363 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000364 candidateSet.ClearEntry(i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 numCandidates--;
366 }
367 }
368
369 if (numCandidates == 0)
370 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000371 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet;
372 assert(_boundingSet.lengthOfSet() == numBoundingSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000373 return numBoundingSet;
374 }
375
376 bool getNewCandidate = true;
377 int curCandidateTMMBR = 0;
378 int curCandidateIndex = 0;
379 int curCandidatePacketOH = 0;
380 int curCandidateSSRC = 0;
381 do
382 {
383 if (getNewCandidate)
384 {
385 // 5. Remove first remaining tuple from candidate list
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000386 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000388 if (candidateSet.Tmmbr(i) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000389 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000390 curCandidateTMMBR = candidateSet.Tmmbr(i);
391 curCandidatePacketOH = candidateSet.PacketOH(i);
392 curCandidateSSRC = candidateSet.Ssrc(i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000393 curCandidateIndex = i;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000394 candidateSet.ClearEntry(curCandidateIndex);
niklase@google.com470e71d2011-07-07 08:21:25 +0000395 break;
396 }
397 }
398 }
399
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000400 // 6. Calculate packet rate and intersection of the current
401 // line with line of last tuple in selected list
402 float packetRate
403 = float(curCandidateTMMBR
404 - _boundingSet.Tmmbr(numBoundingSet-1))*1000
405 / (8*(curCandidatePacketOH
406 - _boundingSet.PacketOH(numBoundingSet-1)));
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000408 // 7. If the packet rate is equal or lower than intersection of
409 // last tuple in selected list,
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 // remove last tuple in selected list & go back to step 6
411 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1])
412 {
413 // remove last tuple and goto step 6
414 numBoundingSet--;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000415 _boundingSet.ClearEntry(numBoundingSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
417 _ptrMaxPRBoundingSet[numBoundingSet] = 0;
418 getNewCandidate = false;
419 } else
420 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000421 // 8. If packet rate is lower than maximum packet rate of
422 // last tuple in selected list, add current tuple to selected
423 // list
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1])
425 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000426 _boundingSet.SetEntry(numBoundingSet,
427 curCandidateTMMBR,
428 curCandidatePacketOH,
429 curCandidateSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000431 _ptrMaxPRBoundingSet[numBoundingSet]
432 = _boundingSet.Tmmbr(numBoundingSet)*1000
433 / float(8*_boundingSet.PacketOH(numBoundingSet));
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 numBoundingSet++;
435 }
436 numCandidates--;
437 getNewCandidate = true;
438 }
439
440 // 9. Go back to step 5 if any tuple remains in candidate list
441 } while (numCandidates > 0);
442 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 return numBoundingSet;
444}
445
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000446bool TMMBRHelp::IsOwner(const uint32_t ssrc,
447 const uint32_t length) const {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000448 CriticalSectionScoped lock(_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000449
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000450 if (length == 0) {
451 // Empty bounding set.
henrike@webrtc.org0ad51862012-03-30 16:54:13 +0000452 return false;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000453 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000454 for(uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000455 (i < length) && (i < _boundingSet.sizeOfSet()); ++i) {
456 if(_boundingSet.Ssrc(i) == ssrc) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000457 return true;
458 }
459 }
460 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000461}
462
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000463bool TMMBRHelp::CalcMinBitRate( uint32_t* minBitrateKbit) const {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000464 CriticalSectionScoped lock(_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000466 if (_candidateSet.sizeOfSet() == 0) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000467 // Empty bounding set.
468 return false;
469 }
470 *minBitrateKbit = std::numeric_limits<uint32_t>::max();
471
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000472 for (uint32_t i = 0; i < _candidateSet.lengthOfSet(); ++i) {
473 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000474 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
475 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
niklase@google.com470e71d2011-07-07 08:21:25 +0000476 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000477 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ?
478 curNetBitRateKbit : *minBitrateKbit;
479 }
480 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000481}
482} // namespace webrtc