15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <utility> 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/time/tick_clock.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/cast/logging/receiver_time_offset_estimator_impl.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace media { 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace cast { 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ReceiverTimeOffsetEstimatorImpl::BoundCalculator::BoundCalculator() 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : has_bound_(false) {} 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ReceiverTimeOffsetEstimatorImpl::BoundCalculator::~BoundCalculator() {} 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetSent( 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 rtp, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 packet_id, 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool audio, 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::TimeTicks t) { 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) | 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<uint64>(audio); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) events_[key].first = t; 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CheckUpdate(key); 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::SetReceived( 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 rtp, 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint16 packet_id, 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool audio, 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::TimeTicks t) { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 key = (static_cast<uint64>(rtp) << 32) | (packet_id << 1) | 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<uint64>(audio); 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) events_[key].second = t; 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CheckUpdate(key); 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReceiverTimeOffsetEstimatorImpl::BoundCalculator::UpdateBound( 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 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 56void 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 73ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl() { 74} 75 76ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() { 77 DCHECK(thread_checker_.CalledOnValidThread()); 78} 79 80 81void 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 103bool 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 121void 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