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

Unified Diff: media/cast/logging/receiver_time_offset_estimator_impl.cc

Issue 556693002: Cast: Logging estimates clock difference based on packets (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: media/cast/logging/receiver_time_offset_estimator_impl.cc
diff --git a/media/cast/logging/receiver_time_offset_estimator_impl.cc b/media/cast/logging/receiver_time_offset_estimator_impl.cc
index 950b3671ae8b1f3efa3519abb23c8e1271c4a744..d5116542d6bfbc08bfd4eceab9de1ab0d4f1bf63 100644
--- a/media/cast/logging/receiver_time_offset_estimator_impl.cc
+++ b/media/cast/logging/receiver_time_offset_estimator_impl.cc
@@ -12,140 +12,134 @@
namespace media {
namespace cast {
-// This should be large enough so that we can collect all 3 events before
-// the entry gets removed from the map.
-const size_t kMaxEventTimesMapSize = 100;
-
-ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl(
- base::TickClock* clock)
- : bounded_(false),
- clock_(clock),
- offset_bounds_valid_(false),
- last_reset_time_(clock_->NowTicks()) {
+ReceiverTimeOffsetEstimatorImpl::BoundCalculator::BoundCalculator()
+ : has_bound_(false) {}
+ReceiverTimeOffsetEstimatorImpl::BoundCalculator::~BoundCalculator() {}
+
+void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetSent(
+ uint32 rtp,
+ uint32 packet_id,
+ bool audio,
+ base::TimeTicks t) {
+ uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) |
+ static_cast<uint64>(audio);
+ events_[key].first = t;
+ CheckUpdate(key);
+}
+
+void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetReceived(
+ uint32 rtp,
+ uint16 packet_id,
+ bool audio,
+ base::TimeTicks t) {
+ uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) |
+ static_cast<uint64>(audio);
+ events_[key].second = t;
+ CheckUpdate(key);
+}
+
+void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::UpdateBound(
+ base::TimeTicks sent, base::TimeTicks received) {
+ base::TimeDelta delta = received - sent;
+ if (has_bound_) {
+ if (delta < bound_) {
+ bound_ = delta;
+ } else {
+ bound_ += (delta - bound_) / kClockDriftSpeed;
+ }
+ } else {
+ bound_ = delta;
+ }
+ has_bound_ = true;
+ }
+
+void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::CheckUpdate(
+ uint64 key) {
+ const TimeTickPair& ticks = events_[key];
+ if (!ticks.first.is_null() && !ticks.second.is_null()) {
+ UpdateBound(ticks.first, ticks.second);
+ events_.erase(key);
+ return;
+ }
+
+ if (events_.size() > kMaxEventTimesMapSize) {
+ EventMap::iterator i = ModMapOldest(&events_);
+ if (i != events_.end()) {
+ events_.erase(i);
+ }
+ }
+}
+
+ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl() {
}
ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
}
+
void ReceiverTimeOffsetEstimatorImpl::OnReceiveFrameEvent(
const FrameEvent& frame_event) {
DCHECK(thread_checker_.CalledOnValidThread());
-
- if (frame_event.media_type != VIDEO_EVENT)
- return;
-
- CastLoggingEvent event = frame_event.type;
- if (event != FRAME_ENCODED && event != FRAME_ACK_SENT &&
- event != FRAME_ACK_RECEIVED)
- return;
-
- EventTimesMap::iterator it = event_times_map_.find(frame_event.rtp_timestamp);
- if (it == event_times_map_.end()) {
- EventTimes event_times;
- it = event_times_map_.insert(std::make_pair(frame_event.rtp_timestamp,
- event_times)).first;
- }
- switch (event) {
- case FRAME_ENCODED:
- // Encode is supposed to happen only once. If we see duplicate event,
- // throw away the entry.
- if (it->second.event_a_time.is_null()) {
- it->second.event_a_time = frame_event.timestamp;
- } else {
- event_times_map_.erase(it);
- return;
- }
- break;
+ switch (frame_event.type) {
case FRAME_ACK_SENT:
- if (it->second.event_b_time.is_null()) {
- it->second.event_b_time = frame_event.timestamp;
- } else if (it->second.event_b_time != frame_event.timestamp) {
- // Duplicate ack sent events are normal due to RTCP redundancy,
- // but they must have the same event timestamp.
- event_times_map_.erase(it);
- return;
- }
+ lower_bound_.SetSent(frame_event.rtp_timestamp,
+ 0,
+ frame_event.media_type == AUDIO_EVENT,
+ frame_event.timestamp);
break;
case FRAME_ACK_RECEIVED:
- // If there are duplicate ack received events, pick the one with the
- // smallest event timestamp so we can get a better bound.
- if (it->second.event_c_time.is_null()) {
- it->second.event_c_time = frame_event.timestamp;
- } else {
- it->second.event_c_time =
- std::min(frame_event.timestamp, it->second.event_c_time);
- }
+ lower_bound_.SetReceived(frame_event.rtp_timestamp,
+ 0,
+ frame_event.media_type == AUDIO_EVENT,
+ frame_event.timestamp);
break;
default:
- NOTREACHED();
- }
-
- if (!it->second.event_a_time.is_null() &&
- !it->second.event_b_time.is_null() &&
- !it->second.event_c_time.is_null()) {
- UpdateOffsetBounds(it->second);
- event_times_map_.erase(it);
+ // Ignored
+ break;
}
-
- // Keep the map size at most |kMaxEventTimesMapSize|.
- if (event_times_map_.size() > kMaxEventTimesMapSize)
- event_times_map_.erase(event_times_map_.begin());
}
bool ReceiverTimeOffsetEstimatorImpl::GetReceiverOffsetBounds(
base::TimeDelta* lower_bound,
base::TimeDelta* upper_bound) {
- if (!bounded_)
+ if (!lower_bound_.has_bound() || !upper_bound_.has_bound())
return false;
- *lower_bound = prev_offset_lower_bound_;
- *upper_bound = prev_offset_upper_bound_;
+ *lower_bound = -lower_bound_.bound();
+ *upper_bound = upper_bound_.bound();
+
+ // Sanitize the output, we don't want the upper bound to be
+ // lower than the lower bound, make them the same.
+ if (upper_bound < lower_bound) {
+ lower_bound += (lower_bound - upper_bound) / 2;
+ upper_bound = lower_bound;
+ }
return true;
}
void ReceiverTimeOffsetEstimatorImpl::OnReceivePacketEvent(
const PacketEvent& packet_event) {
- // Not interested in packet events.
DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void ReceiverTimeOffsetEstimatorImpl::UpdateOffsetBounds(
- const EventTimes& event) {
- base::TimeDelta lower_bound = event.event_b_time - event.event_c_time;
- base::TimeDelta upper_bound = event.event_b_time - event.event_a_time;
-
- if (offset_bounds_valid_) {
- lower_bound = std::max(lower_bound, offset_lower_bound_);
- upper_bound = std::min(upper_bound, offset_upper_bound_);
- }
-
- if (lower_bound > upper_bound) {
- VLOG(2) << "Got bogus offset bound values [" << lower_bound.InMilliseconds()
- << ", " << upper_bound.InMilliseconds() << "].";
- return;
- }
-
- offset_lower_bound_ = lower_bound;
- offset_upper_bound_ = upper_bound;
- offset_bounds_valid_ = true;
- if (!bounded_ ||
- offset_upper_bound_ - offset_lower_bound_ <
- base::TimeDelta::FromMilliseconds(20)) {
- prev_offset_lower_bound_ = offset_lower_bound_;
- prev_offset_upper_bound_ = offset_upper_bound_;
- }
-
- base::TimeTicks now = clock_->NowTicks();
- if (now - last_reset_time_ > base::TimeDelta::FromSeconds(20)) {
- last_reset_time_ = now;
- offset_lower_bound_ = base::TimeDelta();
- offset_upper_bound_ = base::TimeDelta();
- offset_bounds_valid_ = false;
+ switch (packet_event.type) {
+ case PACKET_SENT_TO_NETWORK:
+ upper_bound_.SetSent(packet_event.rtp_timestamp,
+ packet_event.packet_id,
+ packet_event.media_type == AUDIO_EVENT,
+ packet_event.timestamp);
+ break;
+ case PACKET_RECEIVED:
+ upper_bound_.SetReceived(packet_event.rtp_timestamp,
+ packet_event.packet_id,
+ packet_event.media_type == AUDIO_EVENT,
+ packet_event.timestamp);
+ break;
+ default:
+ // Ignored
+ break;
}
-
- bounded_ = true;
}
+
} // namespace cast
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698