Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/tmmbr_help.cc

Issue 1474693002: [Splitting] TMMBRHelp class simplifted (and disappear because become too simple) (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/tmmbr_help.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
14 #include <string.h>
15
16 #include <limits> 13 #include <limits>
14 #include <list>
17 15
18 #include "webrtc/base/checks.h" 16 #include "webrtc/base/checks.h"
19 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" 17
18 using webrtc::rtcp::TmmbItem;
20 19
21 namespace webrtc { 20 namespace webrtc {
22 void 21 namespace {
23 TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) 22 struct Bounding {
24 { 23 Bounding() {}
25 clear(); 24 Bounding(float max_pr, float inter)
26 reserve(minimumSize); 25 : max_packet_rate(max_pr), intersection(inter) {}
26
27 float max_packet_rate = 0.0;
28 float intersection = 0.0;
29 };
30
31 float Ratio(uint32_t bitrate_bps, uint32_t packet_overhead) {
32 if (packet_overhead == 0)
33 return std::numeric_limits<float>::max();
34 return static_cast<float>(bitrate_bps) / packet_overhead;
35 }
36 float MaximumPacketRate(const TmmbItem& entry) {
37 return Ratio(entry.bitrate_bps(), entry.packet_overhead());
27 } 38 }
28 39
29 void 40 float Intersection(const TmmbItem& first, const TmmbItem& second) {
30 TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize) 41 return Ratio(first.bitrate_bps() - second.bitrate_bps(),
31 { 42 first.packet_overhead() - second.packet_overhead());
32 reserve(minimumSize);
33 } 43 }
44 } // namespace
34 45
35 void TMMBRSet::SetEntry(unsigned int i, 46 void FindTMMBRBoundingSet(std::vector<TmmbItem>* most_limiting) {
36 uint32_t tmmbrSet, 47 RTC_CHECK(most_limiting);
37 uint32_t packetOHSet, 48
38 uint32_t ssrcSet) { 49 if (most_limiting->size() <= 1)
39 RTC_DCHECK_LT(i, capacity()); 50 return;
40 if (i >= size()) { 51
41 resize(i+1); 52 // Work on local variable, will be modified
53 std::list<TmmbItem> candidates;
54
55 // Copy and filter.
56 for (const TmmbItem& candidate : *most_limiting) {
57 if (candidate.bitrate_bps() > 0) {
58 candidates.push_back(candidate);
59 }
42 } 60 }
43 (*this)[i].set_bitrate_bps(tmmbrSet * 1000);
44 (*this)[i].set_packet_overhead(packetOHSet);
45 (*this)[i].set_ssrc(ssrcSet);
46 }
47 61
48 void TMMBRSet::AddEntry(uint32_t tmmbrSet, 62 most_limiting->clear();
49 uint32_t packetOHSet,
50 uint32_t ssrcSet) {
51 RTC_DCHECK_LT(size(), capacity());
52 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet);
53 }
54 63
55 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { 64 // Packet rates would have exactly same size as most_limiting.
56 RTC_DCHECK_LT(sourceIdx, size()); 65 // Unlike most_limiting, it will not be returned out of the function.
57 erase(begin() + sourceIdx); 66 std::vector<Bounding> packet_rates;
58 } 67 packet_rates.reserve(candidates.size());
59 68
60 void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) { 69 // 1. Sort by increasing packet_overhead.
61 using std::swap; 70 candidates.sort([](const TmmbItem& first, const TmmbItem& second) {
62 swap((*this)[i], (*this)[j]); 71 return first.packet_overhead() < second.packet_overhead();
63 } 72 });
64 73
65 void TMMBRSet::ClearEntry(uint32_t idx) { 74 // 2. For tuples with same OH, keep the one w/ the lowest bitrate.
66 SetEntry(idx, 0, 0, 0); 75 for (auto it = candidates.begin(); it != candidates.end(); ++it) {
67 } 76 // Get min bitrate for packets w/ same OH.
77 uint32_t packet_overhead = it->packet_overhead();
78 auto next_it = it;
79 ++next_it;
80 while (next_it != candidates.end() &&
81 next_it->packet_overhead() == packet_overhead) {
82 if (next_it->bitrate_bps() < it->bitrate_bps()) {
83 candidates.erase(it);
84 it = next_it;
85 } else {
86 candidates.erase(next_it);
87 next_it = it;
88 }
89 ++next_it;
90 }
91 }
68 92
69 TMMBRHelp::TMMBRHelp() 93 // 3. Select and remove tuple w/ lowest bitrate.
70 : _candidateSet(), 94 // (If more than 1, choose the one w/ highest OH).
71 _boundingSet(), 95 uint32_t min_bitrate = candidates.front().bitrate_bps();
72 _ptrIntersectionBoundingSet(NULL), 96 auto min_bitrate_it = candidates.begin();
73 _ptrMaxPRBoundingSet(NULL) {
74 }
75 97
76 TMMBRHelp::~TMMBRHelp() { 98 for (auto it = candidates.begin(); it != candidates.end(); it++) {
77 delete [] _ptrIntersectionBoundingSet; 99 if (it->bitrate_bps() <= min_bitrate) {
78 delete [] _ptrMaxPRBoundingSet; 100 // Get min bitrate.
79 _ptrIntersectionBoundingSet = 0; 101 min_bitrate = it->bitrate_bps();
80 _ptrMaxPRBoundingSet = 0; 102 min_bitrate_it = it;
81 } 103 }
104 }
105 // First member of selected list.
106 most_limiting->push_back(*min_bitrate_it);
107 packet_rates.push_back(Bounding(MaximumPacketRate(*min_bitrate_it), 0.0));
82 108
83 TMMBRSet* 109 // Remove from candidate list.
84 TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize) 110 candidates.erase(min_bitrate_it);
85 {
86 rtc::CritScope lock(&_criticalSection);
87 111
88 if(minimumSize > _boundingSet.capacity()) 112 for (const TmmbItem& candidate : candidates) {
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*
108 TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize)
109 {
110 rtc::CritScope lock(&_criticalSection);
111
112 _candidateSet.VerifyAndAllocateSet(minimumSize);
113 return &_candidateSet;
114 }
115
116 TMMBRSet*
117 TMMBRHelp::CandidateSet()
118 {
119 return &_candidateSet;
120 }
121
122 int32_t
123 TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet)
124 {
125 rtc::CritScope lock(&_criticalSection);
126
127 // Work on local variable, will be modified
128 TMMBRSet candidateSet;
129 candidateSet.VerifyAndAllocateSet(_candidateSet.capacity());
130
131 for (uint32_t i = 0; i < _candidateSet.size(); i++)
132 {
133 if(_candidateSet.Tmmbr(i))
134 {
135 candidateSet.AddEntry(_candidateSet.Tmmbr(i),
136 _candidateSet.PacketOH(i),
137 _candidateSet.Ssrc(i));
138 }
139 else
140 {
141 // make sure this is zero if tmmbr = 0
142 assert(_candidateSet.PacketOH(i) == 0);
143 // Old code:
144 // _candidateSet.ptrPacketOHSet[i] = 0;
145 }
146 }
147
148 // Number of set candidates
149 int32_t numSetCandidates = candidateSet.lengthOfSet();
150 // Find bounding set
151 uint32_t numBoundingSet = 0;
152 if (numSetCandidates > 0)
153 {
154 numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet);
155 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.size()))
156 {
157 return -1;
158 }
159 boundingSet = &_boundingSet;
160 }
161 return numBoundingSet;
162 }
163
164
165 int32_t
166 TMMBRHelp::FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet)
167 {
168 rtc::CritScope lock(&_criticalSection);
169
170 uint32_t numBoundingSet = 0;
171 VerifyAndAllocateBoundingSet(candidateSet.capacity());
172
173 if (numCandidates == 1)
174 {
175 for (uint32_t i = 0; i < candidateSet.size(); i++)
176 {
177 if (candidateSet.Tmmbr(i) > 0)
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 }
187
188 // 1. Sort by increasing packetOH
189 for (int i = candidateSet.size() - 1; i >= 0; i--)
190 {
191 for (int j = 1; j <= i; j++)
192 {
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
200 for (uint32_t i = 0; i < candidateSet.size(); i++)
201 {
202 if (candidateSet.Tmmbr(i) > 0)
203 {
204 // get min bitrate for packets w/ same OH
205 uint32_t currentPacketOH = candidateSet.PacketOH(i);
206 uint32_t currentMinTMMBR = candidateSet.Tmmbr(i);
207 uint32_t currentMinIndexTMMBR = i;
208 for (uint32_t j = i+1; j < candidateSet.size(); j++)
209 {
210 if(candidateSet.PacketOH(j) == currentPacketOH)
211 {
212 if(candidateSet.Tmmbr(j) < currentMinTMMBR)
213 {
214 currentMinTMMBR = candidateSet.Tmmbr(j);
215 currentMinIndexTMMBR = j;
216 }
217 }
218 }
219 // keep lowest bitrate
220 for (uint32_t j = 0; j < candidateSet.size(); j++)
221 {
222 if(candidateSet.PacketOH(j) == currentPacketOH
223 && j != currentMinIndexTMMBR)
224 {
225 candidateSet.ClearEntry(j);
226 numCandidates--;
227 }
228 }
229 }
230 }
231 // 3. Select and remove tuple w/ lowest tmmbr.
232 // (If more than 1, choose the one w/ highest OH).
233 uint32_t minTMMBR = 0;
234 uint32_t minIndexTMMBR = 0;
235 for (uint32_t i = 0; i < candidateSet.size(); i++)
236 {
237 if (candidateSet.Tmmbr(i) > 0)
238 {
239 minTMMBR = candidateSet.Tmmbr(i);
240 minIndexTMMBR = i;
241 break;
242 }
243 }
244
245 for (uint32_t i = 0; i < candidateSet.size(); i++)
246 {
247 if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR)
248 {
249 // get min bitrate
250 minTMMBR = candidateSet.Tmmbr(i);
251 minIndexTMMBR = i;
252 }
253 }
254 // first member of selected list
255 _boundingSet.SetEntry(numBoundingSet,
256 candidateSet.Tmmbr(minIndexTMMBR),
257 candidateSet.PacketOH(minIndexTMMBR),
258 candidateSet.Ssrc(minIndexTMMBR));
259
260 // set intersection value
261 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
262 // calculate its maximum packet rate (where its line crosses x-axis)
263 uint32_t packet_overhead_bits = 8 * _boundingSet.PacketOH(numBoundingSet);
264 if (packet_overhead_bits == 0) {
265 // Avoid division by zero.
266 _ptrMaxPRBoundingSet[numBoundingSet] = std::numeric_limits<float>::max();
267 } else {
268 _ptrMaxPRBoundingSet[numBoundingSet] =
269 _boundingSet.Tmmbr(numBoundingSet) * 1000 /
270 static_cast<float>(packet_overhead_bits);
271 }
272 numBoundingSet++;
273 // remove from candidate list
274 candidateSet.ClearEntry(minIndexTMMBR);
275 numCandidates--;
276
277 // 4. Discard from candidate list all tuple w/ lower OH 113 // 4. Discard from candidate list all tuple w/ lower OH
278 // (next tuple must be steeper) 114 // (next tuple must be steeper)
279 for (uint32_t i = 0; i < candidateSet.size(); i++) 115 if (candidate.packet_overhead() < most_limiting->front().packet_overhead())
280 { 116 continue;
281 if(candidateSet.Tmmbr(i) > 0 117
282 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0)) 118 // 5. Take next remaining tuple from candidate list.
283 { 119
284 candidateSet.ClearEntry(i); 120 // 6. Calculate packet rate and intersection of the current
285 numCandidates--; 121 // line with line of last tuple in selected list.
286 } 122 float packet_rate = Intersection(candidate, most_limiting->back());
123
124 // 7. If the packet rate is equal or lower than intersection of
125 // last tuple in selected list,
126 // remove last tuple in selected list & go back to step 6.
127 while (packet_rate <= packet_rates.back().intersection) {
128 most_limiting->pop_back();
129 packet_rates.pop_back();
130
131 packet_rate = Intersection(candidate, most_limiting->back());
287 } 132 }
288 133 // 8. If packet rate is lower than maximum packet rate of
289 if (numCandidates == 0) 134 // last tuple in selected list, add current tuple to selected
290 { 135 // list.
291 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet; 136 if (packet_rate < packet_rates.back().max_packet_rate) {
292 assert(_boundingSet.lengthOfSet() == numBoundingSet); 137 most_limiting->push_back(candidate);
293 return numBoundingSet; 138 packet_rates.push_back(
294 } 139 Bounding(MaximumPacketRate(candidate), packet_rate));
295
296 bool getNewCandidate = true;
297 uint32_t curCandidateTMMBR = 0;
298 size_t curCandidateIndex = 0;
299 uint32_t curCandidatePacketOH = 0;
300 uint32_t curCandidateSSRC = 0;
301 do
302 {
303 if (getNewCandidate)
304 {
305 // 5. Remove first remaining tuple from candidate list
306 for (uint32_t i = 0; i < candidateSet.size(); i++)
307 {
308 if (candidateSet.Tmmbr(i) > 0)
309 {
310 curCandidateTMMBR = candidateSet.Tmmbr(i);
311 curCandidatePacketOH = candidateSet.PacketOH(i);
312 curCandidateSSRC = candidateSet.Ssrc(i);
313 curCandidateIndex = i;
314 candidateSet.ClearEntry(curCandidateIndex);
315 break;
316 }
317 }
318 }
319
320 // 6. Calculate packet rate and intersection of the current
321 // line with line of last tuple in selected list
322 RTC_DCHECK_NE(curCandidatePacketOH,
323 _boundingSet.PacketOH(numBoundingSet - 1));
324 float packetRate
325 = float(curCandidateTMMBR
326 - _boundingSet.Tmmbr(numBoundingSet-1))*1000
327 / (8*(curCandidatePacketOH
328 - _boundingSet.PacketOH(numBoundingSet-1)));
329
330 // 7. If the packet rate is equal or lower than intersection of
331 // last tuple in selected list,
332 // remove last tuple in selected list & go back to step 6
333 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1])
334 {
335 // remove last tuple and goto step 6
336 numBoundingSet--;
337 _boundingSet.ClearEntry(numBoundingSet);
338 _ptrIntersectionBoundingSet[numBoundingSet] = 0;
339 _ptrMaxPRBoundingSet[numBoundingSet] = 0;
340 getNewCandidate = false;
341 } else
342 {
343 // 8. If packet rate is lower than maximum packet rate of
344 // last tuple in selected list, add current tuple to selected
345 // list
346 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1])
347 {
348 _boundingSet.SetEntry(numBoundingSet,
349 curCandidateTMMBR,
350 curCandidatePacketOH,
351 curCandidateSSRC);
352 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate;
353 float packet_overhead_bits =
354 8 * _boundingSet.PacketOH(numBoundingSet);
355 RTC_DCHECK_NE(packet_overhead_bits, 0.0f);
356 _ptrMaxPRBoundingSet[numBoundingSet] =
357 _boundingSet.Tmmbr(numBoundingSet) * 1000 /
358 packet_overhead_bits;
359 numBoundingSet++;
360 }
361 numCandidates--;
362 getNewCandidate = true;
363 }
364
365 // 9. Go back to step 5 if any tuple remains in candidate list
366 } while (numCandidates > 0);
367
368 return numBoundingSet;
369 }
370
371 bool TMMBRHelp::IsOwner(const uint32_t ssrc,
372 const uint32_t length) const {
373 rtc::CritScope lock(&_criticalSection);
374
375 if (length == 0) {
376 // Empty bounding set.
377 return false;
378 }
379 for(uint32_t i = 0;
380 (i < length) && (i < _boundingSet.size()); ++i) {
381 if(_boundingSet.Ssrc(i) == ssrc) {
382 return true;
383 } 140 }
384 } 141 }
385 return false;
386 }
387
388 bool TMMBRHelp::CalcMinBitRate( uint32_t* minBitrateKbit) const {
389 rtc::CritScope lock(&_criticalSection);
390
391 if (_candidateSet.size() == 0) {
392 // Empty bounding set.
393 return false;
394 }
395 *minBitrateKbit = std::numeric_limits<uint32_t>::max();
396
397 for (uint32_t i = 0; i < _candidateSet.lengthOfSet(); ++i) {
398 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i);
399 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) {
400 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE;
401 }
402 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ?
403 curNetBitRateKbit : *minBitrateKbit;
404 }
405 return true;
406 } 142 }
407 } // namespace webrtc 143 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/tmmbr_help.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698