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