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/debug/trace_event.h" 6 #include "base/metrics/histogram.h" 7 #include "media/cast/logging/logging_impl.h" 8 #include "net/base/big_endian.h" 9 10 namespace media { 11 namespace cast { 12 13 LoggingImpl::LoggingImpl(base::TickClock* clock, 14 scoped_refptr<base::TaskRunner> main_thread_proxy, 15 const CastLoggingConfig& config) 16 : main_thread_proxy_(main_thread_proxy), 17 config_(config), 18 raw_(clock), 19 stats_(clock) {} 20 21 LoggingImpl::~LoggingImpl() {} 22 23 void LoggingImpl::InsertFrameEvent(CastLoggingEvent event, 24 uint32 rtp_timestamp, 25 uint32 frame_id) { 26 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 27 if (config_.enable_data_collection) { 28 raw_.InsertFrameEvent(event, rtp_timestamp, frame_id); 29 stats_.InsertFrameEvent(event, rtp_timestamp, frame_id); 30 } 31 if (config_.enable_tracing) { 32 std::string event_string = CastLoggingToString(event); 33 TRACE_EVENT_INSTANT2(event_string.c_str(), "FE", 34 TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, "frame_id", 35 frame_id); 36 } 37 } 38 39 void LoggingImpl::InsertFrameEventWithSize(CastLoggingEvent event, 40 uint32 rtp_timestamp, 41 uint32 frame_id, 42 int frame_size) { 43 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 44 if (config_.enable_data_collection) { 45 raw_.InsertFrameEventWithSize(event, rtp_timestamp, frame_id, frame_size); 46 stats_.InsertFrameEventWithSize(event, rtp_timestamp, frame_id, frame_size); 47 } 48 if (config_.enable_uma_stats) { 49 UMA_HISTOGRAM_COUNTS(CastLoggingToString(event), frame_size); 50 } 51 if (config_.enable_tracing) { 52 std::string event_string = CastLoggingToString(event); 53 TRACE_EVENT_INSTANT2(event_string.c_str(), "FES", 54 TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, "frame_size", 55 frame_size); 56 } 57 } 58 59 void LoggingImpl::InsertFrameEventWithDelay(CastLoggingEvent event, 60 uint32 rtp_timestamp, 61 uint32 frame_id, 62 base::TimeDelta delay) { 63 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 64 if (config_.enable_data_collection) { 65 raw_.InsertFrameEventWithDelay(event, rtp_timestamp, frame_id, delay); 66 stats_.InsertFrameEventWithDelay(event, rtp_timestamp, frame_id, delay); 67 } 68 if (config_.enable_uma_stats) { 69 UMA_HISTOGRAM_TIMES(CastLoggingToString(event), delay); 70 } 71 if (config_.enable_tracing) { 72 std::string event_string = CastLoggingToString(event); 73 TRACE_EVENT_INSTANT2(event_string.c_str(), "FED", 74 TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, "delay", 75 delay.InMilliseconds()); 76 } 77 } 78 79 void LoggingImpl::InsertPacketListEvent(CastLoggingEvent event, 80 const PacketList& packets) { 81 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 82 for (unsigned int i = 0; i < packets.size(); ++i) { 83 const Packet& packet = packets[i]; 84 // Parse basic properties. 85 uint32 rtp_timestamp; 86 uint16 packet_id, max_packet_id; 87 const uint8* packet_data = &packet[0]; 88 net::BigEndianReader big_endian_reader(packet_data + 4, 4); 89 big_endian_reader.ReadU32(&rtp_timestamp); 90 net::BigEndianReader cast_big_endian_reader(packet_data + 12 + 2, 4); 91 cast_big_endian_reader.ReadU16(&packet_id); 92 cast_big_endian_reader.ReadU16(&max_packet_id); 93 // rtp_timestamp is enough - no need for frame_id as well. 94 InsertPacketEvent(event, rtp_timestamp, kFrameIdUnknown, packet_id, 95 max_packet_id, packet.size()); 96 } 97 } 98 99 void LoggingImpl::InsertPacketEvent(CastLoggingEvent event, 100 uint32 rtp_timestamp, 101 uint32 frame_id, 102 uint16 packet_id, 103 uint16 max_packet_id, 104 size_t size) { 105 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 106 if (config_.enable_data_collection) { 107 raw_.InsertPacketEvent(event, rtp_timestamp, frame_id, packet_id, 108 max_packet_id, size); 109 stats_.InsertPacketEvent(event, rtp_timestamp, frame_id, packet_id, 110 max_packet_id, size); 111 } 112 if (config_.enable_tracing) { 113 std::string event_string = CastLoggingToString(event); 114 TRACE_EVENT_INSTANT2(event_string.c_str(), "PE", 115 TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, 116 "packet_id", packet_id); 117 } 118 } 119 120 void LoggingImpl::InsertGenericEvent(CastLoggingEvent event, int value) { 121 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 122 if (config_.enable_data_collection) { 123 raw_.InsertGenericEvent(event, value); 124 stats_.InsertGenericEvent(event, value); 125 } 126 if (config_.enable_uma_stats) { 127 UMA_HISTOGRAM_COUNTS(CastLoggingToString(event), value); 128 } 129 if (config_.enable_tracing) { 130 std::string event_string = CastLoggingToString(event); 131 TRACE_EVENT_INSTANT1(event_string.c_str(), "GE", 132 TRACE_EVENT_SCOPE_THREAD, "value", value); 133 } 134 } 135 136 // should just get the entire class, would be much easier. 137 FrameRawMap LoggingImpl::GetFrameRawData() { 138 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 139 return raw_.GetFrameData(); 140 } 141 142 PacketRawMap LoggingImpl::GetPacketRawData() { 143 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 144 return raw_.GetPacketData(); 145 } 146 147 GenericRawMap LoggingImpl::GetGenericRawData() { 148 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 149 return raw_.GetGenericData(); 150 } 151 152 const FrameStatsMap* LoggingImpl::GetFrameStatsData() { 153 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 154 // Get stats data. 155 const FrameStatsMap* stats = stats_.GetFrameStatsData(); 156 if (config_.enable_uma_stats) { 157 FrameStatsMap::const_iterator it; 158 for (it = stats->begin(); it != stats->end(); ++it) { 159 // Check for an active event. 160 if (it->second->framerate_fps > 0) { 161 std::string event_string = CastLoggingToString(it->first); 162 UMA_HISTOGRAM_COUNTS(event_string.append("_framerate_fps"), 163 it->second->framerate_fps); 164 } else { 165 // All active frame events trigger framerate computation. 166 continue; 167 } 168 if (it->second->bitrate_kbps > 0) { 169 std::string evnt_string = CastLoggingToString(it->first); 170 UMA_HISTOGRAM_COUNTS(evnt_string.append("_bitrate_kbps"), 171 it->second->framerate_fps); 172 } 173 if (it->second->avg_delay_ms > 0) { 174 std::string event_string = CastLoggingToString(it->first); 175 UMA_HISTOGRAM_COUNTS(event_string.append("_avg_delay_ms"), 176 it->second->avg_delay_ms); 177 UMA_HISTOGRAM_COUNTS(event_string.append("_min_delay_ms"), 178 it->second->min_delay_ms); 179 UMA_HISTOGRAM_COUNTS(event_string.append("_max_delay_ms"), 180 it->second->max_delay_ms); 181 } 182 } 183 } 184 return stats; 185 } 186 187 const PacketStatsMap* LoggingImpl::GetPacketStatsData() { 188 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 189 // Get stats data. 190 const PacketStatsMap* stats = stats_.GetPacketStatsData(); 191 if (config_.enable_uma_stats) { 192 PacketStatsMap::const_iterator it; 193 for (it = stats->begin(); it != stats->end(); ++it) { 194 if (it->second > 0) { 195 std::string event_string = CastLoggingToString(it->first); 196 UMA_HISTOGRAM_COUNTS(event_string.append("_bitrate_kbps"), it->second); 197 } 198 } 199 } 200 return stats; 201 } 202 203 const GenericStatsMap* LoggingImpl::GetGenericStatsData() { 204 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 205 // Get stats data. 206 const GenericStatsMap* stats = stats_.GetGenericStatsData(); 207 if (config_.enable_uma_stats) { 208 GenericStatsMap::const_iterator it; 209 for (it = stats->begin(); it != stats->end(); ++it) { 210 if (it->second > 0) { 211 UMA_HISTOGRAM_COUNTS(CastLoggingToString(it->first), it->second); 212 } 213 } 214 } 215 return stats; 216 } 217 218 void LoggingImpl::Reset() { 219 DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); 220 raw_.Reset(); 221 stats_.Reset(); 222 } 223 224 } // namespace cast 225 } // namespace media 226