| 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> |
| 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 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" |
| 20 | 18 |
| 21 namespace webrtc { | 19 namespace webrtc { |
| 22 void | 20 void TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) { |
| 23 TMMBRSet::VerifyAndAllocateSet(uint32_t minimumSize) | |
| 24 { | |
| 25 clear(); | 21 clear(); |
| 26 reserve(minimumSize); | 22 reserve(minimumSize); |
| 27 } | 23 } |
| 28 | 24 |
| 29 void | 25 void TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize) { |
| 30 TMMBRSet::VerifyAndAllocateSetKeepingData(uint32_t minimumSize) | |
| 31 { | |
| 32 reserve(minimumSize); | 26 reserve(minimumSize); |
| 33 } | 27 } |
| 34 | 28 |
| 35 void TMMBRSet::SetEntry(unsigned int i, | 29 void TMMBRSet::SetEntry(unsigned int i, |
| 36 uint32_t tmmbrSet, | 30 uint32_t tmmbrSet, |
| 37 uint32_t packetOHSet, | 31 uint32_t packetOHSet, |
| 38 uint32_t ssrcSet) { | 32 uint32_t ssrcSet) { |
| 39 RTC_DCHECK_LT(i, capacity()); | 33 RTC_DCHECK_LT(i, capacity()); |
| 40 if (i >= size()) { | 34 if (i >= size()) { |
| 41 resize(i+1); | 35 resize(i + 1); |
| 42 } | 36 } |
| 43 (*this)[i].set_bitrate_bps(tmmbrSet * 1000); | 37 (*this)[i].set_bitrate_bps(tmmbrSet * 1000); |
| 44 (*this)[i].set_packet_overhead(packetOHSet); | 38 (*this)[i].set_packet_overhead(packetOHSet); |
| 45 (*this)[i].set_ssrc(ssrcSet); | 39 (*this)[i].set_ssrc(ssrcSet); |
| 46 } | 40 } |
| 47 | 41 |
| 48 void TMMBRSet::AddEntry(uint32_t tmmbrSet, | 42 void TMMBRSet::AddEntry(uint32_t tmmbrSet, |
| 49 uint32_t packetOHSet, | 43 uint32_t packetOHSet, |
| 50 uint32_t ssrcSet) { | 44 uint32_t ssrcSet) { |
| 51 RTC_DCHECK_LT(size(), capacity()); | 45 RTC_DCHECK_LT(size(), capacity()); |
| 52 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet); | 46 SetEntry(size(), tmmbrSet, packetOHSet, ssrcSet); |
| 53 } | 47 } |
| 54 | 48 |
| 55 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { | 49 void TMMBRSet::RemoveEntry(uint32_t sourceIdx) { |
| 56 RTC_DCHECK_LT(sourceIdx, size()); | 50 RTC_DCHECK_LT(sourceIdx, size()); |
| 57 erase(begin() + sourceIdx); | 51 erase(begin() + sourceIdx); |
| 58 } | 52 } |
| 59 | 53 |
| 60 void TMMBRSet::SwapEntries(uint32_t i, uint32_t j) { | 54 TMMBRSet* TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize) { |
| 61 using std::swap; | 55 _candidateSet.VerifyAndAllocateSet(minimumSize); |
| 62 swap((*this)[i], (*this)[j]); | 56 return &_candidateSet; |
| 63 } | 57 } |
| 64 | 58 |
| 65 void TMMBRSet::ClearEntry(uint32_t idx) { | 59 TMMBRSet* TMMBRHelp::CandidateSet() { |
| 66 SetEntry(idx, 0, 0, 0); | 60 return &_candidateSet; |
| 67 } | 61 } |
| 68 | 62 |
| 69 TMMBRHelp::TMMBRHelp() | 63 int32_t TMMBRHelp::FindTMMBRBoundingSet(TMMBRSet*& boundingSet) { |
| 70 : _candidateSet(), | 64 // Work on local variable, will be modified |
| 71 _boundingSet(), | 65 TMMBRSet candidateSet; |
| 72 _ptrIntersectionBoundingSet(NULL), | 66 candidateSet.VerifyAndAllocateSet(_candidateSet.capacity()); |
| 73 _ptrMaxPRBoundingSet(NULL) { | 67 |
| 74 } | 68 for (size_t i = 0; i < _candidateSet.size(); i++) { |
| 75 | 69 if (_candidateSet.Tmmbr(i)) { |
| 76 TMMBRHelp::~TMMBRHelp() { | 70 candidateSet.AddEntry(_candidateSet.Tmmbr(i), _candidateSet.PacketOH(i), |
| 77 delete [] _ptrIntersectionBoundingSet; | 71 _candidateSet.Ssrc(i)); |
| 78 delete [] _ptrMaxPRBoundingSet; | 72 } else { |
| 79 _ptrIntersectionBoundingSet = 0; | 73 // make sure this is zero if tmmbr = 0 |
| 80 _ptrMaxPRBoundingSet = 0; | 74 RTC_DCHECK_EQ(_candidateSet.PacketOH(i), 0u); |
| 81 } | 75 // Old code: |
| 82 | 76 // _candidateSet.ptrPacketOHSet[i] = 0; |
| 83 TMMBRSet* | 77 } |
| 84 TMMBRHelp::VerifyAndAllocateBoundingSet(uint32_t minimumSize) | 78 } |
| 85 { | 79 |
| 86 if(minimumSize > _boundingSet.capacity()) | 80 // Number of set candidates |
| 87 { | 81 int32_t numSetCandidates = candidateSet.lengthOfSet(); |
| 88 // make sure that our buffers are big enough | 82 // Find bounding set |
| 89 if(_ptrIntersectionBoundingSet) | 83 uint32_t numBoundingSet = 0; |
| 90 { | 84 if (numSetCandidates > 0) { |
| 91 delete [] _ptrIntersectionBoundingSet; | 85 FindBoundingSet(std::move(candidateSet), &_boundingSet); |
| 92 delete [] _ptrMaxPRBoundingSet; | 86 numBoundingSet = _boundingSet.size(); |
| 87 if (numBoundingSet < 1 || (numBoundingSet > _candidateSet.size())) { |
| 88 return -1; |
| 89 } |
| 90 boundingSet = &_boundingSet; |
| 91 } |
| 92 return numBoundingSet; |
| 93 } |
| 94 |
| 95 void TMMBRHelp::FindBoundingSet(std::vector<rtcp::TmmbItem> candidates, |
| 96 std::vector<rtcp::TmmbItem>* bounding_set) { |
| 97 RTC_DCHECK(bounding_set); |
| 98 RTC_DCHECK(!candidates.empty()); |
| 99 size_t num_candidates = candidates.size(); |
| 100 |
| 101 if (num_candidates == 1) { |
| 102 RTC_DCHECK(candidates[0].bitrate_bps()); |
| 103 *bounding_set = std::move(candidates); |
| 104 return; |
| 105 } |
| 106 |
| 107 // 1. Sort by increasing packet overhead. |
| 108 std::sort(candidates.begin(), candidates.end(), |
| 109 [](const rtcp::TmmbItem& lhs, const rtcp::TmmbItem& rhs) { |
| 110 return lhs.packet_overhead() < rhs.packet_overhead(); |
| 111 }); |
| 112 |
| 113 // 2. For tuples with same overhead, keep the one with the lowest bitrate. |
| 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 |
| 134 // 3. Select and remove tuple with lowest tmmbr. |
| 135 // (If more than 1, choose the one with highest overhead). |
| 136 auto min_bitrate_it = candidates.end(); |
| 137 for (auto it = candidates.begin(); it != candidates.end(); ++it) { |
| 138 if (it->bitrate_bps()) { |
| 139 min_bitrate_it = it; |
| 140 break; |
| 141 } |
| 142 } |
| 143 |
| 144 for (auto it = min_bitrate_it; it != candidates.end(); ++it) { |
| 145 if (it->bitrate_bps() && |
| 146 it->bitrate_bps() <= min_bitrate_it->bitrate_bps()) { |
| 147 // Get min bitrate. |
| 148 min_bitrate_it = it; |
| 149 } |
| 150 } |
| 151 |
| 152 bounding_set->clear(); |
| 153 bounding_set->reserve(num_candidates); |
| 154 std::vector<float> intersection(num_candidates); |
| 155 std::vector<float> max_packet_rate(num_candidates); |
| 156 |
| 157 // First member of selected list. |
| 158 bounding_set->push_back(*min_bitrate_it); |
| 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; |
| 93 } | 193 } |
| 94 _ptrIntersectionBoundingSet = new float[minimumSize]; | 194 } |
| 95 _ptrMaxPRBoundingSet = new float[minimumSize]; | 195 } |
| 96 } | 196 |
| 97 _boundingSet.VerifyAndAllocateSet(minimumSize); | 197 // 6. Calculate packet rate and intersection of the current |
| 98 return &_boundingSet; | 198 // line with line of last tuple in selected list. |
| 99 } | 199 RTC_DCHECK_NE(cur_candidate.packet_overhead(), |
| 100 | 200 bounding_set->back().packet_overhead()); |
| 101 TMMBRSet* TMMBRHelp::BoundingSet() { | 201 float packet_rate = static_cast<float>(cur_candidate.bitrate_bps() - |
| 102 return &_boundingSet; | 202 bounding_set->back().bitrate_bps()) / |
| 103 } | 203 (cur_candidate.packet_overhead() - |
| 104 | 204 bounding_set->back().packet_overhead()); |
| 105 TMMBRSet* | 205 |
| 106 TMMBRHelp::VerifyAndAllocateCandidateSet(uint32_t minimumSize) | 206 // 7. If the packet rate is equal or lower than intersection of |
| 107 { | 207 // last tuple in selected list, |
| 108 _candidateSet.VerifyAndAllocateSet(minimumSize); | 208 // remove last tuple in selected list & go back to step 6. |
| 109 return &_candidateSet; | 209 if (packet_rate <= intersection[bounding_set->size() - 1]) { |
| 110 } | 210 // Remove last tuple and goto step 6. |
| 111 | 211 bounding_set->pop_back(); |
| 112 TMMBRSet* | 212 get_new_candidate = false; |
| 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 { | 213 } else { |
| 260 _ptrMaxPRBoundingSet[numBoundingSet] = | 214 // 8. If packet rate is lower than maximum packet rate of |
| 261 _boundingSet.Tmmbr(numBoundingSet) * 1000 / | 215 // last tuple in selected list, add current tuple to selected |
| 262 static_cast<float>(packet_overhead_bits); | 216 // list. |
| 263 } | 217 if (packet_rate < max_packet_rate[bounding_set->size() - 1]) { |
| 264 numBoundingSet++; | 218 bounding_set->push_back(cur_candidate); |
| 265 // remove from candidate list | 219 intersection[bounding_set->size() - 1] = packet_rate; |
| 266 candidateSet.ClearEntry(minIndexTMMBR); | 220 uint16_t packet_overhead = bounding_set->back().packet_overhead(); |
| 267 numCandidates--; | 221 RTC_DCHECK_NE(packet_overhead, 0); |
| 268 | 222 max_packet_rate[bounding_set->size() - 1] = |
| 269 // 4. Discard from candidate list all tuple w/ lower OH | 223 bounding_set->back().bitrate_bps() / |
| 270 // (next tuple must be steeper) | 224 static_cast<float>(packet_overhead); |
| 271 for (uint32_t i = 0; i < candidateSet.size(); i++) | 225 } |
| 272 { | 226 --num_candidates; |
| 273 if(candidateSet.Tmmbr(i) > 0 | 227 get_new_candidate = true; |
| 274 && candidateSet.PacketOH(i) < _boundingSet.PacketOH(0)) | 228 } |
| 275 { | 229 |
| 276 candidateSet.ClearEntry(i); | 230 // 9. Go back to step 5 if any tuple remains in candidate list. |
| 277 numCandidates--; | 231 } |
| 278 } | 232 } |
| 279 } | 233 |
| 280 | 234 bool TMMBRHelp::IsOwner(const uint32_t ssrc, const uint32_t length) const { |
| 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 (size_t i = 0; (i < length) && (i < _boundingSet.size()); ++i) { |
| 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 (size_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 |