OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/logging/stats_event_subscriber.h" | 5 #include "media/cast/logging/stats_event_subscriber.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 | 9 |
10 #define STAT_ENUM_TO_STRING(enum) \ | 10 #define STAT_ENUM_TO_STRING(enum) \ |
11 case enum: \ | 11 case enum: \ |
12 return #enum | 12 return #enum |
13 | 13 |
14 namespace media { | 14 namespace media { |
15 namespace cast { | 15 namespace cast { |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 using media::cast::CastLoggingEvent; | 19 using media::cast::CastLoggingEvent; |
20 using media::cast::EventMediaType; | 20 using media::cast::EventMediaType; |
21 | 21 |
22 const size_t kMaxFrameEventTimeMapSize = 100; | 22 const size_t kMaxFrameEventTimeMapSize = 100; |
23 const size_t kMaxPacketEventTimeMapSize = 1000; | 23 const size_t kMaxPacketEventTimeMapSize = 1000; |
24 | 24 |
25 CastLoggingEvent GetCapturedEvent(EventMediaType media_type) { | |
26 return media_type == AUDIO_EVENT ? | |
27 kAudioFrameCaptureBegin : kVideoFrameCaptureBegin; | |
28 } | |
29 | |
30 CastLoggingEvent GetEncodedEvent(EventMediaType media_type) { | |
31 return media_type == AUDIO_EVENT ? kAudioFrameEncoded : kVideoFrameEncoded; | |
32 } | |
33 | |
34 CastLoggingEvent GetDecodedEvent(EventMediaType media_type) { | |
35 return media_type == AUDIO_EVENT ? kAudioFrameDecoded : kVideoFrameDecoded; | |
36 } | |
37 | |
38 CastLoggingEvent GetPlayoutEvent(EventMediaType media_type) { | |
39 return media_type == AUDIO_EVENT ? kAudioPlayoutDelay : kVideoRenderDelay; | |
40 } | |
41 | |
42 CastLoggingEvent GetPacketSentEvent(EventMediaType media_type) { | |
43 return media_type == AUDIO_EVENT ? kAudioPacketSentToNetwork : | |
44 kVideoPacketSentToNetwork; | |
45 } | |
46 | |
47 CastLoggingEvent GetPacketReceivedEvent(EventMediaType media_type) { | |
48 return media_type == AUDIO_EVENT ? kAudioPacketReceived : | |
49 kVideoPacketReceived; | |
50 } | |
51 | |
52 CastLoggingEvent GetPacketRetransmittedEvent(EventMediaType media_type) { | |
53 return media_type == AUDIO_EVENT ? kAudioPacketRetransmitted : | |
54 kVideoPacketRetransmitted; | |
55 } | |
56 | |
57 bool IsReceiverEvent(CastLoggingEvent event) { | 25 bool IsReceiverEvent(CastLoggingEvent event) { |
58 return event == kAudioFrameDecoded | 26 return event == FRAME_DECODED |
59 || event == kVideoFrameDecoded | 27 || event == FRAME_PLAYOUT |
60 || event == kAudioPlayoutDelay | 28 || event == FRAME_ACK_SENT |
61 || event == kVideoRenderDelay | 29 || event == PACKET_RECEIVED; |
62 || event == kAudioAckSent | |
63 || event == kVideoAckSent | |
64 || event == kAudioPacketReceived | |
65 || event == kVideoPacketReceived | |
66 || event == kDuplicateAudioPacketReceived | |
67 || event == kDuplicateVideoPacketReceived; | |
68 } | 30 } |
69 | 31 |
70 } // namespace | 32 } // namespace |
71 | 33 |
72 StatsEventSubscriber::StatsEventSubscriber( | 34 StatsEventSubscriber::StatsEventSubscriber( |
73 EventMediaType event_media_type, | 35 EventMediaType event_media_type, |
74 base::TickClock* clock, | 36 base::TickClock* clock, |
75 ReceiverTimeOffsetEstimator* offset_estimator) | 37 ReceiverTimeOffsetEstimator* offset_estimator) |
76 : event_media_type_(event_media_type), | 38 : event_media_type_(event_media_type), |
77 clock_(clock), | 39 clock_(clock), |
78 offset_estimator_(offset_estimator), | 40 offset_estimator_(offset_estimator), |
79 network_latency_datapoints_(0), | 41 network_latency_datapoints_(0), |
80 e2e_latency_datapoints_(0) { | 42 e2e_latency_datapoints_(0) { |
81 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT); | 43 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT); |
82 base::TimeTicks now = clock_->NowTicks(); | 44 base::TimeTicks now = clock_->NowTicks(); |
83 start_time_ = now; | 45 start_time_ = now; |
84 last_response_received_time_ = base::TimeTicks(); | 46 last_response_received_time_ = base::TimeTicks(); |
85 } | 47 } |
86 | 48 |
87 StatsEventSubscriber::~StatsEventSubscriber() { | 49 StatsEventSubscriber::~StatsEventSubscriber() { |
88 DCHECK(thread_checker_.CalledOnValidThread()); | 50 DCHECK(thread_checker_.CalledOnValidThread()); |
89 } | 51 } |
90 | 52 |
91 void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) { | 53 void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) { |
92 DCHECK(thread_checker_.CalledOnValidThread()); | 54 DCHECK(thread_checker_.CalledOnValidThread()); |
93 | 55 |
94 CastLoggingEvent type = frame_event.type; | 56 CastLoggingEvent type = frame_event.type; |
95 if (GetEventMediaType(type) != event_media_type_) | 57 if (frame_event.media_type != event_media_type_) |
96 return; | 58 return; |
97 | 59 |
98 FrameStatsMap::iterator it = frame_stats_.find(type); | 60 FrameStatsMap::iterator it = frame_stats_.find(type); |
99 if (it == frame_stats_.end()) { | 61 if (it == frame_stats_.end()) { |
100 FrameLogStats stats; | 62 FrameLogStats stats; |
101 stats.event_counter = 1; | 63 stats.event_counter = 1; |
102 stats.sum_size = frame_event.size; | 64 stats.sum_size = frame_event.size; |
103 stats.sum_delay = frame_event.delay_delta; | 65 stats.sum_delay = frame_event.delay_delta; |
104 frame_stats_.insert(std::make_pair(type, stats)); | 66 frame_stats_.insert(std::make_pair(type, stats)); |
105 } else { | 67 } else { |
106 ++(it->second.event_counter); | 68 ++(it->second.event_counter); |
107 it->second.sum_size += frame_event.size; | 69 it->second.sum_size += frame_event.size; |
108 it->second.sum_delay += frame_event.delay_delta; | 70 it->second.sum_delay += frame_event.delay_delta; |
109 } | 71 } |
110 | 72 |
111 if (type == GetCapturedEvent(event_media_type_)) { | 73 if (type == FRAME_CAPTURE_BEGIN) { |
112 RecordFrameCapturedTime(frame_event); | 74 RecordFrameCapturedTime(frame_event); |
113 } else if (type == GetPlayoutEvent(event_media_type_)) { | 75 } else if (type == FRAME_PLAYOUT) { |
114 RecordE2ELatency(frame_event); | 76 RecordE2ELatency(frame_event); |
115 } | 77 } |
116 | 78 |
117 if (IsReceiverEvent(type)) | 79 if (IsReceiverEvent(type)) |
118 UpdateLastResponseTime(frame_event.timestamp); | 80 UpdateLastResponseTime(frame_event.timestamp); |
119 } | 81 } |
120 | 82 |
121 void StatsEventSubscriber::OnReceivePacketEvent( | 83 void StatsEventSubscriber::OnReceivePacketEvent( |
122 const PacketEvent& packet_event) { | 84 const PacketEvent& packet_event) { |
123 DCHECK(thread_checker_.CalledOnValidThread()); | 85 DCHECK(thread_checker_.CalledOnValidThread()); |
124 | 86 |
125 CastLoggingEvent type = packet_event.type; | 87 CastLoggingEvent type = packet_event.type; |
126 if (GetEventMediaType(type) != event_media_type_) | 88 if (packet_event.media_type != event_media_type_) |
127 return; | 89 return; |
128 | 90 |
129 PacketStatsMap::iterator it = packet_stats_.find(type); | 91 PacketStatsMap::iterator it = packet_stats_.find(type); |
130 if (it == packet_stats_.end()) { | 92 if (it == packet_stats_.end()) { |
131 PacketLogStats stats; | 93 PacketLogStats stats; |
132 stats.event_counter = 1; | 94 stats.event_counter = 1; |
133 stats.sum_size = packet_event.size; | 95 stats.sum_size = packet_event.size; |
134 packet_stats_.insert(std::make_pair(type, stats)); | 96 packet_stats_.insert(std::make_pair(type, stats)); |
135 } else { | 97 } else { |
136 ++(it->second.event_counter); | 98 ++(it->second.event_counter); |
137 it->second.sum_size += packet_event.size; | 99 it->second.sum_size += packet_event.size; |
138 } | 100 } |
139 | 101 |
140 if (type == GetPacketSentEvent(event_media_type_) || | 102 if (type == PACKET_SENT_TO_NETWORK || |
141 type == GetPacketReceivedEvent(event_media_type_)) { | 103 type == PACKET_RECEIVED) { |
142 RecordNetworkLatency(packet_event); | 104 RecordNetworkLatency(packet_event); |
143 } else if (type == GetPacketRetransmittedEvent(event_media_type_)) { | 105 } else if (type == PACKET_RETRANSMITTED) { |
144 // We only measure network latency using packets that doesn't have to be | 106 // We only measure network latency using packets that doesn't have to be |
145 // retransmitted as there is precisely one sent-receive timestamp pairs. | 107 // retransmitted as there is precisely one sent-receive timestamp pairs. |
146 ErasePacketSentTime(packet_event); | 108 ErasePacketSentTime(packet_event); |
147 } | 109 } |
148 | 110 |
149 if (IsReceiverEvent(type)) | 111 if (IsReceiverEvent(type)) |
150 UpdateLastResponseTime(packet_event.timestamp); | 112 UpdateLastResponseTime(packet_event.timestamp); |
151 } | 113 } |
152 | 114 |
153 scoped_ptr<base::DictionaryValue> StatsEventSubscriber::GetStats() const { | 115 scoped_ptr<base::DictionaryValue> StatsEventSubscriber::GetStats() const { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 } | 165 } |
204 | 166 |
205 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const { | 167 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const { |
206 DCHECK(thread_checker_.CalledOnValidThread()); | 168 DCHECK(thread_checker_.CalledOnValidThread()); |
207 | 169 |
208 stats_map->clear(); | 170 stats_map->clear(); |
209 | 171 |
210 base::TimeTicks end_time = clock_->NowTicks(); | 172 base::TimeTicks end_time = clock_->NowTicks(); |
211 | 173 |
212 PopulateFpsStat( | 174 PopulateFpsStat( |
213 end_time, GetCapturedEvent(event_media_type_), CAPTURE_FPS, stats_map); | 175 end_time, FRAME_CAPTURE_BEGIN, CAPTURE_FPS, stats_map); |
214 PopulateFpsStat( | 176 PopulateFpsStat( |
215 end_time, GetEncodedEvent(event_media_type_), ENCODE_FPS, stats_map); | 177 end_time, FRAME_ENCODED, ENCODE_FPS, stats_map); |
216 PopulateFpsStat( | 178 PopulateFpsStat( |
217 end_time, GetDecodedEvent(event_media_type_), DECODE_FPS, stats_map); | 179 end_time, FRAME_DECODED, DECODE_FPS, stats_map); |
218 PopulatePlayoutDelayStat(stats_map); | 180 PopulatePlayoutDelayStat(stats_map); |
219 PopulateFrameBitrateStat(end_time, stats_map); | 181 PopulateFrameBitrateStat(end_time, stats_map); |
220 PopulatePacketBitrateStat(end_time, | 182 PopulatePacketBitrateStat(end_time, |
221 GetPacketSentEvent(event_media_type_), | 183 PACKET_SENT_TO_NETWORK, |
222 TRANSMISSION_KBPS, | 184 TRANSMISSION_KBPS, |
223 stats_map); | 185 stats_map); |
224 PopulatePacketBitrateStat(end_time, | 186 PopulatePacketBitrateStat(end_time, |
225 GetPacketRetransmittedEvent(event_media_type_), | 187 PACKET_RETRANSMITTED, |
226 RETRANSMISSION_KBPS, | 188 RETRANSMISSION_KBPS, |
227 stats_map); | 189 stats_map); |
228 PopulatePacketLossPercentageStat(stats_map); | 190 PopulatePacketLossPercentageStat(stats_map); |
229 | 191 |
230 if (network_latency_datapoints_ > 0) { | 192 if (network_latency_datapoints_ > 0) { |
231 double avg_network_latency_ms = | 193 double avg_network_latency_ms = |
232 total_network_latency_.InMillisecondsF() / | 194 total_network_latency_.InMillisecondsF() / |
233 network_latency_datapoints_; | 195 network_latency_datapoints_; |
234 stats_map->insert( | 196 stats_map->insert( |
235 std::make_pair(AVG_NETWORK_LATENCY_MS, avg_network_latency_ms)); | 197 std::make_pair(AVG_NETWORK_LATENCY_MS, avg_network_latency_ms)); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 std::make_pair(packet_event.timestamp, packet_event.type); | 279 std::make_pair(packet_event.timestamp, packet_event.type); |
318 packet_sent_times_.insert(std::make_pair(key, value)); | 280 packet_sent_times_.insert(std::make_pair(key, value)); |
319 if (packet_sent_times_.size() > kMaxPacketEventTimeMapSize) | 281 if (packet_sent_times_.size() > kMaxPacketEventTimeMapSize) |
320 packet_sent_times_.erase(packet_sent_times_.begin()); | 282 packet_sent_times_.erase(packet_sent_times_.begin()); |
321 } else { | 283 } else { |
322 std::pair<base::TimeTicks, CastLoggingEvent> value = it->second; | 284 std::pair<base::TimeTicks, CastLoggingEvent> value = it->second; |
323 CastLoggingEvent recorded_type = value.second; | 285 CastLoggingEvent recorded_type = value.second; |
324 bool match = false; | 286 bool match = false; |
325 base::TimeTicks packet_sent_time; | 287 base::TimeTicks packet_sent_time; |
326 base::TimeTicks packet_received_time; | 288 base::TimeTicks packet_received_time; |
327 if (recorded_type == GetPacketSentEvent(event_media_type_) && | 289 if (recorded_type == PACKET_SENT_TO_NETWORK && |
328 packet_event.type == GetPacketReceivedEvent(event_media_type_)) { | 290 packet_event.type == PACKET_RECEIVED) { |
329 packet_sent_time = value.first; | 291 packet_sent_time = value.first; |
330 packet_received_time = packet_event.timestamp; | 292 packet_received_time = packet_event.timestamp; |
331 match = true; | 293 match = true; |
332 } else if (recorded_type == GetPacketReceivedEvent(event_media_type_) && | 294 } else if (recorded_type == PACKET_RECEIVED && |
333 packet_event.type == GetPacketSentEvent(event_media_type_)) { | 295 packet_event.type == PACKET_SENT_TO_NETWORK) { |
334 packet_sent_time = packet_event.timestamp; | 296 packet_sent_time = packet_event.timestamp; |
335 packet_received_time = value.first; | 297 packet_received_time = value.first; |
336 match = true; | 298 match = true; |
337 } | 299 } |
338 if (match) { | 300 if (match) { |
339 // Subtract by offset. | 301 // Subtract by offset. |
340 packet_received_time -= receiver_offset; | 302 packet_received_time -= receiver_offset; |
341 | 303 |
342 total_network_latency_ += packet_received_time - packet_sent_time; | 304 total_network_latency_ += packet_received_time - packet_sent_time; |
343 network_latency_datapoints_++; | 305 network_latency_datapoints_++; |
(...skipping 11 matching lines...) Expand all Loading... |
355 double fps = 0.0; | 317 double fps = 0.0; |
356 base::TimeDelta duration = (end_time - start_time_); | 318 base::TimeDelta duration = (end_time - start_time_); |
357 int count = it->second.event_counter; | 319 int count = it->second.event_counter; |
358 if (duration > base::TimeDelta()) | 320 if (duration > base::TimeDelta()) |
359 fps = count / duration.InSecondsF(); | 321 fps = count / duration.InSecondsF(); |
360 stats_map->insert(std::make_pair(stat, fps)); | 322 stats_map->insert(std::make_pair(stat, fps)); |
361 } | 323 } |
362 } | 324 } |
363 | 325 |
364 void StatsEventSubscriber::PopulatePlayoutDelayStat(StatsMap* stats_map) const { | 326 void StatsEventSubscriber::PopulatePlayoutDelayStat(StatsMap* stats_map) const { |
365 CastLoggingEvent event = GetPlayoutEvent(event_media_type_); | 327 FrameStatsMap::const_iterator it = frame_stats_.find(FRAME_PLAYOUT); |
366 FrameStatsMap::const_iterator it = frame_stats_.find(event); | |
367 if (it != frame_stats_.end()) { | 328 if (it != frame_stats_.end()) { |
368 double avg_delay_ms = 0.0; | 329 double avg_delay_ms = 0.0; |
369 base::TimeDelta sum_delay = it->second.sum_delay; | 330 base::TimeDelta sum_delay = it->second.sum_delay; |
370 int count = it->second.event_counter; | 331 int count = it->second.event_counter; |
371 if (count != 0) | 332 if (count != 0) |
372 avg_delay_ms = sum_delay.InMillisecondsF() / count; | 333 avg_delay_ms = sum_delay.InMillisecondsF() / count; |
373 stats_map->insert(std::make_pair(AVG_PLAYOUT_DELAY_MS, avg_delay_ms)); | 334 stats_map->insert(std::make_pair(AVG_PLAYOUT_DELAY_MS, avg_delay_ms)); |
374 } | 335 } |
375 } | 336 } |
376 | 337 |
377 void StatsEventSubscriber::PopulateFrameBitrateStat(base::TimeTicks end_time, | 338 void StatsEventSubscriber::PopulateFrameBitrateStat(base::TimeTicks end_time, |
378 StatsMap* stats_map) const { | 339 StatsMap* stats_map) const { |
379 CastLoggingEvent event = GetEncodedEvent(event_media_type_); | 340 FrameStatsMap::const_iterator it = frame_stats_.find(FRAME_ENCODED); |
380 FrameStatsMap::const_iterator it = frame_stats_.find(event); | |
381 if (it != frame_stats_.end()) { | 341 if (it != frame_stats_.end()) { |
382 double kbps = 0.0; | 342 double kbps = 0.0; |
383 base::TimeDelta duration = end_time - start_time_; | 343 base::TimeDelta duration = end_time - start_time_; |
384 if (duration > base::TimeDelta()) { | 344 if (duration > base::TimeDelta()) { |
385 kbps = it->second.sum_size / duration.InMillisecondsF() * 8; | 345 kbps = it->second.sum_size / duration.InMillisecondsF() * 8; |
386 } | 346 } |
387 | 347 |
388 stats_map->insert(std::make_pair(ENCODE_KBPS, kbps)); | 348 stats_map->insert(std::make_pair(ENCODE_KBPS, kbps)); |
389 } | 349 } |
390 } | 350 } |
(...skipping 14 matching lines...) Expand all Loading... |
405 stats_map->insert(std::make_pair(stat, kbps)); | 365 stats_map->insert(std::make_pair(stat, kbps)); |
406 } | 366 } |
407 } | 367 } |
408 | 368 |
409 void StatsEventSubscriber::PopulatePacketLossPercentageStat( | 369 void StatsEventSubscriber::PopulatePacketLossPercentageStat( |
410 StatsMap* stats_map) const { | 370 StatsMap* stats_map) const { |
411 // We assume that retransmission means that the packet's previous | 371 // We assume that retransmission means that the packet's previous |
412 // (re)transmission was lost. | 372 // (re)transmission was lost. |
413 // This means the percentage of packet loss is | 373 // This means the percentage of packet loss is |
414 // (# of retransmit events) / (# of transmit + retransmit events). | 374 // (# of retransmit events) / (# of transmit + retransmit events). |
415 CastLoggingEvent packet_sent_event = GetPacketSentEvent(event_media_type_); | |
416 CastLoggingEvent packet_retransmitted_event = | |
417 GetPacketRetransmittedEvent(event_media_type_); | |
418 PacketStatsMap::const_iterator sent_it = | 375 PacketStatsMap::const_iterator sent_it = |
419 packet_stats_.find(packet_sent_event); | 376 packet_stats_.find(PACKET_SENT_TO_NETWORK); |
420 if (sent_it == packet_stats_.end()) | 377 if (sent_it == packet_stats_.end()) |
421 return; | 378 return; |
422 PacketStatsMap::const_iterator retransmitted_it = | 379 PacketStatsMap::const_iterator retransmitted_it = |
423 packet_stats_.find(packet_retransmitted_event); | 380 packet_stats_.find(PACKET_RETRANSMITTED); |
424 int sent_count = sent_it->second.event_counter; | 381 int sent_count = sent_it->second.event_counter; |
425 int retransmitted_count = 0; | 382 int retransmitted_count = 0; |
426 if (retransmitted_it != packet_stats_.end()) | 383 if (retransmitted_it != packet_stats_.end()) |
427 retransmitted_count = retransmitted_it->second.event_counter; | 384 retransmitted_count = retransmitted_it->second.event_counter; |
428 double packet_loss_fraction = static_cast<double>(retransmitted_count) / | 385 double packet_loss_fraction = static_cast<double>(retransmitted_count) / |
429 (sent_count + retransmitted_count); | 386 (sent_count + retransmitted_count); |
430 stats_map->insert( | 387 stats_map->insert( |
431 std::make_pair(PACKET_LOSS_FRACTION, packet_loss_fraction)); | 388 std::make_pair(PACKET_LOSS_FRACTION, packet_loss_fraction)); |
432 } | 389 } |
433 | 390 |
434 StatsEventSubscriber::FrameLogStats::FrameLogStats() | 391 StatsEventSubscriber::FrameLogStats::FrameLogStats() |
435 : event_counter(0), sum_size(0) {} | 392 : event_counter(0), sum_size(0) {} |
436 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {} | 393 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {} |
437 | 394 |
438 StatsEventSubscriber::PacketLogStats::PacketLogStats() | 395 StatsEventSubscriber::PacketLogStats::PacketLogStats() |
439 : event_counter(0), sum_size(0) {} | 396 : event_counter(0), sum_size(0) {} |
440 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {} | 397 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {} |
441 | 398 |
442 } // namespace cast | 399 } // namespace cast |
443 } // namespace media | 400 } // namespace media |
OLD | NEW |