Home | History | Annotate | Download | only in logging
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <algorithm>
      6 #include <utility>
      7 
      8 #include "base/logging.h"
      9 #include "base/time/tick_clock.h"
     10 #include "media/cast/logging/receiver_time_offset_estimator_impl.h"
     11 
     12 namespace media {
     13 namespace cast {
     14 
     15 ReceiverTimeOffsetEstimatorImpl::BoundCalculator::BoundCalculator()
     16     : has_bound_(false) {}
     17 ReceiverTimeOffsetEstimatorImpl::BoundCalculator::~BoundCalculator() {}
     18 
     19 void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetSent(
     20     uint32 rtp,
     21     uint32 packet_id,
     22     bool audio,
     23     base::TimeTicks t) {
     24   uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) |
     25       static_cast<uint64>(audio);
     26   events_[key].first = t;
     27   CheckUpdate(key);
     28 }
     29 
     30 void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetReceived(
     31     uint32 rtp,
     32     uint16 packet_id,
     33     bool audio,
     34     base::TimeTicks t) {
     35   uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) |
     36       static_cast<uint64>(audio);
     37   events_[key].second = t;
     38   CheckUpdate(key);
     39 }
     40 
     41 void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::UpdateBound(
     42     base::TimeTicks sent, base::TimeTicks received) {
     43     base::TimeDelta delta = received - sent;
     44     if (has_bound_) {
     45       if (delta < bound_) {
     46         bound_ = delta;
     47       } else {
     48         bound_ += (delta - bound_) / kClockDriftSpeed;
     49       }
     50     } else {
     51       bound_ = delta;
     52     }
     53     has_bound_ = true;
     54   }
     55 
     56 void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::CheckUpdate(
     57     uint64 key) {
     58   const TimeTickPair& ticks = events_[key];
     59   if (!ticks.first.is_null() && !ticks.second.is_null()) {
     60     UpdateBound(ticks.first, ticks.second);
     61     events_.erase(key);
     62     return;
     63   }
     64 
     65   if (events_.size() > kMaxEventTimesMapSize) {
     66     EventMap::iterator i = ModMapOldest(&events_);
     67     if (i != events_.end()) {
     68       events_.erase(i);
     69     }
     70   }
     71 }
     72 
     73 ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl() {
     74 }
     75 
     76 ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() {
     77   DCHECK(thread_checker_.CalledOnValidThread());
     78 }
     79 
     80 
     81 void ReceiverTimeOffsetEstimatorImpl::OnReceiveFrameEvent(
     82     const FrameEvent& frame_event) {
     83   DCHECK(thread_checker_.CalledOnValidThread());
     84   switch (frame_event.type) {
     85     case FRAME_ACK_SENT:
     86       lower_bound_.SetSent(frame_event.rtp_timestamp,
     87                            0,
     88                            frame_event.media_type == AUDIO_EVENT,
     89                            frame_event.timestamp);
     90       break;
     91     case FRAME_ACK_RECEIVED:
     92       lower_bound_.SetReceived(frame_event.rtp_timestamp,
     93                                0,
     94                                frame_event.media_type == AUDIO_EVENT,
     95                                frame_event.timestamp);
     96       break;
     97     default:
     98       // Ignored
     99       break;
    100   }
    101 }
    102 
    103 bool ReceiverTimeOffsetEstimatorImpl::GetReceiverOffsetBounds(
    104     base::TimeDelta* lower_bound,
    105     base::TimeDelta* upper_bound) {
    106   if (!lower_bound_.has_bound() || !upper_bound_.has_bound())
    107     return false;
    108 
    109   *lower_bound = -lower_bound_.bound();
    110   *upper_bound = upper_bound_.bound();
    111 
    112   // Sanitize the output, we don't want the upper bound to be
    113   // lower than the lower bound, make them the same.
    114   if (upper_bound < lower_bound) {
    115     lower_bound += (lower_bound - upper_bound) / 2;
    116     upper_bound = lower_bound;
    117   }
    118   return true;
    119 }
    120 
    121 void ReceiverTimeOffsetEstimatorImpl::OnReceivePacketEvent(
    122     const PacketEvent& packet_event) {
    123   DCHECK(thread_checker_.CalledOnValidThread());
    124   switch (packet_event.type) {
    125     case PACKET_SENT_TO_NETWORK:
    126       upper_bound_.SetSent(packet_event.rtp_timestamp,
    127                            packet_event.packet_id,
    128                            packet_event.media_type == AUDIO_EVENT,
    129                            packet_event.timestamp);
    130       break;
    131     case PACKET_RECEIVED:
    132       upper_bound_.SetReceived(packet_event.rtp_timestamp,
    133                                packet_event.packet_id,
    134                                packet_event.media_type == AUDIO_EVENT,
    135                                packet_event.timestamp);
    136       break;
    137     default:
    138       // Ignored
    139       break;
    140   }
    141 }
    142 
    143 
    144 }  // namespace cast
    145 }  // namespace media
    146