OLD | NEW |
---|---|
(Empty) | |
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 <utility> | |
6 | |
7 #include "base/logging.h" | |
8 #include "media/cast/logging/receiver_time_offset_estimator_impl.h" | |
9 | |
10 namespace media { | |
11 namespace cast { | |
12 | |
13 // This should be large enough so that we can collect all 3 events before | |
14 // the entry gets removed from the map. | |
15 const size_t kMaxEventTimesMapSize = 100; | |
16 | |
17 ReceiverTimeOffsetEstimatorImpl::ReceiverTimeOffsetEstimatorImpl() | |
18 : bounded_(false) {} | |
19 | |
20 ReceiverTimeOffsetEstimatorImpl::~ReceiverTimeOffsetEstimatorImpl() { | |
21 DCHECK(thread_checker_.CalledOnValidThread()); | |
22 } | |
23 | |
24 void ReceiverTimeOffsetEstimatorImpl::OnReceiveFrameEvent( | |
25 const FrameEvent& frame_event) { | |
26 DCHECK(thread_checker_.CalledOnValidThread()); | |
27 CastLoggingEvent event = frame_event.type; | |
28 if (event != kVideoFrameEncoded && event != kVideoAckSent && | |
29 event != kVideoAckReceived) | |
30 return; | |
31 | |
32 EventTimesMap::iterator it = event_times_map_.find(frame_event.rtp_timestamp); | |
33 if (it == event_times_map_.end()) { | |
34 EventTimes event_times; | |
35 it = event_times_map_.insert(std::make_pair(frame_event.rtp_timestamp, | |
36 event_times)).first; | |
37 } | |
38 switch (event) { | |
39 case kVideoFrameEncoded: | |
40 // Encode is supposed to happen only once. If we see duplicate event, | |
41 // throw away the entry. | |
42 if (it->second.event_a_time.is_null()) { | |
43 it->second.event_a_time = frame_event.timestamp; | |
44 } else { | |
45 event_times_map_.erase(it); | |
46 return; | |
47 } | |
48 break; | |
49 case kVideoAckSent: | |
50 if (it->second.event_b_time.is_null()) { | |
51 it->second.event_b_time = frame_event.timestamp; | |
52 } else if (it->second.event_b_time != frame_event.timestamp) { | |
53 // Duplicate ack sent events are normal due to RTCP redundancy, | |
54 // but they must have the same event timestamp. | |
55 event_times_map_.erase(it); | |
56 return; | |
57 } | |
58 break; | |
59 case kVideoAckReceived: | |
60 // If there are duplicate ack received events, pick the one with the | |
61 // smallest event timestamp so we can get a better bound. | |
62 if (it->second.event_c_time.is_null()) { | |
63 it->second.event_c_time = frame_event.timestamp; | |
64 } else { | |
65 it->second.event_c_time = | |
66 std::min(frame_event.timestamp, it->second.event_c_time); | |
67 } | |
68 break; | |
69 default: | |
70 NOTREACHED(); | |
71 } | |
72 | |
73 if (!it->second.event_a_time.is_null() && | |
74 !it->second.event_b_time.is_null() && | |
75 !it->second.event_c_time.is_null()) { | |
76 UpdateOffsetBounds(it->second); | |
77 event_times_map_.erase(it); | |
78 } | |
79 | |
80 // Keep the map size at most |kMaxEventTimesMapSize|. | |
81 if (event_times_map_.size() > kMaxEventTimesMapSize) | |
82 event_times_map_.erase(event_times_map_.begin()); | |
83 } | |
84 | |
85 bool ReceiverTimeOffsetEstimatorImpl::GetReceiverOffsetBounds( | |
86 base::TimeDelta* lower_bound, | |
87 base::TimeDelta* upper_bound) { | |
88 if (!bounded_) | |
89 return false; | |
90 | |
91 *lower_bound = offset_lower_bound_; | |
92 *upper_bound = offset_upper_bound_; | |
93 return true; | |
94 } | |
95 | |
96 void ReceiverTimeOffsetEstimatorImpl::OnReceivePacketEvent( | |
miu
2014/04/17 02:14:14
Seems like RawEventSubscriber should not declare a
imcheng
2014/04/17 19:19:06
That's a good idea.I will do that in a follow up C
| |
97 const PacketEvent& packet_event) { | |
98 // Not interested in packet events. | |
99 DCHECK(thread_checker_.CalledOnValidThread()); | |
100 } | |
101 | |
102 void ReceiverTimeOffsetEstimatorImpl::OnReceiveGenericEvent( | |
103 const GenericEvent& generic_event) { | |
104 // Not interested in generic events. | |
105 DCHECK(thread_checker_.CalledOnValidThread()); | |
106 } | |
107 | |
108 void ReceiverTimeOffsetEstimatorImpl::UpdateOffsetBounds( | |
109 const EventTimes& event) { | |
110 base::TimeDelta lower_bound = event.event_b_time - event.event_c_time; | |
111 base::TimeDelta upper_bound = event.event_b_time - event.event_a_time; | |
112 | |
113 if (bounded_) { | |
114 lower_bound = std::max(lower_bound, offset_lower_bound_); | |
115 upper_bound = std::min(upper_bound, offset_upper_bound_); | |
116 } | |
117 | |
118 if (lower_bound > upper_bound) { | |
119 VLOG(2) << "Got bogus offset bound values [" << lower_bound.InMilliseconds() | |
miu
2014/04/17 02:14:14
Not sure, but maybe you should add a NOTREACHED()
imcheng
2014/04/17 19:19:06
I don't really trust these values completely. Sinc
| |
120 << ", " << upper_bound.InMilliseconds() << "]."; | |
121 return; | |
122 } | |
123 | |
124 offset_lower_bound_ = lower_bound; | |
125 offset_upper_bound_ = upper_bound; | |
126 bounded_ = true; | |
127 } | |
128 | |
129 } // namespace cast | |
130 } // namespace media | |
OLD | NEW |