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

Side by Side Diff: webrtc/system_wrappers/source/rtp_to_ntp.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
(Empty)
1 /*
2 * Copyright (c) 2012 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 "webrtc/system_wrappers/include/rtp_to_ntp.h"
12
13 #include "webrtc/base/logging.h"
14 #include "webrtc/system_wrappers/include/clock.h"
15
16 namespace webrtc {
17 namespace {
18 // Number of RTCP SR reports to use to map between RTP and NTP.
19 const size_t kNumRtcpReportsToUse = 2;
20
21 // Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps.
22 bool CalculateFrequency(int64_t rtcp_ntp_ms1,
23 uint32_t rtp_timestamp1,
24 int64_t rtcp_ntp_ms2,
25 uint32_t rtp_timestamp2,
26 double* frequency_khz) {
27 if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) {
28 return false;
29 }
30 *frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) /
31 static_cast<double>(rtcp_ntp_ms1 - rtcp_ntp_ms2);
32 return true;
33 }
34
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.
37 bool CompensateForWrapAround(uint32_t new_timestamp,
38 uint32_t old_timestamp,
39 int64_t* compensated_timestamp) {
40 int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp);
41 if (wraps < 0) {
42 // Reordering, don't use this packet.
43 return false;
44 }
45 *compensated_timestamp = new_timestamp + (wraps << 32);
46 return true;
47 }
48 } // namespace
49
50 // Class holding RTP and NTP timestamp from a RTCP SR report.
51 RtcpMeasurement::RtcpMeasurement() : ntp_time(0, 0), rtp_timestamp(0) {}
52
53 RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs,
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;
72 }
73 return false;
74 }
75
76 bool RtcpMeasurements::IsValid(const RtcpMeasurement& other) const {
77 if (!other.ntp_time.Valid())
78 return false;
79
80 int64_t ntp_ms_new = other.ntp_time.ToMs();
81 for (const auto& it : list) {
82 if (ntp_ms_new <= it.ntp_time.ToMs()) {
83 // Old report.
84 return false;
85 }
86 int64_t timestamp_new = other.rtp_timestamp;
87 if (!CompensateForWrapAround(timestamp_new, it.rtp_timestamp,
88 &timestamp_new)) {
89 return false;
90 }
91 if (timestamp_new <= it.rtp_timestamp) {
92 LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp.";
93 return false;
94 }
95 }
96 return true;
97 }
98
99 void RtcpMeasurements::UpdateParameters() {
100 if (list.size() != kNumRtcpReportsToUse)
101 return;
102
103 int64_t timestamp_new = list.front().rtp_timestamp;
104 int64_t timestamp_old = list.back().rtp_timestamp;
105 if (!CompensateForWrapAround(timestamp_new, timestamp_old, &timestamp_new))
106 return;
107
108 int64_t ntp_ms_new = list.front().ntp_time.ToMs();
109 int64_t ntp_ms_old = list.back().ntp_time.ToMs();
110
111 if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old,
112 &params.frequency_khz)) {
113 return;
114 }
115 params.offset_ms = timestamp_new - params.frequency_khz * ntp_ms_new;
116 params.calculated = true;
117 }
118
119 // Updates list holding NTP and RTP timestamp pairs.
120 bool UpdateRtcpList(uint32_t ntp_secs,
121 uint32_t ntp_frac,
122 uint32_t rtp_timestamp,
123 RtcpMeasurements* rtcp_measurements,
124 bool* new_rtcp_sr) {
125 *new_rtcp_sr = false;
126
127 RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp);
128 if (rtcp_measurements->Contains(measurement)) {
129 // RTCP SR report already added.
130 return true;
131 }
132
133 if (!rtcp_measurements->IsValid(measurement)) {
134 // Old report or invalid parameters.
135 return false;
136 }
137
138 // Insert new RTCP SR report.
139 if (rtcp_measurements->list.size() == kNumRtcpReportsToUse)
140 rtcp_measurements->list.pop_back();
141
142 rtcp_measurements->list.push_front(measurement);
143 *new_rtcp_sr = true;
144
145 // List updated, calculate new parameters.
146 rtcp_measurements->UpdateParameters();
147 return true;
148 }
149
150 // Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp
151 // pairs in |rtcp|. The converted timestamp is returned in
152 // |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP
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;
159
160 uint32_t rtcp_timestamp_old = rtcp.list.back().rtp_timestamp;
161 int64_t rtp_timestamp_unwrapped;
162 if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old,
163 &rtp_timestamp_unwrapped)) {
164 return false;
165 }
166
167 double rtp_timestamp_ms =
168 (static_cast<double>(rtp_timestamp_unwrapped) - rtcp.params.offset_ms) /
169 rtcp.params.frequency_khz +
170 0.5f;
171 if (rtp_timestamp_ms < 0) {
172 return false;
173 }
174 *rtp_timestamp_in_ms = rtp_timestamp_ms;
175 return true;
176 }
177
178 int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) {
179 if (new_timestamp < old_timestamp) {
180 // 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
182 // cast to a int32_t, it should be positive.
183 if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) {
184 // Forward wrap around.
185 return 1;
186 }
187 } 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
189 // around. Since it is cast to a int32_t, it should be positive.
190 return -1;
191 }
192 return 0;
193 }
194
195 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/system_wrappers/include/rtp_to_ntp_estimator.h ('k') | webrtc/system_wrappers/source/rtp_to_ntp_estimator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698