OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 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/congestion_controller/acknowledge_bitrate_estimator.h" | 11 #include "webrtc/modules/congestion_controller/acknowledge_bitrate_estimator.h" |
12 | 12 |
13 #include <cmath> | 13 #include <utility> |
14 | 14 |
15 #include "webrtc/base/ptr_util.h" | |
16 #include "webrtc/base/timeutils.h" | |
15 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 17 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
16 | 18 |
17 namespace webrtc { | 19 namespace webrtc { |
18 | 20 |
19 namespace { | 21 namespace { |
20 constexpr int kInitialRateWindowMs = 500; | |
21 constexpr int kRateWindowMs = 150; | |
22 | |
23 bool IsInSendTimeHistory(const PacketFeedback& packet) { | 22 bool IsInSendTimeHistory(const PacketFeedback& packet) { |
24 return packet.send_time_ms >= 0; | 23 return packet.send_time_ms >= 0; |
25 } | 24 } |
26 | |
27 } // namespace | 25 } // namespace |
28 | 26 |
29 AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator() | 27 AcknowledgedBitrateEstimator::AcknowledgedBitrateEstimator( |
30 : sum_(0), | 28 BitrateEstimatorCreator&& bitrate_estimator_creator) |
31 current_win_ms_(0), | 29 : last_alr_state_(false), |
32 prev_time_ms_(-1), | 30 bitrate_estimator_creator_(bitrate_estimator_creator |
33 bitrate_estimate_(-1.0f), | 31 ? std::move(bitrate_estimator_creator) |
34 bitrate_estimate_var_(50.0f) {} | 32 : &rtc::MakeUnique<BitrateEstimator>), |
kwiberg-webrtc
2017/06/08 23:00:29
Can you remove this fallback, and force all caller
tschumi
2017/06/12 11:33:27
Done.
But I'm not completely sure if the added co
| |
33 bitrate_estimator_(bitrate_estimator_creator_()) {} | |
35 | 34 |
36 void AcknowledgedBitrateEstimator::IncomingPacketFeedbackVector( | 35 void AcknowledgedBitrateEstimator::IncomingPacketFeedbackVector( |
37 const std::vector<PacketFeedback>& packet_feedback_vector) { | 36 const std::vector<PacketFeedback>& packet_feedback_vector, |
37 bool alr_state) { | |
38 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), | 38 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), |
39 packet_feedback_vector.end(), | 39 packet_feedback_vector.end(), |
40 PacketFeedbackComparator())); | 40 PacketFeedbackComparator())); |
41 MaybeResetBitrateEstimator(alr_state); | |
41 for (const auto& packet : packet_feedback_vector) { | 42 for (const auto& packet : packet_feedback_vector) { |
42 if (IsInSendTimeHistory(packet)) | 43 if (IsInSendTimeHistory(packet) && !ShouldSkipPreAlrPacket(packet)) |
43 Update(packet.arrival_time_ms, packet.payload_size); | 44 bitrate_estimator_->Update(packet.arrival_time_ms, packet.payload_size); |
44 } | 45 } |
45 } | 46 } |
46 | 47 |
47 void AcknowledgedBitrateEstimator::Update(int64_t now_ms, int bytes) { | 48 rtc::Optional<uint32_t> AcknowledgedBitrateEstimator::bitrate_bps() const { |
48 int rate_window_ms = kRateWindowMs; | 49 return bitrate_estimator_->bitrate_bps(); |
49 // We use a larger window at the beginning to get a more stable sample that | |
50 // we can use to initialize the estimate. | |
51 if (bitrate_estimate_ < 0.f) | |
52 rate_window_ms = kInitialRateWindowMs; | |
53 float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms); | |
54 if (bitrate_sample < 0.0f) | |
55 return; | |
56 if (bitrate_estimate_ < 0.0f) { | |
57 // This is the very first sample we get. Use it to initialize the estimate. | |
58 bitrate_estimate_ = bitrate_sample; | |
59 return; | |
60 } | |
61 // Define the sample uncertainty as a function of how far away it is from the | |
62 // current estimate. | |
63 float sample_uncertainty = | |
64 10.0f * std::abs(bitrate_estimate_ - bitrate_sample) / bitrate_estimate_; | |
65 float sample_var = sample_uncertainty * sample_uncertainty; | |
66 // Update a bayesian estimate of the rate, weighting it lower if the sample | |
67 // uncertainty is large. | |
68 // The bitrate estimate uncertainty is increased with each update to model | |
69 // that the bitrate changes over time. | |
70 float pred_bitrate_estimate_var = bitrate_estimate_var_ + 5.f; | |
71 bitrate_estimate_ = (sample_var * bitrate_estimate_ + | |
72 pred_bitrate_estimate_var * bitrate_sample) / | |
73 (sample_var + pred_bitrate_estimate_var); | |
74 bitrate_estimate_var_ = sample_var * pred_bitrate_estimate_var / | |
75 (sample_var + pred_bitrate_estimate_var); | |
76 } | 50 } |
77 | 51 |
78 float AcknowledgedBitrateEstimator::UpdateWindow(int64_t now_ms, | 52 bool AcknowledgedBitrateEstimator::ShouldSkipPreAlrPacket( |
philipel
2017/06/09 14:49:53
WDYT about renaming this to SentInAlr?
tschumi
2017/06/12 11:33:28
Hmm "SentInAlr" tells just parts of what this func
| |
79 int bytes, | 53 const PacketFeedback& packet) { |
80 int rate_window_ms) { | 54 if (left_alr_state_ms_) { |
81 // Reset if time moves backwards. | 55 if (*left_alr_state_ms_ > packet.send_time_ms) { |
82 if (now_ms < prev_time_ms_) { | 56 return true; |
83 prev_time_ms_ = -1; | 57 } else { |
84 sum_ = 0; | 58 left_alr_state_ms_.reset(); |
85 current_win_ms_ = 0; | |
86 } | |
87 if (prev_time_ms_ >= 0) { | |
88 current_win_ms_ += now_ms - prev_time_ms_; | |
89 // Reset if nothing has been received for more than a full window. | |
90 if (now_ms - prev_time_ms_ > rate_window_ms) { | |
91 sum_ = 0; | |
92 current_win_ms_ %= rate_window_ms; | |
93 } | 59 } |
94 } | 60 } |
95 prev_time_ms_ = now_ms; | 61 return false; |
96 float bitrate_sample = -1.0f; | |
97 if (current_win_ms_ >= rate_window_ms) { | |
98 bitrate_sample = 8.0f * sum_ / static_cast<float>(rate_window_ms); | |
99 current_win_ms_ -= rate_window_ms; | |
100 sum_ = 0; | |
101 } | |
102 sum_ += bytes; | |
103 return bitrate_sample; | |
104 } | 62 } |
105 | 63 |
106 rtc::Optional<uint32_t> AcknowledgedBitrateEstimator::bitrate_bps() const { | 64 bool AcknowledgedBitrateEstimator::HasLeftAlrState(bool alr_state) const { |
107 if (bitrate_estimate_ < 0.f) | 65 return last_alr_state_ && !alr_state; |
108 return rtc::Optional<uint32_t>(); | 66 } |
109 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000); | 67 |
68 void AcknowledgedBitrateEstimator::MaybeResetBitrateEstimator(bool alr_state) { | |
69 if (HasLeftAlrState(alr_state)) { | |
philipel
2017/06/09 14:49:53
If you only expect HasLeftAlrState to be called fr
tschumi
2017/06/12 11:33:28
I assumed that the compiler will inline this anywa
| |
70 bitrate_estimator_ = bitrate_estimator_creator_(); | |
kwiberg-webrtc
2017/06/08 23:00:29
Hmm. If BitrateEstimator had a Reset() method, you
tschumi
2017/06/12 11:33:28
It would be much simpler. Having a reset function
| |
71 left_alr_state_ms_ = rtc::Optional<int64_t>(rtc::TimeMillis()); | |
72 } | |
73 last_alr_state_ = alr_state; | |
110 } | 74 } |
111 | 75 |
112 } // namespace webrtc | 76 } // namespace webrtc |
OLD | NEW |