Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: media/cast/logging/stats_event_subscriber.cc

Issue 472203002: Cast streaming logging: Log additional stats for the GetStats() API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@REAL-NEW-MASTER
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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;
23 const size_t kMaxPacketEventTimeMapSize = 1000; 22 const size_t kMaxPacketEventTimeMapSize = 1000;
24 23
25 bool IsReceiverEvent(CastLoggingEvent event) { 24 bool IsReceiverEvent(CastLoggingEvent event) {
26 return event == FRAME_DECODED 25 return event == FRAME_DECODED
27 || event == FRAME_PLAYOUT 26 || event == FRAME_PLAYOUT
28 || event == FRAME_ACK_SENT 27 || event == FRAME_ACK_SENT
29 || event == PACKET_RECEIVED; 28 || event == PACKET_RECEIVED;
30 } 29 }
31 30
32 } // namespace 31 } // namespace
33 32
34 StatsEventSubscriber::StatsEventSubscriber( 33 StatsEventSubscriber::StatsEventSubscriber(
35 EventMediaType event_media_type, 34 EventMediaType event_media_type,
36 base::TickClock* clock, 35 base::TickClock* clock,
37 ReceiverTimeOffsetEstimator* offset_estimator) 36 ReceiverTimeOffsetEstimator* offset_estimator)
38 : event_media_type_(event_media_type), 37 : event_media_type_(event_media_type),
39 clock_(clock), 38 clock_(clock),
40 offset_estimator_(offset_estimator), 39 offset_estimator_(offset_estimator),
41 network_latency_datapoints_(0), 40 network_latency_datapoints_(0),
42 e2e_latency_datapoints_(0) { 41 e2e_latency_datapoints_(0),
42 num_frames_dropped_by_encoder_(0),
43 num_frames_late_(0) {
43 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT); 44 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT);
44 base::TimeTicks now = clock_->NowTicks(); 45 base::TimeTicks now = clock_->NowTicks();
45 start_time_ = now; 46 start_time_ = now;
46 last_response_received_time_ = base::TimeTicks(); 47 last_response_received_time_ = base::TimeTicks();
47 } 48 }
48 49
49 StatsEventSubscriber::~StatsEventSubscriber() { 50 StatsEventSubscriber::~StatsEventSubscriber() {
50 DCHECK(thread_checker_.CalledOnValidThread()); 51 DCHECK(thread_checker_.CalledOnValidThread());
51 } 52 }
52 53
(...skipping 11 matching lines...) Expand all
64 stats.sum_size = frame_event.size; 65 stats.sum_size = frame_event.size;
65 stats.sum_delay = frame_event.delay_delta; 66 stats.sum_delay = frame_event.delay_delta;
66 frame_stats_.insert(std::make_pair(type, stats)); 67 frame_stats_.insert(std::make_pair(type, stats));
67 } else { 68 } else {
68 ++(it->second.event_counter); 69 ++(it->second.event_counter);
69 it->second.sum_size += frame_event.size; 70 it->second.sum_size += frame_event.size;
70 it->second.sum_delay += frame_event.delay_delta; 71 it->second.sum_delay += frame_event.delay_delta;
71 } 72 }
72 73
73 if (type == FRAME_CAPTURE_BEGIN) { 74 if (type == FRAME_CAPTURE_BEGIN) {
74 RecordFrameCapturedTime(frame_event); 75 RecordFrameCaptureTime(frame_event);
76 } else if (type == FRAME_ENCODED) {
77 MarkAsEncoded(frame_event.rtp_timestamp);
75 } else if (type == FRAME_PLAYOUT) { 78 } else if (type == FRAME_PLAYOUT) {
76 RecordE2ELatency(frame_event); 79 RecordE2ELatency(frame_event);
80 if (frame_event.delay_delta <= base::TimeDelta())
81 num_frames_late_++;
77 } 82 }
78 83
79 if (IsReceiverEvent(type)) 84 if (IsReceiverEvent(type))
80 UpdateLastResponseTime(frame_event.timestamp); 85 UpdateLastResponseTime(frame_event.timestamp);
81 } 86 }
82 87
83 void StatsEventSubscriber::OnReceivePacketEvent( 88 void StatsEventSubscriber::OnReceivePacketEvent(
84 const PacketEvent& packet_event) { 89 const PacketEvent& packet_event) {
85 DCHECK(thread_checker_.CalledOnValidThread()); 90 DCHECK(thread_checker_.CalledOnValidThread());
86 91
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 136
132 void StatsEventSubscriber::Reset() { 137 void StatsEventSubscriber::Reset() {
133 DCHECK(thread_checker_.CalledOnValidThread()); 138 DCHECK(thread_checker_.CalledOnValidThread());
134 139
135 frame_stats_.clear(); 140 frame_stats_.clear();
136 packet_stats_.clear(); 141 packet_stats_.clear();
137 total_network_latency_ = base::TimeDelta(); 142 total_network_latency_ = base::TimeDelta();
138 network_latency_datapoints_ = 0; 143 network_latency_datapoints_ = 0;
139 total_e2e_latency_ = base::TimeDelta(); 144 total_e2e_latency_ = base::TimeDelta();
140 e2e_latency_datapoints_ = 0; 145 e2e_latency_datapoints_ = 0;
141 frame_captured_times_.clear(); 146 num_frames_dropped_by_encoder_ = 0;
147 num_frames_late_ = 0;
148 recent_captured_frames_.clear();
142 packet_sent_times_.clear(); 149 packet_sent_times_.clear();
143 start_time_ = clock_->NowTicks(); 150 start_time_ = clock_->NowTicks();
144 last_response_received_time_ = base::TimeTicks(); 151 last_response_received_time_ = base::TimeTicks();
145 } 152 }
146 153
147 // static 154 // static
148 const char* StatsEventSubscriber::CastStatToString(CastStat stat) { 155 const char* StatsEventSubscriber::CastStatToString(CastStat stat) {
149 switch (stat) { 156 switch (stat) {
150 STAT_ENUM_TO_STRING(CAPTURE_FPS); 157 STAT_ENUM_TO_STRING(CAPTURE_FPS);
151 STAT_ENUM_TO_STRING(ENCODE_FPS); 158 STAT_ENUM_TO_STRING(ENCODE_FPS);
152 STAT_ENUM_TO_STRING(DECODE_FPS); 159 STAT_ENUM_TO_STRING(DECODE_FPS);
153 STAT_ENUM_TO_STRING(AVG_ENCODE_TIME_MS); 160 STAT_ENUM_TO_STRING(AVG_ENCODE_TIME_MS);
154 STAT_ENUM_TO_STRING(AVG_PLAYOUT_DELAY_MS); 161 STAT_ENUM_TO_STRING(AVG_PLAYOUT_DELAY_MS);
155 STAT_ENUM_TO_STRING(AVG_NETWORK_LATENCY_MS); 162 STAT_ENUM_TO_STRING(AVG_NETWORK_LATENCY_MS);
156 STAT_ENUM_TO_STRING(AVG_E2E_LATENCY_MS); 163 STAT_ENUM_TO_STRING(AVG_E2E_LATENCY_MS);
157 STAT_ENUM_TO_STRING(ENCODE_KBPS); 164 STAT_ENUM_TO_STRING(ENCODE_KBPS);
158 STAT_ENUM_TO_STRING(TRANSMISSION_KBPS); 165 STAT_ENUM_TO_STRING(TRANSMISSION_KBPS);
159 STAT_ENUM_TO_STRING(RETRANSMISSION_KBPS); 166 STAT_ENUM_TO_STRING(RETRANSMISSION_KBPS);
160 STAT_ENUM_TO_STRING(PACKET_LOSS_FRACTION); 167 STAT_ENUM_TO_STRING(PACKET_LOSS_FRACTION);
161 STAT_ENUM_TO_STRING(MS_SINCE_LAST_RECEIVER_RESPONSE); 168 STAT_ENUM_TO_STRING(MS_SINCE_LAST_RECEIVER_RESPONSE);
169 STAT_ENUM_TO_STRING(NUM_FRAMES_CAPTURED);
170 STAT_ENUM_TO_STRING(NUM_FRAMES_DROPPED_BY_ENCODER);
171 STAT_ENUM_TO_STRING(NUM_FRAMES_LATE);
172 STAT_ENUM_TO_STRING(NUM_PACKETS_SENT);
173 STAT_ENUM_TO_STRING(NUM_PACKETS_RETRANSMITTED);
174 STAT_ENUM_TO_STRING(NUM_PACKETS_RTX_REJECTED);
162 } 175 }
163 NOTREACHED(); 176 NOTREACHED();
164 return ""; 177 return "";
165 } 178 }
166 179
167 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const { 180 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const {
168 DCHECK(thread_checker_.CalledOnValidThread()); 181 DCHECK(thread_checker_.CalledOnValidThread());
169 182
170 stats_map->clear(); 183 stats_map->clear();
171 184
172 base::TimeTicks end_time = clock_->NowTicks(); 185 base::TimeTicks end_time = clock_->NowTicks();
173 186
174 PopulateFpsStat( 187 PopulateFpsStat(
175 end_time, FRAME_CAPTURE_BEGIN, CAPTURE_FPS, stats_map); 188 end_time, FRAME_CAPTURE_BEGIN, CAPTURE_FPS, stats_map);
176 PopulateFpsStat( 189 PopulateFpsStat(
177 end_time, FRAME_ENCODED, ENCODE_FPS, stats_map); 190 end_time, FRAME_ENCODED, ENCODE_FPS, stats_map);
178 PopulateFpsStat( 191 PopulateFpsStat(
179 end_time, FRAME_DECODED, DECODE_FPS, stats_map); 192 end_time, FRAME_DECODED, DECODE_FPS, stats_map);
180 PopulatePlayoutDelayStat(stats_map); 193 PopulatePlayoutDelayStat(stats_map);
181 PopulateFrameBitrateStat(end_time, stats_map); 194 PopulateFrameBitrateStat(end_time, stats_map);
182 PopulatePacketBitrateStat(end_time, 195 PopulatePacketBitrateStat(end_time,
183 PACKET_SENT_TO_NETWORK, 196 PACKET_SENT_TO_NETWORK,
184 TRANSMISSION_KBPS, 197 TRANSMISSION_KBPS,
185 stats_map); 198 stats_map);
186 PopulatePacketBitrateStat(end_time, 199 PopulatePacketBitrateStat(end_time,
187 PACKET_RETRANSMITTED, 200 PACKET_RETRANSMITTED,
188 RETRANSMISSION_KBPS, 201 RETRANSMISSION_KBPS,
189 stats_map); 202 stats_map);
190 PopulatePacketLossPercentageStat(stats_map); 203 PopulatePacketLossPercentageStat(stats_map);
204 PopulateFrameCountStat(FRAME_CAPTURE_END, NUM_FRAMES_CAPTURED, stats_map);
205 PopulatePacketCountStat(PACKET_SENT_TO_NETWORK, NUM_PACKETS_SENT, stats_map);
206 PopulatePacketCountStat(
207 PACKET_RETRANSMITTED, NUM_PACKETS_RETRANSMITTED, stats_map);
208 PopulatePacketCountStat(
209 PACKET_RTX_REJECTED, NUM_PACKETS_RTX_REJECTED, stats_map);
191 210
192 if (network_latency_datapoints_ > 0) { 211 if (network_latency_datapoints_ > 0) {
193 double avg_network_latency_ms = 212 double avg_network_latency_ms =
194 total_network_latency_.InMillisecondsF() / 213 total_network_latency_.InMillisecondsF() /
195 network_latency_datapoints_; 214 network_latency_datapoints_;
196 stats_map->insert( 215 stats_map->insert(
197 std::make_pair(AVG_NETWORK_LATENCY_MS, avg_network_latency_ms)); 216 std::make_pair(AVG_NETWORK_LATENCY_MS, avg_network_latency_ms));
198 } 217 }
199 218
200 if (e2e_latency_datapoints_ > 0) { 219 if (e2e_latency_datapoints_ > 0) {
201 double avg_e2e_latency_ms = 220 double avg_e2e_latency_ms =
202 total_e2e_latency_.InMillisecondsF() / e2e_latency_datapoints_; 221 total_e2e_latency_.InMillisecondsF() / e2e_latency_datapoints_;
203 stats_map->insert(std::make_pair(AVG_E2E_LATENCY_MS, avg_e2e_latency_ms)); 222 stats_map->insert(std::make_pair(AVG_E2E_LATENCY_MS, avg_e2e_latency_ms));
204 } 223 }
205 224
206 if (!last_response_received_time_.is_null()) { 225 if (!last_response_received_time_.is_null()) {
207 stats_map->insert( 226 stats_map->insert(
208 std::make_pair(MS_SINCE_LAST_RECEIVER_RESPONSE, 227 std::make_pair(MS_SINCE_LAST_RECEIVER_RESPONSE,
209 (end_time - last_response_received_time_).InMillisecondsF())); 228 (end_time - last_response_received_time_).InMillisecondsF()));
210 } 229 }
230
231 stats_map->insert(std::make_pair(NUM_FRAMES_DROPPED_BY_ENCODER,
232 num_frames_dropped_by_encoder_));
233 stats_map->insert(std::make_pair(NUM_FRAMES_LATE, num_frames_late_));
211 } 234 }
212 235
213 bool StatsEventSubscriber::GetReceiverOffset(base::TimeDelta* offset) { 236 bool StatsEventSubscriber::GetReceiverOffset(base::TimeDelta* offset) {
214 base::TimeDelta receiver_offset_lower_bound; 237 base::TimeDelta receiver_offset_lower_bound;
215 base::TimeDelta receiver_offset_upper_bound; 238 base::TimeDelta receiver_offset_upper_bound;
216 if (!offset_estimator_->GetReceiverOffsetBounds( 239 if (!offset_estimator_->GetReceiverOffsetBounds(
217 &receiver_offset_lower_bound, &receiver_offset_upper_bound)) { 240 &receiver_offset_lower_bound, &receiver_offset_upper_bound)) {
218 return false; 241 return false;
219 } 242 }
220 243
221 *offset = (receiver_offset_lower_bound + receiver_offset_upper_bound) / 2; 244 *offset = (receiver_offset_lower_bound + receiver_offset_upper_bound) / 2;
222 return true; 245 return true;
223 } 246 }
224 247
225 void StatsEventSubscriber::RecordFrameCapturedTime( 248 void StatsEventSubscriber::RecordFrameCaptureTime(
226 const FrameEvent& frame_event) { 249 const FrameEvent& frame_event) {
227 frame_captured_times_.insert( 250 recent_captured_frames_.insert(std::make_pair(
228 std::make_pair(frame_event.rtp_timestamp, frame_event.timestamp)); 251 frame_event.rtp_timestamp, FrameInfo(frame_event.timestamp)));
229 if (frame_captured_times_.size() > kMaxFrameEventTimeMapSize) 252 if (recent_captured_frames_.size() > kMaxFrameInfoMapSize) {
230 frame_captured_times_.erase(frame_captured_times_.begin()); 253 FrameInfoMap::iterator erase_it = recent_captured_frames_.begin();
254 if (!erase_it->second.encoded)
255 num_frames_dropped_by_encoder_++;
256 recent_captured_frames_.erase(erase_it);
257 }
258 }
259
260 void StatsEventSubscriber::MarkAsEncoded(RtpTimestamp rtp_timestamp) {
261 FrameInfoMap::iterator it = recent_captured_frames_.find(rtp_timestamp);
262 if (it != recent_captured_frames_.end())
263 it->second.encoded = true;
231 } 264 }
232 265
233 void StatsEventSubscriber::RecordE2ELatency(const FrameEvent& frame_event) { 266 void StatsEventSubscriber::RecordE2ELatency(const FrameEvent& frame_event) {
234 base::TimeDelta receiver_offset; 267 base::TimeDelta receiver_offset;
235 if (!GetReceiverOffset(&receiver_offset)) 268 if (!GetReceiverOffset(&receiver_offset))
236 return; 269 return;
237 270
238 FrameEventTimeMap::iterator it = 271 FrameInfoMap::iterator it =
239 frame_captured_times_.find(frame_event.rtp_timestamp); 272 recent_captured_frames_.find(frame_event.rtp_timestamp);
240 if (it == frame_captured_times_.end()) 273 if (it == recent_captured_frames_.end())
241 return; 274 return;
242 275
243 // Playout time is event time + playout delay. 276 // Playout time is event time + playout delay.
244 base::TimeTicks playout_time = 277 base::TimeTicks playout_time =
245 frame_event.timestamp + frame_event.delay_delta - receiver_offset; 278 frame_event.timestamp + frame_event.delay_delta - receiver_offset;
246 total_e2e_latency_ += playout_time - it->second; 279 total_e2e_latency_ += playout_time - it->second.capture_time;
247 e2e_latency_datapoints_++; 280 e2e_latency_datapoints_++;
248 } 281 }
249 282
250 void StatsEventSubscriber::UpdateLastResponseTime( 283 void StatsEventSubscriber::UpdateLastResponseTime(
251 base::TimeTicks receiver_time) { 284 base::TimeTicks receiver_time) {
252 base::TimeDelta receiver_offset; 285 base::TimeDelta receiver_offset;
253 if (!GetReceiverOffset(&receiver_offset)) 286 if (!GetReceiverOffset(&receiver_offset))
254 return; 287 return;
255 base::TimeTicks sender_time = receiver_time - receiver_offset; 288 base::TimeTicks sender_time = receiver_time - receiver_offset;
256 last_response_received_time_ = sender_time; 289 last_response_received_time_ = sender_time;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 if (it != frame_stats_.end()) { 349 if (it != frame_stats_.end()) {
317 double fps = 0.0; 350 double fps = 0.0;
318 base::TimeDelta duration = (end_time - start_time_); 351 base::TimeDelta duration = (end_time - start_time_);
319 int count = it->second.event_counter; 352 int count = it->second.event_counter;
320 if (duration > base::TimeDelta()) 353 if (duration > base::TimeDelta())
321 fps = count / duration.InSecondsF(); 354 fps = count / duration.InSecondsF();
322 stats_map->insert(std::make_pair(stat, fps)); 355 stats_map->insert(std::make_pair(stat, fps));
323 } 356 }
324 } 357 }
325 358
359 void StatsEventSubscriber::PopulateFrameCountStat(CastLoggingEvent event,
360 CastStat stat,
361 StatsMap* stats_map) const {
362 FrameStatsMap::const_iterator it = frame_stats_.find(event);
363 if (it != frame_stats_.end()) {
364 stats_map->insert(std::make_pair(stat, it->second.event_counter));
365 }
366 }
367
368 void StatsEventSubscriber::PopulatePacketCountStat(CastLoggingEvent event,
369 CastStat stat,
370 StatsMap* stats_map) const {
371 PacketStatsMap::const_iterator it = packet_stats_.find(event);
372 if (it != packet_stats_.end()) {
373 stats_map->insert(std::make_pair(stat, it->second.event_counter));
374 }
375 }
376
326 void StatsEventSubscriber::PopulatePlayoutDelayStat(StatsMap* stats_map) const { 377 void StatsEventSubscriber::PopulatePlayoutDelayStat(StatsMap* stats_map) const {
327 FrameStatsMap::const_iterator it = frame_stats_.find(FRAME_PLAYOUT); 378 FrameStatsMap::const_iterator it = frame_stats_.find(FRAME_PLAYOUT);
328 if (it != frame_stats_.end()) { 379 if (it != frame_stats_.end()) {
329 double avg_delay_ms = 0.0; 380 double avg_delay_ms = 0.0;
330 base::TimeDelta sum_delay = it->second.sum_delay; 381 base::TimeDelta sum_delay = it->second.sum_delay;
331 int count = it->second.event_counter; 382 int count = it->second.event_counter;
332 if (count != 0) 383 if (count != 0)
333 avg_delay_ms = sum_delay.InMillisecondsF() / count; 384 avg_delay_ms = sum_delay.InMillisecondsF() / count;
334 stats_map->insert(std::make_pair(AVG_PLAYOUT_DELAY_MS, avg_delay_ms)); 385 stats_map->insert(std::make_pair(AVG_PLAYOUT_DELAY_MS, avg_delay_ms));
335 } 386 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 440 }
390 441
391 StatsEventSubscriber::FrameLogStats::FrameLogStats() 442 StatsEventSubscriber::FrameLogStats::FrameLogStats()
392 : event_counter(0), sum_size(0) {} 443 : event_counter(0), sum_size(0) {}
393 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {} 444 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {}
394 445
395 StatsEventSubscriber::PacketLogStats::PacketLogStats() 446 StatsEventSubscriber::PacketLogStats::PacketLogStats()
396 : event_counter(0), sum_size(0) {} 447 : event_counter(0), sum_size(0) {}
397 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {} 448 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {}
398 449
450 StatsEventSubscriber::FrameInfo::FrameInfo(base::TimeTicks capture_time)
451 : capture_time(capture_time), encoded(false) {
452 }
453 StatsEventSubscriber::FrameInfo::~FrameInfo() {
454 }
455
399 } // namespace cast 456 } // namespace cast
400 } // namespace media 457 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/logging/stats_event_subscriber.h ('k') | media/cast/logging/stats_event_subscriber_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698