blob: 5c090504ca07fe5b4f9f0bb4838f3ef55238a7f3 [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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
20namespace webrtc {
21TMMBRSet::TMMBRSet() :
hta@webrtc.org54536bb2012-05-03 14:07:23 +000022 _sizeOfSet(0),
23 _lengthOfSet(0)
niklase@google.com470e71d2011-07-07 08:21:25 +000024{
25}
26
27TMMBRSet::~TMMBRSet()
28{
hta@webrtc.org54536bb2012-05-03 14:07:23 +000029 _sizeOfSet = 0;
30 _lengthOfSet = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000031}
32
33void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000034TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +000035{
hta@webrtc.org54536bb2012-05-03 14:07:23 +000036 if(minimumSize > _sizeOfSet)
niklase@google.com470e71d2011-07-07 08:21:25 +000037 {
38 // make sure that our buffers are big enough
hta@webrtc.org54536bb2012-05-03 14:07:23 +000039 _data.resize(minimumSize);
40 _sizeOfSet = minimumSize;
niklase@google.com470e71d2011-07-07 08:21:25 +000041 }
42 // reset memory
pbos@webrtc.org2f446732013-04-08 11:08:41 +000043 for(uint32_t i = 0; i < _sizeOfSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +000044 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000045 _data.at(i).tmmbr = 0;
46 _data.at(i).packet_oh = 0;
47 _data.at(i).ssrc = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000048 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +000049 _lengthOfSet = 0;
50}
51
52void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000053TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize)
hta@webrtc.org54536bb2012-05-03 14:07:23 +000054{
55 if(minimumSize > _sizeOfSet)
56 {
57 {
58 _data.resize(minimumSize);
59 }
60 _sizeOfSet = minimumSize;
61 }
62}
63
64void TMMBRSet::SetEntry(unsigned int i,
pbos@webrtc.org2f446732013-04-08 11:08:41 +000065 uint32_t tmmbrSet,
66 uint32_t packetOHSet,
67 uint32_t ssrcSet) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000068 assert(i < _sizeOfSet);
69 _data.at(i).tmmbr = tmmbrSet;
70 _data.at(i).packet_oh = packetOHSet;
71 _data.at(i).ssrc = ssrcSet;
72 if (i >= _lengthOfSet) {
73 _lengthOfSet = i + 1;
74 }
75}
76
pbos@webrtc.org2f446732013-04-08 11:08:41 +000077void TMMBRSet::AddEntry(uint32_t tmmbrSet,
78 uint32_t packetOHSet,
79 uint32_t ssrcSet) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000080 assert(_lengthOfSet < _sizeOfSet);
81 SetEntry(_lengthOfSet, tmmbrSet, packetOHSet, ssrcSet);
82}
83
pbos@webrtc.org2f446732013-04-08 11:08:41 +000084void TMMBRSet::RemoveEntry(uint32_t sourceIdx) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000085 assert(sourceIdx < _lengthOfSet);
86 _data.erase(_data.begin() + sourceIdx);
87 _lengthOfSet--;
88 _data.resize(_sizeOfSet); // Ensure that size remains the same.
89}
90
pbos@webrtc.org2f446732013-04-08 11:08:41 +000091void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000092 SetElement temp;
93 temp = _data[i];
94 _data[i] = _data[j];
95 _data[j] = temp;
96}
97
pbos@webrtc.org2f446732013-04-08 11:08:41 +000098void TMMBRSet::ClearEntry(uint32_t idx) {
hta@webrtc.org54536bb2012-05-03 14:07:23 +000099 SetEntry(idx, 0, 0, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000100}
101
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000102TMMBRHelp::TMMBRHelp()
103 : _criticalSection(CriticalSectionWrapper::CreateCriticalSection()),
104 _candidateSet(),
105 _boundingSet(),
106 _boundingSetToSend(),
107 _ptrIntersectionBoundingSet(NULL),
108 _ptrMaxPRBoundingSet(NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000109}
110
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000111TMMBRHelp::~TMMBRHelp() {
112 delete [] _ptrIntersectionBoundingSet;
113 delete [] _ptrMaxPRBoundingSet;
114 _ptrIntersectionBoundingSet = 0;
115 _ptrMaxPRBoundingSet = 0;
116 delete _criticalSection;
niklase@google.com470e71d2011-07-07 08:21:25 +0000117}
118
119TMMBRSet*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000120TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000121{
122 CriticalSectionScoped lock(_criticalSection);
123
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000124 if(minimumSize > _boundingSet.sizeOfSet())
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 {
126 // make sure that our buffers are big enough
127 if(_ptrIntersectionBoundingSet)
128 {
129 delete [] _ptrIntersectionBoundingSet;
130 delete [] _ptrMaxPRBoundingSet;
131 }
132 _ptrIntersectionBoundingSet = new float[minimumSize];
133 _ptrMaxPRBoundingSet = new float[minimumSize];
134 }
135 _boundingSet.VerifyAndAllocateSet(minimumSize);
136 return &_boundingSet;
137}
138
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000139TMMBRSet* TMMBRHelp::BoundingSet() {
140 return &_boundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000141}
142
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000143int32_t
Peter Boström9d0c4322016-02-16 17:59:27 +0100144TMMBRHelp::SetTMMBRBoundingSetToSend(const TMMBRSet* boundingSetToSend)
niklase@google.com470e71d2011-07-07 08:21:25 +0000145{
146 CriticalSectionScoped lock(_criticalSection);
147
148 if (boundingSetToSend == NULL)
149 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000150 _boundingSetToSend.clearSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000151 return 0;
152 }
153
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000154 VerifyAndAllocateBoundingSetToSend(boundingSetToSend->lengthOfSet());
155 _boundingSetToSend.clearSet();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000156 for (uint32_t i = 0; i < boundingSetToSend->lengthOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 {
158 // cap at our configured max bitrate
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000159 uint32_t bitrate = boundingSetToSend->Tmmbr(i);
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000160 _boundingSetToSend.SetEntry(i, bitrate,
161 boundingSetToSend->PacketOH(i),
162 boundingSetToSend->Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000164 return 0;
165}
166
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000167int32_t
168TMMBRHelp::VerifyAndAllocateBoundingSetToSend(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000169{
170 CriticalSectionScoped lock(_criticalSection);
171
172 _boundingSetToSend.VerifyAndAllocateSet(minimumSize);
173 return 0;
174}
175
176TMMBRSet*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000177TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize)
niklase@google.com470e71d2011-07-07 08:21:25 +0000178{
179 CriticalSectionScoped lock(_criticalSection);
180
181 _candidateSet.VerifyAndAllocateSet(minimumSize);
182 return &_candidateSet;
183}
184
185TMMBRSet*
186TMMBRHelp::CandidateSet()
187{
188 return &_candidateSet;
189}
190
191TMMBRSet*
192TMMBRHelp::BoundingSetToSend()
193{
194 return &_boundingSetToSend;
195}
196
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000197int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000198TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet)
199{
200 CriticalSectionScoped lock(_criticalSection);
201
202 // Work on local variable, will be modified
203 TMMBRSet candidateSet;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000204 candidateSet.VerifyAndAllocateSet(_candidateSet.sizeOfSet());
niklase@google.com470e71d2011-07-07 08:21:25 +0000205
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000206 // TODO(hta) Figure out if this should be lengthOfSet instead.
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000207 for (uint32_t i = 0; i < _candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000209 if(_candidateSet.Tmmbr(i))
niklase@google.com470e71d2011-07-07 08:21:25 +0000210 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000211 candidateSet.AddEntry(_candidateSet.Tmmbr(i),
212 _candidateSet.PacketOH(i),
213 _candidateSet.Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000214 }
215 else
216 {
217 // make sure this is zero if tmmbr = 0
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000218 assert(_candidateSet.PacketOH(i) == 0);
219 // Old code:
220 // _candidateSet.ptrPacketOHSet[i] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 }
222 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000223
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000224 // Number of set candidates
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000225 int32_t numSetCandidates = candidateSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000226 // Find bounding set
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000227 uint32_t numBoundingSet = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 if (numSetCandidates > 0)
229 {
230 numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet);
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000231 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.sizeOfSet()))
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 {
233 return -1;
234 }
235 boundingSet = &_boundingSet;
236 }
237 return numBoundingSet;
238}
239
240
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000241int32_t
242TMMBRHelp::FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet)
niklase@google.com470e71d2011-07-07 08:21:25 +0000243{
244 CriticalSectionScoped lock(_criticalSection);
245
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000246 uint32_t numBoundingSet = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000247 VerifyAndAllocateBoundingSet(candidateSet.sizeOfSet());
niklase@google.com470e71d2011-07-07 08:21:25 +0000248
249 if (numCandidates == 1)
250 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000251 // TODO(hta): lengthOfSet instead of sizeOfSet?
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000252 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000254 if (candidateSet.Tmmbr(i) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000255 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000256 _boundingSet.AddEntry(candidateSet.Tmmbr(i),
257 candidateSet.PacketOH(i),
258 candidateSet.Ssrc(i));
niklase@google.com470e71d2011-07-07 08:21:25 +0000259 numBoundingSet++;
260 }
261 }
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000262 return (numBoundingSet == 1) ? 1 : -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000263 }
tommi@webrtc.orgeec6ecd2014-07-11 19:09:59 +0000264
265 // 1. Sort by increasing packetOH
266 for (int i = candidateSet.sizeOfSet() - 1; i >= 0; i--)
267 {
268 for (int j = 1; j <= i; j++)
269 {
270 if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j))
271 {
272 candidateSet.SwapEntries(j-1, j);
273 }
274 }
275 }
276 // 2. For tuples with same OH, keep the one w/ the lowest bitrate
277 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
278 {
279 if (candidateSet.Tmmbr(i) > 0)
280 {
281 // get min bitrate for packets w/ same OH
282 uint32_t currentPacketOH = candidateSet.PacketOH(i);
283 uint32_t currentMinTMMBR = candidateSet.Tmmbr(i);
284 uint32_t currentMinIndexTMMBR = i;
285 for (uint32_t j = i+1; j < candidateSet.sizeOfSet(); j++)
286 {
287 if(candidateSet.PacketOH(j) == currentPacketOH)
288 {
289 if(candidateSet.Tmmbr(j) < currentMinTMMBR)
290 {
291 currentMinTMMBR = candidateSet.Tmmbr(j);
292 currentMinIndexTMMBR = j;
293 }
294 }
295 }
296 // keep lowest bitrate
297 for (uint32_t j = 0; j < candidateSet.sizeOfSet(); j++)
298 {
299 if(candidateSet.PacketOH(j) == currentPacketOH
300 && j != currentMinIndexTMMBR)
301 {
302 candidateSet.ClearEntry(j);
303 }
304 }
305 }
306 }
307 // 3. Select and remove tuple w/ lowest tmmbr.
308 // (If more than 1, choose the one w/ highest OH).
309 uint32_t minTMMBR = 0;
310 uint32_t minIndexTMMBR = 0;
311 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
312 {
313 if (candidateSet.Tmmbr(i) > 0)
314 {
315 minTMMBR = candidateSet.Tmmbr(i);
316 minIndexTMMBR = i;
317 break;
318 }
319 }
320
321 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
322 {
323 if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR)
324 {
325 // get min bitrate
326 minTMMBR = candidateSet.Tmmbr(i);
327 minIndexTMMBR = i;
328 }
329 }
330 // first member of selected list
331 _boundingSet.SetEntry(numBoundingSet,
332 candidateSet.Tmmbr(minIndexTMMBR),
333 candidateSet.PacketOH(minIndexTMMBR),
334 candidateSet.Ssrc(minIndexTMMBR));
335
336 // set intersection value
337 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
338 // calculate its maximum packet rate (where its line crosses x-axis)
339 _ptrMaxPRBoundingSet[numBoundingSet]
340 = _boundingSet.Tmmbr(numBoundingSet) * 1000
341 / float(8 * _boundingSet.PacketOH(numBoundingSet));
342 numBoundingSet++;
343 // remove from candidate list
344 candidateSet.ClearEntry(minIndexTMMBR);
345 numCandidates--;
346
347 // 4. Discard from candidate list all tuple w/ lower OH
348 // (next tuple must be steeper)
349 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
350 {
351 if(candidateSet.Tmmbr(i) > 0
352 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0))
353 {
354 candidateSet.ClearEntry(i);
355 numCandidates--;
356 }
357 }
358
359 if (numCandidates == 0)
360 {
361 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet;
362 assert(_boundingSet.lengthOfSet() == numBoundingSet);
363 return numBoundingSet;
364 }
365
366 bool getNewCandidate = true;
367 int curCandidateTMMBR = 0;
368 int curCandidateIndex = 0;
369 int curCandidatePacketOH = 0;
370 int curCandidateSSRC = 0;
371 do
372 {
373 if (getNewCandidate)
374 {
375 // 5. Remove first remaining tuple from candidate list
376 for (uint32_t i = 0; i < candidateSet.sizeOfSet(); i++)
377 {
378 if (candidateSet.Tmmbr(i) > 0)
379 {
380 curCandidateTMMBR = candidateSet.Tmmbr(i);
381 curCandidatePacketOH = candidateSet.PacketOH(i);
382 curCandidateSSRC = candidateSet.Ssrc(i);
383 curCandidateIndex = i;
384 candidateSet.ClearEntry(curCandidateIndex);
385 break;
386 }
387 }
388 }
389
390 // 6. Calculate packet rate and intersection of the current
391 // line with line of last tuple in selected list
392 float packetRate
393 = float(curCandidateTMMBR
394 - _boundingSet.Tmmbr(numBoundingSet-1))*1000
395 / (8*(curCandidatePacketOH
396 - _boundingSet.PacketOH(numBoundingSet-1)));
397
398 // 7. If the packet rate is equal or lower than intersection of
399 // last tuple in selected list,
400 // remove last tuple in selected list & go back to step 6
401 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1])
402 {
403 // remove last tuple and goto step 6
404 numBoundingSet--;
405 _boundingSet.ClearEntry(numBoundingSet);
406 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
407 _ptrMaxPRBoundingSet[numBoundingSet] = 0;
408 getNewCandidate = false;
409 } else
410 {
411 // 8. If packet rate is lower than maximum packet rate of
412 // last tuple in selected list, add current tuple to selected
413 // list
414 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1])
415 {
416 _boundingSet.SetEntry(numBoundingSet,
417 curCandidateTMMBR,
418 curCandidatePacketOH,
419 curCandidateSSRC);
420 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate;
421 _ptrMaxPRBoundingSet[numBoundingSet]
422 = _boundingSet.Tmmbr(numBoundingSet)*1000
423 / float(8*_boundingSet.PacketOH(numBoundingSet));
424 numBoundingSet++;
425 }
426 numCandidates--;
427 getNewCandidate = true;
428 }
429
430 // 9. Go back to step 5 if any tuple remains in candidate list
431 } while (numCandidates > 0);
432
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 return numBoundingSet;
434}
435
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000436bool TMMBRHelp::IsOwner(const uint32_t ssrc,
437 const uint32_t length) const {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000438 CriticalSectionScoped lock(_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000439
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000440 if (length == 0) {
441 // Empty bounding set.
henrike@webrtc.org0ad51862012-03-30 16:54:13 +0000442 return false;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000443 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000444 for(uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000445 (i < length) && (i < _boundingSet.sizeOfSet()); ++i) {
446 if(_boundingSet.Ssrc(i) == ssrc) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000447 return true;
448 }
449 }
450 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000451}
452
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000453bool TMMBRHelp::CalcMinBitRate( uint32_t* minBitrateKbit) const {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000454 CriticalSectionScoped lock(_criticalSection);
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000456 if (_candidateSet.sizeOfSet() == 0) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000457 // Empty bounding set.
458 return false;
459 }
460 *minBitrateKbit = std::numeric_limits<uint32_t>::max();
461
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000462 for (uint32_t i = 0; i < _candidateSet.lengthOfSet(); ++i) {
463 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000464 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
465 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
niklase@google.com470e71d2011-07-07 08:21:25 +0000466 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000467 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ?
468 curNetBitRateKbit : *minBitrateKbit;
469 }
470 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000471}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000472} // namespace webrtc