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

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

Issue 482383005: Cast logging: Additional stats for 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/format_macros.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
8 #include "base/values.h" 10 #include "base/values.h"
9 11
10 #define STAT_ENUM_TO_STRING(enum) \ 12 #define STAT_ENUM_TO_STRING(enum) \
11 case enum: \ 13 case enum: \
12 return #enum 14 return #enum
13 15
14 namespace media { 16 namespace media {
15 namespace cast { 17 namespace cast {
16 18
17 namespace { 19 namespace {
18 20
19 using media::cast::CastLoggingEvent; 21 using media::cast::CastLoggingEvent;
20 using media::cast::EventMediaType; 22 using media::cast::EventMediaType;
21 23
22 const size_t kMaxPacketEventTimeMapSize = 1000; 24 const size_t kMaxPacketEventTimeMapSize = 1000;
23 25
24 bool IsReceiverEvent(CastLoggingEvent event) { 26 bool IsReceiverEvent(CastLoggingEvent event) {
25 return event == FRAME_DECODED 27 return event == FRAME_DECODED
26 || event == FRAME_PLAYOUT 28 || event == FRAME_PLAYOUT
27 || event == FRAME_ACK_SENT 29 || event == FRAME_ACK_SENT
28 || event == PACKET_RECEIVED; 30 || event == PACKET_RECEIVED;
29 } 31 }
30 32
31 } // namespace 33 } // namespace
32 34
35 StatsEventSubscriber::SimpleHistogram::SimpleHistogram(int64 min,
36 int64 max,
37 int64 width)
38 : min_(min), max_(max), width_(width), buckets_((max - min) / width + 2) {
39 CHECK_GT(buckets_.size(), 2u);
40 CHECK_EQ(0, (max_ - min_) % width_);
41 }
42
43 StatsEventSubscriber::SimpleHistogram::~SimpleHistogram() {
44 }
45
46 void StatsEventSubscriber::SimpleHistogram::Add(int64 sample) {
47 if (sample < min_) {
48 ++buckets_.front();
49 } else if (sample >= max_) {
50 ++buckets_.back();
51 } else {
52 size_t index = 1 + (sample - min_) / width_;
53 DCHECK_LT(index, buckets_.size());
54 ++buckets_[index];
55 }
56 }
57
58 void StatsEventSubscriber::SimpleHistogram::Reset() {
59 buckets_.assign(buckets_.size(), 0);
60 }
61
62 scoped_ptr<base::ListValue>
63 StatsEventSubscriber::SimpleHistogram::GetHistogram() const {
64 scoped_ptr<base::ListValue> histo(new base::ListValue);
65
66 scoped_ptr<base::DictionaryValue> bucket(new base::DictionaryValue);
67
68 bucket->SetString("bucket", base::StringPrintf("< %" PRId64, min_));
69 bucket->SetInteger("count", buckets_.front());
70 histo->Append(bucket.release());
71
72 for (size_t i = 1; i < buckets_.size() - 1; i++) {
73 bucket.reset(new base::DictionaryValue);
74
75 int64 lower = min_ + (i - 1) * width_;
76 int64 upper = lower + width_ - 1;
77 bucket->SetString(
78 "bucket", base::StringPrintf("%" PRId64 " - %" PRId64, lower, upper));
79 bucket->SetInteger("count", buckets_[i]);
80 histo->Append(bucket.release());
81 }
82
83 bucket.reset(new base::DictionaryValue);
84
85 bucket->SetString("bucket", base::StringPrintf(">= %" PRId64, max_));
86 bucket->SetInteger("count", buckets_.back());
87 histo->Append(bucket.release());
88
89 return histo.Pass();
90 }
91
33 StatsEventSubscriber::StatsEventSubscriber( 92 StatsEventSubscriber::StatsEventSubscriber(
34 EventMediaType event_media_type, 93 EventMediaType event_media_type,
35 base::TickClock* clock, 94 base::TickClock* clock,
36 ReceiverTimeOffsetEstimator* offset_estimator) 95 ReceiverTimeOffsetEstimator* offset_estimator)
37 : event_media_type_(event_media_type), 96 : event_media_type_(event_media_type),
38 clock_(clock), 97 clock_(clock),
39 offset_estimator_(offset_estimator), 98 offset_estimator_(offset_estimator),
40 network_latency_datapoints_(0), 99 network_latency_datapoints_(0),
41 e2e_latency_datapoints_(0), 100 e2e_latency_datapoints_(0),
42 num_frames_dropped_by_encoder_(0), 101 num_frames_dropped_by_encoder_(0),
43 num_frames_late_(0) { 102 num_frames_late_(0),
103 start_time_(clock_->NowTicks()) {
44 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT); 104 DCHECK(event_media_type == AUDIO_EVENT || event_media_type == VIDEO_EVENT);
45 base::TimeTicks now = clock_->NowTicks(); 105
46 start_time_ = now; 106 InitHistograms();
47 last_response_received_time_ = base::TimeTicks();
48 } 107 }
49 108
50 StatsEventSubscriber::~StatsEventSubscriber() { 109 StatsEventSubscriber::~StatsEventSubscriber() {
51 DCHECK(thread_checker_.CalledOnValidThread()); 110 DCHECK(thread_checker_.CalledOnValidThread());
52 } 111 }
53 112
54 void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) { 113 void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) {
55 DCHECK(thread_checker_.CalledOnValidThread()); 114 DCHECK(thread_checker_.CalledOnValidThread());
56 115
57 CastLoggingEvent type = frame_event.type; 116 CastLoggingEvent type = frame_event.type;
58 if (frame_event.media_type != event_media_type_) 117 if (frame_event.media_type != event_media_type_)
59 return; 118 return;
60 119
61 FrameStatsMap::iterator it = frame_stats_.find(type); 120 FrameStatsMap::iterator it = frame_stats_.find(type);
62 if (it == frame_stats_.end()) { 121 if (it == frame_stats_.end()) {
63 FrameLogStats stats; 122 FrameLogStats stats;
64 stats.event_counter = 1; 123 stats.event_counter = 1;
65 stats.sum_size = frame_event.size; 124 stats.sum_size = frame_event.size;
66 stats.sum_delay = frame_event.delay_delta; 125 stats.sum_delay = frame_event.delay_delta;
67 frame_stats_.insert(std::make_pair(type, stats)); 126 frame_stats_.insert(std::make_pair(type, stats));
68 } else { 127 } else {
69 ++(it->second.event_counter); 128 ++(it->second.event_counter);
70 it->second.sum_size += frame_event.size; 129 it->second.sum_size += frame_event.size;
71 it->second.sum_delay += frame_event.delay_delta; 130 it->second.sum_delay += frame_event.delay_delta;
72 } 131 }
73 132
133 bool is_receiver_event = IsReceiverEvent(type);
134 UpdateFirstLastEventTime(frame_event.timestamp, is_receiver_event);
135
74 if (type == FRAME_CAPTURE_BEGIN) { 136 if (type == FRAME_CAPTURE_BEGIN) {
75 RecordFrameCaptureTime(frame_event); 137 RecordFrameCaptureTime(frame_event);
138 } else if (type == FRAME_CAPTURE_END) {
139 RecordCaptureLatency(frame_event);
76 } else if (type == FRAME_ENCODED) { 140 } else if (type == FRAME_ENCODED) {
77 MarkAsEncoded(frame_event.rtp_timestamp); 141 RecordEncodeLatency(frame_event);
142 } else if (type == FRAME_ACK_SENT) {
143 RecordFrameTxLatency(frame_event);
78 } else if (type == FRAME_PLAYOUT) { 144 } else if (type == FRAME_PLAYOUT) {
79 RecordE2ELatency(frame_event); 145 RecordE2ELatency(frame_event);
80 if (frame_event.delay_delta <= base::TimeDelta()) 146 base::TimeDelta delay_delta = frame_event.delay_delta;
147 histograms_[PLAYOUT_DELAY_MS_HISTO]->Add(delay_delta.InMillisecondsF());
148 if (delay_delta <= base::TimeDelta())
81 num_frames_late_++; 149 num_frames_late_++;
82 } 150 }
83 151
84 if (IsReceiverEvent(type)) 152 if (is_receiver_event)
85 UpdateLastResponseTime(frame_event.timestamp); 153 UpdateLastResponseTime(frame_event.timestamp);
86 } 154 }
87 155
88 void StatsEventSubscriber::OnReceivePacketEvent( 156 void StatsEventSubscriber::OnReceivePacketEvent(
89 const PacketEvent& packet_event) { 157 const PacketEvent& packet_event) {
90 DCHECK(thread_checker_.CalledOnValidThread()); 158 DCHECK(thread_checker_.CalledOnValidThread());
91 159
92 CastLoggingEvent type = packet_event.type; 160 CastLoggingEvent type = packet_event.type;
93 if (packet_event.media_type != event_media_type_) 161 if (packet_event.media_type != event_media_type_)
94 return; 162 return;
95 163
96 PacketStatsMap::iterator it = packet_stats_.find(type); 164 PacketStatsMap::iterator it = packet_stats_.find(type);
97 if (it == packet_stats_.end()) { 165 if (it == packet_stats_.end()) {
98 PacketLogStats stats; 166 PacketLogStats stats;
99 stats.event_counter = 1; 167 stats.event_counter = 1;
100 stats.sum_size = packet_event.size; 168 stats.sum_size = packet_event.size;
101 packet_stats_.insert(std::make_pair(type, stats)); 169 packet_stats_.insert(std::make_pair(type, stats));
102 } else { 170 } else {
103 ++(it->second.event_counter); 171 ++(it->second.event_counter);
104 it->second.sum_size += packet_event.size; 172 it->second.sum_size += packet_event.size;
105 } 173 }
106 174
175 bool is_receiver_event = IsReceiverEvent(type);
176 UpdateFirstLastEventTime(packet_event.timestamp, is_receiver_event);
177
107 if (type == PACKET_SENT_TO_NETWORK || 178 if (type == PACKET_SENT_TO_NETWORK ||
108 type == PACKET_RECEIVED) { 179 type == PACKET_RECEIVED) {
109 RecordNetworkLatency(packet_event); 180 RecordNetworkLatency(packet_event);
110 } else if (type == PACKET_RETRANSMITTED) { 181 } else if (type == PACKET_RETRANSMITTED) {
111 // We only measure network latency using packets that doesn't have to be 182 // We only measure network latency using packets that doesn't have to be
112 // retransmitted as there is precisely one sent-receive timestamp pairs. 183 // retransmitted as there is precisely one sent-receive timestamp pairs.
113 ErasePacketSentTime(packet_event); 184 ErasePacketSentTime(packet_event);
114 } 185 }
115 186
116 if (IsReceiverEvent(type)) 187 if (is_receiver_event)
117 UpdateLastResponseTime(packet_event.timestamp); 188 UpdateLastResponseTime(packet_event.timestamp);
118 } 189 }
119 190
191 void StatsEventSubscriber::UpdateFirstLastEventTime(base::TimeTicks timestamp,
192 bool is_receiver_event) {
193 if (is_receiver_event) {
194 base::TimeDelta receiver_offset;
195 if (!GetReceiverOffset(&receiver_offset))
196 return;
197 timestamp -= receiver_offset;
198 }
199
200 if (first_event_time_.is_null()) {
201 first_event_time_ = timestamp;
202 } else {
203 first_event_time_ = std::min(first_event_time_, timestamp);
204 }
205 if (last_event_time_.is_null()) {
206 last_event_time_ = timestamp;
207 } else {
208 last_event_time_ = std::max(last_event_time_, timestamp);
209 }
210 }
211
120 scoped_ptr<base::DictionaryValue> StatsEventSubscriber::GetStats() const { 212 scoped_ptr<base::DictionaryValue> StatsEventSubscriber::GetStats() const {
121 StatsMap stats_map; 213 StatsMap stats_map;
122 GetStatsInternal(&stats_map); 214 GetStatsInternal(&stats_map);
123 scoped_ptr<base::DictionaryValue> ret(new base::DictionaryValue); 215 scoped_ptr<base::DictionaryValue> ret(new base::DictionaryValue);
124 216
125 scoped_ptr<base::DictionaryValue> stats(new base::DictionaryValue); 217 scoped_ptr<base::DictionaryValue> stats(new base::DictionaryValue);
126 for (StatsMap::const_iterator it = stats_map.begin(); it != stats_map.end(); 218 for (StatsMap::const_iterator it = stats_map.begin(); it != stats_map.end();
127 ++it) { 219 ++it) {
128 stats->SetDouble(CastStatToString(it->first), it->second); 220 stats->SetDouble(CastStatToString(it->first), it->second);
129 } 221 }
222 for (HistogramMap::const_iterator it = histograms_.begin();
223 it != histograms_.end();
224 ++it) {
225 stats->Set(CastStatToString(it->first),
226 it->second->GetHistogram().release());
227 }
130 228
131 ret->Set(event_media_type_ == AUDIO_EVENT ? "audio" : "video", 229 ret->Set(event_media_type_ == AUDIO_EVENT ? "audio" : "video",
132 stats.release()); 230 stats.release());
133 231
134 return ret.Pass(); 232 return ret.Pass();
135 } 233 }
136 234
137 void StatsEventSubscriber::Reset() { 235 void StatsEventSubscriber::Reset() {
138 DCHECK(thread_checker_.CalledOnValidThread()); 236 DCHECK(thread_checker_.CalledOnValidThread());
139 237
140 frame_stats_.clear(); 238 frame_stats_.clear();
141 packet_stats_.clear(); 239 packet_stats_.clear();
142 total_network_latency_ = base::TimeDelta(); 240 total_network_latency_ = base::TimeDelta();
143 network_latency_datapoints_ = 0; 241 network_latency_datapoints_ = 0;
144 total_e2e_latency_ = base::TimeDelta(); 242 total_e2e_latency_ = base::TimeDelta();
145 e2e_latency_datapoints_ = 0; 243 e2e_latency_datapoints_ = 0;
146 num_frames_dropped_by_encoder_ = 0; 244 num_frames_dropped_by_encoder_ = 0;
147 num_frames_late_ = 0; 245 num_frames_late_ = 0;
148 recent_captured_frames_.clear(); 246 recent_frame_infos_.clear();
149 packet_sent_times_.clear(); 247 packet_sent_times_.clear();
150 start_time_ = clock_->NowTicks(); 248 start_time_ = clock_->NowTicks();
151 last_response_received_time_ = base::TimeTicks(); 249 last_response_received_time_ = base::TimeTicks();
250 for (HistogramMap::iterator it = histograms_.begin(); it != histograms_.end();
251 ++it) {
252 it->second->Reset();
253 }
254
255 first_event_time_ = base::TimeTicks();
256 last_event_time_ = base::TimeTicks();
152 } 257 }
153 258
154 // static 259 // static
155 const char* StatsEventSubscriber::CastStatToString(CastStat stat) { 260 const char* StatsEventSubscriber::CastStatToString(CastStat stat) {
156 switch (stat) { 261 switch (stat) {
157 STAT_ENUM_TO_STRING(CAPTURE_FPS); 262 STAT_ENUM_TO_STRING(CAPTURE_FPS);
158 STAT_ENUM_TO_STRING(ENCODE_FPS); 263 STAT_ENUM_TO_STRING(ENCODE_FPS);
159 STAT_ENUM_TO_STRING(DECODE_FPS); 264 STAT_ENUM_TO_STRING(DECODE_FPS);
160 STAT_ENUM_TO_STRING(AVG_ENCODE_TIME_MS); 265 STAT_ENUM_TO_STRING(AVG_ENCODE_TIME_MS);
161 STAT_ENUM_TO_STRING(AVG_PLAYOUT_DELAY_MS); 266 STAT_ENUM_TO_STRING(AVG_PLAYOUT_DELAY_MS);
162 STAT_ENUM_TO_STRING(AVG_NETWORK_LATENCY_MS); 267 STAT_ENUM_TO_STRING(AVG_NETWORK_LATENCY_MS);
163 STAT_ENUM_TO_STRING(AVG_E2E_LATENCY_MS); 268 STAT_ENUM_TO_STRING(AVG_E2E_LATENCY_MS);
164 STAT_ENUM_TO_STRING(ENCODE_KBPS); 269 STAT_ENUM_TO_STRING(ENCODE_KBPS);
165 STAT_ENUM_TO_STRING(TRANSMISSION_KBPS); 270 STAT_ENUM_TO_STRING(TRANSMISSION_KBPS);
166 STAT_ENUM_TO_STRING(RETRANSMISSION_KBPS); 271 STAT_ENUM_TO_STRING(RETRANSMISSION_KBPS);
167 STAT_ENUM_TO_STRING(PACKET_LOSS_FRACTION); 272 STAT_ENUM_TO_STRING(PACKET_LOSS_FRACTION);
168 STAT_ENUM_TO_STRING(MS_SINCE_LAST_RECEIVER_RESPONSE); 273 STAT_ENUM_TO_STRING(MS_SINCE_LAST_RECEIVER_RESPONSE);
169 STAT_ENUM_TO_STRING(NUM_FRAMES_CAPTURED); 274 STAT_ENUM_TO_STRING(NUM_FRAMES_CAPTURED);
170 STAT_ENUM_TO_STRING(NUM_FRAMES_DROPPED_BY_ENCODER); 275 STAT_ENUM_TO_STRING(NUM_FRAMES_DROPPED_BY_ENCODER);
171 STAT_ENUM_TO_STRING(NUM_FRAMES_LATE); 276 STAT_ENUM_TO_STRING(NUM_FRAMES_LATE);
172 STAT_ENUM_TO_STRING(NUM_PACKETS_SENT); 277 STAT_ENUM_TO_STRING(NUM_PACKETS_SENT);
173 STAT_ENUM_TO_STRING(NUM_PACKETS_RETRANSMITTED); 278 STAT_ENUM_TO_STRING(NUM_PACKETS_RETRANSMITTED);
174 STAT_ENUM_TO_STRING(NUM_PACKETS_RTX_REJECTED); 279 STAT_ENUM_TO_STRING(NUM_PACKETS_RTX_REJECTED);
280 STAT_ENUM_TO_STRING(DURATION_MS);
Alpha Left Google 2014/08/22 01:49:04 This seems redundant since we have first event tim
imcheng 2014/08/22 19:14:17 Removed.
281 STAT_ENUM_TO_STRING(FIRST_EVENT_TIME_MS);
282 STAT_ENUM_TO_STRING(LAST_EVENT_TIME_MS);
283 STAT_ENUM_TO_STRING(CAPTURE_LATENCY_MS_HISTO);
284 STAT_ENUM_TO_STRING(ENCODE_LATENCY_MS_HISTO);
285 STAT_ENUM_TO_STRING(PACKET_LATENCY_MS_HISTO);
286 STAT_ENUM_TO_STRING(FRAME_LATENCY_MS_HISTO);
287 STAT_ENUM_TO_STRING(PLAYOUT_DELAY_MS_HISTO);
175 } 288 }
176 NOTREACHED(); 289 NOTREACHED();
177 return ""; 290 return "";
178 } 291 }
179 292
293 const int kMaxLatencyBucketMs = 800;
294 const int kBucketWidthMs = 20;
295
296 void StatsEventSubscriber::InitHistograms() {
297 histograms_[CAPTURE_LATENCY_MS_HISTO].reset(
298 new SimpleHistogram(0, kMaxLatencyBucketMs, kBucketWidthMs));
299 histograms_[ENCODE_LATENCY_MS_HISTO].reset(
300 new SimpleHistogram(0, kMaxLatencyBucketMs, kBucketWidthMs));
301 histograms_[PACKET_LATENCY_MS_HISTO].reset(
302 new SimpleHistogram(0, kMaxLatencyBucketMs, kBucketWidthMs));
303 histograms_[FRAME_LATENCY_MS_HISTO].reset(
304 new SimpleHistogram(0, kMaxLatencyBucketMs, kBucketWidthMs));
305 histograms_[PLAYOUT_DELAY_MS_HISTO].reset(
306 new SimpleHistogram(0, kMaxLatencyBucketMs, kBucketWidthMs));
307 }
308
180 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const { 309 void StatsEventSubscriber::GetStatsInternal(StatsMap* stats_map) const {
181 DCHECK(thread_checker_.CalledOnValidThread()); 310 DCHECK(thread_checker_.CalledOnValidThread());
182 311
183 stats_map->clear(); 312 stats_map->clear();
184 313
185 base::TimeTicks end_time = clock_->NowTicks(); 314 base::TimeTicks end_time = clock_->NowTicks();
315 stats_map->insert(
316 std::make_pair(DURATION_MS, (end_time - start_time_).InMillisecondsF()));
186 317
187 PopulateFpsStat( 318 PopulateFpsStat(
188 end_time, FRAME_CAPTURE_BEGIN, CAPTURE_FPS, stats_map); 319 end_time, FRAME_CAPTURE_BEGIN, CAPTURE_FPS, stats_map);
189 PopulateFpsStat( 320 PopulateFpsStat(
190 end_time, FRAME_ENCODED, ENCODE_FPS, stats_map); 321 end_time, FRAME_ENCODED, ENCODE_FPS, stats_map);
191 PopulateFpsStat( 322 PopulateFpsStat(
192 end_time, FRAME_DECODED, DECODE_FPS, stats_map); 323 end_time, FRAME_DECODED, DECODE_FPS, stats_map);
193 PopulatePlayoutDelayStat(stats_map); 324 PopulatePlayoutDelayStat(stats_map);
194 PopulateFrameBitrateStat(end_time, stats_map); 325 PopulateFrameBitrateStat(end_time, stats_map);
195 PopulatePacketBitrateStat(end_time, 326 PopulatePacketBitrateStat(end_time,
(...skipping 28 matching lines...) Expand all
224 355
225 if (!last_response_received_time_.is_null()) { 356 if (!last_response_received_time_.is_null()) {
226 stats_map->insert( 357 stats_map->insert(
227 std::make_pair(MS_SINCE_LAST_RECEIVER_RESPONSE, 358 std::make_pair(MS_SINCE_LAST_RECEIVER_RESPONSE,
228 (end_time - last_response_received_time_).InMillisecondsF())); 359 (end_time - last_response_received_time_).InMillisecondsF()));
229 } 360 }
230 361
231 stats_map->insert(std::make_pair(NUM_FRAMES_DROPPED_BY_ENCODER, 362 stats_map->insert(std::make_pair(NUM_FRAMES_DROPPED_BY_ENCODER,
232 num_frames_dropped_by_encoder_)); 363 num_frames_dropped_by_encoder_));
233 stats_map->insert(std::make_pair(NUM_FRAMES_LATE, num_frames_late_)); 364 stats_map->insert(std::make_pair(NUM_FRAMES_LATE, num_frames_late_));
365 stats_map->insert(std::make_pair(
366 FIRST_EVENT_TIME_MS,
367 (first_event_time_ - base::TimeTicks::UnixEpoch()).InMillisecondsF()));
368 stats_map->insert(std::make_pair(
369 LAST_EVENT_TIME_MS,
370 (last_event_time_ - base::TimeTicks::UnixEpoch()).InMillisecondsF()));
234 } 371 }
235 372
236 bool StatsEventSubscriber::GetReceiverOffset(base::TimeDelta* offset) { 373 bool StatsEventSubscriber::GetReceiverOffset(base::TimeDelta* offset) {
237 base::TimeDelta receiver_offset_lower_bound; 374 base::TimeDelta receiver_offset_lower_bound;
238 base::TimeDelta receiver_offset_upper_bound; 375 base::TimeDelta receiver_offset_upper_bound;
239 if (!offset_estimator_->GetReceiverOffsetBounds( 376 if (!offset_estimator_->GetReceiverOffsetBounds(
240 &receiver_offset_lower_bound, &receiver_offset_upper_bound)) { 377 &receiver_offset_lower_bound, &receiver_offset_upper_bound)) {
241 return false; 378 return false;
242 } 379 }
243 380
244 *offset = (receiver_offset_lower_bound + receiver_offset_upper_bound) / 2; 381 *offset = (receiver_offset_lower_bound + receiver_offset_upper_bound) / 2;
245 return true; 382 return true;
246 } 383 }
247 384
385 void StatsEventSubscriber::MaybeInsertFrameInfo(RtpTimestamp rtp_timestamp,
386 const FrameInfo& frame_info) {
387 // No need to insert if |rtp_timestamp| is the smaller than every key in the
388 // map as it is just going to get erased anyway.
389 if (recent_frame_infos_.size() == kMaxFrameInfoMapSize &&
390 rtp_timestamp < recent_frame_infos_.begin()->first) {
391 return;
392 }
393
394 recent_frame_infos_.insert(std::make_pair(rtp_timestamp, frame_info));
395
396 if (recent_frame_infos_.size() >= kMaxFrameInfoMapSize) {
397 FrameInfoMap::iterator erase_it = recent_frame_infos_.begin();
398 if (erase_it->second.encode_time.is_null())
399 num_frames_dropped_by_encoder_++;
400 recent_frame_infos_.erase(erase_it);
401 }
402 }
403
248 void StatsEventSubscriber::RecordFrameCaptureTime( 404 void StatsEventSubscriber::RecordFrameCaptureTime(
249 const FrameEvent& frame_event) { 405 const FrameEvent& frame_event) {
250 recent_captured_frames_.insert(std::make_pair( 406 FrameInfo frame_info;
251 frame_event.rtp_timestamp, FrameInfo(frame_event.timestamp))); 407 frame_info.capture_time = frame_event.timestamp;
252 if (recent_captured_frames_.size() > kMaxFrameInfoMapSize) { 408 MaybeInsertFrameInfo(frame_event.rtp_timestamp, frame_info);
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 } 409 }
259 410
260 void StatsEventSubscriber::MarkAsEncoded(RtpTimestamp rtp_timestamp) { 411 void StatsEventSubscriber::RecordCaptureLatency(const FrameEvent& frame_event) {
261 FrameInfoMap::iterator it = recent_captured_frames_.find(rtp_timestamp); 412 FrameInfoMap::iterator it =
262 if (it != recent_captured_frames_.end()) 413 recent_frame_infos_.find(frame_event.rtp_timestamp);
263 it->second.encoded = true; 414 if (it == recent_frame_infos_.end())
415 return;
416
417 if (!it->second.capture_time.is_null()) {
418 double capture_latency_ms =
419 (it->second.capture_time - frame_event.timestamp).InMillisecondsF();
420 histograms_[CAPTURE_LATENCY_MS_HISTO]->Add(capture_latency_ms);
421 }
422
423 it->second.capture_end_time = frame_event.timestamp;
424 }
425
426 void StatsEventSubscriber::RecordEncodeLatency(const FrameEvent& frame_event) {
427 FrameInfoMap::iterator it =
428 recent_frame_infos_.find(frame_event.rtp_timestamp);
429 if (it == recent_frame_infos_.end()) {
430 FrameInfo frame_info;
431 frame_info.encode_time = frame_event.timestamp;
432 MaybeInsertFrameInfo(frame_event.rtp_timestamp, frame_info);
433 return;
434 }
435
436 if (!it->second.capture_end_time.is_null()) {
437 double encode_latency_ms =
438 (frame_event.timestamp - it->second.capture_end_time).InMillisecondsF();
439 histograms_[ENCODE_LATENCY_MS_HISTO]->Add(encode_latency_ms);
440 }
441
442 it->second.encode_time = frame_event.timestamp;
443 }
444
445 void StatsEventSubscriber::RecordFrameTxLatency(const FrameEvent& frame_event) {
446 FrameInfoMap::iterator it =
447 recent_frame_infos_.find(frame_event.rtp_timestamp);
448 if (it == recent_frame_infos_.end())
449 return;
450
451 if (it->second.encode_time.is_null())
452 return;
453
454 base::TimeDelta receiver_offset;
455 if (!GetReceiverOffset(&receiver_offset))
456 return;
457
458 base::TimeTicks sender_time = frame_event.timestamp - receiver_offset;
459 double frame_tx_latency_ms =
460 (sender_time - it->second.encode_time).InMillisecondsF();
461 histograms_[FRAME_LATENCY_MS_HISTO]->Add(frame_tx_latency_ms);
264 } 462 }
265 463
266 void StatsEventSubscriber::RecordE2ELatency(const FrameEvent& frame_event) { 464 void StatsEventSubscriber::RecordE2ELatency(const FrameEvent& frame_event) {
267 base::TimeDelta receiver_offset; 465 base::TimeDelta receiver_offset;
268 if (!GetReceiverOffset(&receiver_offset)) 466 if (!GetReceiverOffset(&receiver_offset))
269 return; 467 return;
270 468
271 FrameInfoMap::iterator it = 469 FrameInfoMap::iterator it =
272 recent_captured_frames_.find(frame_event.rtp_timestamp); 470 recent_frame_infos_.find(frame_event.rtp_timestamp);
273 if (it == recent_captured_frames_.end()) 471 if (it == recent_frame_infos_.end())
274 return; 472 return;
275 473
276 // Playout time is event time + playout delay. 474 // Playout time is event time + playout delay.
277 base::TimeTicks playout_time = 475 base::TimeTicks playout_time =
278 frame_event.timestamp + frame_event.delay_delta - receiver_offset; 476 frame_event.timestamp + frame_event.delay_delta - receiver_offset;
279 total_e2e_latency_ += playout_time - it->second.capture_time; 477 total_e2e_latency_ += playout_time - it->second.capture_time;
280 e2e_latency_datapoints_++; 478 e2e_latency_datapoints_++;
281 } 479 }
282 480
283 void StatsEventSubscriber::UpdateLastResponseTime( 481 void StatsEventSubscriber::UpdateLastResponseTime(
(...skipping 15 matching lines...) Expand all
299 void StatsEventSubscriber::RecordNetworkLatency( 497 void StatsEventSubscriber::RecordNetworkLatency(
300 const PacketEvent& packet_event) { 498 const PacketEvent& packet_event) {
301 base::TimeDelta receiver_offset; 499 base::TimeDelta receiver_offset;
302 if (!GetReceiverOffset(&receiver_offset)) 500 if (!GetReceiverOffset(&receiver_offset))
303 return; 501 return;
304 502
305 std::pair<RtpTimestamp, uint16> key( 503 std::pair<RtpTimestamp, uint16> key(
306 std::make_pair(packet_event.rtp_timestamp, packet_event.packet_id)); 504 std::make_pair(packet_event.rtp_timestamp, packet_event.packet_id));
307 PacketEventTimeMap::iterator it = packet_sent_times_.find(key); 505 PacketEventTimeMap::iterator it = packet_sent_times_.find(key);
308 if (it == packet_sent_times_.end()) { 506 if (it == packet_sent_times_.end()) {
309 std::pair<RtpTimestamp, uint16> key(
310 std::make_pair(packet_event.rtp_timestamp, packet_event.packet_id));
311 std::pair<base::TimeTicks, CastLoggingEvent> value = 507 std::pair<base::TimeTicks, CastLoggingEvent> value =
312 std::make_pair(packet_event.timestamp, packet_event.type); 508 std::make_pair(packet_event.timestamp, packet_event.type);
313 packet_sent_times_.insert(std::make_pair(key, value)); 509 packet_sent_times_.insert(std::make_pair(key, value));
314 if (packet_sent_times_.size() > kMaxPacketEventTimeMapSize) 510 if (packet_sent_times_.size() > kMaxPacketEventTimeMapSize)
315 packet_sent_times_.erase(packet_sent_times_.begin()); 511 packet_sent_times_.erase(packet_sent_times_.begin());
316 } else { 512 } else {
317 std::pair<base::TimeTicks, CastLoggingEvent> value = it->second; 513 std::pair<base::TimeTicks, CastLoggingEvent> value = it->second;
318 CastLoggingEvent recorded_type = value.second; 514 CastLoggingEvent recorded_type = value.second;
319 bool match = false; 515 bool match = false;
320 base::TimeTicks packet_sent_time; 516 base::TimeTicks packet_sent_time;
321 base::TimeTicks packet_received_time; 517 base::TimeTicks packet_received_time;
322 if (recorded_type == PACKET_SENT_TO_NETWORK && 518 if (recorded_type == PACKET_SENT_TO_NETWORK &&
323 packet_event.type == PACKET_RECEIVED) { 519 packet_event.type == PACKET_RECEIVED) {
324 packet_sent_time = value.first; 520 packet_sent_time = value.first;
325 packet_received_time = packet_event.timestamp; 521 packet_received_time = packet_event.timestamp;
326 match = true; 522 match = true;
327 } else if (recorded_type == PACKET_RECEIVED && 523 } else if (recorded_type == PACKET_RECEIVED &&
328 packet_event.type == PACKET_SENT_TO_NETWORK) { 524 packet_event.type == PACKET_SENT_TO_NETWORK) {
329 packet_sent_time = packet_event.timestamp; 525 packet_sent_time = packet_event.timestamp;
330 packet_received_time = value.first; 526 packet_received_time = value.first;
331 match = true; 527 match = true;
332 } 528 }
333 if (match) { 529 if (match) {
334 // Subtract by offset. 530 // Subtract by offset.
335 packet_received_time -= receiver_offset; 531 packet_received_time -= receiver_offset;
532 base::TimeDelta latency_delta = packet_received_time - packet_sent_time;
336 533
337 total_network_latency_ += packet_received_time - packet_sent_time; 534 total_network_latency_ += latency_delta;
338 network_latency_datapoints_++; 535 network_latency_datapoints_++;
536
537 histograms_[PACKET_LATENCY_MS_HISTO]->Add(
538 latency_delta.InMillisecondsF());
539
339 packet_sent_times_.erase(it); 540 packet_sent_times_.erase(it);
340 } 541 }
341 } 542 }
342 } 543 }
343 544
344 void StatsEventSubscriber::PopulateFpsStat(base::TimeTicks end_time, 545 void StatsEventSubscriber::PopulateFpsStat(base::TimeTicks end_time,
345 CastLoggingEvent event, 546 CastLoggingEvent event,
346 CastStat stat, 547 CastStat stat,
347 StatsMap* stats_map) const { 548 StatsMap* stats_map) const {
348 FrameStatsMap::const_iterator it = frame_stats_.find(event); 549 FrameStatsMap::const_iterator it = frame_stats_.find(event);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 } 641 }
441 642
442 StatsEventSubscriber::FrameLogStats::FrameLogStats() 643 StatsEventSubscriber::FrameLogStats::FrameLogStats()
443 : event_counter(0), sum_size(0) {} 644 : event_counter(0), sum_size(0) {}
444 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {} 645 StatsEventSubscriber::FrameLogStats::~FrameLogStats() {}
445 646
446 StatsEventSubscriber::PacketLogStats::PacketLogStats() 647 StatsEventSubscriber::PacketLogStats::PacketLogStats()
447 : event_counter(0), sum_size(0) {} 648 : event_counter(0), sum_size(0) {}
448 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {} 649 StatsEventSubscriber::PacketLogStats::~PacketLogStats() {}
449 650
450 StatsEventSubscriber::FrameInfo::FrameInfo(base::TimeTicks capture_time) 651 StatsEventSubscriber::FrameInfo::FrameInfo() : encoded(false) {
451 : capture_time(capture_time), encoded(false) {
452 } 652 }
453 StatsEventSubscriber::FrameInfo::~FrameInfo() { 653 StatsEventSubscriber::FrameInfo::~FrameInfo() {
454 } 654 }
455 655
456 } // namespace cast 656 } // namespace cast
457 } // namespace media 657 } // 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