1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/memory/linked_ptr.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "media/cast/logging/logging_stats.h"
8
9 namespace media {
10 namespace cast {
11
LoggingStats(base::TickClock * clock)12 LoggingStats::LoggingStats(base::TickClock* clock)
13 : frame_stats_(),
14 packet_stats_(),
15 generic_stats_(),
16 start_time_(),
17 clock_(clock) {
18 memset(counts_, 0, sizeof(counts_));
19 memset(start_time_, 0, sizeof(start_time_));
20 }
21
~LoggingStats()22 LoggingStats::~LoggingStats() {}
23
Reset()24 void LoggingStats::Reset() {
25 frame_stats_.clear();
26 packet_stats_.clear();
27 generic_stats_.clear();
28 memset(counts_, 0, sizeof(counts_));
29 }
30
InsertFrameEvent(CastLoggingEvent event,uint32 rtp_timestamp,uint32 frame_id)31 void LoggingStats::InsertFrameEvent(CastLoggingEvent event,
32 uint32 rtp_timestamp,
33 uint32 frame_id) {
34 InsertBaseFrameEvent(event, frame_id, rtp_timestamp);
35 }
36
InsertFrameEventWithSize(CastLoggingEvent event,uint32 rtp_timestamp,uint32 frame_id,int frame_size)37 void LoggingStats::InsertFrameEventWithSize(CastLoggingEvent event,
38 uint32 rtp_timestamp,
39 uint32 frame_id,
40 int frame_size) {
41 InsertBaseFrameEvent(event, frame_id, rtp_timestamp);
42 // Update size.
43 FrameStatsMap::iterator it = frame_stats_.find(event);
44 DCHECK(it != frame_stats_.end());
45 it->second->bitrate_kbps += frame_size;
46 }
47
InsertFrameEventWithDelay(CastLoggingEvent event,uint32 rtp_timestamp,uint32 frame_id,base::TimeDelta delay)48 void LoggingStats::InsertFrameEventWithDelay(CastLoggingEvent event,
49 uint32 rtp_timestamp,
50 uint32 frame_id,
51 base::TimeDelta delay) {
52 InsertBaseFrameEvent(event, frame_id, rtp_timestamp);
53 // Update size.
54 FrameStatsMap::iterator it = frame_stats_.find(event);
55 DCHECK(it != frame_stats_.end());
56 // Using the average delay as a counter, will divide by the counter when
57 // triggered.
58 it->second->avg_delay_ms += delay.InMilliseconds();
59 if (delay.InMilliseconds() > it->second->max_delay_ms)
60 it->second->max_delay_ms = delay.InMilliseconds();
61 if ((delay.InMilliseconds() < it->second->min_delay_ms) ||
62 (counts_[event] == 1) )
63 it->second->min_delay_ms = delay.InMilliseconds();
64 }
65
InsertBaseFrameEvent(CastLoggingEvent event,uint32 frame_id,uint32 rtp_timestamp)66 void LoggingStats::InsertBaseFrameEvent(CastLoggingEvent event,
67 uint32 frame_id,
68 uint32 rtp_timestamp) {
69 // Does this belong to an existing event?
70 FrameStatsMap::iterator it = frame_stats_.find(event);
71 if (it == frame_stats_.end()) {
72 // New event.
73 start_time_[event] = clock_->NowTicks();
74 linked_ptr<FrameLogStats> stats(new FrameLogStats());
75 frame_stats_.insert(std::make_pair(event, stats));
76 }
77
78 ++counts_[event];
79 }
80
InsertPacketEvent(CastLoggingEvent event,uint32 rtp_timestamp,uint32 frame_id,uint16 packet_id,uint16 max_packet_id,size_t size)81 void LoggingStats::InsertPacketEvent(CastLoggingEvent event,
82 uint32 rtp_timestamp,
83 uint32 frame_id,
84 uint16 packet_id,
85 uint16 max_packet_id,
86 size_t size) {
87 // Does this packet belong to an existing event?
88 PacketStatsMap::iterator it = packet_stats_.find(event);
89 if (it == packet_stats_.end()) {
90 // New event.
91 start_time_[event] = clock_->NowTicks();
92 packet_stats_.insert(std::make_pair(event, size));
93 } else {
94 // Add to existing.
95 it->second += size;
96 }
97 ++counts_[event];
98 }
99
InsertGenericEvent(CastLoggingEvent event,int value)100 void LoggingStats::InsertGenericEvent(CastLoggingEvent event, int value) {
101 // Does this event belong to an existing event?
102 GenericStatsMap::iterator it = generic_stats_.find(event);
103 if (it == generic_stats_.end()) {
104 // New event.
105 start_time_[event] = clock_->NowTicks();
106 generic_stats_.insert(std::make_pair(event, value));
107 } else {
108 // Add to existing (will be used to compute average).
109 it->second += value;
110 }
111 ++counts_[event];
112 }
113
GetFrameStatsData()114 const FrameStatsMap* LoggingStats::GetFrameStatsData() {
115 // Compute framerate and bitrate (when available).
116 FrameStatsMap::iterator it;
117 for (it = frame_stats_.begin(); it != frame_stats_.end(); ++it) {
118 base::TimeDelta time_diff = clock_->NowTicks() - start_time_[it->first];
119 it->second->framerate_fps = counts_[it->first] / time_diff.InSecondsF();
120 if (it->second->bitrate_kbps > 0) {
121 it->second->bitrate_kbps = (8 / 1000) *
122 it->second->bitrate_kbps / time_diff.InSecondsF();
123 }
124 if (it->second->avg_delay_ms > 0)
125 it->second->avg_delay_ms /= counts_[it->first];
126 }
127 return &frame_stats_;
128 }
129
GetPacketStatsData()130 const PacketStatsMap* LoggingStats::GetPacketStatsData() {
131 PacketStatsMap::iterator it;
132 for (it = packet_stats_.begin(); it != packet_stats_.end(); ++it) {
133 if (counts_[it->first] == 0) continue;
134 base::TimeDelta time_diff = clock_->NowTicks() - start_time_[it->first];
135 it->second = (8 / 1000) * it->second / time_diff.InSecondsF();
136 }
137 return &packet_stats_;
138 }
139
GetGenericStatsData()140 const GenericStatsMap* LoggingStats::GetGenericStatsData() {
141 // Compute averages.
142 GenericStatsMap::iterator it;
143 for (it = generic_stats_.begin(); it != generic_stats_.end(); ++it) {
144 it->second /= counts_[ it->first];
145 }
146 return &generic_stats_;
147 }
148
149 } // namespace cast
150 } // namespace media
151