普通文本  |  151行  |  5.17 KB

// 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