普通文本  |  226行  |  8.37 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/debug/trace_event.h"
#include "base/metrics/histogram.h"
#include "media/cast/logging/logging_impl.h"
#include "net/base/big_endian.h"

namespace media {
namespace cast {

LoggingImpl::LoggingImpl(base::TickClock* clock,
                         scoped_refptr<base::TaskRunner> main_thread_proxy,
                         const CastLoggingConfig& config)
    : main_thread_proxy_(main_thread_proxy),
      config_(config),
      raw_(clock),
      stats_(clock) {}

LoggingImpl::~LoggingImpl() {}

void LoggingImpl::InsertFrameEvent(CastLoggingEvent event,
                                   uint32 rtp_timestamp,
                                   uint32 frame_id) {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  if (config_.enable_data_collection) {
    raw_.InsertFrameEvent(event, rtp_timestamp, frame_id);
    stats_.InsertFrameEvent(event, rtp_timestamp, frame_id);
  }
  if (config_.enable_tracing) {
    std::string event_string = CastLoggingToString(event);
    TRACE_EVENT_INSTANT2(event_string.c_str(), "FE",
        TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, "frame_id",
        frame_id);
  }
}

void LoggingImpl::InsertFrameEventWithSize(CastLoggingEvent event,
                                           uint32 rtp_timestamp,
                                           uint32 frame_id,
                                           int frame_size) {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  if (config_.enable_data_collection) {
    raw_.InsertFrameEventWithSize(event, rtp_timestamp, frame_id, frame_size);
    stats_.InsertFrameEventWithSize(event, rtp_timestamp, frame_id, frame_size);
  }
  if (config_.enable_uma_stats) {
    UMA_HISTOGRAM_COUNTS(CastLoggingToString(event), frame_size);
  }
  if (config_.enable_tracing) {
    std::string event_string = CastLoggingToString(event);
    TRACE_EVENT_INSTANT2(event_string.c_str(), "FES",
        TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, "frame_size",
        frame_size);
  }
}

void LoggingImpl::InsertFrameEventWithDelay(CastLoggingEvent event,
                                            uint32 rtp_timestamp,
                                            uint32 frame_id,
                                            base::TimeDelta delay) {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  if (config_.enable_data_collection) {
    raw_.InsertFrameEventWithDelay(event, rtp_timestamp, frame_id, delay);
    stats_.InsertFrameEventWithDelay(event, rtp_timestamp, frame_id, delay);
  }
  if (config_.enable_uma_stats) {
    UMA_HISTOGRAM_TIMES(CastLoggingToString(event), delay);
  }
  if (config_.enable_tracing) {
    std::string event_string = CastLoggingToString(event);
    TRACE_EVENT_INSTANT2(event_string.c_str(), "FED",
        TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp, "delay",
        delay.InMilliseconds());
  }
}

void LoggingImpl::InsertPacketListEvent(CastLoggingEvent event,
                                        const PacketList& packets) {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  for (unsigned int i = 0; i < packets.size(); ++i) {
    const Packet& packet = packets[i];
    // Parse basic properties.
    uint32 rtp_timestamp;
    uint16 packet_id, max_packet_id;
    const uint8* packet_data = &packet[0];
    net::BigEndianReader big_endian_reader(packet_data + 4, 4);
    big_endian_reader.ReadU32(&rtp_timestamp);
    net::BigEndianReader cast_big_endian_reader(packet_data + 12 + 2, 4);
    cast_big_endian_reader.ReadU16(&packet_id);
    cast_big_endian_reader.ReadU16(&max_packet_id);
    // rtp_timestamp is enough - no need for frame_id as well.
    InsertPacketEvent(event, rtp_timestamp, kFrameIdUnknown, packet_id,
                      max_packet_id, packet.size());
  }
}

void LoggingImpl::InsertPacketEvent(CastLoggingEvent event,
                                    uint32 rtp_timestamp,
                                    uint32 frame_id,
                                    uint16 packet_id,
                                    uint16 max_packet_id,
                                    size_t size) {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  if (config_.enable_data_collection) {
    raw_.InsertPacketEvent(event, rtp_timestamp, frame_id, packet_id,
                           max_packet_id, size);
    stats_.InsertPacketEvent(event, rtp_timestamp, frame_id, packet_id,
                             max_packet_id, size);
  }
  if (config_.enable_tracing) {
    std::string event_string = CastLoggingToString(event);
    TRACE_EVENT_INSTANT2(event_string.c_str(), "PE",
        TRACE_EVENT_SCOPE_THREAD, "rtp_timestamp", rtp_timestamp,
        "packet_id", packet_id);
  }
}

void LoggingImpl::InsertGenericEvent(CastLoggingEvent event, int value) {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  if (config_.enable_data_collection) {
    raw_.InsertGenericEvent(event, value);
    stats_.InsertGenericEvent(event, value);
  }
  if (config_.enable_uma_stats) {
    UMA_HISTOGRAM_COUNTS(CastLoggingToString(event), value);
  }
  if (config_.enable_tracing) {
    std::string event_string = CastLoggingToString(event);
    TRACE_EVENT_INSTANT1(event_string.c_str(), "GE",
        TRACE_EVENT_SCOPE_THREAD, "value", value);
  }
}

// should just get the entire class, would be much easier.
FrameRawMap LoggingImpl::GetFrameRawData() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  return raw_.GetFrameData();
}

PacketRawMap LoggingImpl::GetPacketRawData() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  return raw_.GetPacketData();
}

