OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" | 11 #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" |
12 | 12 |
13 #include <assert.h> | 13 #include <algorithm> |
14 #include <string.h> | |
15 | |
16 #include <limits> | 14 #include <limits> |
15 #include <memory> | |
17 | 16 |
18 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
19 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" | 18 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" |
20 | 19 |
21 namespace webrtc { | 20 namespace webrtc { |
22 void | 21 void |
23 TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) | 22 TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) |
24 { | 23 { |
25 clear(); | 24 clear(); |
26 reserve(minimumSize); | 25 reserve(minimumSize); |
(...skipping 23 matching lines...) Expand all Loading... | |
50 uint32_t ssrcSet) { | 49 uint32_t ssrcSet) { |
51 RTC_DCHECK_LT(size(), capacity()); | 50 RTC_DCHECK_LT(size(), capacity()); |
52 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet); | 51 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet); |
53 } | 52 } |
54 | 53 |
55 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { | 54 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { |
56 RTC_DCHECK_LT(sourceIdx, size()); | 55 RTC_DCHECK_LT(sourceIdx, size()); |
57 erase(begin() + sourceIdx); | 56 erase(begin() + sourceIdx); |
58 } | 57 } |
59 | 58 |
60 void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) { | |
61 using std::swap; | |
62 swap((*this)[i], (*this)[j]); | |
63 } | |
64 | |
65 void TMMBRSet::ClearEntry(uint32_t idx) { | |
66 SetEntry(idx, 0, 0, 0); | |
67 } | |
68 | |
69 TMMBRHelp::TMMBRHelp() | |
70 : _candidateSet(), | |
71 _boundingSet(), | |
72 _ptrIntersectionBoundingSet(NULL), | |
73 _ptrMaxPRBoundingSet(NULL) { | |
74 } | |
75 | |
76 TMMBRHelp::~TMMBRHelp() { | |
77 delete [] _ptrIntersectionBoundingSet; | |
78 delete [] _ptrMaxPRBoundingSet; | |
79 _ptrIntersectionBoundingSet = 0; | |
80 _ptrMaxPRBoundingSet = 0; | |
81 } | |
82 | |
83 TMMBRSet* | |
84 TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize) | |
85 { | |
86 rtc::CritScope lock(&_criticalSection); | |
87 | |
88 if(minimumSize > _boundingSet.capacity()) | |
89 { | |
90 // make sure that our buffers are big enough | |
91 if(_ptrIntersectionBoundingSet) | |
92 { | |
93 delete [] _ptrIntersectionBoundingSet; | |
94 delete [] _ptrMaxPRBoundingSet; | |
95 } | |
96 _ptrIntersectionBoundingSet = new float[minimumSize]; | |
97 _ptrMaxPRBoundingSet = new float[minimumSize]; | |
98 } | |
99 _boundingSet.VerifyAndAllocateSet(minimumSize); | |
100 return &_boundingSet; | |
101 } | |
102 | |
103 TMMBRSet* TMMBRHelp::BoundingSet() { | |
104 return &_boundingSet; | |
105 } | |
106 | |
107 TMMBRSet* | 59 TMMBRSet* |
108 TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize) | 60 TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize) |
109 { | 61 { |
110 rtc::CritScope lock(&_criticalSection); | 62 rtc::CritScope lock(&_criticalSection); |
111 | 63 |
112 _candidateSet.VerifyAndAllocateSet(minimumSize); | 64 _candidateSet.VerifyAndAllocateSet(minimumSize); |
113 return &_candidateSet; | 65 return &_candidateSet; |
114 } | 66 } |
115 | 67 |
116 TMMBRSet* | 68 TMMBRSet* |
(...skipping 15 matching lines...) Expand all Loading... | |
132 { | 84 { |
133 if(_candidateSet.Tmmbr(i)) | 85 if(_candidateSet.Tmmbr(i)) |
134 { | 86 { |
135 candidateSet.AddEntry(_candidateSet.Tmmbr(i), | 87 candidateSet.AddEntry(_candidateSet.Tmmbr(i), |
136 _candidateSet.PacketOH(i), | 88 _candidateSet.PacketOH(i), |
137 _candidateSet.Ssrc(i)); | 89 _candidateSet.Ssrc(i)); |
138 } | 90 } |
139 else | 91 else |
140 { | 92 { |
141 // make sure this is zero if tmmbr = 0 | 93 // make sure this is zero if tmmbr = 0 |
142 assert(_candidateSet.PacketOH(i) == 0); | 94 RTC_DCHECK_EQ(_candidateSet.PacketOH(i), 0u); |
143 // Old code: | 95 // Old code: |
144 // _candidateSet.ptrPacketOHSet[i] = 0; | 96 // _candidateSet.ptrPacketOHSet[i] = 0; |
145 } | 97 } |
146 } | 98 } |
147 | 99 |
148 // Number of set candidates | 100 // Number of set candidates |
149 int32_t numSetCandidates = candidateSet.lengthOfSet(); | 101 int32_t numSetCandidates = candidateSet.lengthOfSet(); |
150 // Find bounding set | 102 // Find bounding set |
151 uint32_t numBoundingSet = 0; | 103 uint32_t numBoundingSet = 0; |
152 if (numSetCandidates > 0) | 104 if (numSetCandidates > 0) |
153 { | 105 { |
154 numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet); | 106 FindBoundingSet(std::move(candidateSet), &_boundingSet); |
107 numBoundingSet = _boundingSet.size(); | |
155 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.size())) | 108 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.size())) |
156 { | 109 { |
157 return -1; | 110 return -1; |
158 } | 111 } |
159 boundingSet = &_boundingSet; | 112 boundingSet = &_boundingSet; |
160 } | 113 } |
161 return numBoundingSet; | 114 return numBoundingSet; |
162 } | 115 } |
163 | 116 |
164 | 117 |
165 int32_t | 118 void |
166 TMMBRHelp::FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet) | 119 TMMBRHelp::FindBoundingSet(std::vector<rtcp::TmmbItem> candidateSet, |
120 std::vector<rtcp::TmmbItem>* boundingSet) | |
167 { | 121 { |
168 rtc::CritScope lock(&_criticalSection); | 122 RTC_DCHECK(boundingSet); |
123 RTC_DCHECK(!candidateSet.empty()); | |
124 size_t numCandidates = candidateSet.size(); | |
169 | 125 |
170 uint32_t numBoundingSet = 0; | 126 uint32_t numBoundingSet = 0; |
171 VerifyAndAllocateBoundingSet(candidateSet.capacity()); | 127 boundingSet->clear(); |
128 boundingSet->reserve(candidateSet.size()); | |
172 | 129 |
173 if (numCandidates == 1) | 130 if (numCandidates == 1) |
174 { | 131 { |
175 for (uint32_t i = 0; i < candidateSet.size(); i++) | 132 RTC_DCHECK(candidateSet[0].bitrate_bps()); |
176 { | 133 *boundingSet = std::move(candidateSet); |
177 if (candidateSet.Tmmbr(i) > 0) | 134 return; |
178 { | |
179 _boundingSet.AddEntry(candidateSet.Tmmbr(i), | |
180 candidateSet.PacketOH(i), | |
181 candidateSet.Ssrc(i)); | |
182 numBoundingSet++; | |
183 } | |
184 } | |
185 return (numBoundingSet == 1) ? 1 : -1; | |
186 } | 135 } |
187 | 136 |
188 // 1. Sort by increasing packetOH | 137 // 1. Sort by increasing packetOH |
189 for (int i = candidateSet.size() - 1; i >= 0; i--) | 138 std::sort(candidateSet.begin(), candidateSet.end(), |
190 { | 139 [](const rtcp::TmmbItem& lhs, const rtcp::TmmbItem& rhs) { |
191 for (int j = 1; j <= i; j++) | 140 return lhs.packet_overhead() < rhs.packet_overhead(); |
192 { | 141 }); |
193 if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j)) | |
194 { | |
195 candidateSet.SwapEntries(j-1, j); | |
196 } | |
197 } | |
198 } | |
199 // 2. For tuples with same OH, keep the one w/ the lowest bitrate | 142 // 2. For tuples with same OH, keep the one w/ the lowest bitrate |
200 for (uint32_t i = 0; i < candidateSet.size(); i++) | 143 for (uint32_t i = 0; i < candidateSet.size(); i++) |
201 { | 144 { |
202 if (candidateSet.Tmmbr(i) > 0) | 145 if (candidateSet[i].bitrate_bps()) |
203 { | 146 { |
204 // get min bitrate for packets w/ same OH | 147 // get min bitrate for packets w/ same OH |
205 uint32_t currentPacketOH = candidateSet.PacketOH(i); | 148 uint32_t currentPacketOH = candidateSet[i].packet_overhead(); |
206 uint32_t currentMinTMMBR = candidateSet.Tmmbr(i); | 149 uint32_t currentMinTMMBR = candidateSet[i].bitrate_bps(); |
207 uint32_t currentMinIndexTMMBR = i; | 150 uint32_t currentMinIndexTMMBR = i; |
208 for (uint32_t j = i+1; j < candidateSet.size(); j++) | 151 for (uint32_t j = i+1; j < candidateSet.size(); j++) |
209 { | 152 { |
210 if(candidateSet.PacketOH(j) == currentPacketOH) | 153 if(candidateSet[j].packet_overhead() == currentPacketOH) |
211 { | 154 { |
212 if(candidateSet.Tmmbr(j) < currentMinTMMBR) | 155 if(candidateSet[j].bitrate_bps() < currentMinTMMBR) |
213 { | 156 { |
214 currentMinTMMBR = candidateSet.Tmmbr(j); | 157 currentMinTMMBR = candidateSet[j].bitrate_bps(); |
215 currentMinIndexTMMBR = j; | 158 currentMinIndexTMMBR = j; |
216 } | 159 } |
217 } | 160 } |
218 } | 161 } |
219 // keep lowest bitrate | 162 // keep lowest bitrate |
220 for (uint32_t j = 0; j < candidateSet.size(); j++) | 163 for (uint32_t j = 0; j < candidateSet.size(); j++) |
221 { | 164 { |
222 if(candidateSet.PacketOH(j) == currentPacketOH | 165 if(candidateSet[j].packet_overhead() == currentPacketOH |
223 && j != currentMinIndexTMMBR) | 166 && j != currentMinIndexTMMBR) |
224 { | 167 { |
225 candidateSet.ClearEntry(j); | 168 candidateSet[j].set_bitrate_bps(0); |
226 numCandidates--; | 169 numCandidates--; |
227 } | 170 } |
228 } | 171 } |
229 } | 172 } |
230 } | 173 } |
231 // 3. Select and remove tuple w/ lowest tmmbr. | 174 // 3. Select and remove tuple w/ lowest tmmbr. |
232 // (If more than 1, choose the one w/ highest OH). | 175 // (If more than 1, choose the one w/ highest OH). |
233 uint32_t minTMMBR = 0; | 176 uint32_t minTMMBR = 0; |
234 uint32_t minIndexTMMBR = 0; | 177 uint32_t minIndexTMMBR = 0; |
235 for (uint32_t i = 0; i < candidateSet.size(); i++) | 178 for (uint32_t i = 0; i < candidateSet.size(); i++) |
236 { | 179 { |
237 if (candidateSet.Tmmbr(i) > 0) | 180 if (candidateSet[i].bitrate_bps()) |
238 { | 181 { |
239 minTMMBR = candidateSet.Tmmbr(i); | 182 minTMMBR = candidateSet[i].bitrate_bps(); |
240 minIndexTMMBR = i; | 183 minIndexTMMBR = i; |
241 break; | 184 break; |
242 } | 185 } |
243 } | 186 } |
244 | 187 |
245 for (uint32_t i = 0; i < candidateSet.size(); i++) | 188 for (uint32_t i = 0; i < candidateSet.size(); i++) |
246 { | 189 { |
247 if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR) | 190 if (candidateSet[i].bitrate_bps() && |
191 candidateSet[i].bitrate_bps() <= minTMMBR) | |
248 { | 192 { |
249 // get min bitrate | 193 // get min bitrate |
250 minTMMBR = candidateSet.Tmmbr(i); | 194 minTMMBR = candidateSet[i].bitrate_bps(); |
251 minIndexTMMBR = i; | 195 minIndexTMMBR = i; |
252 } | 196 } |
253 } | 197 } |
254 // first member of selected list | 198 // first member of selected list |
255 _boundingSet.SetEntry(numBoundingSet, | 199 boundingSet->push_back(candidateSet[minIndexTMMBR]); |
256 candidateSet.Tmmbr(minIndexTMMBR), | |
257 candidateSet.PacketOH(minIndexTMMBR), | |
258 candidateSet.Ssrc(minIndexTMMBR)); | |
259 | 200 |
201 std::unique_ptr<float[]> _ptrIntersectionBoundingSet(new float[numCandidates ]); | |
202 std::unique_ptr<float[]> _ptrMaxPRBoundingSet(new float[numCandidates]); | |
260 // set intersection value | 203 // set intersection value |
261 _ptrIntersectionBoundingSet[numBoundingSet] = 0; | 204 _ptrIntersectionBoundingSet[numBoundingSet] = 0; |
262 // calculate its maximum packet rate (where its line crosses x-axis) | 205 // calculate its maximum packet rate (where its line crosses x-axis) |
263 uint32_t packet_overhead_bits = 8 * _boundingSet.PacketOH(numBoundingSet); | 206 uint32_t packet_overhead_bits = 8 * boundingSet->back().packet_overhead(); |
264 if (packet_overhead_bits == 0) { | 207 if (packet_overhead_bits == 0) { |
265 // Avoid division by zero. | 208 // Avoid division by zero. |
266 _ptrMaxPRBoundingSet[numBoundingSet] = std::numeric_limits<float>::max(); | 209 _ptrMaxPRBoundingSet[numBoundingSet] = std::numeric_limits<float>::max(); |
267 } else { | 210 } else { |
268 _ptrMaxPRBoundingSet[numBoundingSet] = | 211 _ptrMaxPRBoundingSet[numBoundingSet] = |
269 _boundingSet.Tmmbr(numBoundingSet) * 1000 / | 212 boundingSet->back().bitrate_bps() / |
270 static_cast<float>(packet_overhead_bits); | 213 static_cast<float>(packet_overhead_bits); |
271 } | 214 } |
272 numBoundingSet++; | 215 numBoundingSet++; |
273 // remove from candidate list | 216 // remove from candidate list |
274 candidateSet.ClearEntry(minIndexTMMBR); | 217 candidateSet[minIndexTMMBR].set_bitrate_bps(0); |
275 numCandidates--; | 218 numCandidates--; |
276 | 219 |
277 // 4. Discard from candidate list all tuple w/ lower OH | 220 // 4. Discard from candidate list all tuple w/ lower OH |
278 // (next tuple must be steeper) | 221 // (next tuple must be steeper) |
279 for (uint32_t i = 0; i < candidateSet.size(); i++) | 222 for (uint32_t i = 0; i < candidateSet.size(); i++) |
280 { | 223 { |
281 if(candidateSet.Tmmbr(i) > 0 | 224 if(candidateSet[i].bitrate_bps() |
282 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0)) | 225 && candidateSet[i].packet_overhead() < boundingSet->front().packet_o verhead()) |
283 { | 226 { |
284 candidateSet.ClearEntry(i); | 227 candidateSet[i].set_bitrate_bps(0); |
285 numCandidates--; | 228 numCandidates--; |
286 } | 229 } |
287 } | 230 } |
288 | 231 |
289 if (numCandidates == 0) | 232 if (numCandidates == 0) |
290 { | 233 { |
291 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet; | 234 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet; |
292 assert(_boundingSet.lengthOfSet() == numBoundingSet); | 235 RTC_DCHECK_EQ(boundingSet->size(), numBoundingSet); |
293 return numBoundingSet; | 236 return; |
294 } | 237 } |
295 | 238 |
296 bool getNewCandidate = true; | 239 bool getNewCandidate = true; |
297 uint32_t curCandidateTMMBR = 0; | 240 rtcp::TmmbItem curCandidate; |
298 size_t curCandidateIndex = 0; | |
299 uint32_t curCandidatePacketOH = 0; | |
300 uint32_t curCandidateSSRC = 0; | |
301 do | 241 do |
302 { | 242 { |
303 if (getNewCandidate) | 243 if (getNewCandidate) |
304 { | 244 { |
305 // 5. Remove first remaining tuple from candidate list | 245 // 5. Remove first remaining tuple from candidate list |
306 for (uint32_t i = 0; i < candidateSet.size(); i++) | 246 for (uint32_t i = 0; i < candidateSet.size(); i++) |
307 { | 247 { |
308 if (candidateSet.Tmmbr(i) > 0) | 248 if (candidateSet[i].bitrate_bps()) |
309 { | 249 { |
310 curCandidateTMMBR = candidateSet.Tmmbr(i); | 250 curCandidate = candidateSet[i]; |
311 curCandidatePacketOH = candidateSet.PacketOH(i); | 251 candidateSet[i].set_bitrate_bps(0); |
312 curCandidateSSRC = candidateSet.Ssrc(i); | |
313 curCandidateIndex = i; | |
314 candidateSet.ClearEntry(curCandidateIndex); | |
315 break; | 252 break; |
316 } | 253 } |
317 } | 254 } |
318 } | 255 } |
319 | 256 |
320 // 6. Calculate packet rate and intersection of the current | 257 // 6. Calculate packet rate and intersection of the current |
321 // line with line of last tuple in selected list | 258 // line with line of last tuple in selected list |
322 RTC_DCHECK_NE(curCandidatePacketOH, | 259 RTC_DCHECK_NE(curCandidate.packet_overhead(), |
323 _boundingSet.PacketOH(numBoundingSet - 1)); | 260 boundingSet->back().packet_overhead()); |
324 float packetRate | 261 float packetRate |
325 = float(curCandidateTMMBR | 262 = float(curCandidate.bitrate_bps() |
326 - _boundingSet.Tmmbr(numBoundingSet-1))*1000 | 263 - boundingSet->back().bitrate_bps()) |
327 / (8*(curCandidatePacketOH | 264 / (8*(curCandidate.packet_overhead() |
328 - _boundingSet.PacketOH(numBoundingSet-1))); | 265 - boundingSet->back().packet_overhead())); |
329 | 266 |
330 // 7. If the packet rate is equal or lower than intersection of | 267 // 7. If the packet rate is equal or lower than intersection of |
331 // last tuple in selected list, | 268 // last tuple in selected list, |
332 // remove last tuple in selected list & go back to step 6 | 269 // remove last tuple in selected list & go back to step 6 |
333 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1]) | 270 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1]) |
334 { | 271 { |
335 // remove last tuple and goto step 6 | 272 // remove last tuple and goto step 6 |
336 numBoundingSet--; | 273 numBoundingSet--; |
337 _boundingSet.ClearEntry(numBoundingSet); | 274 boundingSet->pop_back(); |
338 _ptrIntersectionBoundingSet[numBoundingSet] = 0; | |
339 _ptrMaxPRBoundingSet[numBoundingSet] = 0; | |
340 getNewCandidate = false; | 275 getNewCandidate = false; |
341 } else | 276 } else |
342 { | 277 { |
343 // 8. If packet rate is lower than maximum packet rate of | 278 // 8. If packet rate is lower than maximum packet rate of |
344 // last tuple in selected list, add current tuple to selected | 279 // last tuple in selected list, add current tuple to selected |
345 // list | 280 // list |
346 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1]) | 281 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1]) |
347 { | 282 { |
348 _boundingSet.SetEntry(numBoundingSet, | 283 boundingSet->push_back(curCandidate); |
349 curCandidateTMMBR, | |
350 curCandidatePacketOH, | |
351 curCandidateSSRC); | |
352 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate; | 284 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate; |
353 float packet_overhead_bits = | 285 float packet_overhead_bits = |
354 8 * _boundingSet.PacketOH(numBoundingSet); | 286 8 * boundingSet->back().packet_overhead(); |
355 RTC_DCHECK_NE(packet_overhead_bits, 0.0f); | 287 RTC_DCHECK_NE(packet_overhead_bits, 0.0f); |
356 _ptrMaxPRBoundingSet[numBoundingSet] = | 288 _ptrMaxPRBoundingSet[numBoundingSet] = |
357 _boundingSet.Tmmbr(numBoundingSet) * 1000 / | 289 boundingSet->back().bitrate_bps() * 1000 / |
danilchap
2016/05/20 13:38:53
overlooked removing *1000 here, removed in patchse
| |
358 packet_overhead_bits; | 290 packet_overhead_bits; |
359 numBoundingSet++; | 291 numBoundingSet++; |
360 } | 292 } |
361 numCandidates--; | 293 numCandidates--; |
362 getNewCandidate = true; | 294 getNewCandidate = true; |
363 } | 295 } |
364 | 296 |
365 // 9. Go back to step 5 if any tuple remains in candidate list | 297 // 9. Go back to step 5 if any tuple remains in candidate list |
366 } while (numCandidates > 0); | 298 } while (numCandidates > 0); |
367 | 299 |
368 return numBoundingSet; | 300 RTC_DCHECK_EQ(boundingSet->size(), numBoundingSet); |
369 } | 301 } |
370 | 302 |
371 bool TMMBRHelp::IsOwner(const uint32_t ssrc, | 303 bool TMMBRHelp::IsOwner(const uint32_t ssrc, |
372 const uint32_t length) const { | 304 const uint32_t length) const { |
373 rtc::CritScope lock(&_criticalSection); | 305 rtc::CritScope lock(&_criticalSection); |
374 | 306 |
375 if (length == 0) { | 307 if (length == 0) { |
376 // Empty bounding set. | 308 // Empty bounding set. |
377 return false; | 309 return false; |
378 } | 310 } |
(...skipping 19 matching lines...) Expand all Loading... | |
398 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i); | 330 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i); |
399 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) { | 331 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) { |
400 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE; | 332 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE; |
401 } | 333 } |
402 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ? | 334 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ? |
403 curNetBitRateKbit : *minBitrateKbit; | 335 curNetBitRateKbit : *minBitrateKbit; |
404 } | 336 } |
405 return true; | 337 return true; |
406 } | 338 } |
407 } // namespace webrtc | 339 } // namespace webrtc |
OLD | NEW |