diff --git a/modules/congestion_controller/goog_cc/BUILD.gn b/modules/congestion_controller/goog_cc/BUILD.gn index e3be246347..d169d37acf 100644 --- a/modules/congestion_controller/goog_cc/BUILD.gn +++ b/modules/congestion_controller/goog_cc/BUILD.gn @@ -180,8 +180,6 @@ rtc_library("delay_based_bwe") { sources = [ "delay_based_bwe.cc", "delay_based_bwe.h", - "inter_arrival_delta.cc", - "inter_arrival_delta.h", ] deps = [ @@ -189,9 +187,8 @@ rtc_library("delay_based_bwe") { "../../../api:network_state_predictor_api", "../../../api/rtc_event_log", "../../../api/transport:network_control", + "../../../api/transport:network_control", "../../../api/transport:webrtc_key_value_config", - "../../../api/units:time_delta", - "../../../api/units:timestamp", "../../../logging:rtc_event_bwe", "../../../rtc_base:checks", "../../../rtc_base:rtc_base_approved", diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/modules/congestion_controller/goog_cc/delay_based_bwe.cc index 6f635e1fbf..2390c147b8 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -20,7 +20,6 @@ #include "absl/strings/match.h" #include "api/rtc_event_log/rtc_event.h" #include "api/rtc_event_log/rtc_event_log.h" -#include "api/units/time_delta.h" #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h" #include "modules/congestion_controller/goog_cc/trendline_estimator.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" @@ -32,7 +31,15 @@ namespace webrtc { namespace { constexpr TimeDelta kStreamTimeOut = TimeDelta::Seconds(2); -constexpr TimeDelta kSendTimeGroupLength = TimeDelta::Millis(5); +constexpr int kTimestampGroupLengthMs = 5; +constexpr int kAbsSendTimeFraction = 18; +constexpr int kAbsSendTimeInterArrivalUpshift = 8; +constexpr int kInterArrivalShift = + kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; +constexpr int kTimestampGroupTicks = + (kTimestampGroupLengthMs << kInterArrivalShift) / 1000; +constexpr double kTimestampToMs = + 1000.0 / static_cast(1 << kInterArrivalShift); // This ssrc is used to fulfill the current API but will be removed // after the API has been changed. @@ -174,12 +181,12 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback, // Reset if the stream has timed out. if (last_seen_packet_.IsInfinite() || at_time - last_seen_packet_ > kStreamTimeOut) { - video_inter_arrival_ = - std::make_unique(kSendTimeGroupLength); + video_inter_arrival_.reset( + new InterArrival(kTimestampGroupTicks, kTimestampToMs, true)); video_delay_detector_.reset( new TrendlineEstimator(key_value_config_, network_state_predictor_)); - audio_inter_arrival_ = - std::make_unique(kSendTimeGroupLength); + audio_inter_arrival_.reset( + new InterArrival(kTimestampGroupTicks, kTimestampToMs, true)); audio_delay_detector_.reset( new TrendlineEstimator(key_value_config_, network_state_predictor_)); active_delay_detector_ = video_delay_detector_.get(); @@ -204,7 +211,7 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback, // As an alternative to ignoring small packets, we can separate audio and // video packets for overuse detection. - auto* inter_arrival_for_packet = video_inter_arrival_.get(); + InterArrival* inter_arrival_for_packet = video_inter_arrival_.get(); DelayIncreaseDetectorInterface* delay_detector_for_packet = video_delay_detector_.get(); if (separate_audio_.enabled) { @@ -225,15 +232,25 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback, } } - TimeDelta send_delta = TimeDelta::Zero(); - TimeDelta recv_delta = TimeDelta::Zero(); + uint32_t send_time_24bits = + static_cast( + ((static_cast(packet_feedback.sent_packet.send_time.ms()) + << kAbsSendTimeFraction) + + 500) / + 1000) & + 0x00FFFFFF; + // Shift up send time to use the full 32 bits that inter_arrival works with, + // so wrapping works properly. + uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; + + uint32_t timestamp_delta = 0; + int64_t recv_delta_ms = 0; int size_delta = 0; - bool calculated_deltas = inter_arrival_for_packet->ComputeDeltas( - packet_feedback.sent_packet.send_time, packet_feedback.receive_time, - at_time, packet_size.bytes(), &send_delta, &recv_delta, &size_delta); - - delay_detector_for_packet->Update(recv_delta.ms(), send_delta.ms(), + timestamp, packet_feedback.receive_time.ms(), at_time.ms(), + packet_size.bytes(), ×tamp_delta, &recv_delta_ms, &size_delta); + double send_delta_ms = (1000.0 * timestamp_delta) / (1 << kInterArrivalShift); + delay_detector_for_packet->Update(recv_delta_ms, send_delta_ms, packet_feedback.sent_packet.send_time.ms(), packet_feedback.receive_time.ms(), packet_size.bytes(), calculated_deltas); diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.h b/modules/congestion_controller/goog_cc/delay_based_bwe.h index e2372ec6ec..85ad0ddfba 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -22,9 +22,9 @@ #include "api/transport/network_types.h" #include "api/transport/webrtc_key_value_config.h" #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h" -#include "modules/congestion_controller/goog_cc/inter_arrival_delta.h" #include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h" #include "modules/remote_bitrate_estimator/aimd_rate_control.h" +#include "modules/remote_bitrate_estimator/inter_arrival.h" #include "rtc_base/experiments/struct_parameters_parser.h" #include "rtc_base/race_checker.h" @@ -133,9 +133,9 @@ class DelayBasedBwe { Timestamp last_video_packet_recv_time_; NetworkStatePredictor* network_state_predictor_; - std::unique_ptr video_inter_arrival_; + std::unique_ptr video_inter_arrival_; std::unique_ptr video_delay_detector_; - std::unique_ptr audio_inter_arrival_; + std::unique_ptr audio_inter_arrival_; std::unique_ptr audio_delay_detector_; DelayIncreaseDetectorInterface* active_delay_detector_; diff --git a/modules/congestion_controller/goog_cc/inter_arrival_delta.cc b/modules/congestion_controller/goog_cc/inter_arrival_delta.cc deleted file mode 100644 index 791867db67..0000000000 --- a/modules/congestion_controller/goog_cc/inter_arrival_delta.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/congestion_controller/goog_cc/inter_arrival_delta.h" - -#include - -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "rtc_base/logging.h" - -namespace webrtc { - -static constexpr TimeDelta kBurstDeltaThreshold = TimeDelta::Millis(5); -static constexpr TimeDelta kMaxBurstDuration = TimeDelta::Millis(100); -constexpr TimeDelta InterArrivalDelta::kArrivalTimeOffsetThreshold; - -InterArrivalDelta::InterArrivalDelta(TimeDelta send_time_group_length) - : send_time_group_length_(send_time_group_length), - current_timestamp_group_(), - prev_timestamp_group_(), - num_consecutive_reordered_packets_(0) {} - -bool InterArrivalDelta::ComputeDeltas(Timestamp send_time, - Timestamp arrival_time, - Timestamp system_time, - size_t packet_size, - TimeDelta* send_time_delta, - TimeDelta* arrival_time_delta, - int* packet_size_delta) { - bool calculated_deltas = false; - if (current_timestamp_group_.IsFirstPacket()) { - // We don't have enough data to update the filter, so we store it until we - // have two frames of data to process. - current_timestamp_group_.send_time = send_time; - current_timestamp_group_.first_send_time = send_time; - current_timestamp_group_.first_arrival = arrival_time; - } else if (current_timestamp_group_.first_send_time > send_time) { - // Reordered packet. - return false; - } else if (NewTimestampGroup(arrival_time, send_time)) { - // First packet of a later send burst, the previous packets sample is ready. - if (prev_timestamp_group_.complete_time.IsFinite()) { - *send_time_delta = - current_timestamp_group_.send_time - prev_timestamp_group_.send_time; - *arrival_time_delta = current_timestamp_group_.complete_time - - prev_timestamp_group_.complete_time; - - TimeDelta system_time_delta = current_timestamp_group_.last_system_time - - prev_timestamp_group_.last_system_time; - - if (*arrival_time_delta - system_time_delta >= - kArrivalTimeOffsetThreshold) { - RTC_LOG(LS_WARNING) - << "The arrival time clock offset has changed (diff = " - << arrival_time_delta->ms() - system_time_delta.ms() - << " ms), resetting."; - Reset(); - return false; - } - if (*arrival_time_delta < TimeDelta::Zero()) { - // The group of packets has been reordered since receiving its local - // arrival timestamp. - ++num_consecutive_reordered_packets_; - if (num_consecutive_reordered_packets_ >= kReorderedResetThreshold) { - RTC_LOG(LS_WARNING) - << "Packets between send burst arrived out of order, resetting." - << " arrival_time_delta" << arrival_time_delta->ms() - << " send time delta " << send_time_delta->ms(); - Reset(); - } - return false; - } else { - num_consecutive_reordered_packets_ = 0; - } - *packet_size_delta = static_cast(current_timestamp_group_.size) - - static_cast(prev_timestamp_group_.size); - calculated_deltas = true; - } - prev_timestamp_group_ = current_timestamp_group_; - // The new timestamp is now the current frame. - current_timestamp_group_.first_send_time = send_time; - current_timestamp_group_.send_time = send_time; - current_timestamp_group_.first_arrival = arrival_time; - current_timestamp_group_.size = 0; - } else { - current_timestamp_group_.send_time = - std::max(current_timestamp_group_.send_time, send_time); - } - // Accumulate the frame size. - current_timestamp_group_.size += packet_size; - current_timestamp_group_.complete_time = arrival_time; - current_timestamp_group_.last_system_time = system_time; - - return calculated_deltas; -} - -// Assumes that |timestamp| is not reordered compared to -// |current_timestamp_group_|. -bool InterArrivalDelta::NewTimestampGroup(Timestamp arrival_time, - Timestamp send_time) const { - if (current_timestamp_group_.IsFirstPacket()) { - return false; - } else if (BelongsToBurst(arrival_time, send_time)) { - return false; - } else { - return send_time - current_timestamp_group_.first_send_time > - send_time_group_length_; - } -} - -bool InterArrivalDelta::BelongsToBurst(Timestamp arrival_time, - Timestamp send_time) const { - RTC_DCHECK(current_timestamp_group_.complete_time.IsFinite()); - TimeDelta arrival_time_delta = - arrival_time - current_timestamp_group_.complete_time; - TimeDelta send_time_delta = send_time - current_timestamp_group_.send_time; - if (send_time_delta.IsZero()) - return true; - TimeDelta propagation_delta = arrival_time_delta - send_time_delta; - if (propagation_delta < TimeDelta::Zero() && - arrival_time_delta <= kBurstDeltaThreshold && - arrival_time - current_timestamp_group_.first_arrival < kMaxBurstDuration) - return true; - return false; -} - -void InterArrivalDelta::Reset() { - num_consecutive_reordered_packets_ = 0; - current_timestamp_group_ = SendTimeGroup(); - prev_timestamp_group_ = SendTimeGroup(); -} -} // namespace webrtc diff --git a/modules/congestion_controller/goog_cc/inter_arrival_delta.h b/modules/congestion_controller/goog_cc/inter_arrival_delta.h deleted file mode 100644 index 28dc806249..0000000000 --- a/modules/congestion_controller/goog_cc/inter_arrival_delta.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_ -#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_ - -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" - -namespace webrtc { - -// Helper class to compute the inter-arrival time delta and the size delta -// between two send bursts. This code is branched from -// modules/remote_bitrate_estimator/inter_arrival. -class InterArrivalDelta { - public: - // After this many packet groups received out of order InterArrival will - // reset, assuming that clocks have made a jump. - static constexpr int kReorderedResetThreshold = 3; - static constexpr TimeDelta kArrivalTimeOffsetThreshold = - TimeDelta::Seconds(3); - - // A send time group is defined as all packets with a send time which are at - // most send_time_group_length older than the first timestamp in that - // group. - explicit InterArrivalDelta(TimeDelta send_time_group_length); - - InterArrivalDelta() = delete; - InterArrivalDelta(const InterArrivalDelta&) = delete; - InterArrivalDelta& operator=(const InterArrivalDelta&) = delete; - - // This function returns true if a delta was computed, or false if the current - // group is still incomplete or if only one group has been completed. - // |send_time| is the send time. - // |arrival_time| is the time at which the packet arrived. - // |packet_size| is the size of the packet. - // |timestamp_delta| (output) is the computed send time delta. - // |arrival_time_delta_ms| (output) is the computed arrival-time delta. - // |packet_size_delta| (output) is the computed size delta. - bool ComputeDeltas(Timestamp send_time, - Timestamp arrival_time, - Timestamp system_time, - size_t packet_size, - TimeDelta* send_time_delta, - TimeDelta* arrival_time_delta, - int* packet_size_delta); - - private: - struct SendTimeGroup { - SendTimeGroup() - : size(0), - first_send_time(Timestamp::MinusInfinity()), - send_time(Timestamp::MinusInfinity()), - first_arrival(Timestamp::MinusInfinity()), - complete_time(Timestamp::MinusInfinity()), - last_system_time(Timestamp::MinusInfinity()) {} - - bool IsFirstPacket() const { return complete_time.IsInfinite(); } - - size_t size; - Timestamp first_send_time; - Timestamp send_time; - Timestamp first_arrival; - Timestamp complete_time; - Timestamp last_system_time; - }; - - // Returns true if the last packet was the end of the current batch and the - // packet with |send_time| is the first of a new batch. - bool NewTimestampGroup(Timestamp arrival_time, Timestamp send_time) const; - - bool BelongsToBurst(Timestamp arrival_time, Timestamp send_time) const; - - void Reset(); - - const TimeDelta send_time_group_length_; - SendTimeGroup current_timestamp_group_; - SendTimeGroup prev_timestamp_group_; - int num_consecutive_reordered_packets_; -}; -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_