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 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 22 LoggingStats::~LoggingStats() {} 23 24 void LoggingStats::Reset() { 25 frame_stats_.clear(); 26 packet_stats_.clear(); 27 generic_stats_.clear(); 28 memset(counts_, 0, sizeof(counts_)); 29 } 30 31 void LoggingStats::InsertFrameEvent(CastLoggingEvent event, 32 uint32 rtp_timestamp, 33 uint32 frame_id) { 34 InsertBaseFrameEvent(event, frame_id, rtp_timestamp); 35 } 36 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 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 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 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 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 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 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 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