xref: /aosp_15_r20/external/webrtc/call/receive_time_calculator.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "call/receive_time_calculator.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <string>
15*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/experiments/field_trial_parser.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_minmax.h"
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
21*d9f75844SAndroid Build Coastguard Worker namespace {
22*d9f75844SAndroid Build Coastguard Worker 
23*d9f75844SAndroid Build Coastguard Worker const char kBweReceiveTimeCorrection[] = "WebRTC-Bwe-ReceiveTimeFix";
24*d9f75844SAndroid Build Coastguard Worker }  // namespace
25*d9f75844SAndroid Build Coastguard Worker 
ReceiveTimeCalculatorConfig(const FieldTrialsView & field_trials)26*d9f75844SAndroid Build Coastguard Worker ReceiveTimeCalculatorConfig::ReceiveTimeCalculatorConfig(
27*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials)
28*d9f75844SAndroid Build Coastguard Worker     : max_packet_time_repair("maxrep", TimeDelta::Millis(2000)),
29*d9f75844SAndroid Build Coastguard Worker       stall_threshold("stall", TimeDelta::Millis(5)),
30*d9f75844SAndroid Build Coastguard Worker       tolerance("tol", TimeDelta::Millis(1)),
31*d9f75844SAndroid Build Coastguard Worker       max_stall("maxstall", TimeDelta::Seconds(5)) {
32*d9f75844SAndroid Build Coastguard Worker   std::string trial_string = field_trials.Lookup(kBweReceiveTimeCorrection);
33*d9f75844SAndroid Build Coastguard Worker   ParseFieldTrial(
34*d9f75844SAndroid Build Coastguard Worker       {&max_packet_time_repair, &stall_threshold, &tolerance, &max_stall},
35*d9f75844SAndroid Build Coastguard Worker       trial_string);
36*d9f75844SAndroid Build Coastguard Worker }
37*d9f75844SAndroid Build Coastguard Worker ReceiveTimeCalculatorConfig::ReceiveTimeCalculatorConfig(
38*d9f75844SAndroid Build Coastguard Worker     const ReceiveTimeCalculatorConfig&) = default;
39*d9f75844SAndroid Build Coastguard Worker ReceiveTimeCalculatorConfig::~ReceiveTimeCalculatorConfig() = default;
40*d9f75844SAndroid Build Coastguard Worker 
ReceiveTimeCalculator(const FieldTrialsView & field_trials)41*d9f75844SAndroid Build Coastguard Worker ReceiveTimeCalculator::ReceiveTimeCalculator(
42*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials)
43*d9f75844SAndroid Build Coastguard Worker     : config_(field_trials) {}
44*d9f75844SAndroid Build Coastguard Worker 
45*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<ReceiveTimeCalculator>
CreateFromFieldTrial(const FieldTrialsView & field_trials)46*d9f75844SAndroid Build Coastguard Worker ReceiveTimeCalculator::CreateFromFieldTrial(
47*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials) {
48*d9f75844SAndroid Build Coastguard Worker   if (!field_trials.IsEnabled(kBweReceiveTimeCorrection))
49*d9f75844SAndroid Build Coastguard Worker     return nullptr;
50*d9f75844SAndroid Build Coastguard Worker   return std::make_unique<ReceiveTimeCalculator>(field_trials);
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker 
ReconcileReceiveTimes(int64_t packet_time_us,int64_t system_time_us,int64_t safe_time_us)53*d9f75844SAndroid Build Coastguard Worker int64_t ReceiveTimeCalculator::ReconcileReceiveTimes(int64_t packet_time_us,
54*d9f75844SAndroid Build Coastguard Worker                                                      int64_t system_time_us,
55*d9f75844SAndroid Build Coastguard Worker                                                      int64_t safe_time_us) {
56*d9f75844SAndroid Build Coastguard Worker   int64_t stall_time_us = system_time_us - packet_time_us;
57*d9f75844SAndroid Build Coastguard Worker   if (total_system_time_passed_us_ < config_.stall_threshold->us()) {
58*d9f75844SAndroid Build Coastguard Worker     stall_time_us = rtc::SafeMin(stall_time_us, config_.max_stall->us());
59*d9f75844SAndroid Build Coastguard Worker   }
60*d9f75844SAndroid Build Coastguard Worker   int64_t corrected_time_us = safe_time_us - stall_time_us;
61*d9f75844SAndroid Build Coastguard Worker 
62*d9f75844SAndroid Build Coastguard Worker   if (last_packet_time_us_ == -1 && stall_time_us < 0) {
63*d9f75844SAndroid Build Coastguard Worker     static_clock_offset_us_ = stall_time_us;
64*d9f75844SAndroid Build Coastguard Worker     corrected_time_us += static_clock_offset_us_;
65*d9f75844SAndroid Build Coastguard Worker   } else if (last_packet_time_us_ > 0) {
66*d9f75844SAndroid Build Coastguard Worker     // All repairs depend on variables being intialized
67*d9f75844SAndroid Build Coastguard Worker     int64_t packet_time_delta_us = packet_time_us - last_packet_time_us_;
68*d9f75844SAndroid Build Coastguard Worker     int64_t system_time_delta_us = system_time_us - last_system_time_us_;
69*d9f75844SAndroid Build Coastguard Worker     int64_t safe_time_delta_us = safe_time_us - last_safe_time_us_;
70*d9f75844SAndroid Build Coastguard Worker 
71*d9f75844SAndroid Build Coastguard Worker     // Repair backwards clock resets during initial stall. In this case, the
72*d9f75844SAndroid Build Coastguard Worker     // reset is observed only in packet time but never in system time.
73*d9f75844SAndroid Build Coastguard Worker     if (system_time_delta_us < 0)
74*d9f75844SAndroid Build Coastguard Worker       total_system_time_passed_us_ += config_.stall_threshold->us();
75*d9f75844SAndroid Build Coastguard Worker     else
76*d9f75844SAndroid Build Coastguard Worker       total_system_time_passed_us_ += system_time_delta_us;
77*d9f75844SAndroid Build Coastguard Worker     if (packet_time_delta_us < 0 &&
78*d9f75844SAndroid Build Coastguard Worker         total_system_time_passed_us_ < config_.stall_threshold->us()) {
79*d9f75844SAndroid Build Coastguard Worker       static_clock_offset_us_ -= packet_time_delta_us;
80*d9f75844SAndroid Build Coastguard Worker     }
81*d9f75844SAndroid Build Coastguard Worker     corrected_time_us += static_clock_offset_us_;
82*d9f75844SAndroid Build Coastguard Worker 
83*d9f75844SAndroid Build Coastguard Worker     // Detect resets inbetween clock readings in socket and app.
84*d9f75844SAndroid Build Coastguard Worker     bool forward_clock_reset =
85*d9f75844SAndroid Build Coastguard Worker         corrected_time_us + config_.tolerance->us() < last_corrected_time_us_;
86*d9f75844SAndroid Build Coastguard Worker     bool obvious_backward_clock_reset = system_time_us < packet_time_us;
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker     // Harder case with backward clock reset during stall, the reset being
89*d9f75844SAndroid Build Coastguard Worker     // smaller than the stall. Compensate throughout the stall.
90*d9f75844SAndroid Build Coastguard Worker     bool small_backward_clock_reset =
91*d9f75844SAndroid Build Coastguard Worker         !obvious_backward_clock_reset &&
92*d9f75844SAndroid Build Coastguard Worker         safe_time_delta_us > system_time_delta_us + config_.tolerance->us();
93*d9f75844SAndroid Build Coastguard Worker     bool stall_start =
94*d9f75844SAndroid Build Coastguard Worker         packet_time_delta_us >= 0 &&
95*d9f75844SAndroid Build Coastguard Worker         system_time_delta_us > packet_time_delta_us + config_.tolerance->us();
96*d9f75844SAndroid Build Coastguard Worker     bool stall_is_over = safe_time_delta_us > config_.stall_threshold->us();
97*d9f75844SAndroid Build Coastguard Worker     bool packet_time_caught_up =
98*d9f75844SAndroid Build Coastguard Worker         packet_time_delta_us < 0 && system_time_delta_us >= 0;
99*d9f75844SAndroid Build Coastguard Worker     if (stall_start && small_backward_clock_reset)
100*d9f75844SAndroid Build Coastguard Worker       small_reset_during_stall_ = true;
101*d9f75844SAndroid Build Coastguard Worker     else if (stall_is_over || packet_time_caught_up)
102*d9f75844SAndroid Build Coastguard Worker       small_reset_during_stall_ = false;
103*d9f75844SAndroid Build Coastguard Worker 
104*d9f75844SAndroid Build Coastguard Worker     // If resets are detected, advance time by (capped) packet time increase.
105*d9f75844SAndroid Build Coastguard Worker     if (forward_clock_reset || obvious_backward_clock_reset ||
106*d9f75844SAndroid Build Coastguard Worker         small_reset_during_stall_) {
107*d9f75844SAndroid Build Coastguard Worker       corrected_time_us = last_corrected_time_us_ +
108*d9f75844SAndroid Build Coastguard Worker                           rtc::SafeClamp(packet_time_delta_us, 0,
109*d9f75844SAndroid Build Coastguard Worker                                          config_.max_packet_time_repair->us());
110*d9f75844SAndroid Build Coastguard Worker     }
111*d9f75844SAndroid Build Coastguard Worker   }
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   last_corrected_time_us_ = corrected_time_us;
114*d9f75844SAndroid Build Coastguard Worker   last_packet_time_us_ = packet_time_us;
115*d9f75844SAndroid Build Coastguard Worker   last_system_time_us_ = system_time_us;
116*d9f75844SAndroid Build Coastguard Worker   last_safe_time_us_ = safe_time_us;
117*d9f75844SAndroid Build Coastguard Worker   return corrected_time_us;
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
121