andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 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 | |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 11 | #include <map> |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 12 | |
sprang@webrtc.org | 7374da3 | 2013-12-03 10:31:59 +0000 | [diff] [blame] | 13 | #include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h" |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 14 | #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" |
| 15 | #include "webrtc/modules/remote_bitrate_estimator/overuse_detector.h" |
| 16 | #include "webrtc/modules/remote_bitrate_estimator/remote_rate_control.h" |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 17 | #include "webrtc/system_wrappers/interface/clock.h" |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 18 | #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
| 19 | #include "webrtc/system_wrappers/interface/scoped_ptr.h" |
pbos@webrtc.org | 46f7288 | 2013-12-16 12:24:44 +0000 | [diff] [blame] | 20 | #include "webrtc/system_wrappers/interface/trace.h" |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 21 | #include "webrtc/typedefs.h" |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 22 | |
| 23 | namespace webrtc { |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 24 | namespace { |
| 25 | class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator { |
| 26 | public: |
| 27 | RemoteBitrateEstimatorSingleStream(RemoteBitrateObserver* observer, |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 28 | Clock* clock, |
| 29 | uint32_t min_bitrate_bps); |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 30 | virtual ~RemoteBitrateEstimatorSingleStream() {} |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 31 | |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 32 | // Called for each incoming packet. If this is a new SSRC, a new |
| 33 | // BitrateControl will be created. Updates the incoming payload bitrate |
| 34 | // estimate and the over-use detector. If an over-use is detected the |
| 35 | // remote bitrate estimate will be updated. Note that |payload_size| is the |
| 36 | // packet size excluding headers. |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 37 | virtual void IncomingPacket(int64_t arrival_time_ms, |
| 38 | int payload_size, |
pbos@webrtc.org | 988a5b3 | 2013-07-31 15:16:52 +0000 | [diff] [blame] | 39 | const RTPHeader& header) OVERRIDE; |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 40 | |
| 41 | // Triggers a new estimate calculation. |
| 42 | // Implements the Module interface. |
pbos@webrtc.org | 988a5b3 | 2013-07-31 15:16:52 +0000 | [diff] [blame] | 43 | virtual int32_t Process() OVERRIDE; |
| 44 | virtual int32_t TimeUntilNextProcess() OVERRIDE; |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 45 | // Set the current round-trip time experienced by the stream. |
| 46 | // Implements the StatsObserver interface. |
pbos@webrtc.org | 988a5b3 | 2013-07-31 15:16:52 +0000 | [diff] [blame] | 47 | virtual void OnRttUpdate(uint32_t rtt) OVERRIDE; |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 48 | |
| 49 | // Removes all data for |ssrc|. |
pbos@webrtc.org | 988a5b3 | 2013-07-31 15:16:52 +0000 | [diff] [blame] | 50 | virtual void RemoveStream(unsigned int ssrc) OVERRIDE; |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 51 | |
| 52 | // Returns true if a valid estimate exists and sets |bitrate_bps| to the |
| 53 | // estimated payload bitrate in bits per second. |ssrcs| is the list of ssrcs |
| 54 | // currently being received and of which the bitrate estimate is based upon. |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 55 | virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs, |
pbos@webrtc.org | 988a5b3 | 2013-07-31 15:16:52 +0000 | [diff] [blame] | 56 | unsigned int* bitrate_bps) const OVERRIDE; |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 57 | |
jiayl@webrtc.org | d1e7fac | 2014-02-10 19:12:14 +0000 | [diff] [blame] | 58 | virtual bool GetStats( |
| 59 | ReceiveBandwidthEstimatorStats* output) const OVERRIDE; |
| 60 | |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 61 | private: |
| 62 | typedef std::map<unsigned int, OveruseDetector> SsrcOveruseDetectorMap; |
| 63 | |
| 64 | // Triggers a new estimate calculation. |
| 65 | void UpdateEstimate(int64_t time_now); |
| 66 | |
| 67 | void GetSsrcs(std::vector<unsigned int>* ssrcs) const; |
| 68 | |
| 69 | Clock* clock_; |
| 70 | SsrcOveruseDetectorMap overuse_detectors_; |
sprang@webrtc.org | 7374da3 | 2013-12-03 10:31:59 +0000 | [diff] [blame] | 71 | RateStatistics incoming_bitrate_; |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 72 | RemoteRateControl remote_rate_; |
| 73 | RemoteBitrateObserver* observer_; |
| 74 | scoped_ptr<CriticalSectionWrapper> crit_sect_; |
| 75 | int64_t last_process_time_; |
| 76 | }; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 77 | |
| 78 | RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream( |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 79 | RemoteBitrateObserver* observer, |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 80 | Clock* clock, |
| 81 | uint32_t min_bitrate_bps) |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 82 | : clock_(clock), |
sprang@webrtc.org | 7374da3 | 2013-12-03 10:31:59 +0000 | [diff] [blame] | 83 | incoming_bitrate_(500, 8000), |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 84 | remote_rate_(min_bitrate_bps), |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 85 | observer_(observer), |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 86 | crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), |
| 87 | last_process_time_(-1) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 88 | assert(observer_); |
| 89 | } |
| 90 | |
| 91 | void RemoteBitrateEstimatorSingleStream::IncomingPacket( |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 92 | int64_t arrival_time_ms, |
stefan@webrtc.org | 376495a | 2012-11-13 15:02:13 +0000 | [diff] [blame] | 93 | int payload_size, |
stefan@webrtc.org | d8ecee5 | 2013-06-04 12:15:40 +0000 | [diff] [blame] | 94 | const RTPHeader& header) { |
| 95 | uint32_t ssrc = header.ssrc; |
| 96 | uint32_t rtp_timestamp = header.timestamp + |
| 97 | header.extension.transmissionTimeOffset; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 98 | CriticalSectionScoped cs(crit_sect_.get()); |
| 99 | SsrcOveruseDetectorMap::iterator it = overuse_detectors_.find(ssrc); |
| 100 | if (it == overuse_detectors_.end()) { |
| 101 | // This is a new SSRC. Adding to map. |
| 102 | // TODO(holmer): If the channel changes SSRC the old SSRC will still be |
| 103 | // around in this map until the channel is deleted. This is OK since the |
| 104 | // callback will no longer be called for the old SSRC. This will be |
| 105 | // automatically cleaned up when we have one RemoteBitrateEstimator per REMB |
| 106 | // group. |
| 107 | std::pair<SsrcOveruseDetectorMap::iterator, bool> insert_result = |
| 108 | overuse_detectors_.insert(std::make_pair(ssrc, OveruseDetector( |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 109 | OverUseDetectorOptions()))); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 110 | it = insert_result.first; |
| 111 | } |
| 112 | OveruseDetector* overuse_detector = &it->second; |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 113 | incoming_bitrate_.Update(payload_size, arrival_time_ms); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 114 | const BandwidthUsage prior_state = overuse_detector->State(); |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 115 | overuse_detector->Update(payload_size, -1, rtp_timestamp, arrival_time_ms); |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 116 | if (overuse_detector->State() == kBwOverusing) { |
sprang@webrtc.org | 7374da3 | 2013-12-03 10:31:59 +0000 | [diff] [blame] | 117 | unsigned int incoming_bitrate = incoming_bitrate_.Rate(arrival_time_ms); |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 118 | if (prior_state != kBwOverusing || |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 119 | remote_rate_.TimeToReduceFurther(arrival_time_ms, incoming_bitrate)) { |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 120 | // The first overuse should immediately trigger a new estimate. |
| 121 | // We also have to update the estimate immediately if we are overusing |
| 122 | // and the target bitrate is too high compared to what we are receiving. |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 123 | UpdateEstimate(arrival_time_ms); |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 124 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 128 | int32_t RemoteBitrateEstimatorSingleStream::Process() { |
| 129 | if (TimeUntilNextProcess() > 0) { |
| 130 | return 0; |
| 131 | } |
| 132 | UpdateEstimate(clock_->TimeInMilliseconds()); |
| 133 | last_process_time_ = clock_->TimeInMilliseconds(); |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | int32_t RemoteBitrateEstimatorSingleStream::TimeUntilNextProcess() { |
| 138 | if (last_process_time_ < 0) { |
| 139 | return 0; |
| 140 | } |
| 141 | return last_process_time_ + kProcessIntervalMs - clock_->TimeInMilliseconds(); |
| 142 | } |
| 143 | |
| 144 | void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t time_now) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 145 | CriticalSectionScoped cs(crit_sect_.get()); |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 146 | BandwidthUsage bw_state = kBwNormal; |
| 147 | double sum_noise_var = 0.0; |
| 148 | SsrcOveruseDetectorMap::iterator it = overuse_detectors_.begin(); |
| 149 | while (it != overuse_detectors_.end()) { |
| 150 | const int64_t time_of_last_received_packet = |
| 151 | it->second.time_of_last_received_packet(); |
| 152 | if (time_of_last_received_packet >= 0 && |
| 153 | time_now - time_of_last_received_packet > kStreamTimeOutMs) { |
| 154 | // This over-use detector hasn't received packets for |kStreamTimeOutMs| |
| 155 | // milliseconds and is considered stale. |
| 156 | overuse_detectors_.erase(it++); |
| 157 | } else { |
| 158 | sum_noise_var += it->second.NoiseVar(); |
| 159 | // Make sure that we trigger an over-use if any of the over-use detectors |
| 160 | // is detecting over-use. |
| 161 | if (it->second.State() > bw_state) { |
| 162 | bw_state = it->second.State(); |
| 163 | } |
| 164 | ++it; |
| 165 | } |
| 166 | } |
| 167 | // We can't update the estimate if we don't have any active streams. |
| 168 | if (overuse_detectors_.empty()) { |
| 169 | remote_rate_.Reset(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 170 | return; |
| 171 | } |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 172 | double mean_noise_var = sum_noise_var / |
| 173 | static_cast<double>(overuse_detectors_.size()); |
| 174 | const RateControlInput input(bw_state, |
sprang@webrtc.org | 7374da3 | 2013-12-03 10:31:59 +0000 | [diff] [blame] | 175 | incoming_bitrate_.Rate(time_now), |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 176 | mean_noise_var); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 177 | const RateControlRegion region = remote_rate_.Update(&input, time_now); |
| 178 | unsigned int target_bitrate = remote_rate_.UpdateBandwidthEstimate(time_now); |
| 179 | if (remote_rate_.ValidEstimate()) { |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 180 | std::vector<unsigned int> ssrcs; |
| 181 | GetSsrcs(&ssrcs); |
solenberg@webrtc.org | b7716d8 | 2013-05-22 19:04:19 +0000 | [diff] [blame] | 182 | observer_->OnReceiveBitrateChanged(ssrcs, target_bitrate); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 183 | } |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 184 | for (it = overuse_detectors_.begin(); it != overuse_detectors_.end(); ++it) { |
| 185 | it->second.SetRateControlRegion(region); |
| 186 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 187 | } |
| 188 | |
stefan@webrtc.org | 2a5dbce | 2013-02-01 14:33:42 +0000 | [diff] [blame] | 189 | void RemoteBitrateEstimatorSingleStream::OnRttUpdate(uint32_t rtt) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 190 | CriticalSectionScoped cs(crit_sect_.get()); |
| 191 | remote_rate_.SetRtt(rtt); |
| 192 | } |
| 193 | |
| 194 | void RemoteBitrateEstimatorSingleStream::RemoveStream(unsigned int ssrc) { |
| 195 | CriticalSectionScoped cs(crit_sect_.get()); |
| 196 | // Ignoring the return value which is the number of elements erased. |
| 197 | overuse_detectors_.erase(ssrc); |
| 198 | } |
| 199 | |
| 200 | bool RemoteBitrateEstimatorSingleStream::LatestEstimate( |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 201 | std::vector<unsigned int>* ssrcs, |
| 202 | unsigned int* bitrate_bps) const { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 203 | CriticalSectionScoped cs(crit_sect_.get()); |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 204 | assert(bitrate_bps); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 205 | if (!remote_rate_.ValidEstimate()) { |
| 206 | return false; |
| 207 | } |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 208 | GetSsrcs(ssrcs); |
| 209 | if (ssrcs->empty()) |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 210 | *bitrate_bps = 0; |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 211 | else |
| 212 | *bitrate_bps = remote_rate_.LatestEstimate(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 213 | return true; |
| 214 | } |
| 215 | |
jiayl@webrtc.org | d1e7fac | 2014-02-10 19:12:14 +0000 | [diff] [blame] | 216 | bool RemoteBitrateEstimatorSingleStream::GetStats( |
| 217 | ReceiveBandwidthEstimatorStats* output) const { |
| 218 | // Not implemented. |
| 219 | return false; |
| 220 | } |
| 221 | |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 222 | void RemoteBitrateEstimatorSingleStream::GetSsrcs( |
| 223 | std::vector<unsigned int>* ssrcs) const { |
| 224 | assert(ssrcs); |
| 225 | ssrcs->resize(overuse_detectors_.size()); |
| 226 | int i = 0; |
| 227 | for (SsrcOveruseDetectorMap::const_iterator it = overuse_detectors_.begin(); |
| 228 | it != overuse_detectors_.end(); ++it, ++i) { |
| 229 | (*ssrcs)[i] = it->first; |
| 230 | } |
| 231 | } |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 232 | } // namespace |
stefan@webrtc.org | 7d32491 | 2012-11-19 10:09:20 +0000 | [diff] [blame] | 233 | |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 234 | RemoteBitrateEstimator* RemoteBitrateEstimatorFactory::Create( |
| 235 | RemoteBitrateObserver* observer, |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 236 | Clock* clock, |
| 237 | uint32_t min_bitrate_bps) const { |
pbos@webrtc.org | 46f7288 | 2013-12-16 12:24:44 +0000 | [diff] [blame] | 238 | WEBRTC_TRACE(kTraceStateInfo, kTraceRemoteBitrateEstimator, -1, |
| 239 | "RemoteBitrateEstimatorFactory: Instantiating."); |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 240 | return new RemoteBitrateEstimatorSingleStream(observer, clock, |
| 241 | min_bitrate_bps); |
andresp@webrtc.org | 0425392 | 2013-05-14 12:10:58 +0000 | [diff] [blame] | 242 | } |
solenberg@webrtc.org | f40e9b6 | 2013-05-27 16:02:56 +0000 | [diff] [blame] | 243 | |
| 244 | RemoteBitrateEstimator* AbsoluteSendTimeRemoteBitrateEstimatorFactory::Create( |
| 245 | RemoteBitrateObserver* observer, |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 246 | Clock* clock, |
| 247 | uint32_t min_bitrate_bps) const { |
pbos@webrtc.org | 46f7288 | 2013-12-16 12:24:44 +0000 | [diff] [blame] | 248 | WEBRTC_TRACE(kTraceStateInfo, kTraceRemoteBitrateEstimator, -1, |
| 249 | "AbsoluteSendTimeRemoteBitrateEstimatorFactory: Instantiating."); |
henrik.lundin@webrtc.org | c49a3fa | 2013-12-13 08:42:42 +0000 | [diff] [blame] | 250 | return new RemoteBitrateEstimatorSingleStream(observer, clock, |
| 251 | min_bitrate_bps); |
solenberg@webrtc.org | f40e9b6 | 2013-05-27 16:02:56 +0000 | [diff] [blame] | 252 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 253 | } // namespace webrtc |