blob: af9509089240fc59ff969ea86a210fd991178d32 [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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
hta@webrtc.org54536bb2012-05-03 14:07:23 +000013#include <assert.h>
hta@webrtc.org54536bb2012-05-03 14:07:23 +000014#include <string.h>
danilchapb8b6fbb2015-12-10 05:05:27 -080015
16#include <limits>
17
danilchapf6ff9712016-02-24 09:23:37 -080018#include "webrtc/base/checks.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
21namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000022void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000023TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +000024{
danilchapa4f31bd2016-02-29 05:26:01 -080025 clear();
26 reserve(minimumSize);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000027}
28
29void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000030TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize)
hta@webrtc.org54536bb2012-05-03 14:07:23 +000031{
danilchapa4f31bd2016-02-29 05:26:01 -080032 reserve(minimumSize);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000033}
34
35void TMMBRSet::SetEntry(unsigned int i,
pbos@webrtc.org2f446732013-04-08 11:08:41 +000036 uint32_t tmmbrSet,
37 uint32_t packetOHSet,
38 uint32_t ssrcSet) {
danilchapa4f31bd2016-02-29 05:26:01 -080039 RTC_DCHECK_LT(i, capacity());
40 if (i >= size()) {
41 resize(i+1);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000042 }
danilchapa4f31bd2016-02-29 05:26:01 -080043 (*this)[i].set_bitrate_bps(tmmbrSet * 1000);
44 (*this)[i].set_packet_overhead(packetOHSet);
45 (*this)[i].set_ssrc(ssrcSet);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000046}
47
pbos@webrtc.org2f446732013-04-08 11:08:41 +000048void TMMBRSet::AddEntry(uint32_t tmmbrSet,
49 uint32_t packetOHSet,
50 uint32_t ssrcSet) {
danilchapa4f31bd2016-02-29 05:26:01 -080051 RTC_DCHECK_LT(size(), capacity());
52 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000053}
54
pbos@webrtc.org2f446732013-04-08 11:08:41 +000055void TMMBRSet::RemoveEntry(uint32_t sourceIdx) {
danilchapa4f31bd2016-02-29 05:26:01 -080056 RTC_DCHECK_LT(sourceIdx, size());
57 erase(begin() + sourceIdx);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000058}
59
pbos@webrtc.org2f446732013-04-08 11:08:41 +000060void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) {
danilchapa4f31bd2016-02-29 05:26:01 -080061 using std::swap;
62 swap((*this)[i], (*this)[j]);
hta@webrtc.org54536bb2012-05-03 14:07:23 +000063}
64
pbos@webrtc.org2f446732013-04-08 11:08:41 +000065void TMMBRSet::ClearEntry(uint32_t idx) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000066 SetEntry(idx, 0, 0, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +000067}
68
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000069TMMBRHelp::TMMBRHelp()
danilchap7c9426c2016-04-14 03:05:31 -070070 : _candidateSet(),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000071 _boundingSet(),
72 _boundingSetToSend(),
73 _ptrIntersectionBoundingSet(NULL),
74 _ptrMaxPRBoundingSet(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +000075}
76
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000077TMMBRHelp::~TMMBRHelp() {
78 delete [] _ptrIntersectionBoundingSet;
79 delete [] _ptrMaxPRBoundingSet;
80 _ptrIntersectionBoundingSet = 0;
81 _ptrMaxPRBoundingSet = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000082}
83
84TMMBRSet*
pbos@webrtc.org2f446732013-04-08 11:08:41 +000085TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +000086{
danilchap7c9426c2016-04-14 03:05:31 -070087 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +000088
danilchapa4f31bd2016-02-29 05:26:01 -080089 if(minimumSize > _boundingSet.capacity())
niklase@google.com470e71d2011-07-07 08:21:25 +000090 {
91 // make sure that our buffers are big enough
92 if(_ptrIntersectionBoundingSet)
93 {
94 delete [] _ptrIntersectionBoundingSet;
95 delete [] _ptrMaxPRBoundingSet;
96 }
97 _ptrIntersectionBoundingSet = new float[minimumSize];
98 _ptrMaxPRBoundingSet = new float[minimumSize];
99 }
100 _boundingSet.VerifyAndAllocateSet(minimumSize);
101 return &_boundingSet;
102}
103
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000104TMMBRSet* TMMBRHelp::BoundingSet() {
105 return &_boundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106}
107
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000108int32_t
Peter Boström9d0c4322016-02-16 17:59:27 +0100109TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend)
niklase@google.com470e71d2011-07-07 08:21:25 +0000110{
danilchap7c9426c2016-04-14 03:05:31 -0700111 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000112
113 if (boundingSetToSend == NULL)
114 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000115 _boundingSetToSend.clearSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 return 0;
117 }
118
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000119 VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet());
120 _boundingSetToSend.clearSet();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000121 for (uint32_t i = 0; i < boundingSetToSend->lengthOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000122 {
123 // cap at our configured max bitrate
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000124 uint32_t bitrate = boundingSetToSend->Tmmbr(i);
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000125 _boundingSetToSend.SetEntry(i, bitrate,
126 boundingSetToSend->PacketOH(i),
127 boundingSetToSend->Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000129 return 0;
130}
131
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000132int32_t
133TMMBRHelp::VerifyAndAllocateBoundingSetToSend(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000134{
danilchap7c9426c2016-04-14 03:05:31 -0700135 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
137 _boundingSetToSend.VerifyAndAllocateSet(minimumSize);
138 return 0;
139}
140
141TMMBRSet*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000142TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000143{
danilchap7c9426c2016-04-14 03:05:31 -0700144 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
146 _candidateSet.VerifyAndAllocateSet(minimumSize);
147 return &_candidateSet;
148}
149
150TMMBRSet*
151TMMBRHelp::CandidateSet()
152{
153 return &_candidateSet;
154}
155
156TMMBRSet*
157TMMBRHelp::BoundingSetToSend()
158{
159 return &_boundingSetToSend;
160}
161
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000162int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000163TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet)
164{
danilchap7c9426c2016-04-14 03:05:31 -0700165 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
167 // Work on local variable, will be modified
168 TMMBRSet candidateSet;
danilchapa4f31bd2016-02-29 05:26:01 -0800169 candidateSet.VerifyAndAllocateSet(_candidateSet.capacity());
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
danilchapa4f31bd2016-02-29 05:26:01 -0800171 for (uint32_t i = 0; i < _candidateSet.size(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000173 if(_candidateSet.Tmmbr(i))
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000175 candidateSet.AddEntry(_candidateSet.Tmmbr(i),
176 _candidateSet.PacketOH(i),
177 _candidateSet.Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 }
179 else
180 {
181 // make sure this is zero if tmmbr = 0
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000182 assert(_candidateSet.PacketOH(i) == 0);
183 // Old code:
184 // _candidateSet.ptrPacketOHSet[i] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 }
186 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000187
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000188 // Number of set candidates
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000189 int32_t numSetCandidates = candidateSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 // Find bounding set
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000191 uint32_t numBoundingSet = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000192 if (numSetCandidates > 0)
193 {
194 numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet);
danilchapa4f31bd2016-02-29 05:26:01 -0800195 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.size()))
niklase@google.com470e71d2011-07-07 08:21:25 +0000196 {
197 return -1;
198 }
199 boundingSet = &_boundingSet;
200 }
201 return numBoundingSet;
202}
203
204
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000205int32_t
206TMMBRHelp::FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet)
niklase@google.com470e71d2011-07-07 08:21:25 +0000207{
danilchap7c9426c2016-04-14 03:05:31 -0700208 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000209
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000210 uint32_t numBoundingSet = 0;
danilchapa4f31bd2016-02-29 05:26:01 -0800211 VerifyAndAllocateBoundingSet(candidateSet.capacity());
niklase@google.com470e71d2011-07-07 08:21:25 +0000212
213 if (numCandidates == 1)
214 {
danilchapa4f31bd2016-02-29 05:26:01 -0800215 for (uint32_t i = 0; i < candidateSet.size(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000216 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000217 if (candidateSet.Tmmbr(i) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000218 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000219 _boundingSet.AddEntry(candidateSet.Tmmbr(i),
220 candidateSet.PacketOH(i),
221 candidateSet.Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000222 numBoundingSet++;
223 }
224 }
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000225 return (numBoundingSet == 1) ? 1 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226 }
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000227
228 // 1. Sort by increasing packetOH
danilchapa4f31bd2016-02-29 05:26:01 -0800229 for (int i = candidateSet.size() - 1; i >= 0; i--)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000230 {
231 for (int j = 1; j <= i; j++)
232 {
233 if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j))
234 {
235 candidateSet.SwapEntries(j-1, j);
236 }
237 }
238 }
239 // 2. For tuples with same OH, keep the one w/ the lowest bitrate
danilchapa4f31bd2016-02-29 05:26:01 -0800240 for (uint32_t i = 0; i < candidateSet.size(); i++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000241 {
242 if (candidateSet.Tmmbr(i) > 0)
243 {
244 // get min bitrate for packets w/ same OH
245 uint32_t currentPacketOH = candidateSet.PacketOH(i);
246 uint32_t currentMinTMMBR = candidateSet.Tmmbr(i);
247 uint32_t currentMinIndexTMMBR = i;
danilchapa4f31bd2016-02-29 05:26:01 -0800248 for (uint32_t j = i+1; j < candidateSet.size(); j++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000249 {
250 if(candidateSet.PacketOH(j) == currentPacketOH)
251 {
252 if(candidateSet.Tmmbr(j) < currentMinTMMBR)
253 {
254 currentMinTMMBR = candidateSet.Tmmbr(j);
255 currentMinIndexTMMBR = j;
256 }
257 }
258 }
259 // keep lowest bitrate
danilchapa4f31bd2016-02-29 05:26:01 -0800260 for (uint32_t j = 0; j < candidateSet.size(); j++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000261 {
262 if(candidateSet.PacketOH(j) == currentPacketOH
263 && j != currentMinIndexTMMBR)
264 {
265 candidateSet.ClearEntry(j);
danilchapf6ff9712016-02-24 09:23:37 -0800266 numCandidates--;
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000267 }
268 }
269 }
270 }
271 // 3. Select and remove tuple w/ lowest tmmbr.
272 // (If more than 1, choose the one w/ highest OH).
273 uint32_t minTMMBR = 0;
274 uint32_t minIndexTMMBR = 0;
danilchapa4f31bd2016-02-29 05:26:01 -0800275 for (uint32_t i = 0; i < candidateSet.size(); i++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000276 {
277 if (candidateSet.Tmmbr(i) > 0)
278 {
279 minTMMBR = candidateSet.Tmmbr(i);
280 minIndexTMMBR = i;
281 break;
282 }
283 }
284
danilchapa4f31bd2016-02-29 05:26:01 -0800285 for (uint32_t i = 0; i < candidateSet.size(); i++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000286 {
287 if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR)
288 {
289 // get min bitrate
290 minTMMBR = candidateSet.Tmmbr(i);
291 minIndexTMMBR = i;
292 }
293 }
294 // first member of selected list
295 _boundingSet.SetEntry(numBoundingSet,
296 candidateSet.Tmmbr(minIndexTMMBR),
297 candidateSet.PacketOH(minIndexTMMBR),
298 candidateSet.Ssrc(minIndexTMMBR));
299
300 // set intersection value
301 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
302 // calculate its maximum packet rate (where its line crosses x-axis)
danilchapf6ff9712016-02-24 09:23:37 -0800303 uint32_t packet_overhead_bits = 8 * _boundingSet.PacketOH(numBoundingSet);
304 if (packet_overhead_bits == 0) {
305 // Avoid division by zero.
306 _ptrMaxPRBoundingSet[numBoundingSet] = std::numeric_limits<float>::max();
307 } else {
308 _ptrMaxPRBoundingSet[numBoundingSet] =
309 _boundingSet.Tmmbr(numBoundingSet) * 1000 /
310 static_cast<float>(packet_overhead_bits);
311 }
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000312 numBoundingSet++;
313 // remove from candidate list
314 candidateSet.ClearEntry(minIndexTMMBR);
315 numCandidates--;
316
317 // 4. Discard from candidate list all tuple w/ lower OH
318 // (next tuple must be steeper)
danilchapa4f31bd2016-02-29 05:26:01 -0800319 for (uint32_t i = 0; i < candidateSet.size(); i++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000320 {
321 if(candidateSet.Tmmbr(i) > 0
322 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0))
323 {
324 candidateSet.ClearEntry(i);
325 numCandidates--;
326 }
327 }
328
329 if (numCandidates == 0)
330 {
331 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet;
332 assert(_boundingSet.lengthOfSet() == numBoundingSet);
333 return numBoundingSet;
334 }
335
336 bool getNewCandidate = true;
danilchapf6ff9712016-02-24 09:23:37 -0800337 uint32_t curCandidateTMMBR = 0;
338 size_t curCandidateIndex = 0;
339 uint32_t curCandidatePacketOH = 0;
340 uint32_t curCandidateSSRC = 0;
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000341 do
342 {
343 if (getNewCandidate)
344 {
345 // 5. Remove first remaining tuple from candidate list
danilchapa4f31bd2016-02-29 05:26:01 -0800346 for (uint32_t i = 0; i < candidateSet.size(); i++)
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000347 {
348 if (candidateSet.Tmmbr(i) > 0)
349 {
350 curCandidateTMMBR = candidateSet.Tmmbr(i);
351 curCandidatePacketOH = candidateSet.PacketOH(i);
352 curCandidateSSRC = candidateSet.Ssrc(i);
353 curCandidateIndex = i;
354 candidateSet.ClearEntry(curCandidateIndex);
355 break;
356 }
357 }
358 }
359
360 // 6. Calculate packet rate and intersection of the current
361 // line with line of last tuple in selected list
danilchapf6ff9712016-02-24 09:23:37 -0800362 RTC_DCHECK_NE(curCandidatePacketOH,
363 _boundingSet.PacketOH(numBoundingSet - 1));
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000364 float packetRate
365 = float(curCandidateTMMBR
366 - _boundingSet.Tmmbr(numBoundingSet-1))*1000
367 / (8*(curCandidatePacketOH
368 - _boundingSet.PacketOH(numBoundingSet-1)));
369
370 // 7. If the packet rate is equal or lower than intersection of
371 // last tuple in selected list,
372 // remove last tuple in selected list & go back to step 6
373 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1])
374 {
375 // remove last tuple and goto step 6
376 numBoundingSet--;
377 _boundingSet.ClearEntry(numBoundingSet);
378 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
379 _ptrMaxPRBoundingSet[numBoundingSet] = 0;
380 getNewCandidate = false;
381 } else
382 {
383 // 8. If packet rate is lower than maximum packet rate of
384 // last tuple in selected list, add current tuple to selected
385 // list
386 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1])
387 {
388 _boundingSet.SetEntry(numBoundingSet,
389 curCandidateTMMBR,
390 curCandidatePacketOH,
391 curCandidateSSRC);
392 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate;
danilchapf6ff9712016-02-24 09:23:37 -0800393 float packet_overhead_bits =
394 8 * _boundingSet.PacketOH(numBoundingSet);
395 RTC_DCHECK_NE(packet_overhead_bits, 0.0f);
396 _ptrMaxPRBoundingSet[numBoundingSet] =
397 _boundingSet.Tmmbr(numBoundingSet) * 1000 /
398 packet_overhead_bits;
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000399 numBoundingSet++;
400 }
401 numCandidates--;
402 getNewCandidate = true;
403 }
404
405 // 9. Go back to step 5 if any tuple remains in candidate list
406 } while (numCandidates > 0);
407
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 return numBoundingSet;
409}
410
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000411bool TMMBRHelp::IsOwner(const uint32_t ssrc,
412 const uint32_t length) const {
danilchap7c9426c2016-04-14 03:05:31 -0700413 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000415 if (length == 0) {
416 // Empty bounding set.
henrike@webrtc.org0ad51862012-03-30 16:54:13 +0000417 return false;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000418 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000419 for(uint32_t i = 0;
danilchapa4f31bd2016-02-29 05:26:01 -0800420 (i < length) && (i < _boundingSet.size()); ++i) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000421 if(_boundingSet.Ssrc(i) == ssrc) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000422 return true;
423 }
424 }
425 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000426}
427
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000428bool TMMBRHelp::CalcMinBitRate( uint32_t* minBitrateKbit) const {
danilchap7c9426c2016-04-14 03:05:31 -0700429 rtc::CritScope lock(&_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000430
danilchapa4f31bd2016-02-29 05:26:01 -0800431 if (_candidateSet.size() == 0) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000432 // Empty bounding set.
433 return false;
434 }
435 *minBitrateKbit = std::numeric_limits<uint32_t>::max();
436
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000437 for (uint32_t i = 0; i < _candidateSet.lengthOfSet(); ++i) {
438 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000439 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
440 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000442 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ?
443 curNetBitRateKbit : *minBitrateKbit;
444 }
445 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000446}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000447} // namespace webrtc