OLD | NEW |
---|---|
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.h" |
12 | 12 |
13 #include "webrtc/base/logging.h" | |
13 #include "webrtc/system_wrappers/include/clock.h" | 14 #include "webrtc/system_wrappers/include/clock.h" |
14 | 15 |
15 #include <assert.h> | |
16 | |
17 namespace webrtc { | 16 namespace webrtc { |
18 | 17 namespace { |
19 RtcpMeasurement::RtcpMeasurement() | 18 // Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps. |
20 : ntp_secs(0), ntp_frac(0), rtp_timestamp(0) {} | 19 bool CalculateFrequency(int64_t rtcp_ntp_ms1, |
21 | 20 uint32_t rtp_timestamp1, |
22 RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, | 21 int64_t rtcp_ntp_ms2, |
23 uint32_t timestamp) | 22 uint32_t rtp_timestamp2, |
24 : ntp_secs(ntp_secs), ntp_frac(ntp_frac), rtp_timestamp(timestamp) {} | 23 double* frequency_khz) { |
25 | |
26 // Calculates the RTP timestamp frequency from two pairs of NTP and RTP | |
27 // timestamps. | |
28 bool CalculateFrequency( | |
29 int64_t rtcp_ntp_ms1, | |
30 uint32_t rtp_timestamp1, | |
31 int64_t rtcp_ntp_ms2, | |
32 uint32_t rtp_timestamp2, | |
33 double* frequency_khz) { | |
34 if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) { | 24 if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) { |
35 return false; | 25 return false; |
36 } | 26 } |
37 *frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) / | 27 *frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) / |
38 static_cast<double>(rtcp_ntp_ms1 - rtcp_ntp_ms2); | 28 static_cast<double>(rtcp_ntp_ms1 - rtcp_ntp_ms2); |
39 return true; | 29 return true; |
40 } | 30 } |
41 | 31 |
42 // Detects if there has been a wraparound between |old_timestamp| and | 32 // Detects if there has been a wraparound between |old_timestamp| and |
43 // |new_timestamp|, and compensates by adding 2^32 if that is the case. | 33 // |new_timestamp|, and compensates by adding 2^32 if that is the case. |
44 bool CompensateForWrapAround(uint32_t new_timestamp, | 34 bool CompensateForWrapAround(uint32_t new_timestamp, |
45 uint32_t old_timestamp, | 35 uint32_t old_timestamp, |
46 int64_t* compensated_timestamp) { | 36 int64_t* compensated_timestamp) { |
47 assert(compensated_timestamp); | |
48 int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp); | 37 int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp); |
49 if (wraps < 0) { | 38 if (wraps < 0) { |
50 // Reordering, don't use this packet. | 39 // Reordering, don't use this packet. |
51 return false; | 40 return false; |
52 } | 41 } |
53 *compensated_timestamp = new_timestamp + (wraps << 32); | 42 *compensated_timestamp = new_timestamp + (wraps << 32); |
54 return true; | 43 return true; |
55 } | 44 } |
45 } // namespace | |
56 | 46 |
47 // Class holding RTP and NTP timestamp from a RTCP SR report. | |
48 RtcpMeasurement::RtcpMeasurement() | |
49 : ntp_secs(0), ntp_frac(0), rtp_timestamp(0) {} | |
50 | |
51 RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, | |
52 uint32_t ntp_frac, | |
53 uint32_t timestamp) | |
54 : ntp_secs(ntp_secs), ntp_frac(ntp_frac), rtp_timestamp(timestamp) {} | |
55 | |
56 bool RtcpMeasurement::IsEqual(const RtcpMeasurement& other) const { | |
57 return (ntp_secs == other.ntp_secs && ntp_frac == other.ntp_frac) || | |
stefan-webrtc
2016/10/18 23:38:27
Why ||? Comment on that (I assume it's because we
åsapersson
2016/10/19 14:35:28
Done.
| |
58 (rtp_timestamp == other.rtp_timestamp); | |
59 } | |
60 | |
61 // Class holding list of RTP and NTP timestamp pairs. | |
62 RtcpMeasurements::RtcpMeasurements() {} | |
63 RtcpMeasurements::~RtcpMeasurements() {} | |
64 | |
65 bool RtcpMeasurements::Contains(const RtcpMeasurement& other) const { | |
66 for (const auto& it : list) { | |
67 if (it.IsEqual(other)) | |
68 return true; | |
69 } | |
70 return false; | |
71 } | |
72 | |
73 bool RtcpMeasurements::IsValid(const RtcpMeasurement& other) const { | |
74 if (other.ntp_secs == 0 && other.ntp_frac == 0) | |
75 return false; | |
76 | |
77 int64_t ntp_ms_new = Clock::NtpToMs(other.ntp_secs, other.ntp_frac); | |
78 for (const auto& it : list) { | |
79 if (ntp_ms_new <= Clock::NtpToMs(it.ntp_secs, it.ntp_frac)) { | |
80 // Old report. | |
81 return false; | |
82 } | |
83 int64_t timestamp_new = other.rtp_timestamp; | |
84 if (!CompensateForWrapAround(timestamp_new, it.rtp_timestamp, | |
85 ×tamp_new)) { | |
86 return false; | |
87 } | |
88 if (timestamp_new <= it.rtp_timestamp) { | |
89 LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp."; | |
90 return false; | |
91 } | |
92 } | |
93 return true; | |
94 } | |
95 | |
96 bool RtcpMeasurements::UpdateParameters() { | |
97 if (list.size() != 2) | |
98 return false; | |
99 | |
100 int64_t timestamp_new = list.front().rtp_timestamp; | |
101 int64_t timestamp_old = list.back().rtp_timestamp; | |
102 if (!CompensateForWrapAround(timestamp_new, timestamp_old, ×tamp_new)) | |
103 return false; | |
104 | |
105 int64_t ntp_ms_new = | |
106 Clock::NtpToMs(list.front().ntp_secs, list.front().ntp_frac); | |
107 int64_t ntp_ms_old = | |
108 Clock::NtpToMs(list.back().ntp_secs, list.back().ntp_frac); | |
109 | |
110 if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old, | |
111 ¶ms.frequency_khz)) { | |
112 return false; | |
113 } | |
114 params.offset_ms = timestamp_new - params.frequency_khz * ntp_ms_new; | |
115 params.calculated = true; | |
116 return true; | |
117 } | |
118 | |
119 // Updates list holding NTP and RTP timestamp pairs. | |
57 bool UpdateRtcpList(uint32_t ntp_secs, | 120 bool UpdateRtcpList(uint32_t ntp_secs, |
58 uint32_t ntp_frac, | 121 uint32_t ntp_frac, |
59 uint32_t rtp_timestamp, | 122 uint32_t rtp_timestamp, |
60 RtcpList* rtcp_list, | 123 RtcpMeasurements* rtcp_measurements, |
61 bool* new_rtcp_sr) { | 124 bool* new_rtcp_sr) { |
62 *new_rtcp_sr = false; | 125 *new_rtcp_sr = false; |
63 if (ntp_secs == 0 && ntp_frac == 0) { | 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. | |
64 return false; | 135 return false; |
65 } | 136 } |
66 | 137 |
67 RtcpMeasurement measurement; | 138 // Two RTCP SR reports are needed to map between RTP and NTP. |
68 measurement.ntp_secs = ntp_secs; | 139 // More than two will not improve the mapping. |
69 measurement.ntp_frac = ntp_frac; | 140 if (rtcp_measurements->list.size() == 2) |
70 measurement.rtp_timestamp = rtp_timestamp; | 141 rtcp_measurements->list.pop_back(); |
71 | 142 |
72 for (RtcpList::iterator it = rtcp_list->begin(); | 143 rtcp_measurements->list.push_front(measurement); |
73 it != rtcp_list->end(); ++it) { | 144 *new_rtcp_sr = true; |
74 if ((measurement.ntp_secs == (*it).ntp_secs && | |
75 measurement.ntp_frac == (*it).ntp_frac) || | |
76 (measurement.rtp_timestamp == (*it).rtp_timestamp)) { | |
77 // This RTCP has already been added to the list. | |
78 return true; | |
79 } | |
80 } | |
81 | 145 |
82 // We need two RTCP SR reports to map between RTP and NTP. More than two will | 146 // List updated, calculate new parameters. |
83 // not improve the mapping. | 147 rtcp_measurements->UpdateParameters(); |
84 if (rtcp_list->size() == 2) { | |
85 rtcp_list->pop_back(); | |
86 } | |
87 rtcp_list->push_front(measurement); | |
88 *new_rtcp_sr = true; | |
89 return true; | 148 return true; |
90 } | 149 } |
91 | 150 |
92 // Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp | 151 // Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp |
93 // pairs in |rtcp|. The converted timestamp is returned in | 152 // pairs in |rtcp|. The converted timestamp is returned in |
94 // |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP | 153 // |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP |
95 // timestamps and returns false if it can't do the conversion due to reordering. | 154 // timestamps and returns false if it can't do the conversion due to reordering. |
96 bool RtpToNtpMs(int64_t rtp_timestamp, | 155 bool RtpToNtpMs(int64_t rtp_timestamp, |
97 const RtcpList& rtcp, | 156 const RtcpMeasurements& rtcp, |
98 int64_t* rtp_timestamp_in_ms) { | 157 int64_t* rtp_timestamp_in_ms) { |
99 if (rtcp.size() != 2) | 158 if (!rtcp.params.calculated || rtcp.list.empty()) |
100 return false; | 159 return false; |
101 | 160 |
102 int64_t rtcp_ntp_ms_new = Clock::NtpToMs(rtcp.front().ntp_secs, | 161 uint32_t rtcp_timestamp_old = rtcp.list.back().rtp_timestamp; |
103 rtcp.front().ntp_frac); | |
104 int64_t rtcp_ntp_ms_old = Clock::NtpToMs(rtcp.back().ntp_secs, | |
105 rtcp.back().ntp_frac); | |
106 int64_t rtcp_timestamp_new = rtcp.front().rtp_timestamp; | |
107 int64_t rtcp_timestamp_old = rtcp.back().rtp_timestamp; | |
108 if (!CompensateForWrapAround(rtcp_timestamp_new, | |
109 rtcp_timestamp_old, | |
110 &rtcp_timestamp_new)) { | |
111 return false; | |
112 } | |
113 if (rtcp_timestamp_new < rtcp_timestamp_old) | |
114 return false; | |
115 | |
116 double freq_khz; | |
117 if (!CalculateFrequency(rtcp_ntp_ms_new, | |
118 rtcp_timestamp_new, | |
119 rtcp_ntp_ms_old, | |
120 rtcp_timestamp_old, | |
121 &freq_khz)) { | |
122 return false; | |
123 } | |
124 double offset = rtcp_timestamp_new - freq_khz * rtcp_ntp_ms_new; | |
125 int64_t rtp_timestamp_unwrapped; | 162 int64_t rtp_timestamp_unwrapped; |
126 if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old, | 163 if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old, |
127 &rtp_timestamp_unwrapped)) { | 164 &rtp_timestamp_unwrapped)) { |
128 return false; | 165 return false; |
129 } | 166 } |
130 double rtp_timestamp_ntp_ms = (static_cast<double>(rtp_timestamp_unwrapped) - | 167 |
131 offset) / freq_khz + 0.5f; | 168 double rtp_timestamp_ms = |
132 if (rtp_timestamp_ntp_ms < 0) { | 169 (static_cast<double>(rtp_timestamp_unwrapped) - rtcp.params.offset_ms) / |
170 rtcp.params.frequency_khz + | |
171 0.5f; | |
172 if (rtp_timestamp_ms < 0) { | |
133 return false; | 173 return false; |
134 } | 174 } |
135 *rtp_timestamp_in_ms = rtp_timestamp_ntp_ms; | 175 *rtp_timestamp_in_ms = rtp_timestamp_ms; |
136 return true; | 176 return true; |
137 } | 177 } |
138 | 178 |
139 int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) { | 179 int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) { |
140 if (new_timestamp < old_timestamp) { | 180 if (new_timestamp < old_timestamp) { |
141 // This difference should be less than -2^31 if we have had a wrap around | 181 // This difference should be less than -2^31 if we have had a wrap around |
142 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is | 182 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is |
143 // cast to a int32_t, it should be positive. | 183 // cast to a int32_t, it should be positive. |
144 if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) { | 184 if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) { |
145 // Forward wrap around. | 185 // Forward wrap around. |
146 return 1; | 186 return 1; |
147 } | 187 } |
148 } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) { | 188 } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) { |
149 // This difference should be less than -2^31 if we have had a backward wrap | 189 // This difference should be less than -2^31 if we have had a backward wrap |
150 // around. Since it is cast to a int32_t, it should be positive. | 190 // around. Since it is cast to a int32_t, it should be positive. |
151 return -1; | 191 return -1; |
152 } | 192 } |
153 return 0; | 193 return 0; |
154 } | 194 } |
155 | 195 |
156 } // namespace webrtc | 196 } // namespace webrtc |
OLD | NEW |