1 /*
2 * Copyright (c) 2019 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 "modules/rtp_rtcp/source/absolute_capture_time_interpolator.h"
12
13 #include <limits>
14
15 #include "rtc_base/checks.h"
16
17 namespace webrtc {
18 namespace {
19
20 constexpr Timestamp kInvalidLastReceiveTime = Timestamp::MinusInfinity();
21 } // namespace
22
23 constexpr TimeDelta AbsoluteCaptureTimeInterpolator::kInterpolationMaxInterval;
24
AbsoluteCaptureTimeInterpolator(Clock * clock)25 AbsoluteCaptureTimeInterpolator::AbsoluteCaptureTimeInterpolator(Clock* clock)
26 : clock_(clock), last_receive_time_(kInvalidLastReceiveTime) {}
27
GetSource(uint32_t ssrc,rtc::ArrayView<const uint32_t> csrcs)28 uint32_t AbsoluteCaptureTimeInterpolator::GetSource(
29 uint32_t ssrc,
30 rtc::ArrayView<const uint32_t> csrcs) {
31 if (csrcs.empty()) {
32 return ssrc;
33 }
34
35 return csrcs[0];
36 }
37
38 absl::optional<AbsoluteCaptureTime>
OnReceivePacket(uint32_t source,uint32_t rtp_timestamp,uint32_t rtp_clock_frequency,const absl::optional<AbsoluteCaptureTime> & received_extension)39 AbsoluteCaptureTimeInterpolator::OnReceivePacket(
40 uint32_t source,
41 uint32_t rtp_timestamp,
42 uint32_t rtp_clock_frequency,
43 const absl::optional<AbsoluteCaptureTime>& received_extension) {
44 const Timestamp receive_time = clock_->CurrentTime();
45
46 MutexLock lock(&mutex_);
47
48 AbsoluteCaptureTime extension;
49 if (received_extension == absl::nullopt) {
50 if (!ShouldInterpolateExtension(receive_time, source, rtp_timestamp,
51 rtp_clock_frequency)) {
52 last_receive_time_ = kInvalidLastReceiveTime;
53 return absl::nullopt;
54 }
55
56 extension.absolute_capture_timestamp = InterpolateAbsoluteCaptureTimestamp(
57 rtp_timestamp, rtp_clock_frequency, last_rtp_timestamp_,
58 last_absolute_capture_timestamp_);
59 extension.estimated_capture_clock_offset =
60 last_estimated_capture_clock_offset_;
61 } else {
62 last_source_ = source;
63 last_rtp_timestamp_ = rtp_timestamp;
64 last_rtp_clock_frequency_ = rtp_clock_frequency;
65 last_absolute_capture_timestamp_ =
66 received_extension->absolute_capture_timestamp;
67 last_estimated_capture_clock_offset_ =
68 received_extension->estimated_capture_clock_offset;
69
70 last_receive_time_ = receive_time;
71
72 extension = *received_extension;
73 }
74
75 return extension;
76 }
77
InterpolateAbsoluteCaptureTimestamp(uint32_t rtp_timestamp,uint32_t rtp_clock_frequency,uint32_t last_rtp_timestamp,uint64_t last_absolute_capture_timestamp)78 uint64_t AbsoluteCaptureTimeInterpolator::InterpolateAbsoluteCaptureTimestamp(
79 uint32_t rtp_timestamp,
80 uint32_t rtp_clock_frequency,
81 uint32_t last_rtp_timestamp,
82 uint64_t last_absolute_capture_timestamp) {
83 RTC_DCHECK_GT(rtp_clock_frequency, 0);
84
85 return last_absolute_capture_timestamp +
86 static_cast<int64_t>(
87 rtc::dchecked_cast<uint64_t>(rtp_timestamp - last_rtp_timestamp)
88 << 32) /
89 rtp_clock_frequency;
90 }
91
ShouldInterpolateExtension(Timestamp receive_time,uint32_t source,uint32_t rtp_timestamp,uint32_t rtp_clock_frequency) const92 bool AbsoluteCaptureTimeInterpolator::ShouldInterpolateExtension(
93 Timestamp receive_time,
94 uint32_t source,
95 uint32_t rtp_timestamp,
96 uint32_t rtp_clock_frequency) const {
97 // Shouldn't if we don't have a previously received extension stored.
98 if (last_receive_time_ == kInvalidLastReceiveTime) {
99 return false;
100 }
101
102 // Shouldn't if the last received extension is too old.
103 if ((receive_time - last_receive_time_) > kInterpolationMaxInterval) {
104 return false;
105 }
106
107 // Shouldn't if the source has changed.
108 if (last_source_ != source) {
109 return false;
110 }
111
112 // Shouldn't if the RTP clock frequency has changed.
113 if (last_rtp_clock_frequency_ != rtp_clock_frequency) {
114 return false;
115 }
116
117 // Shouldn't if the RTP clock frequency is invalid.
118 if (rtp_clock_frequency <= 0) {
119 return false;
120 }
121
122 return true;
123 }
124
125 } // namespace webrtc
126