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.
8 #include "base/logging.h"
9 #include "media/cast/logging/receiver_time_offset_estimator_impl.h"
14 // This should be large enough so that we can collect all 3 events before
15 // the entry gets removed from the map.
16 const size_t kMaxEventTimesMapSize
= 100;
18 ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl()
21 ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() {
22 DCHECK(thread_checker_
.CalledOnValidThread());
25 void ReceiverTimeOffsetEstimatorImpl::OnReceiveFrameEvent(
26 const FrameEvent
& frame_event
) {
27 DCHECK(thread_checker_
.CalledOnValidThread());
28 CastLoggingEvent event
= frame_event
.type
;
29 if (event
!= kVideoFrameEncoded
&& event
!= kVideoAckSent
&&
30 event
!= kVideoAckReceived
)
33 EventTimesMap::iterator it
= event_times_map_
.find(frame_event
.rtp_timestamp
);
34 if (it
== event_times_map_
.end()) {
35 EventTimes event_times
;
36 it
= event_times_map_
.insert(std::make_pair(frame_event
.rtp_timestamp
,
40 case kVideoFrameEncoded
:
41 // Encode is supposed to happen only once. If we see duplicate event,
42 // throw away the entry.
43 if (it
->second
.event_a_time
.is_null()) {
44 it
->second
.event_a_time
= frame_event
.timestamp
;
46 event_times_map_
.erase(it
);
51 if (it
->second
.event_b_time
.is_null()) {
52 it
->second
.event_b_time
= frame_event
.timestamp
;
53 } else if (it
->second
.event_b_time
!= frame_event
.timestamp
) {
54 // Duplicate ack sent events are normal due to RTCP redundancy,
55 // but they must have the same event timestamp.
56 event_times_map_
.erase(it
);
60 case kVideoAckReceived
:
61 // If there are duplicate ack received events, pick the one with the
62 // smallest event timestamp so we can get a better bound.
63 if (it
->second
.event_c_time
.is_null()) {
64 it
->second
.event_c_time
= frame_event
.timestamp
;
66 it
->second
.event_c_time
=
67 std::min(frame_event
.timestamp
, it
->second
.event_c_time
);
74 if (!it
->second
.event_a_time
.is_null() &&
75 !it
->second
.event_b_time
.is_null() &&
76 !it
->second
.event_c_time
.is_null()) {
77 UpdateOffsetBounds(it
->second
);
78 event_times_map_
.erase(it
);
81 // Keep the map size at most |kMaxEventTimesMapSize|.
82 if (event_times_map_
.size() > kMaxEventTimesMapSize
)
83 event_times_map_
.erase(event_times_map_
.begin());
86 bool ReceiverTimeOffsetEstimatorImpl::GetReceiverOffsetBounds(
87 base::TimeDelta
* lower_bound
,
88 base::TimeDelta
* upper_bound
) {
92 *lower_bound
= offset_lower_bound_
;
93 *upper_bound
= offset_upper_bound_
;
97 void ReceiverTimeOffsetEstimatorImpl::OnReceivePacketEvent(
98 const PacketEvent
& packet_event
) {
99 // Not interested in packet events.
100 DCHECK(thread_checker_
.CalledOnValidThread());
103 void ReceiverTimeOffsetEstimatorImpl::UpdateOffsetBounds(
104 const EventTimes
& event
) {
105 base::TimeDelta lower_bound
= event
.event_b_time
- event
.event_c_time
;
106 base::TimeDelta upper_bound
= event
.event_b_time
- event
.event_a_time
;
109 lower_bound
= std::max(lower_bound
, offset_lower_bound_
);
110 upper_bound
= std::min(upper_bound
, offset_upper_bound_
);
113 if (lower_bound
> upper_bound
) {
114 VLOG(2) << "Got bogus offset bound values [" << lower_bound
.InMilliseconds()
115 << ", " << upper_bound
.InMilliseconds() << "].";
119 offset_lower_bound_
= lower_bound
;
120 offset_upper_bound_
= upper_bound
;