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 TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) { |
23 TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) | |
24 { | |
25 clear(); | 22 clear(); |
26 reserve(minimumSize); | 23 reserve(minimumSize); |
27 } | 24 } |
28 | 25 |
29 void | 26 void TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize) { |
30 TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize) | |
31 { | |
32 reserve(minimumSize); | 27 reserve(minimumSize); |
33 } | 28 } |
34 | 29 |
35 void TMMBRSet::SetEntry(unsigned int i, | 30 void TMMBRSet::SetEntry(unsigned int i, |
36 uint32_t tmmbrSet, | 31 uint32_t tmmbrSet, |
37 uint32_t packetOHSet, | 32 uint32_t packetOHSet, |
38 uint32_t ssrcSet) { | 33 uint32_t ssrcSet) { |
39 RTC_DCHECK_LT(i, capacity()); | 34 RTC_DCHECK_LT(i, capacity()); |
40 if (i >= size()) { | 35 if (i >= size()) { |
41 resize(i+1); | 36 resize(i + 1); |
42 } | 37 } |
43 (*this)[i].set_bitrate_bps(tmmbrSet * 1000); | 38 (*this)[i].set_bitrate_bps(tmmbrSet * 1000); |
44 (*this)[i].set_packet_overhead(packetOHSet); | 39 (*this)[i].set_packet_overhead(packetOHSet); |
45 (*this)[i].set_ssrc(ssrcSet); | 40 (*this)[i].set_ssrc(ssrcSet); |
46 } | 41 } |
47 | 42 |
48 void TMMBRSet::AddEntry(uint32_t tmmbrSet, | 43 void TMMBRSet::AddEntry(uint32_t tmmbrSet, |
49 uint32_t packetOHSet, | 44 uint32_t packetOHSet, |
50 uint32_t ssrcSet) { | 45 uint32_t ssrcSet) { |
51 RTC_DCHECK_LT(size(), capacity()); | 46 RTC_DCHECK_LT(size(), capacity()); |
52 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet); | 47 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet); |
53 } | 48 } |
54 | 49 |
55 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { | 50 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { |
56 RTC_DCHECK_LT(sourceIdx, size()); | 51 RTC_DCHECK_LT(sourceIdx, size()); |
57 erase(begin() + sourceIdx); | 52 erase(begin() + sourceIdx); |
58 } | 53 } |
59 | 54 |
60 void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) { | 55 TMMBRSet* TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize) { |
61 using std::swap; | 56 _candidateSet.VerifyAndAllocateSet(minimumSize); |
62 swap((*this)[i], (*this)[j]); | 57 return &_candidateSet; |
63 } | 58 } |
64 | 59 |
65 void TMMBRSet::ClearEntry(uint32_t idx) { | 60 TMMBRSet* TMMBRHelp::CandidateSet() { |
66 SetEntry(idx, 0, 0, 0); | 61 return &_candidateSet; |
67 } | 62 } |
68 | 63 |
69 TMMBRHelp::TMMBRHelp() | 64 int32_t TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet) { |
70 : _candidateSet(), | 65 // Work on local variable, will be modified |
71 _boundingSet(), | 66 TMMBRSet candidateSet; |
72 _ptrIntersectionBoundingSet(NULL), | 67 candidateSet.VerifyAndAllocateSet(_candidateSet.capacity()); |
73 _ptrMaxPRBoundingSet(NULL) { | 68 |
69 for (uint32_t i = 0; i < _candidateSet.size(); i++) { | |
philipel
2016/08/04 12:39:48
size_t
danilchap
2016/08/04 13:55:35
Done.
| |
70 if (_candidateSet.Tmmbr(i)) { | |
71 candidateSet.AddEntry(_candidateSet.Tmmbr(i), _candidateSet.PacketOH(i), | |
72 _candidateSet.Ssrc(i)); | |
73 } else { | |
74 // make sure this is zero if tmmbr = 0 | |
75 RTC_DCHECK_EQ(_candidateSet.PacketOH(i), 0u); | |
76 // Old code: | |
77 // _candidateSet.ptrPacketOHSet[i] = 0; | |
78 } | |
79 } | |
80 | |
81 // Number of set candidates | |
82 int32_t numSetCandidates = candidateSet.lengthOfSet(); | |
83 // Find bounding set | |
84 uint32_t numBoundingSet = 0; | |
85 if (numSetCandidates > 0) { | |
86 FindBoundingSet(std::move(candidateSet), &_boundingSet); | |
87 numBoundingSet = _boundingSet.size(); | |
88 if (numBoundingSet < 1 || (numBoundingSet > _candidateSet.size())) { | |
89 return -1; | |
90 } | |
91 boundingSet = &_boundingSet; | |
92 } | |
93 return numBoundingSet; | |
74 } | 94 } |
75 | 95 |
76 TMMBRHelp::~TMMBRHelp() { | 96 void TMMBRHelp::FindBoundingSet(std::vector<rtcp::TmmbItem> candidates, |
philipel
2016/08/04 12:39:48
If you change line 104 to copy that single element
danilchap
2016/08/04 13:55:35
Disagree, candidates variables mutated more often
philipel
2016/08/04 14:37:19
True.
| |
77 delete [] _ptrIntersectionBoundingSet; | 97 std::vector<rtcp::TmmbItem>* bounding_set) { |
78 delete [] _ptrMaxPRBoundingSet; | 98 RTC_DCHECK(bounding_set); |
79 _ptrIntersectionBoundingSet = 0; | 99 RTC_DCHECK(!candidates.empty()); |
80 _ptrMaxPRBoundingSet = 0; | 100 size_t num_candidates = candidates.size(); |
101 | |
102 if (num_candidates == 1) { | |
103 RTC_DCHECK(candidates[0].bitrate_bps()); | |
104 *bounding_set = std::move(candidates); | |
105 return; | |
106 } | |
107 | |
108 // 1. Sort by increasing packet overhead. | |
109 std::sort(candidates.begin(), candidates.end(), | |
110 [](const rtcp::TmmbItem& lhs, const rtcp::TmmbItem& rhs) { | |
111 return lhs.packet_overhead() < rhs.packet_overhead(); | |
112 }); | |
113 // 2. For tuples with same overhead, keep the one with the lowest bitrate. | |
philipel
2016/08/04 12:39:48
Add empty line between 112-113.
danilchap
2016/08/04 13:55:35
Done.
| |
114 for (auto it = candidates.begin(); it != candidates.end();) { | |
115 RTC_DCHECK(it->bitrate_bps()); | |
116 auto current_min = it; | |
117 auto next_it = it + 1; | |
118 // Use fact candidates are sorted by overhead, so candidates with same | |
119 // overhead are adjusted. | |
120 while (next_it != candidates.end() && | |
121 next_it->packet_overhead() == current_min->packet_overhead()) { | |
122 if (next_it->bitrate_bps() < current_min->bitrate_bps()) { | |
123 current_min->set_bitrate_bps(0); | |
124 current_min = next_it; | |
125 } else { | |
126 next_it->set_bitrate_bps(0); | |
127 } | |
128 ++next_it; | |
129 --num_candidates; | |
130 } | |
131 it = next_it; | |
132 } | |
133 // 3. Select and remove tuple with lowest tmmbr. | |
philipel
2016/08/04 12:39:48
Add empty line between 132-133
danilchap
2016/08/04 13:55:35
Done.
| |
134 // (If more than 1, choose the one with highest overhead). | |
135 auto min_bitrate_it = candidates.end(); | |
136 for (auto it = candidates.begin(); it != candidates.end(); ++it) { | |
philipel
2016/08/04 12:39:48
Combine this loop with the loop on line 143 or cha
danilchap
2016/08/04 13:55:35
Done.
| |
137 if (it->bitrate_bps()) { | |
138 min_bitrate_it = it; | |
139 break; | |
140 } | |
141 } | |
142 | |
143 for (auto it = candidates.begin(); it != candidates.end(); ++it) { | |
144 if (it->bitrate_bps() && | |
145 it->bitrate_bps() <= min_bitrate_it->bitrate_bps()) { | |
146 // Get min bitrate. | |
147 min_bitrate_it = it; | |
148 } | |
149 } | |
150 | |
151 // First member of selected list. | |
152 bounding_set->clear(); | |
153 bounding_set->reserve(num_candidates); | |
154 std::unique_ptr<float[]> intersection(new float[num_candidates]); | |
155 std::unique_ptr<float[]> max_packet_rate(new float[num_candidates]); | |
156 | |
157 bounding_set->push_back(*min_bitrate_it); | |
158 | |
159 intersection[0] = 0; | |
160 // Calculate its maximum packet rate (where its line crosses x-axis). | |
161 uint16_t packet_overhead = bounding_set->back().packet_overhead(); | |
162 if (packet_overhead == 0) { | |
163 // Avoid division by zero. | |
164 max_packet_rate[0] = std::numeric_limits<float>::max(); | |
165 } else { | |
166 max_packet_rate[0] = bounding_set->back().bitrate_bps() / | |
167 static_cast<float>(packet_overhead); | |
168 } | |
169 // Remove from candidate list. | |
170 min_bitrate_it->set_bitrate_bps(0); | |
171 --num_candidates; | |
172 | |
173 // 4. Discard from candidate list all tuple with lower overhead | |
174 // (next tuple must be steeper). | |
175 for (auto it = candidates.begin(); it != candidates.end(); ++it) { | |
176 if (it->bitrate_bps() && | |
177 it->packet_overhead() < bounding_set->front().packet_overhead()) { | |
178 it->set_bitrate_bps(0); | |
179 --num_candidates; | |
180 } | |
181 } | |
182 | |
183 bool get_new_candidate = true; | |
184 rtcp::TmmbItem cur_candidate; | |
185 while (num_candidates > 0) { | |
186 if (get_new_candidate) { | |
187 // 5. Remove first remaining tuple from candidate list. | |
188 for (auto it = candidates.begin(); it != candidates.end(); ++it) { | |
189 if (it->bitrate_bps()) { | |
190 cur_candidate = *it; | |
191 it->set_bitrate_bps(0); | |
192 break; | |
193 } | |
194 } | |
195 } | |
196 | |
197 // 6. Calculate packet rate and intersection of the current | |
198 // line with line of last tuple in selected list. | |
199 RTC_DCHECK_NE(cur_candidate.packet_overhead(), | |
200 bounding_set->back().packet_overhead()); | |
201 float packet_rate = float(cur_candidate.bitrate_bps() - | |
202 bounding_set->back().bitrate_bps()) / | |
203 (cur_candidate.packet_overhead() - | |
204 bounding_set->back().packet_overhead()); | |
205 | |
206 // 7. If the packet rate is equal or lower than intersection of | |
207 // last tuple in selected list, | |
208 // remove last tuple in selected list & go back to step 6. | |
209 if (packet_rate <= intersection[bounding_set->size() - 1]) { | |
philipel
2016/08/04 12:39:48
Reading form uninitialized memory?
Use std::vecto
danilchap
2016/08/04 13:55:35
Done.
There is some logic that first bounding_set-
| |
210 // Remove last tuple and goto step 6. | |
211 bounding_set->pop_back(); | |
212 get_new_candidate = false; | |
213 } else { | |
214 // 8. If packet rate is lower than maximum packet rate of | |
215 // last tuple in selected list, add current tuple to selected | |
216 // list. | |
217 if (packet_rate < max_packet_rate[bounding_set->size() - 1]) { | |
philipel
2016/08/04 12:39:48
Ditto.
danilchap
2016/08/04 13:55:35
Done.
| |
218 bounding_set->push_back(cur_candidate); | |
219 intersection[bounding_set->size() - 1] = packet_rate; | |
220 uint16_t packet_overhead = bounding_set->back().packet_overhead(); | |
221 RTC_DCHECK_NE(packet_overhead, 0); | |
222 max_packet_rate[bounding_set->size() - 1] = | |
223 bounding_set->back().bitrate_bps() / | |
224 static_cast<float>(packet_overhead); | |
225 } | |
226 --num_candidates; | |
227 get_new_candidate = true; | |
228 } | |
229 | |
230 // 9. Go back to step 5 if any tuple remains in candidate list. | |
231 } | |
81 } | 232 } |
82 | 233 |
83 TMMBRSet* | 234 bool TMMBRHelp::IsOwner(const uint32_t ssrc, const uint32_t length) const { |
84 TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize) | |
85 { | |
86 if(minimumSize > _boundingSet.capacity()) | |
87 { | |
88 // make sure that our buffers are big enough | |
89 if(_ptrIntersectionBoundingSet) | |
90 { | |
91 delete [] _ptrIntersectionBoundingSet; | |
92 delete [] _ptrMaxPRBoundingSet; | |
93 } | |
94 _ptrIntersectionBoundingSet = new float[minimumSize]; | |
95 _ptrMaxPRBoundingSet = new float[minimumSize]; | |
96 } | |
97 _boundingSet.VerifyAndAllocateSet(minimumSize); | |
98 return &_boundingSet; | |
99 } | |
100 | |
101 TMMBRSet* TMMBRHelp::BoundingSet() { | |
102 return &_boundingSet; | |
103 } | |
104 | |
105 TMMBRSet* | |
106 TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize) | |
107 { | |
108 _candidateSet.VerifyAndAllocateSet(minimumSize); | |
109 return &_candidateSet; | |
110 } | |
111 | |
112 TMMBRSet* | |
113 TMMBRHelp::CandidateSet() | |
114 { | |
115 return &_candidateSet; | |
116 } | |
117 | |
118 int32_t | |
119 TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet) | |
120 { | |
121 // Work on local variable, will be modified | |
122 TMMBRSet candidateSet; | |
123 candidateSet.VerifyAndAllocateSet(_candidateSet.capacity()); | |
124 | |
125 for (uint32_t i = 0; i < _candidateSet.size(); i++) | |
126 { | |
127 if(_candidateSet.Tmmbr(i)) | |
128 { | |
129 candidateSet.AddEntry(_candidateSet.Tmmbr(i), | |
130 _candidateSet.PacketOH(i), | |
131 _candidateSet.Ssrc(i)); | |
132 } | |
133 else | |
134 { | |
135 // make sure this is zero if tmmbr = 0 | |
136 assert(_candidateSet.PacketOH(i) == 0); | |
137 // Old code: | |
138 // _candidateSet.ptrPacketOHSet[i] = 0; | |
139 } | |
140 } | |
141 | |
142 // Number of set candidates | |
143 int32_t numSetCandidates = candidateSet.lengthOfSet(); | |
144 // Find bounding set | |
145 uint32_t numBoundingSet = 0; | |
146 if (numSetCandidates > 0) | |
147 { | |
148 numBoundingSet = FindTMMBRBoundingSet(numSetCandidates, candidateSet); | |
149 if(numBoundingSet < 1 || (numBoundingSet > _candidateSet.size())) | |
150 { | |
151 return -1; | |
152 } | |
153 boundingSet = &_boundingSet; | |
154 } | |
155 return numBoundingSet; | |
156 } | |
157 | |
158 | |
159 int32_t | |
160 TMMBRHelp::FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet) | |
161 { | |
162 uint32_t numBoundingSet = 0; | |
163 VerifyAndAllocateBoundingSet(candidateSet.capacity()); | |
164 | |
165 if (numCandidates == 1) | |
166 { | |
167 for (uint32_t i = 0; i < candidateSet.size(); i++) | |
168 { | |
169 if (candidateSet.Tmmbr(i) > 0) | |
170 { | |
171 _boundingSet.AddEntry(candidateSet.Tmmbr(i), | |
172 candidateSet.PacketOH(i), | |
173 candidateSet.Ssrc(i)); | |
174 numBoundingSet++; | |
175 } | |
176 } | |
177 return (numBoundingSet == 1) ? 1 : -1; | |
178 } | |
179 | |
180 // 1. Sort by increasing packetOH | |
181 for (int i = candidateSet.size() - 1; i >= 0; i--) | |
182 { | |
183 for (int j = 1; j <= i; j++) | |
184 { | |
185 if (candidateSet.PacketOH(j-1) > candidateSet.PacketOH(j)) | |
186 { | |
187 candidateSet.SwapEntries(j-1, j); | |
188 } | |
189 } | |
190 } | |
191 // 2. For tuples with same OH, keep the one w/ the lowest bitrate | |
192 for (uint32_t i = 0; i < candidateSet.size(); i++) | |
193 { | |
194 if (candidateSet.Tmmbr(i) > 0) | |
195 { | |
196 // get min bitrate for packets w/ same OH | |
197 uint32_t currentPacketOH = candidateSet.PacketOH(i); | |
198 uint32_t currentMinTMMBR = candidateSet.Tmmbr(i); | |
199 uint32_t currentMinIndexTMMBR = i; | |
200 for (uint32_t j = i+1; j < candidateSet.size(); j++) | |
201 { | |
202 if(candidateSet.PacketOH(j) == currentPacketOH) | |
203 { | |
204 if(candidateSet.Tmmbr(j) < currentMinTMMBR) | |
205 { | |
206 currentMinTMMBR = candidateSet.Tmmbr(j); | |
207 currentMinIndexTMMBR = j; | |
208 } | |
209 } | |
210 } | |
211 // keep lowest bitrate | |
212 for (uint32_t j = 0; j < candidateSet.size(); j++) | |
213 { | |
214 if(candidateSet.PacketOH(j) == currentPacketOH | |
215 && j != currentMinIndexTMMBR) | |
216 { | |
217 candidateSet.ClearEntry(j); | |
218 numCandidates--; | |
219 } | |
220 } | |
221 } | |
222 } | |
223 // 3. Select and remove tuple w/ lowest tmmbr. | |
224 // (If more than 1, choose the one w/ highest OH). | |
225 uint32_t minTMMBR = 0; | |
226 uint32_t minIndexTMMBR = 0; | |
227 for (uint32_t i = 0; i < candidateSet.size(); i++) | |
228 { | |
229 if (candidateSet.Tmmbr(i) > 0) | |
230 { | |
231 minTMMBR = candidateSet.Tmmbr(i); | |
232 minIndexTMMBR = i; | |
233 break; | |
234 } | |
235 } | |
236 | |
237 for (uint32_t i = 0; i < candidateSet.size(); i++) | |
238 { | |
239 if (candidateSet.Tmmbr(i) > 0 && candidateSet.Tmmbr(i) <= minTMMBR) | |
240 { | |
241 // get min bitrate | |
242 minTMMBR = candidateSet.Tmmbr(i); | |
243 minIndexTMMBR = i; | |
244 } | |
245 } | |
246 // first member of selected list | |
247 _boundingSet.SetEntry(numBoundingSet, | |
248 candidateSet.Tmmbr(minIndexTMMBR), | |
249 candidateSet.PacketOH(minIndexTMMBR), | |
250 candidateSet.Ssrc(minIndexTMMBR)); | |
251 | |
252 // set intersection value | |
253 _ptrIntersectionBoundingSet[numBoundingSet] = 0; | |
254 // calculate its maximum packet rate (where its line crosses x-axis) | |
255 uint32_t packet_overhead_bits = 8 * _boundingSet.PacketOH(numBoundingSet); | |
256 if (packet_overhead_bits == 0) { | |
257 // Avoid division by zero. | |
258 _ptrMaxPRBoundingSet[numBoundingSet] = std::numeric_limits<float>::max(); | |
259 } else { | |
260 _ptrMaxPRBoundingSet[numBoundingSet] = | |
261 _boundingSet.Tmmbr(numBoundingSet) * 1000 / | |
262 static_cast<float>(packet_overhead_bits); | |
263 } | |
264 numBoundingSet++; | |
265 // remove from candidate list | |
266 candidateSet.ClearEntry(minIndexTMMBR); | |
267 numCandidates--; | |
268 | |
269 // 4. Discard from candidate list all tuple w/ lower OH | |
270 // (next tuple must be steeper) | |
271 for (uint32_t i = 0; i < candidateSet.size(); i++) | |
272 { | |
273 if(candidateSet.Tmmbr(i) > 0 | |
274 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0)) | |
275 { | |
276 candidateSet.ClearEntry(i); | |
277 numCandidates--; | |
278 } | |
279 } | |
280 | |
281 if (numCandidates == 0) | |
282 { | |
283 // Should be true already:_boundingSet.lengthOfSet = numBoundingSet; | |
284 assert(_boundingSet.lengthOfSet() == numBoundingSet); | |
285 return numBoundingSet; | |
286 } | |
287 | |
288 bool getNewCandidate = true; | |
289 uint32_t curCandidateTMMBR = 0; | |
290 size_t curCandidateIndex = 0; | |
291 uint32_t curCandidatePacketOH = 0; | |
292 uint32_t curCandidateSSRC = 0; | |
293 do | |
294 { | |
295 if (getNewCandidate) | |
296 { | |
297 // 5. Remove first remaining tuple from candidate list | |
298 for (uint32_t i = 0; i < candidateSet.size(); i++) | |
299 { | |
300 if (candidateSet.Tmmbr(i) > 0) | |
301 { | |
302 curCandidateTMMBR = candidateSet.Tmmbr(i); | |
303 curCandidatePacketOH = candidateSet.PacketOH(i); | |
304 curCandidateSSRC = candidateSet.Ssrc(i); | |
305 curCandidateIndex = i; | |
306 candidateSet.ClearEntry(curCandidateIndex); | |
307 break; | |
308 } | |
309 } | |
310 } | |
311 | |
312 // 6. Calculate packet rate and intersection of the current | |
313 // line with line of last tuple in selected list | |
314 RTC_DCHECK_NE(curCandidatePacketOH, | |
315 _boundingSet.PacketOH(numBoundingSet - 1)); | |
316 float packetRate | |
317 = float(curCandidateTMMBR | |
318 - _boundingSet.Tmmbr(numBoundingSet-1))*1000 | |
319 / (8*(curCandidatePacketOH | |
320 - _boundingSet.PacketOH(numBoundingSet-1))); | |
321 | |
322 // 7. If the packet rate is equal or lower than intersection of | |
323 // last tuple in selected list, | |
324 // remove last tuple in selected list & go back to step 6 | |
325 if(packetRate <= _ptrIntersectionBoundingSet[numBoundingSet-1]) | |
326 { | |
327 // remove last tuple and goto step 6 | |
328 numBoundingSet--; | |
329 _boundingSet.ClearEntry(numBoundingSet); | |
330 _ptrIntersectionBoundingSet[numBoundingSet] = 0; | |
331 _ptrMaxPRBoundingSet[numBoundingSet] = 0; | |
332 getNewCandidate = false; | |
333 } else | |
334 { | |
335 // 8. If packet rate is lower than maximum packet rate of | |
336 // last tuple in selected list, add current tuple to selected | |
337 // list | |
338 if (packetRate < _ptrMaxPRBoundingSet[numBoundingSet-1]) | |
339 { | |
340 _boundingSet.SetEntry(numBoundingSet, | |
341 curCandidateTMMBR, | |
342 curCandidatePacketOH, | |
343 curCandidateSSRC); | |
344 _ptrIntersectionBoundingSet[numBoundingSet] = packetRate; | |
345 float packet_overhead_bits = | |
346 8 * _boundingSet.PacketOH(numBoundingSet); | |
347 RTC_DCHECK_NE(packet_overhead_bits, 0.0f); | |
348 _ptrMaxPRBoundingSet[numBoundingSet] = | |
349 _boundingSet.Tmmbr(numBoundingSet) * 1000 / | |
350 packet_overhead_bits; | |
351 numBoundingSet++; | |
352 } | |
353 numCandidates--; | |
354 getNewCandidate = true; | |
355 } | |
356 | |
357 // 9. Go back to step 5 if any tuple remains in candidate list | |
358 } while (numCandidates > 0); | |
359 | |
360 return numBoundingSet; | |
361 } | |
362 | |
363 bool TMMBRHelp::IsOwner(const uint32_t ssrc, | |
364 const uint32_t length) const { | |
365 if (length == 0) { | 235 if (length == 0) { |
366 // Empty bounding set. | 236 // Empty bounding set. |
367 return false; | 237 return false; |
368 } | 238 } |
369 for(uint32_t i = 0; | 239 for (uint32_t i = 0; (i < length) && (i < _boundingSet.size()); ++i) { |
philipel
2016/08/04 12:39:48
size_t
danilchap
2016/08/04 13:55:35
Done.
| |
370 (i < length) && (i < _boundingSet.size()); ++i) { | 240 if (_boundingSet.Ssrc(i) == ssrc) { |
371 if(_boundingSet.Ssrc(i) == ssrc) { | |
372 return true; | 241 return true; |
373 } | 242 } |
374 } | 243 } |
375 return false; | 244 return false; |
376 } | 245 } |
377 | 246 |
378 bool TMMBRHelp::CalcMinBitRate( uint32_t* minBitrateKbit) const { | 247 bool TMMBRHelp::CalcMinBitRate(uint32_t* minBitrateKbit) const { |
379 if (_candidateSet.size() == 0) { | 248 if (_candidateSet.size() == 0) { |
380 // Empty bounding set. | 249 // Empty bounding set. |
381 return false; | 250 return false; |
382 } | 251 } |
383 *minBitrateKbit = std::numeric_limits<uint32_t>::max(); | 252 *minBitrateKbit = std::numeric_limits<uint32_t>::max(); |
384 | 253 |
385 for (uint32_t i = 0; i < _candidateSet.lengthOfSet(); ++i) { | 254 for (uint32_t i = 0; i < _candidateSet.lengthOfSet(); ++i) { |
386 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i); | 255 uint32_t curNetBitRateKbit = _candidateSet.Tmmbr(i); |
387 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) { | 256 if (curNetBitRateKbit < MIN_VIDEO_BW_MANAGEMENT_BITRATE) { |
388 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE; | 257 curNetBitRateKbit = MIN_VIDEO_BW_MANAGEMENT_BITRATE; |
389 } | 258 } |
390 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ? | 259 *minBitrateKbit = curNetBitRateKbit < *minBitrateKbit ? curNetBitRateKbit |
391 curNetBitRateKbit : *minBitrateKbit; | 260 : *minBitrateKbit; |
392 } | 261 } |
393 return true; | 262 return true; |
394 } | 263 } |
395 } // namespace webrtc | 264 } // namespace webrtc |
OLD | NEW |