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

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

Issue 2963133003: More gracefully handle rtp timestamp jumps in the rtp to ntp estimator. (Closed)
Patch Set: . Created 3 years, 5 months 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
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 } 47 }
48 48
49 bool Contains(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements, 49 bool Contains(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements,
50 const RtpToNtpEstimator::RtcpMeasurement& other) { 50 const RtpToNtpEstimator::RtcpMeasurement& other) {
51 for (const auto& measurement : measurements) { 51 for (const auto& measurement : measurements) {
52 if (measurement.IsEqual(other)) 52 if (measurement.IsEqual(other))
53 return true; 53 return true;
54 } 54 }
55 return false; 55 return false;
56 } 56 }
57
58 bool IsValid(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements,
59 const RtpToNtpEstimator::RtcpMeasurement& other) {
60 if (!other.ntp_time.Valid())
61 return false;
62
63 int64_t ntp_ms_new = other.ntp_time.ToMs();
64 for (const auto& measurement : measurements) {
65 if (ntp_ms_new <= measurement.ntp_time.ToMs()) {
66 // Old report.
67 return false;
68 }
69 int64_t timestamp_new = other.rtp_timestamp;
70 if (!CompensateForWrapAround(timestamp_new, measurement.rtp_timestamp,
71 &timestamp_new)) {
72 return false;
73 }
74 if (timestamp_new <= measurement.rtp_timestamp) {
75 LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp.";
76 return false;
77 }
78 }
79 return true;
80 }
81 } // namespace 57 } // namespace
82 58
83 RtpToNtpEstimator::RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, 59 RtpToNtpEstimator::RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs,
84 uint32_t ntp_frac, 60 uint32_t ntp_frac,
85 uint32_t timestamp) 61 uint32_t timestamp)
86 : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {} 62 : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {}
87 63
88 bool RtpToNtpEstimator::RtcpMeasurement::IsEqual( 64 bool RtpToNtpEstimator::RtcpMeasurement::IsEqual(
89 const RtcpMeasurement& other) const { 65 const RtcpMeasurement& other) const {
90 // Use || since two equal timestamps will result in zero frequency and in 66 // Use || since two equal timestamps will result in zero frequency and in
91 // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency. 67 // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency.
92 return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp); 68 return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp);
93 } 69 }
94 70
95 // Class for converting an RTP timestamp to the NTP domain. 71 // Class for converting an RTP timestamp to the NTP domain.
96 RtpToNtpEstimator::RtpToNtpEstimator() {} 72 RtpToNtpEstimator::RtpToNtpEstimator() : consecutive_invalid_samples_(0) {}
97 RtpToNtpEstimator::~RtpToNtpEstimator() {} 73 RtpToNtpEstimator::~RtpToNtpEstimator() {}
98 74
99 void RtpToNtpEstimator::UpdateParameters() { 75 void RtpToNtpEstimator::UpdateParameters() {
100 if (measurements_.size() != kNumRtcpReportsToUse) 76 if (measurements_.size() != kNumRtcpReportsToUse)
101 return; 77 return;
102 78
103 int64_t timestamp_new = measurements_.front().rtp_timestamp; 79 int64_t timestamp_new = measurements_.front().rtp_timestamp;
104 int64_t timestamp_old = measurements_.back().rtp_timestamp; 80 int64_t timestamp_old = measurements_.back().rtp_timestamp;
105 if (!CompensateForWrapAround(timestamp_new, timestamp_old, &timestamp_new)) 81 if (!CompensateForWrapAround(timestamp_new, timestamp_old, &timestamp_new))
106 return; 82 return;
107 83
108 int64_t ntp_ms_new = measurements_.front().ntp_time.ToMs(); 84 int64_t ntp_ms_new = measurements_.front().ntp_time.ToMs();
109 int64_t ntp_ms_old = measurements_.back().ntp_time.ToMs(); 85 int64_t ntp_ms_old = measurements_.back().ntp_time.ToMs();
110 86
111 if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old, 87 if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old,
112 &params_.frequency_khz)) { 88 &params_.frequency_khz)) {
113 return; 89 return;
114 } 90 }
115 params_.offset_ms = timestamp_new - params_.frequency_khz * ntp_ms_new; 91 params_.offset_ms = timestamp_new - params_.frequency_khz * ntp_ms_new;
116 params_.calculated = true; 92 params_.calculated = true;
117 } 93 }
118 94
119 bool RtpToNtpEstimator::UpdateMeasurements(uint32_t ntp_secs, 95 bool RtpToNtpEstimator::UpdateMeasurements(uint32_t ntp_secs,
120 uint32_t ntp_frac, 96 uint32_t ntp_frac,
121 uint32_t rtp_timestamp, 97 uint32_t rtp_timestamp,
122 bool* new_rtcp_sr) { 98 bool* new_rtcp_sr) {
123 *new_rtcp_sr = false; 99 *new_rtcp_sr = false;
124 100
125 RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp); 101 RtcpMeasurement new_measurement(ntp_secs, ntp_frac, rtp_timestamp);
126 if (Contains(measurements_, measurement)) { 102 if (Contains(measurements_, new_measurement)) {
127 // RTCP SR report already added. 103 // RTCP SR report already added.
128 return true; 104 return true;
129 } 105 }
130 if (!IsValid(measurements_, measurement)) { 106 if (!new_measurement.ntp_time.Valid())
131 // Old report or invalid parameters.
132 return false; 107 return false;
108
109 int64_t ntp_ms_new = new_measurement.ntp_time.ToMs();
110 bool invalid_sample = false;
111 for (const auto& measurement : measurements_) {
112 if (ntp_ms_new <= measurement.ntp_time.ToMs()) {
113 // Old report.
114 invalid_sample = true;
115 break;
116 }
117 int64_t timestamp_new = new_measurement.rtp_timestamp;
118 if (!CompensateForWrapAround(timestamp_new, measurement.rtp_timestamp,
119 &timestamp_new)) {
120 invalid_sample = true;
121 break;
122 }
123 if (timestamp_new <= measurement.rtp_timestamp) {
124 LOG(LS_WARNING)
125 << "Newer RTCP SR report with older RTP timestamp, dropping";
126 invalid_sample = true;
127 break;
128 }
133 } 129 }
130 if (invalid_sample) {
131 ++consecutive_invalid_samples_;
132 if (consecutive_invalid_samples_ < kMaxInvalidSamples) {
133 return false;
134 }
135 LOG(LS_WARNING) << "Multiple consecutively invalid RTCP SR reports, "
136 "clearing measurements.";
137 measurements_.clear();
138 }
139 consecutive_invalid_samples_ = 0;
134 140
135 // Insert new RTCP SR report. 141 // Insert new RTCP SR report.
136 if (measurements_.size() == kNumRtcpReportsToUse) 142 if (measurements_.size() == kNumRtcpReportsToUse)
137 measurements_.pop_back(); 143 measurements_.pop_back();
138 144
139 measurements_.push_front(measurement); 145 measurements_.push_front(new_measurement);
140 *new_rtcp_sr = true; 146 *new_rtcp_sr = true;
141 147
142 // List updated, calculate new parameters. 148 // List updated, calculate new parameters.
143 UpdateParameters(); 149 UpdateParameters();
144 return true; 150 return true;
145 } 151 }
146 152
147 bool RtpToNtpEstimator::Estimate(int64_t rtp_timestamp, 153 bool RtpToNtpEstimator::Estimate(int64_t rtp_timestamp,
148 int64_t* rtp_timestamp_ms) const { 154 int64_t* rtp_timestamp_ms) const {
149 if (!params_.calculated || measurements_.empty()) 155 if (!params_.calculated || measurements_.empty())
(...skipping 29 matching lines...) Expand all
179 } 185 }
180 } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) { 186 } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) {
181 // This difference should be less than -2^31 if we have had a backward wrap 187 // This difference should be less than -2^31 if we have had a backward wrap
182 // around. Since it is cast to a int32_t, it should be positive. 188 // around. Since it is cast to a int32_t, it should be positive.
183 return -1; 189 return -1;
184 } 190 }
185 return 0; 191 return 0;
186 } 192 }
187 193
188 } // namespace webrtc 194 } // 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_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698