Make rtc::TimestampWrapAroundHandler handle backwards wrapping
Also fix a timestamp issue in video analyzer test.
BUG=webrtc:5637, webrtc:5537
Review URL: https://codereview.webrtc.org/1779773002
Cr-Commit-Position: refs/heads/master@{#11938}
diff --git a/webrtc/base/timeutils.cc b/webrtc/base/timeutils.cc
index 24b04ee..b7803ae 100644
--- a/webrtc/base/timeutils.cc
+++ b/webrtc/base/timeutils.cc
@@ -193,17 +193,25 @@
}
TimestampWrapAroundHandler::TimestampWrapAroundHandler()
- : last_ts_(0), num_wrap_(0) {}
+ : last_ts_(0), num_wrap_(-1) {}
int64_t TimestampWrapAroundHandler::Unwrap(uint32_t ts) {
- if (ts < last_ts_) {
- if (last_ts_ > 0xf0000000 && ts < 0x0fffffff) {
- ++num_wrap_;
- }
+ if (num_wrap_ == -1) {
+ last_ts_ = ts;
+ num_wrap_ = 0;
+ return ts;
}
+
+ if (ts < last_ts_) {
+ if (last_ts_ >= 0xf0000000 && ts < 0x0fffffff)
+ ++num_wrap_;
+ } else if ((ts - last_ts_) > 0xf0000000) {
+ // Backwards wrap. Unwrap with last wrap count and don't update last_ts_.
+ return ts + ((num_wrap_ - 1) << 32);
+ }
+
last_ts_ = ts;
- int64_t unwrapped_ts = ts + (num_wrap_ << 32);
- return unwrapped_ts;
+ return ts + (num_wrap_ << 32);
}
int64_t TmToSeconds(const std::tm& tm) {
diff --git a/webrtc/base/timeutils_unittest.cc b/webrtc/base/timeutils_unittest.cc
index 688658b..7e342d0 100644
--- a/webrtc/base/timeutils_unittest.cc
+++ b/webrtc/base/timeutils_unittest.cc
@@ -153,18 +153,48 @@
};
TEST_F(TimestampWrapAroundHandlerTest, Unwrap) {
- uint32_t ts = 0xfffffff2;
- int64_t unwrapped_ts = ts;
- EXPECT_EQ(ts, wraparound_handler_.Unwrap(ts));
+ // Start value.
+ int64_t ts = 2;
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+
+ // Wrap backwards.
+ ts = -2;
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+
+ // Forward to 2 again.
ts = 2;
- unwrapped_ts += 0x10;
- EXPECT_EQ(unwrapped_ts, wraparound_handler_.Unwrap(ts));
- ts = 0xfffffff2;
- unwrapped_ts += 0xfffffff0;
- EXPECT_EQ(unwrapped_ts, wraparound_handler_.Unwrap(ts));
- ts = 0;
- unwrapped_ts += 0xe;
- EXPECT_EQ(unwrapped_ts, wraparound_handler_.Unwrap(ts));
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+
+ // Max positive skip ahead, until max value (0xffffffff).
+ for (uint32_t i = 0; i <= 0xf; ++i) {
+ ts = (i << 28) + 0x0fffffff;
+ EXPECT_EQ(
+ ts, wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+ }
+
+ // Wrap around.
+ ts += 2;
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+
+ // Max wrap backward...
+ ts -= 0x0fffffff;
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+
+ // ...and back again.
+ ts += 0x0fffffff;
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
+}
+
+TEST_F(TimestampWrapAroundHandlerTest, NoNegativeStart) {
+ int64_t ts = 0xfffffff0;
+ EXPECT_EQ(ts,
+ wraparound_handler_.Unwrap(static_cast<uint32_t>(ts & 0xffffffff)));
}
class TmToSeconds : public testing::Test {
diff --git a/webrtc/video/video_quality_test.cc b/webrtc/video/video_quality_test.cc
index e43ddb1..c882992 100644
--- a/webrtc/video/video_quality_test.cc
+++ b/webrtc/video/video_quality_test.cc
@@ -161,13 +161,13 @@
bool result = transport_->SendRtp(packet, length, options);
{
rtc::CritScope lock(&crit_);
- int64_t timestamp = wrap_handler_.Unwrap(header.timestamp);
if (rtp_timestamp_delta_ == 0) {
- rtp_timestamp_delta_ = timestamp - first_send_frame_.timestamp();
+ rtp_timestamp_delta_ = header.timestamp - first_send_frame_.timestamp();
first_send_frame_.Reset();
}
- timestamp -= rtp_timestamp_delta_;
+ int64_t timestamp =
+ wrap_handler_.Unwrap(header.timestamp - rtp_timestamp_delta_);
send_times_[timestamp] = current_time;
if (!transport_->DiscardedLastPacket() &&
header.ssrc == ssrc_to_analyze_) {