GenericRawMap LoggingImpl::GetGenericRawData() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  return raw_.GetGenericData();
}

const FrameStatsMap* LoggingImpl::GetFrameStatsData() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  // Get stats data.
  const FrameStatsMap* stats = stats_.GetFrameStatsData();
  if (config_.enable_uma_stats) {
    FrameStatsMap::const_iterator it;
    for (it = stats->begin(); it != stats->end(); ++it) {
      // Check for an active event.
      if (it->second->framerate_fps > 0) {
        std::string event_string = CastLoggingToString(it->first);
        UMA_HISTOGRAM_COUNTS(event_string.append("_framerate_fps"),
                             it->second->framerate_fps);
      } else {
        // All active frame events trigger framerate computation.
        continue;
      }
      if (it->second->bitrate_kbps > 0) {
        std::string evnt_string = CastLoggingToString(it->first);
        UMA_HISTOGRAM_COUNTS(evnt_string.append("_bitrate_kbps"),
                             it->second->framerate_fps);
      }
      if (it->second->avg_delay_ms > 0) {
        std::string event_string = CastLoggingToString(it->first);
        UMA_HISTOGRAM_COUNTS(event_string.append("_avg_delay_ms"),
                             it->second->avg_delay_ms);
        UMA_HISTOGRAM_COUNTS(event_string.append("_min_delay_ms"),
                             it->second->min_delay_ms);
        UMA_HISTOGRAM_COUNTS(event_string.append("_max_delay_ms"),
                             it->second->max_delay_ms);
      }
    }
  }
  return stats;
}

const PacketStatsMap* LoggingImpl::GetPacketStatsData() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  // Get stats data.
  const PacketStatsMap* stats = stats_.GetPacketStatsData();
  if (config_.enable_uma_stats) {
    PacketStatsMap::const_iterator it;
    for (it = stats->begin(); it != stats->end(); ++it) {
      if (it->second > 0) {
        std::string event_string = CastLoggingToString(it->first);
        UMA_HISTOGRAM_COUNTS(event_string.append("_bitrate_kbps"), it->second);
      }
    }
  }
  return stats;
}

const GenericStatsMap* LoggingImpl::GetGenericStatsData() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  // Get stats data.
  const GenericStatsMap* stats = stats_.GetGenericStatsData();
  if (config_.enable_uma_stats) {
    GenericStatsMap::const_iterator it;
    for (it = stats->begin(); it != stats->end(); ++it) {
      if (it->second > 0) {
        UMA_HISTOGRAM_COUNTS(CastLoggingToString(it->first), it->second);
      }
    }
  }
  return stats;
}

void LoggingImpl::Reset() {
  DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
  raw_.Reset();
  stats_.Reset();
}

}  // namespace cast
}  // namespace media