blob: 94d1fd18cc45a91fc11ca21edd5e4151364c29f2 [file] [log] [blame]
Sebastian Janssonb34556e2018-03-21 14:38:32 +01001/*
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 Rodbro76ad1542018-10-12 11:15:09 +020012
Mirko Bonadei317a1f02019-09-17 17:06:18 +020013#include <memory>
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020014#include <string>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <type_traits>
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020016
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020017#include "rtc_base/experiments/field_trial_parser.h"
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020018#include "rtc_base/numerics/safe_minmax.h"
Sebastian Janssonb34556e2018-03-21 14:38:32 +010019#include "system_wrappers/include/field_trial.h"
20
21namespace webrtc {
22namespace {
Sebastian Janssonb34556e2018-03-21 14:38:32 +010023using ::webrtc::field_trial::IsEnabled;
24
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020025const char kBweReceiveTimeCorrection[] = "WebRTC-Bwe-ReceiveTimeFix";
Sebastian Janssonb34556e2018-03-21 14:38:32 +010026} // namespace
27
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020028ReceiveTimeCalculatorConfig::ReceiveTimeCalculatorConfig()
Danil Chapovalov0c626af2020-02-10 11:16:00 +010029 : max_packet_time_repair("maxrep", TimeDelta::Millis(2000)),
30 stall_threshold("stall", TimeDelta::Millis(5)),
31 tolerance("tol", TimeDelta::Millis(1)),
32 max_stall("maxstall", TimeDelta::Seconds(5)) {
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020033 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}
39ReceiveTimeCalculatorConfig::ReceiveTimeCalculatorConfig(
40 const ReceiveTimeCalculatorConfig&) = default;
41ReceiveTimeCalculatorConfig::~ReceiveTimeCalculatorConfig() = default;
42
43ReceiveTimeCalculator::ReceiveTimeCalculator()
44 : config_(ReceiveTimeCalculatorConfig()) {}
Sebastian Janssonb34556e2018-03-21 14:38:32 +010045
46std::unique_ptr<ReceiveTimeCalculator>
47ReceiveTimeCalculator::CreateFromFieldTrial() {
48 if (!IsEnabled(kBweReceiveTimeCorrection))
49 return nullptr;
Mirko Bonadei317a1f02019-09-17 17:06:18 +020050 return std::make_unique<ReceiveTimeCalculator>();
Sebastian Janssonb34556e2018-03-21 14:38:32 +010051}
52
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020053int64_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 Janssonb34556e2018-03-21 14:38:32 +010061
Christoffer Rodbro76ad1542018-10-12 11:15:09 +020062 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 Janssonb34556e2018-03-21 14:38:32 +0100110 }
111 }
Christoffer Rodbro76ad1542018-10-12 11:15:09 +0200112
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 Janssonb34556e2018-03-21 14:38:32 +0100118}
Christoffer Rodbro76ad1542018-10-12 11:15:09 +0200119
Sebastian Janssonb34556e2018-03-21 14:38:32 +0100120} // namespace webrtc