Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 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 | |
| 11 | #include "call/receive_time_calculator.h" |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 12 | |
| 13 | #include <string> |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 14 | #include <type_traits> |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 15 | |
Karl Wiberg | 918f50c | 2018-07-05 11:40:33 +0200 | [diff] [blame] | 16 | #include "absl/memory/memory.h" |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 17 | #include "rtc_base/experiments/field_trial_parser.h" |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 18 | #include "rtc_base/numerics/safe_minmax.h" |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 19 | #include "system_wrappers/include/field_trial.h" |
| 20 | |
| 21 | namespace webrtc { |
| 22 | namespace { |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 23 | using ::webrtc::field_trial::IsEnabled; |
| 24 | |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 25 | const char kBweReceiveTimeCorrection[] = "WebRTC-Bwe-ReceiveTimeFix"; |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 26 | } // namespace |
| 27 | |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 28 | ReceiveTimeCalculatorConfig::ReceiveTimeCalculatorConfig() |
| 29 | : max_packet_time_repair("maxrep", TimeDelta::ms(2000)), |
| 30 | stall_threshold("stall", TimeDelta::ms(5)), |
| 31 | tolerance("tol", TimeDelta::ms(1)), |
| 32 | max_stall("maxstall", TimeDelta::seconds(5)) { |
| 33 | std::string trial_string = |
| 34 | field_trial::FindFullName(kBweReceiveTimeCorrection); |
| 35 | ParseFieldTrial( |
| 36 | {&max_packet_time_repair, &stall_threshold, &tolerance, &max_stall}, |
| 37 | trial_string); |
| 38 | } |
| 39 | ReceiveTimeCalculatorConfig::ReceiveTimeCalculatorConfig( |
| 40 | const ReceiveTimeCalculatorConfig&) = default; |
| 41 | ReceiveTimeCalculatorConfig::~ReceiveTimeCalculatorConfig() = default; |
| 42 | |
| 43 | ReceiveTimeCalculator::ReceiveTimeCalculator() |
| 44 | : config_(ReceiveTimeCalculatorConfig()) {} |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 45 | |
| 46 | std::unique_ptr<ReceiveTimeCalculator> |
| 47 | ReceiveTimeCalculator::CreateFromFieldTrial() { |
| 48 | if (!IsEnabled(kBweReceiveTimeCorrection)) |
| 49 | return nullptr; |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 50 | return absl::make_unique<ReceiveTimeCalculator>(); |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 51 | } |
| 52 | |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 53 | int64_t ReceiveTimeCalculator::ReconcileReceiveTimes(int64_t packet_time_us, |
| 54 | int64_t system_time_us, |
| 55 | int64_t safe_time_us) { |
| 56 | int64_t stall_time_us = system_time_us - packet_time_us; |
| 57 | if (total_system_time_passed_us_ < config_.stall_threshold->us()) { |
| 58 | stall_time_us = rtc::SafeMin(stall_time_us, config_.max_stall->us()); |
| 59 | } |
| 60 | int64_t corrected_time_us = safe_time_us - stall_time_us; |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 61 | |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 62 | if (last_packet_time_us_ == -1 && stall_time_us < 0) { |
| 63 | static_clock_offset_us_ = stall_time_us; |
| 64 | corrected_time_us += static_clock_offset_us_; |
| 65 | } else if (last_packet_time_us_ > 0) { |
| 66 | // All repairs depend on variables being intialized |
| 67 | int64_t packet_time_delta_us = packet_time_us - last_packet_time_us_; |
| 68 | int64_t system_time_delta_us = system_time_us - last_system_time_us_; |
| 69 | int64_t safe_time_delta_us = safe_time_us - last_safe_time_us_; |
| 70 | |
| 71 | // Repair backwards clock resets during initial stall. In this case, the |
| 72 | // reset is observed only in packet time but never in system time. |
| 73 | if (system_time_delta_us < 0) |
| 74 | total_system_time_passed_us_ += config_.stall_threshold->us(); |
| 75 | else |
| 76 | total_system_time_passed_us_ += system_time_delta_us; |
| 77 | if (packet_time_delta_us < 0 && |
| 78 | total_system_time_passed_us_ < config_.stall_threshold->us()) { |
| 79 | static_clock_offset_us_ -= packet_time_delta_us; |
| 80 | } |
| 81 | corrected_time_us += static_clock_offset_us_; |
| 82 | |
| 83 | // Detect resets inbetween clock readings in socket and app. |
| 84 | bool forward_clock_reset = |
| 85 | corrected_time_us + config_.tolerance->us() < last_corrected_time_us_; |
| 86 | bool obvious_backward_clock_reset = system_time_us < packet_time_us; |
| 87 | |
| 88 | // Harder case with backward clock reset during stall, the reset being |
| 89 | // smaller than the stall. Compensate throughout the stall. |
| 90 | bool small_backward_clock_reset = |
| 91 | !obvious_backward_clock_reset && |
| 92 | safe_time_delta_us > system_time_delta_us + config_.tolerance->us(); |
| 93 | bool stall_start = |
| 94 | packet_time_delta_us >= 0 && |
| 95 | system_time_delta_us > packet_time_delta_us + config_.tolerance->us(); |
| 96 | bool stall_is_over = safe_time_delta_us > config_.stall_threshold->us(); |
| 97 | bool packet_time_caught_up = |
| 98 | packet_time_delta_us < 0 && system_time_delta_us >= 0; |
| 99 | if (stall_start && small_backward_clock_reset) |
| 100 | small_reset_during_stall_ = true; |
| 101 | else if (stall_is_over || packet_time_caught_up) |
| 102 | small_reset_during_stall_ = false; |
| 103 | |
| 104 | // If resets are detected, advance time by (capped) packet time increase. |
| 105 | if (forward_clock_reset || obvious_backward_clock_reset || |
| 106 | small_reset_during_stall_) { |
| 107 | corrected_time_us = last_corrected_time_us_ + |
| 108 | rtc::SafeClamp(packet_time_delta_us, 0, |
| 109 | config_.max_packet_time_repair->us()); |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 110 | } |
| 111 | } |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 112 | |
| 113 | last_corrected_time_us_ = corrected_time_us; |
| 114 | last_packet_time_us_ = packet_time_us; |
| 115 | last_system_time_us_ = system_time_us; |
| 116 | last_safe_time_us_ = safe_time_us; |
| 117 | return corrected_time_us; |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 118 | } |
Christoffer Rodbro | 76ad154 | 2018-10-12 11:15:09 +0200 | [diff] [blame] | 119 | |
Sebastian Jansson | b34556e | 2018-03-21 14:38:32 +0100 | [diff] [blame] | 120 | } // namespace webrtc |