Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: webrtc/system_wrappers/source/rtp_to_ntp_estimator.cc

Issue 2574133003: Make class of static functions in rtp_to_ntp.h: (Closed)
Patch Set: address comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/system_wrappers/include/rtp_to_ntp.h" 11 #include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h"
12 12
13 #include "webrtc/base/logging.h" 13 #include "webrtc/base/logging.h"
14 #include "webrtc/system_wrappers/include/clock.h" 14 #include "webrtc/system_wrappers/include/clock.h"
15 15
16 namespace webrtc { 16 namespace webrtc {
17 namespace { 17 namespace {
18 // Number of RTCP SR reports to use to map between RTP and NTP. 18 // Number of RTCP SR reports to use to map between RTP and NTP.
19 const size_t kNumRtcpReportsToUse = 2; 19 const size_t kNumRtcpReportsToUse = 2;
20 20
21 // Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps. 21 // Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps.
22 bool CalculateFrequency(int64_t rtcp_ntp_ms1, 22 bool CalculateFrequency(int64_t ntp_ms1,
23 uint32_t rtp_timestamp1, 23 uint32_t rtp_timestamp1,
24 int64_t rtcp_ntp_ms2, 24 int64_t ntp_ms2,
25 uint32_t rtp_timestamp2, 25 uint32_t rtp_timestamp2,
26 double* frequency_khz) { 26 double* frequency_khz) {
27 if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) { 27 if (ntp_ms1 <= ntp_ms2)
28 return false; 28 return false;
29 } 29
30 *frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) / 30 *frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) /
31 static_cast<double>(rtcp_ntp_ms1 - rtcp_ntp_ms2); 31 static_cast<double>(ntp_ms1 - ntp_ms2);
32 return true; 32 return true;
33 } 33 }
34 34
35 // Detects if there has been a wraparound between |old_timestamp| and 35 // Detects if there has been a wraparound between |old_timestamp| and
36 // |new_timestamp|, and compensates by adding 2^32 if that is the case. 36 // |new_timestamp|, and compensates by adding 2^32 if that is the case.
37 bool CompensateForWrapAround(uint32_t new_timestamp, 37 bool CompensateForWrapAround(uint32_t new_timestamp,
38 uint32_t old_timestamp, 38 uint32_t old_timestamp,
39 int64_t* compensated_timestamp) { 39 int64_t* compensated_timestamp) {
40 int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp); 40 int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp);
41 if (wraps < 0) { 41 if (wraps < 0) {
42 // Reordering, don't use this packet. 42 // Reordering, don't use this packet.
43 return false; 43 return false;
44 } 44 }
45 *compensated_timestamp = new_timestamp + (wraps << 32); 45 *compensated_timestamp = new_timestamp + (wraps << 32);
46 return true; 46 return true;
47 } 47 }
48 } // namespace
49 48
50 // Class holding RTP and NTP timestamp from a RTCP SR report. 49 bool Contains(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements,
51 RtcpMeasurement::RtcpMeasurement() : ntp_time(0, 0), rtp_timestamp(0) {} 50 const RtpToNtpEstimator::RtcpMeasurement& other) {
52 51 for (const auto& measurement : measurements) {
53 RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, 52 if (measurement.IsEqual(other))
54 uint32_t ntp_frac,
55 uint32_t timestamp)
56 : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {}
57
58 bool RtcpMeasurement::IsEqual(const RtcpMeasurement& other) const {
59 // Use || since two equal timestamps will result in zero frequency and in
60 // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency.
61 return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp);
62 }
63
64 // Class holding list of RTP and NTP timestamp pairs.
65 RtcpMeasurements::RtcpMeasurements() {}
66 RtcpMeasurements::~RtcpMeasurements() {}
67
68 bool RtcpMeasurements::Contains(const RtcpMeasurement& other) const {
69 for (const auto& it : list) {
70 if (it.IsEqual(other))
71 return true; 53 return true;
72 } 54 }
73 return false; 55 return false;
74 } 56 }
75 57
76 bool RtcpMeasurements::IsValid(const RtcpMeasurement& other) const { 58 bool IsValid(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements,
59 const RtpToNtpEstimator::RtcpMeasurement& other) {
77 if (!other.ntp_time.Valid()) 60 if (!other.ntp_time.Valid())
78 return false; 61 return false;
79 62
80 int64_t ntp_ms_new = other.ntp_time.ToMs(); 63 int64_t ntp_ms_new = other.ntp_time.ToMs();
81 for (const auto& it : list) { 64 for (const auto& measurement : measurements) {
82 if (ntp_ms_new <= it.ntp_time.ToMs()) { 65 if (ntp_ms_new <= measurement.ntp_time.ToMs()) {
83 // Old report. 66 // Old report.
84 return false; 67 return false;
85 } 68 }
86 int64_t timestamp_new = other.rtp_timestamp; 69 int64_t timestamp_new = other.rtp_timestamp;
87 if (!CompensateForWrapAround(timestamp_new, it.rtp_timestamp, 70 if (!CompensateForWrapAround(timestamp_new, measurement.rtp_timestamp,
88 &timestamp_new)) { 71 &timestamp_new)) {
89 return false; 72 return false;
90 } 73 }
91 if (timestamp_new <= it.rtp_timestamp) { 74 if (timestamp_new <= measurement.rtp_timestamp) {
92 LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp."; 75 LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp.";
93 return false; 76 return false;
94 } 77 }
95 } 78 }
96 return true; 79 return true;
97 } 80 }
81 } // namespace
98 82
99 void RtcpMeasurements::UpdateParameters() { 83 RtpToNtpEstimator::RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs,
100 if (list.size() != kNumRtcpReportsToUse) 84 uint32_t ntp_frac,
85 uint32_t timestamp)
86 : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {}
87
88 bool RtpToNtpEstimator::RtcpMeasurement::IsEqual(
89 const RtcpMeasurement& other) const {
90 // Use || since two equal timestamps will result in zero frequency and in
91 // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency.
92 return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp);
93 }
94
95 // Class for converting an RTP timestamp to the NTP domain.
96 RtpToNtpEstimator::RtpToNtpEstimator() {}
97 RtpToNtpEstimator::~RtpToNtpEstimator() {}
98
99 void RtpToNtpEstimator::UpdateParameters() {
100 if (measurements_.size() != kNumRtcpReportsToUse)
101 return; 101 return;
102 102
103 int64_t timestamp_new = list.front().rtp_timestamp; 103 int64_t timestamp_new = measurements_.front().rtp_timestamp;
104 int64_t timestamp_old = list.back().rtp_timestamp; 104 int64_t timestamp_old = measurements_.back().rtp_timestamp;
105 if (!CompensateForWrapAround(timestamp_new, timestamp_old, &timestamp_new)) 105 if (!CompensateForWrapAround(timestamp_new, timestamp_old, &timestamp_new))
106 return; 106 return;
107 107
108 int64_t ntp_ms_new = list.front().ntp_time.ToMs(); 108 int64_t ntp_ms_new = measurements_.front().ntp_time.ToMs();
109 int64_t ntp_ms_old = list.back().ntp_time.ToMs(); 109 int64_t ntp_ms_old = measurements_.back().ntp_time.ToMs();
110 110
111 if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old, 111 if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old,
112 &params.frequency_khz)) { 112 &params_.frequency_khz)) {
113 return; 113 return;
114 } 114 }
115 params.offset_ms = timestamp_new - params.frequency_khz * ntp_ms_new; 115 params_.offset_ms = timestamp_new - params_.frequency_khz * ntp_ms_new;
116 params.calculated = true; 116 params_.calculated = true;
117 } 117 }
118 118
119 // Updates list holding NTP and RTP timestamp pairs. 119 bool RtpToNtpEstimator::UpdateMeasurements(uint32_t ntp_secs,
120 bool UpdateRtcpList(uint32_t ntp_secs, 120 uint32_t ntp_frac,
121 uint32_t ntp_frac, 121 uint32_t rtp_timestamp,
122 uint32_t rtp_timestamp, 122 bool* new_rtcp_sr) {
123 RtcpMeasurements* rtcp_measurements,
124 bool* new_rtcp_sr) {
125 *new_rtcp_sr = false; 123 *new_rtcp_sr = false;
126 124
127 RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp); 125 RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp);
128 if (rtcp_measurements->Contains(measurement)) { 126 if (Contains(measurements_, measurement)) {
129 // RTCP SR report already added. 127 // RTCP SR report already added.
130 return true; 128 return true;
131 } 129 }
132 130 if (!IsValid(measurements_, measurement)) {
133 if (!rtcp_measurements->IsValid(measurement)) {
134 // Old report or invalid parameters. 131 // Old report or invalid parameters.
135 return false; 132 return false;
136 } 133 }
137 134
138 // Insert new RTCP SR report. 135 // Insert new RTCP SR report.
139 if (rtcp_measurements->list.size() == kNumRtcpReportsToUse) 136 if (measurements_.size() == kNumRtcpReportsToUse)
140 rtcp_measurements->list.pop_back(); 137 measurements_.pop_back();
141 138
142 rtcp_measurements->list.push_front(measurement); 139 measurements_.push_front(measurement);
143 *new_rtcp_sr = true; 140 *new_rtcp_sr = true;
144 141
145 // List updated, calculate new parameters. 142 // List updated, calculate new parameters.
146 rtcp_measurements->UpdateParameters(); 143 UpdateParameters();
147 return true; 144 return true;
148 } 145 }
149 146
150 // Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp 147 bool RtpToNtpEstimator::Estimate(int64_t rtp_timestamp,
151 // pairs in |rtcp|. The converted timestamp is returned in 148 int64_t* rtp_timestamp_ms) const {
152 // |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP 149 if (!params_.calculated || measurements_.empty())
153 // timestamps and returns false if it can't do the conversion due to reordering.
154 bool RtpToNtpMs(int64_t rtp_timestamp,
155 const RtcpMeasurements& rtcp,
156 int64_t* rtp_timestamp_in_ms) {
157 if (!rtcp.params.calculated || rtcp.list.empty())
158 return false; 150 return false;
159 151
160 uint32_t rtcp_timestamp_old = rtcp.list.back().rtp_timestamp; 152 uint32_t rtp_timestamp_old = measurements_.back().rtp_timestamp;
161 int64_t rtp_timestamp_unwrapped; 153 int64_t rtp_timestamp_unwrapped;
162 if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old, 154 if (!CompensateForWrapAround(rtp_timestamp, rtp_timestamp_old,
163 &rtp_timestamp_unwrapped)) { 155 &rtp_timestamp_unwrapped)) {
164 return false; 156 return false;
165 } 157 }
166 158
167 double rtp_timestamp_ms = 159 double rtp_ms =
168 (static_cast<double>(rtp_timestamp_unwrapped) - rtcp.params.offset_ms) / 160 (static_cast<double>(rtp_timestamp_unwrapped) - params_.offset_ms) /
169 rtcp.params.frequency_khz + 161 params_.frequency_khz +
170 0.5f; 162 0.5f;
171 if (rtp_timestamp_ms < 0) { 163
164 if (rtp_ms < 0)
172 return false; 165 return false;
173 } 166
174 *rtp_timestamp_in_ms = rtp_timestamp_ms; 167 *rtp_timestamp_ms = rtp_ms;
175 return true; 168 return true;
176 } 169 }
177 170
178 int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) { 171 int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) {
179 if (new_timestamp < old_timestamp) { 172 if (new_timestamp < old_timestamp) {
180 // This difference should be less than -2^31 if we have had a wrap around 173 // This difference should be less than -2^31 if we have had a wrap around
181 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is 174 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
182 // cast to a int32_t, it should be positive. 175 // cast to a int32_t, it should be positive.
183 if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) { 176 if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) {
184 // Forward wrap around. 177 // Forward wrap around.
185 return 1; 178 return 1;
186 } 179 }
187 } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) { 180 } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) {
188 // This difference should be less than -2^31 if we have had a backward wrap 181 // This difference should be less than -2^31 if we have had a backward wrap
189 // around. Since it is cast to a int32_t, it should be positive. 182 // around. Since it is cast to a int32_t, it should be positive.
190 return -1; 183 return -1;
191 } 184 }
192 return 0; 185 return 0;
193 } 186 }
194 187
195 } // namespace webrtc 188 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/system_wrappers/source/rtp_to_ntp.cc ('k') | webrtc/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698