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" |
| 9 |
| 10 #define STAT_ENUM_TO_STRING(enum) \ |
| 11 case enum: \ |
| 12 return #enum |
8 | 13 |
9 namespace media { | 14 namespace media { |
10 namespace cast { | 15 namespace cast { |
11 | 16 |
12 StatsEventSubscriber::StatsEventSubscriber(EventMediaType event_media_type) | 17 namespace { |
13 : event_media_type_(event_media_type) {} | 18 |
| 19 using media::cast::CastLoggingEvent; |
| 20 using media::cast::EventMediaType; |
| 21 |
| 22 const size_t kMaxFrameEventTimeMapSize = 100; |
| 23 const size_t kMaxPacketEventTimeMapSize = 1000; |
| 24 |
| 25 CastLoggingEvent GetCapturedEvent(EventMediaType media_type) { |
| 26 return media_type == AUDIO_EVENT ? kAudioFrameCaptured : kVideoFrameCaptured; |
| 27 } |
| 28 |
| 29 CastLoggingEvent GetEncodedEvent(EventMediaType media_type) { |
| 30 return media_type == AUDIO_EVENT ? kAudioFrameEncoded : kVideoFrameEncoded; |
| 31 } |
| 32 |
| 33 CastLoggingEvent GetDecodedEvent(EventMediaType media_type) { |
| 34 return media_type == AUDIO_EVENT ? kAudioFrameDecoded : kVideoFrameDecoded; |
| 35 } |
| 36 |
| 37 CastLoggingEvent GetPlayoutEvent(EventMediaType media_type) { |
| 38 return media_type == AUDIO_EVENT ? kAudioPlayoutDelay : kVideoRenderDelay; |
| 39 } |
| 40 |
| 41 CastLoggingEvent GetPacketSentEvent(EventMediaType media_type) { |
| 42 return media_type == AUDIO_EVENT ? kAudioPacketSentToNetwork : |
| 43 kVideoPacketSentToNetwork; |
| 44 } |
| 45 |
| 46 CastLoggingEvent GetPacketReceivedEvent(EventMediaType media_type) { |
| 47 return media_type == AUDIO_EVENT ? kAudioPacketReceived : |
| 48 kVideoPacketReceived; |
| 49 } |
| 50 |
| 51 CastLoggingEvent GetPacketRetransmittedEvent(EventMediaType media_type) { |
| 52 return media_type == AUDIO_EVENT ? kAudioPacketRetransmitted : |
| 53 kVideoPacketRetransmitted; |
| 54 } |
| 55 |
| 56 bool IsReceiverEvent(CastLoggingEvent event) { |
| 57 return event == kAudioFrameDecoded |
| 58 || event == kVideoFrameDecoded |
| 59 || event == kAudioPlayoutDelay |
| 60 || event == kVideoRenderDelay |
| 61 || event == kAudioAckSent |
| 62 || event == kVideoAckSent |
| 63 || event == kAudioPacketReceived |
| 64 || event == kVideoPacketReceived |
| 65 || event == kDuplicateAudioPacketReceived |
| 66 || event == kDuplicateVideoPacketReceived; |
| 67 } |
| 68 |
| 69 } // namespace |
| 70 |
| 71 StatsEventSubscriber::StatsEventSubscriber( |
| 72 EventMediaType event_media_type, |
| 73 base::TickClock* clock, |
| 74 ReceiverTimeOffsetEstimator* offset_estimator) |
| 75 : event_media_type_(event_media_type), |
| 76 clock_(clock), |
| 77 offset_estimator_(offset_estimator), |
| 78 network_latency_datapoints_(0), |
| 79 e2e_latency_datapoints_(0) { |
| 80 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT); |
| 81 base::TimeTicks now = clock_->NowTicks(); |
| 82 start_time_ = now; |
| 83 last_response_received_time_ = base::TimeTicks(); |
| 84 } |
14 | 85 |
15 StatsEventSubscriber::~StatsEventSubscriber() { | 86 StatsEventSubscriber::~StatsEventSubscriber() { |
16 DCHECK(thread_checker_.CalledOnValidThread()); | 87 DCHECK(thread_checker_.CalledOnValidThread()); |
17 } | 88 } |
18 | 89 |
19 void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) { | 90 void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) { |
20 DCHECK(thread_checker_.CalledOnValidThread()); | 91 DCHECK(thread_checker_.CalledOnValidThread()); |
21 | 92 |
22 CastLoggingEvent type = frame_event.type; | 93 CastLoggingEvent type = frame_event.type; |
23 if (GetEventMediaType(type) != event_media_type_) | 94 if (GetEventMediaType(type) != event_media_type_) |
24 return; | 95 return; |
25 | 96 |
26 FrameStatsMap::iterator it = frame_stats_.find(type); | 97 FrameStatsMap::iterator it = frame_stats_.find(type); |
27 if (it == frame_stats_.end()) { | 98 if (it == frame_stats_.end()) { |
28 FrameLogStats stats; | 99 FrameLogStats stats; |
29 stats.first_event_time = frame_event.timestamp; | |
30 stats.last_event_time = frame_event.timestamp; | |
31 stats.event_counter = 1; | 100 stats.event_counter = 1; |
32 stats.sum_size = frame_event.size; | 101 stats.sum_size = frame_event.size; |
33 stats.min_delay = frame_event.delay_delta; | |
34 stats.max_delay = frame_event.delay_delta; | |
35 stats.sum_delay = frame_event.delay_delta; | 102 stats.sum_delay = frame_event.delay_delta; |
36 frame_stats_.insert(std::make_pair(type, stats)); | 103 frame_stats_.insert(std::make_pair(type, stats)); |
37 } else { | 104 } else { |
38 ++(it->second.event_counter); | 105 ++(it->second.event_counter); |
39 it->second.last_event_time = frame_event.timestamp; | |
40 it->second.sum_size += frame_event.size; | 106 it->second.sum_size += frame_event.size; |
41 it->second.sum_delay += frame_event.delay_delta; | 107 it->second.sum_delay += frame_event.delay_delta; |
42 if (frame_event.delay_delta > it->second.max_delay) | |
43 it->second.max_delay = frame_event.delay_delta; | |
44 if (frame_event.delay_delta < it->second.min_delay) | |
45 it->second.min_delay = frame_event.delay_delta; | |
46 } | 108 } |
| 109 |
| 110 if (type == GetCapturedEvent(event_media_type_)) { |
| 111 RecordFrameCapturedTime(frame_event); |
| 112 } else if (type == GetPlayoutEvent(event_media_type_)) { |
| 113 RecordE2ELatency(frame_event); |
| 114 } |
| 115 |
| 116 if (IsReceiverEvent(type)) |
| 117 UpdateLastResponseTime(frame_event.timestamp); |
47 } | 118 } |
48 | 119 |
49 void StatsEventSubscriber::OnReceivePacketEvent( | 120 void StatsEventSubscriber::OnReceivePacketEvent( |
50 const PacketEvent& packet_event) { | 121 const PacketEvent& packet_event) { |
51 DCHECK(thread_checker_.CalledOnValidThread()); | 122 DCHECK(thread_checker_.CalledOnValidThread()); |
52 | 123 |
53 CastLoggingEvent type = packet_event.type; | 124 CastLoggingEvent type = packet_event.type; |
54 if (GetEventMediaType(type) != event_media_type_) | 125 if (GetEventMediaType(type) != event_media_type_) |
55 return; | 126 return; |
56 | 127 |
57 PacketStatsMap::iterator it = packet_stats_.find(type); | 128 PacketStatsMap::iterator it = packet_stats_.find(type); |
58 if (it == packet_stats_.end()) { | 129 if (it == packet_stats_.end()) { |
59 PacketLogStats stats; | 130 PacketLogStats stats; |
60 stats.first_event_time = packet_event.timestamp; | |
61 stats.last_event_time = packet_event.timestamp; | |
62 stats.event_counter = 1; | 131 stats.event_counter = 1; |
63 stats.sum_size = packet_event.size; | 132 stats.sum_size = packet_event.size; |
64 packet_stats_.insert(std::make_pair(type, stats)); | 133 packet_stats_.insert(std::make_pair(type, stats)); |
65 } else { | 134 } else { |
66 it->second.last_event_time = packet_event.timestamp; | |
67 ++(it->second.event_counter); | 135 ++(it->second.event_counter); |
68 it->second.sum_size += packet_event.size; | 136 it->second.sum_size += packet_event.size; |
69 } | 137 } |
| 138 |
| 139 if (type == GetPacketSentEvent(event_media_type_) || |
| 140 type == GetPacketReceivedEvent(event_media_type_)) { |
| 141 RecordNetworkLatency(packet_event); |
| 142 } else if (type == GetPacketRetransmittedEvent(event_media_type_)) { |
| 143 // We only measure network latency using packets that doesn't have to be |
| 144 // retransmitted as there is precisely one sent-receive timestamp pairs. |
| 145 ErasePacketSentTime(packet_event); |
| 146 } |
| 147 |
| 148 if (IsReceiverEvent(type)) |
| 149 UpdateLastResponseTime(packet_event.timestamp); |
70 } | 150 } |
71 | 151 |
72 void StatsEventSubscriber::GetFrameStats(FrameStatsMap* frame_stats_map) const { | 152 scoped_ptr<base::DictionaryValue> StatsEventSubscriber::GetStats() const { |
73 DCHECK(thread_checker_.CalledOnValidThread()); | 153 StatsMap stats_map; |
74 DCHECK(frame_stats_map); | 154 GetStatsInternal(&stats_map); |
| 155 scoped_ptr<base::DictionaryValue> ret(new base::DictionaryValue); |
75 | 156 |
76 frame_stats_map->clear(); | 157 scoped_ptr<base::DictionaryValue> stats(new base::DictionaryValue); |
77 frame_stats_map->insert(frame_stats_.begin(), frame_stats_.end()); | 158 for (StatsMap::const_iterator it = stats_map.begin(); it != stats_map.end(); |
78 } | 159 ++it) { |
| 160 stats->SetDouble(CastStatToString(it->first), it->second); |
| 161 } |
79 | 162 |
80 void StatsEventSubscriber::GetPacketStats( | 163 ret->Set(event_media_type_ == AUDIO_EVENT ? "audio" : "video", |
81 PacketStatsMap* packet_stats_map) const { | 164 stats.release()); |
82 DCHECK(thread_checker_.CalledOnValidThread()); | |
83 DCHECK(packet_stats_map); | |
84 | 165 |
85 packet_stats_map->clear(); | 166 return ret.Pass(); |
86 packet_stats_map->insert(packet_stats_.begin(), packet_stats_.end()); | |
87 } | 167 } |
88 | 168 |
89 void StatsEventSubscriber::Reset() { | 169 void StatsEventSubscriber::Reset() { |
90 DCHECK(thread_checker_.CalledOnValidThread()); | 170 DCHECK(thread_checker_.CalledOnValidThread()); |
91 | 171 |
92 frame_stats_.clear(); | 172 frame_stats_.clear(); |
93 packet_stats_.clear(); | 173 packet_stats_.clear(); |
94 } | 174 total_network_latency_ = base::TimeDelta(); |
| 175 network_latency_datapoints_ = 0; |
| 176 total_e2e_latency_ = base::TimeDelta(); |
| 177 e2e_latency_datapoints_ = 0; |
| 178 frame_captured_times_.clear(); |
| 179 packet_sent_times_.clear(); |
| 180 start_time_ = clock_->NowTicks(); |
| 181 last_response_received_time_ = base::TimeTicks(); |
| 182 } |
| 183 |
| 184 // static |
| 185 const char* StatsEventSubscriber::CastStatToString(CastStat stat) { |
| 186 switch (stat) { |
| 187 STAT_ENUM_TO_STRING(CAPTURE_FPS); |
| 188 STAT_ENUM_TO_STRING(ENCODE_FPS); |
| 189 STAT_ENUM_TO_STRING(DECODE_FPS); |
| 190 STAT_ENUM_TO_STRING(AVG_ENCODE_TIME_MS); |
| 191 STAT_ENUM_TO_STRING(AVG_PLAYOUT_DELAY_MS); |
| 192 STAT_ENUM_TO_STRING(AVG_NETWORK_LATENCY_MS); |
| 193 STAT_ENUM_TO_STRING(AVG_E2E_LATENCY_MS); |
| 194 STAT_ENUM_TO_STRING(ENCODE_KBPS); |
| 195 STAT_ENUM_TO_STRING(TRANSMISSION_KBPS); |
| 196 STAT_ENUM_TO_STRING(RETRANSMISSION_KBPS); |
| 197 STAT_ENUM_TO_STRING(PACKET_LOSS_FRACTION); |
| 198 STAT_ENUM_TO_STRING(MS_SINCE_LAST_RECEIVER_RESPONSE); |
| 199 } |
| 200 NOTREACHED(); |
| 201 return ""; |
| 202 } |
| 203 |
| 204 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const { |
| 205 DCHECK(thread_checker_.CalledOnValidThread()); |
| 206 |
| 207 stats_map->clear(); |
| 208 |
| 209 base::TimeTicks end_time = clock_->NowTicks(); |
| 210 |
| 211 PopulateFpsStat( |
| 212 end_time, GetCapturedEvent(event_media_type_), CAPTURE_FPS, stats_map); |
| 213 PopulateFpsStat( |
| 214 end_time, GetEncodedEvent(event_media_type_), ENCODE_FPS, stats_map); |
| 215 PopulateFpsStat( |
| 216 end_time, GetDecodedEvent(event_media_type_), DECODE_FPS, stats_map); |
| 217 PopulatePlayoutDelayStat(stats_map); |
| 218 PopulateFrameBitrateStat(end_time, stats_map); |
| 219 PopulatePacketBitrateStat(end_time, |
| 220 GetPacketSentEvent(event_media_type_), |
| 221 TRANSMISSION_KBPS, |
| 222 stats_map); |
| 223 PopulatePacketBitrateStat(end_time, |
| 224 GetPacketRetransmittedEvent(event_media_type_), |
| 225 RETRANSMISSION_KBPS, |
| 226 stats_map); |
| 227 PopulatePacketLossPercentageStat(stats_map); |
| 228 |
| 229 if (network_latency_datapoints_ > 0) { |
| 230 double avg_network_latency_ms = |
| 231 total_network_latency_.InMillisecondsF() / |
| 232 network_latency_datapoints_; |
| 233 stats_map->insert( |
| 234 std::make_pair(AVG_NETWORK_LATENCY_MS, avg_network_latency_ms)); |
| 235 } |
| 236 |
| 237 if (e2e_latency_datapoints_ > 0) { |
| 238 double avg_e2e_latency_ms = |
| 239 total_e2e_latency_.InMillisecondsF() / e2e_latency_datapoints_; |
| 240 stats_map->insert(std::make_pair(AVG_E2E_LATENCY_MS, avg_e2e_latency_ms)); |
| 241 } |
| 242 |
| 243 if (!last_response_received_time_.is_null()) { |
| 244 stats_map->insert( |
| 245 std::make_pair(MS_SINCE_LAST_RECEIVER_RESPONSE, |
| 246 (end_time - last_response_received_time_).InMillisecondsF())); |
| 247 } |
| 248 } |
| 249 |
| 250 bool StatsEventSubscriber::GetReceiverOffset(base::TimeDelta* offset) { |
| 251 base::TimeDelta receiver_offset_lower_bound; |
| 252 base::TimeDelta receiver_offset_upper_bound; |
| 253 if (!offset_estimator_->GetReceiverOffsetBounds( |
| 254 &receiver_offset_lower_bound, &receiver_offset_upper_bound)) { |
| 255 return false; |
| 256 } |
| 257 |
| 258 *offset = (receiver_offset_lower_bound + receiver_offset_upper_bound) / 2; |
| 259 return true; |
| 260 } |
| 261 |
| 262 void StatsEventSubscriber::RecordFrameCapturedTime( |
| 263 const FrameEvent& frame_event) { |
| 264 frame_captured_times_.insert( |
| 265 std::make_pair(frame_event.rtp_timestamp, frame_event.timestamp)); |
| 266 if (frame_captured_times_.size() > kMaxFrameEventTimeMapSize) |
| 267 frame_captured_times_.erase(frame_captured_times_.begin()); |
| 268 } |
| 269 |
| 270 void StatsEventSubscriber::RecordE2ELatency(const FrameEvent& frame_event) { |
| 271 base::TimeDelta receiver_offset; |
| 272 if (!GetReceiverOffset(&receiver_offset)) |
| 273 return; |
| 274 |
| 275 FrameEventTimeMap::iterator it = |
| 276 frame_captured_times_.find(frame_event.rtp_timestamp); |
| 277 if (it == frame_captured_times_.end()) |
| 278 return; |
| 279 |
| 280 // Playout time is event time + playout delay. |
| 281 base::TimeTicks playout_time = |
| 282 frame_event.timestamp + frame_event.delay_delta - receiver_offset; |
| 283 total_e2e_latency_ += playout_time - it->second; |
| 284 e2e_latency_datapoints_++; |
| 285 } |
| 286 |
| 287 void StatsEventSubscriber::UpdateLastResponseTime( |
| 288 base::TimeTicks receiver_time) { |
| 289 base::TimeDelta receiver_offset; |
| 290 if (!GetReceiverOffset(&receiver_offset)) |
| 291 return; |
| 292 base::TimeTicks sender_time = receiver_time - receiver_offset; |
| 293 last_response_received_time_ = sender_time; |
| 294 } |
| 295 |
| 296 void StatsEventSubscriber::ErasePacketSentTime( |
| 297 const PacketEvent& packet_event) { |
| 298 std::pair<RtpTimestamp, uint16> key( |
| 299 std::make_pair(packet_event.rtp_timestamp, packet_event.packet_id)); |
| 300 packet_sent_times_.erase(key); |
| 301 } |
| 302 |
| 303 void StatsEventSubscriber::RecordNetworkLatency( |
| 304 const PacketEvent& packet_event) { |
| 305 base::TimeDelta receiver_offset; |
| 306 if (!GetReceiverOffset(&receiver_offset)) |
| 307 return; |
| 308 |
| 309 std::pair<RtpTimestamp, uint16> key( |
| 310 std::make_pair(packet_event.rtp_timestamp, packet_event.packet_id)); |
| 311 PacketEventTimeMap::iterator it = packet_sent_times_.find(key); |
| 312 if (it == packet_sent_times_.end()) { |
| 313 std::pair<RtpTimestamp, uint16> key( |
| 314 std::make_pair(packet_event.rtp_timestamp, packet_event.packet_id)); |
| 315 std::pair<base::TimeTicks, CastLoggingEvent> value = |
| 316 std::make_pair(packet_event.timestamp, packet_event.type); |
| 317 packet_sent_times_.insert(std::make_pair(key, value)); |
| 318 if (packet_sent_times_.size() > kMaxPacketEventTimeMapSize) |
| 319 packet_sent_times_.erase(packet_sent_times_.begin()); |
| 320 } else { |
| 321 std::pair<base::TimeTicks, CastLoggingEvent> value = it->second; |
| 322 CastLoggingEvent recorded_type = value.second; |
| 323 bool match = false; |
| 324 base::TimeTicks packet_sent_time; |
| 325 base::TimeTicks packet_received_time; |
| 326 if (recorded_type == GetPacketSentEvent(event_media_type_) && |
| 327 packet_event.type == GetPacketReceivedEvent(event_media_type_)) { |
| 328 packet_sent_time = value.first; |
| 329 packet_received_time = packet_event.timestamp; |
| 330 match = true; |
| 331 } else if (recorded_type == GetPacketReceivedEvent(event_media_type_) && |
| 332 packet_event.type == GetPacketSentEvent(event_media_type_)) { |
| 333 packet_sent_time = packet_event.timestamp; |
| 334 packet_received_time = value.first; |
| 335 match = true; |
| 336 } |
| 337 if (match) { |
| 338 // Subtract by offset. |
| 339 packet_received_time -= receiver_offset; |
| 340 |
| 341 total_network_latency_ += packet_received_time - packet_sent_time; |
| 342 network_latency_datapoints_++; |
| 343 packet_sent_times_.erase(it); |
| 344 } |
| 345 } |
| 346 } |
| 347 |
| 348 void StatsEventSubscriber::PopulateFpsStat(base::TimeTicks end_time, |
| 349 CastLoggingEvent event, |
| 350 CastStat stat, |
| 351 StatsMap* stats_map) const { |
| 352 FrameStatsMap::const_iterator it = frame_stats_.find(event); |
| 353 if (it != frame_stats_.end()) { |
| 354 double fps = 0.0; |
| 355 base::TimeDelta duration = (end_time - start_time_); |
| 356 int count = it->second.event_counter; |
| 357 if (duration > base::TimeDelta()) |
| 358 fps = count / duration.InSecondsF(); |
| 359 stats_map->insert(std::make_pair(stat, fps)); |
| 360 } |
| 361 } |
| 362 |
| 363 void StatsEventSubscriber::PopulatePlayoutDelayStat(StatsMap* stats_map) const { |
| 364 CastLoggingEvent event = GetPlayoutEvent(event_media_type_); |
| 365 FrameStatsMap::const_iterator it = frame_stats_.find(event); |
| 366 if (it != frame_stats_.end()) { |
| 367 double avg_delay_ms = 0.0; |
| 368 base::TimeDelta sum_delay = it->second.sum_delay; |
| 369 int count = it->second.event_counter; |
| 370 if (count != 0) |
| 371 avg_delay_ms = sum_delay.InMillisecondsF() / count; |
| 372 stats_map->insert(std::make_pair(AVG_PLAYOUT_DELAY_MS, avg_delay_ms)); |
| 373 } |
| 374 } |
| 375 |
| 376 void StatsEventSubscriber::PopulateFrameBitrateStat(base::TimeTicks end_time, |
| 377 StatsMap* stats_map) const { |
| 378 CastLoggingEvent event = GetEncodedEvent(event_media_type_); |
| 379 FrameStatsMap::const_iterator it = frame_stats_.find(event); |
| 380 if (it != frame_stats_.end()) { |
| 381 double kbps = 0.0; |
| 382 base::TimeDelta duration = end_time - start_time_; |
| 383 if (duration > base::TimeDelta()) { |
| 384 kbps = it->second.sum_size / duration.InMillisecondsF() * 8; |
| 385 } |
| 386 |
| 387 stats_map->insert(std::make_pair(ENCODE_KBPS, kbps)); |
| 388 } |
| 389 } |
| 390 |
| 391 void StatsEventSubscriber::PopulatePacketBitrateStat( |
| 392 base::TimeTicks end_time, |
| 393 CastLoggingEvent event, |
| 394 CastStat stat, |
| 395 StatsMap* stats_map) const { |
| 396 PacketStatsMap::const_iterator it = packet_stats_.find(event); |
| 397 if (it != packet_stats_.end()) { |
| 398 double kbps = 0; |
| 399 base::TimeDelta duration = end_time - start_time_; |
| 400 if (duration > base::TimeDelta()) { |
| 401 kbps = it->second.sum_size / duration.InMillisecondsF() * 8; |
| 402 } |
| 403 |
| 404 stats_map->insert(std::make_pair(stat, kbps)); |
| 405 } |
| 406 } |
| 407 |
| 408 void StatsEventSubscriber::PopulatePacketLossPercentageStat( |
| 409 StatsMap* stats_map) const { |
| 410 // We assume that retransmission means that the packet's previous |
| 411 // (re)transmission was lost. |
| 412 // This means the percentage of packet loss is |
| 413 // (# of retransmit events) / (# of transmit + retransmit events). |
| 414 CastLoggingEvent packet_sent_event = GetPacketSentEvent(event_media_type_); |
| 415 CastLoggingEvent packet_retransmitted_event = |
| 416 GetPacketRetransmittedEvent(event_media_type_); |
| 417 PacketStatsMap::const_iterator sent_it = |
| 418 packet_stats_.find(packet_sent_event); |
| 419 if (sent_it == packet_stats_.end()) |
| 420 return; |
| 421 PacketStatsMap::const_iterator retransmitted_it = |
| 422 packet_stats_.find(packet_retransmitted_event); |
| 423 int sent_count = sent_it->second.event_counter; |
| 424 int retransmitted_count = 0; |
| 425 if (retransmitted_it != packet_stats_.end()) |
| 426 retransmitted_count = retransmitted_it->second.event_counter; |
| 427 double packet_loss_fraction = static_cast<double>(retransmitted_count) / |
| 428 (sent_count + retransmitted_count); |
| 429 stats_map->insert( |
| 430 std::make_pair(PACKET_LOSS_FRACTION, packet_loss_fraction)); |
| 431 } |
| 432 |
| 433 StatsEventSubscriber::FrameLogStats::FrameLogStats() |
| 434 : event_counter(0), sum_size(0) {} |
| 435 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {} |
| 436 |
| 437 StatsEventSubscriber::PacketLogStats::PacketLogStats() |
| 438 : event_counter(0), sum_size(0) {} |
| 439 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {} |
95 | 440 |
96 } // namespace cast | 441 } // namespace cast |
97 } // namespace media | 442 } // namespace media |
OLD | NEW |