// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_ #define MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_ #include #include #include #include "base/macros.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "media/cast/common/mod_util.h" #include "media/cast/logging/logging_defines.h" #include "media/cast/logging/receiver_time_offset_estimator.h" 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 = 500; // The lower, this is, the faster we adjust to clock drift. // (But with more jitter.) const size_t kClockDriftSpeed = 500; // This implementation listens to two pair of events // 1. FRAME_ACK_SENT / FRAME_ACK_RECEIVED (receiver->sender) // 2. PACKET_SENT_TO_NETWORK / PACKET_RECEIVED (sender->receiver) // There is a causal relationship between these events in that these events // must happen in order. This class obtains the lower and upper bounds for // the offset by taking the difference of timestamps. class ReceiverTimeOffsetEstimatorImpl : public ReceiverTimeOffsetEstimator { public: ReceiverTimeOffsetEstimatorImpl(); ~ReceiverTimeOffsetEstimatorImpl() final; // RawEventSubscriber implementations. void OnReceiveFrameEvent(const FrameEvent& frame_event) final; void OnReceivePacketEvent(const PacketEvent& packet_event) final; // ReceiverTimeOffsetEstimator implementation. bool GetReceiverOffsetBounds(base::TimeDelta* lower_bound, base::TimeDelta* upper_bound) final; private: // This helper uses the difference between sent and recived event // to calculate an upper bound on the difference between the clocks // on the sender and receiver. Note that this difference can take // very large positive or negative values, but the smaller value is // always the better estimate, since a receive event cannot possibly // happen before a send event. Note that we use this to calculate // both upper and lower bounds by reversing the sender/receiver // relationship. class BoundCalculator { public: typedef std::pair TimeTickPair; typedef std::map EventMap; BoundCalculator(); ~BoundCalculator(); bool has_bound() const { return has_bound_; } base::TimeDelta bound() const { return bound_; } void SetSent(RtpTimeTicks rtp, uint16_t packet_id, bool audio, base::TimeTicks t); void SetReceived(RtpTimeTicks rtp, uint16_t packet_id, bool audio, base::TimeTicks t); private: void UpdateBound(base::TimeTicks a, base::TimeTicks b); void CheckUpdate(uint64_t key); private: EventMap events_; bool has_bound_; base::TimeDelta bound_; }; // Fixed size storage to store event times for recent frames. BoundCalculator upper_bound_; BoundCalculator lower_bound_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(ReceiverTimeOffsetEstimatorImpl); }; } // namespace cast } // namespace media #endif // MEDIA_CAST_LOGGING_RECEIVER_TIME_OFFSET_ESTIMATOR_IMPL_H_