Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / cast / logging / receiver_time_offset_estimator_impl.cc
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