// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "media/cast/logging/logging_stats.h" namespace media { namespace cast { LoggingStats::LoggingStats(base::TickClock* clock) : frame_stats_(), packet_stats_(), generic_stats_(), start_time_(), clock_(clock) { memset(counts_, 0, sizeof(counts_)); memset(start_time_, 0, sizeof(start_time_)); } LoggingStats::~LoggingStats() {} void LoggingStats::Reset() { frame_stats_.clear(); packet_stats_.clear(); generic_stats_.clear(); memset(counts_, 0, sizeof(counts_)); } void LoggingStats::InsertFrameEvent(CastLoggingEvent event, uint32 rtp_timestamp, uint32 frame_id) { InsertBaseFrameEvent(event, frame_id, rtp_timestamp); } void LoggingStats::InsertFrameEventWithSize(CastLoggingEvent event, uint32 rtp_timestamp, uint32 frame_id, int frame_size) { InsertBaseFrameEvent(event, frame_id, rtp_timestamp); // Update size. FrameStatsMap::iterator it = frame_stats_.find(event); DCHECK(it != frame_stats_.end()); it->second->bitrate_kbps += frame_size; } void LoggingStats::InsertFrameEventWithDelay(CastLoggingEvent event, uint32 rtp_timestamp, uint32 frame_id, base::TimeDelta delay) { InsertBaseFrameEvent(event, frame_id, rtp_timestamp); // Update size. FrameStatsMap::iterator it = frame_stats_.find(event); DCHECK(it != frame_stats_.end()); // Using the average delay as a counter, will divide by the counter when // triggered. it->second->avg_delay_ms += delay.InMilliseconds(); if (delay.InMilliseconds() > it->second->max_delay_ms) it->second->max_delay_ms = delay.InMilliseconds(); if ((delay.InMilliseconds() < it->second->min_delay_ms) || (counts_[event] == 1) ) it->second->min_delay_ms = delay.InMilliseconds(); } void LoggingStats::InsertBaseFrameEvent(CastLoggingEvent event, uint32 frame_id, uint32 rtp_timestamp) { // Does this belong to an existing event? FrameStatsMap::iterator it = frame_stats_.find(event); if (it == frame_stats_.end()) { // New event. start_time_[event] = clock_->NowTicks(); linked_ptr<FrameLogStats> stats(new FrameLogStats()); frame_stats_.insert(std::make_pair(event, stats)); } ++counts_[event]; } void LoggingStats::InsertPacketEvent(CastLoggingEvent event, uint32 rtp_timestamp, uint32 frame_id, uint16 packet_id, uint16 max_packet_id, size_t size) { // Does this packet belong to an existing event? PacketStatsMap::iterator it = packet_stats_.find(event); if (it == packet_stats_.end()) { // New event. start_time_[event] = clock_->NowTicks(); packet_stats_.insert(std::make_pair(event, size)); } else { // Add to existing. it->second += size; } ++counts_[event]; } void LoggingStats::InsertGenericEvent(CastLoggingEvent event, int value) { // Does this event belong to an existing event? GenericStatsMap::iterator it = generic_stats_.find(event); if (it == generic_stats_.end()) { // New event. start_time_[event] = clock_->NowTicks(); generic_stats_.insert(std::make_pair(event, value)); } else { // Add to existing (will be used to compute average). it->second += value; } ++counts_[event]; } const FrameStatsMap* LoggingStats::GetFrameStatsData() { // Compute framerate and bitrate (when available). FrameStatsMap::iterator it; for (it = frame_stats_.begin(); it != frame_stats_.end(); ++it) { base::TimeDelta time_diff = clock_->NowTicks() - start_time_[it->first]; it->second->framerate_fps = counts_[it->first] / time_diff.InSecondsF(); if (it->second->bitrate_kbps > 0) { it->second->bitrate_kbps = (8 / 1000) * it->second->bitrate_kbps / time_diff.InSecondsF(); } if (it->second->avg_delay_ms > 0) it->second->avg_delay_ms /= counts_[it->first]; } return &frame_stats_; } const PacketStatsMap* LoggingStats::GetPacketStatsData() { PacketStatsMap::iterator it; for (it = packet_stats_.begin(); it != packet_stats_.end(); ++it) { if (counts_[it->first] == 0) continue; base::TimeDelta time_diff = clock_->NowTicks() - start_time_[it->first]; it->second = (8 / 1000) * it->second / time_diff.InSecondsF(); } return &packet_stats_; } const GenericStatsMap* LoggingStats::GetGenericStatsData() { // Compute averages. GenericStatsMap::iterator it; for (it = generic_stats_.begin(); it != generic_stats_.end(); ++it) { it->second /= counts_[ it->first]; } return &generic_stats_; } } // namespace cast } // namespace media