C++程序  |  177行  |  6.23 KB

// Copyright 2014 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.

#ifndef MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_
#define MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_

#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/tick_clock.h"
#include "media/cast/logging/logging_defines.h"
#include "media/cast/logging/raw_event_subscriber.h"
#include "media/cast/logging/receiver_time_offset_estimator.h"

namespace base {
class DictionaryValue;
}

namespace media {
namespace cast {

class StatsEventSubscriberTest;

// A RawEventSubscriber implementation that subscribes to events,
// and aggregates them into stats.
class StatsEventSubscriber : public RawEventSubscriber {
 public:
  StatsEventSubscriber(EventMediaType event_media_type,
                       base::TickClock* clock,
                       ReceiverTimeOffsetEstimator* offset_estimator);

  virtual ~StatsEventSubscriber();

  // RawReventSubscriber implementations.
  virtual void OnReceiveFrameEvent(const FrameEvent& frame_event) OVERRIDE;
  virtual void OnReceivePacketEvent(const PacketEvent& packet_event) OVERRIDE;

  // Returns stats as a DictionaryValue. The dictionary contains one entry -
  // "audio" or "video" pointing to an inner dictionary.
  // The inner dictionary consists of string - double entries, where the string
  // describes the name of the stat, and the double describes
  // the value of the stat. See CastStat and StatsMap below.
  scoped_ptr<base::DictionaryValue> GetStats() const;

  // Resets stats in this object.
  void Reset();

 private:
  friend class StatsEventSubscriberTest;
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, EmptyStats);
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, Capture);
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, Encode);
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, Decode);
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, PlayoutDelay);
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, E2ELatency);
  FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, Packets);

  // Generic statistics given the raw data. More specific data (e.g. frame rate
  // and bit rate) can be computed given the basic metrics.
  // Some of the metrics will only be set when applicable, e.g. delay and size.
  struct FrameLogStats {
    FrameLogStats();
    ~FrameLogStats();
    int event_counter;
    size_t sum_size;
    base::TimeDelta sum_delay;
  };

  struct PacketLogStats {
    PacketLogStats();
    ~PacketLogStats();
    int event_counter;
    size_t sum_size;
  };

  enum CastStat {
    // Capture frame rate.
    CAPTURE_FPS,
    // Encode frame rate.
    ENCODE_FPS,
    // Decode frame rate.
    DECODE_FPS,
    // Average encode duration in milliseconds.
    // TODO(imcheng): This stat is not populated yet because we do not have
    // the time when encode started. Record it in FRAME_ENCODED event.
    AVG_ENCODE_TIME_MS,
    // Average playout delay in milliseconds, with target delay already
    // accounted for. Ideally, every frame should have a playout delay of 0.
    AVG_PLAYOUT_DELAY_MS,
    // Duration from when a packet is transmitted to when it is received.
    // This measures latency from sender to receiver.
    AVG_NETWORK_LATENCY_MS,
    // Duration from when a frame is captured to when it should be played out.
    AVG_E2E_LATENCY_MS,
    // Encode bitrate in kbps.
    ENCODE_KBPS,
    // Packet transmission bitrate in kbps.
    TRANSMISSION_KBPS,
    // Packet retransmission bitrate in kbps.
    RETRANSMISSION_KBPS,
    // Fraction of packet loss.
    PACKET_LOSS_FRACTION,
    // Duration in milliseconds since last receiver response.
    MS_SINCE_LAST_RECEIVER_RESPONSE
  };

  typedef std::map<CastStat, double> StatsMap;
  typedef std::map<RtpTimestamp, base::TimeTicks> FrameEventTimeMap;
  typedef std::map<
      std::pair<RtpTimestamp, uint16>,
      std::pair<base::TimeTicks, CastLoggingEvent> >
      PacketEventTimeMap;
  typedef std::map<CastLoggingEvent, FrameLogStats> FrameStatsMap;
  typedef std::map<CastLoggingEvent, PacketLogStats> PacketStatsMap;

  static const char* CastStatToString(CastStat stat);

  // Assigns |stats_map| with stats data. Used for testing.
  void GetStatsInternal(StatsMap* stats_map) const;

  bool GetReceiverOffset(base::TimeDelta* offset);
  void RecordFrameCapturedTime(const FrameEvent& frame_event);
  void RecordE2ELatency(const FrameEvent& frame_event);
  void RecordPacketSentTime(const PacketEvent& packet_event);
  void ErasePacketSentTime(const PacketEvent& packet_event);
  void RecordNetworkLatency(const PacketEvent& packet_event);
  void UpdateLastResponseTime(base::TimeTicks receiver_time);

  void PopulateFpsStat(base::TimeTicks now,
                       CastLoggingEvent event,
                       CastStat stat,
                       StatsMap* stats_map) const;
  void PopulatePlayoutDelayStat(StatsMap* stats_map) const;
  void PopulateFrameBitrateStat(base::TimeTicks now, StatsMap* stats_map) const;
  void PopulatePacketBitrateStat(base::TimeTicks now,
                                 CastLoggingEvent event,
                                 CastStat stat,
                                 StatsMap* stats_map) const;
  void PopulatePacketLossPercentageStat(StatsMap* stats_map) const;

  const EventMediaType event_media_type_;

  // Not owned by this class.
  base::TickClock* const clock_;

  // Not owned by this class.
  ReceiverTimeOffsetEstimator* const offset_estimator_;

  FrameStatsMap frame_stats_;
  PacketStatsMap packet_stats_;

  base::TimeDelta total_network_latency_;
  int network_latency_datapoints_;
  base::TimeDelta total_e2e_latency_;
  int e2e_latency_datapoints_;

  base::TimeTicks last_response_received_time_;

  // Fixed size map to record when recent frames were captured.
  FrameEventTimeMap frame_captured_times_;

  // Fixed size map to record when recent packets were sent.
  PacketEventTimeMap packet_sent_times_;

  // Sender time assigned on creation and |Reset()|.
  base::TimeTicks start_time_;

  base::ThreadChecker thread_checker_;
  DISALLOW_COPY_AND_ASSIGN(StatsEventSubscriber);
};

}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_