// 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 #include #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/linked_ptr.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; class ListValue; } 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); ~StatsEventSubscriber() final; // RawReventSubscriber implementations. void OnReceiveFrameEvent(const FrameEvent& frame_event) final; void OnReceivePacketEvent(const PacketEvent& packet_event) final; // 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 GetStats() const; // Resets stats in this object. void Reset(); private: friend class StatsEventSubscriberTest; FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, EmptyStats); FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, CaptureEncode); 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); FRIEND_TEST_ALL_PREFIXES(StatsEventSubscriberTest, Histograms); static const size_t kMaxFrameInfoMapSize = 100; // 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; }; class SimpleHistogram { public: // This will create N+2 buckets where N = (max - min) / width: // Underflow bucket: < min // Bucket 0: [min, min + width - 1] // Bucket 1: [min + width, min + 2 * width - 1] // ... // Bucket N-1: [max - width, max - 1] // Overflow bucket: >= max // |min| must be less than |max|. // |width| must divide |max - min| evenly. SimpleHistogram(int64_t min, int64_t max, int64_t width); ~SimpleHistogram(); void Add(int64_t sample); void Reset(); scoped_ptr GetHistogram() const; private: int64_t min_; int64_t max_; int64_t width_; std::vector buckets_; }; enum CastStat { // Capture frame rate. CAPTURE_FPS, // Encode frame rate. ENCODE_FPS, // Decode frame rate. DECODE_FPS, // Average capture latency in milliseconds. AVG_CAPTURE_LATENCY_MS, // Average encode duration in milliseconds. AVG_ENCODE_TIME_MS, // Duration from when a frame is encoded to when the packet is first // sent. AVG_QUEUEING_LATENCY_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 encoded to when the packet is first // received. AVG_PACKET_LATENCY_MS, // Average latency between frame encoded and the moment when the frame // is fully received. AVG_FRAME_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, // Duration in milliseconds since last receiver response. MS_SINCE_LAST_RECEIVER_RESPONSE, // Number of frames captured. NUM_FRAMES_CAPTURED, // Number of frames dropped by encoder. NUM_FRAMES_DROPPED_BY_ENCODER, // Number of late frames. NUM_FRAMES_LATE, // Number of packets that were sent (not retransmitted). NUM_PACKETS_SENT, // Number of packets that were retransmitted. NUM_PACKETS_RETRANSMITTED, // Number of packets that were received by receiver. NUM_PACKETS_RECEIVED, // Number of packets that had their retransmission cancelled. NUM_PACKETS_RTX_REJECTED, // Unix time in milliseconds of first event since reset. FIRST_EVENT_TIME_MS, // Unix time in milliseconds of last event since reset. LAST_EVENT_TIME_MS, // Histograms CAPTURE_LATENCY_MS_HISTO, ENCODE_TIME_MS_HISTO, QUEUEING_LATENCY_MS_HISTO, NETWORK_LATENCY_MS_HISTO, PACKET_LATENCY_MS_HISTO, FRAME_LATENCY_MS_HISTO, E2E_LATENCY_MS_HISTO, LATE_FRAME_MS_HISTO }; struct FrameInfo { FrameInfo(); ~FrameInfo(); base::TimeTicks capture_time; base::TimeTicks capture_end_time; base::TimeTicks encode_end_time; bool encoded; }; typedef std::map StatsMap; typedef std::map > HistogramMap; typedef std::map FrameInfoMap; typedef std::map, std::pair> PacketEventTimeMap; typedef std::map FrameStatsMap; typedef std::map PacketStatsMap; static const char* CastStatToString(CastStat stat); void InitHistograms(); // Assigns |stats_map| with stats data. Used for testing. void GetStatsInternal(StatsMap* stats_map) const; // Return a histogram of the type specified. SimpleHistogram* GetHistogramForTesting(CastStat stats) const; void UpdateFirstLastEventTime(base::TimeTicks timestamp, bool is_receiver_event); bool GetReceiverOffset(base::TimeDelta* offset); void MaybeInsertFrameInfo(RtpTimeTicks rtp_timestamp, const FrameInfo& frame_info); void RecordFrameCaptureTime(const FrameEvent& frame_event); void RecordCaptureLatency(const FrameEvent& frame_event); void RecordEncodeLatency(const FrameEvent& frame_event); void RecordFrameTxLatency(const FrameEvent& frame_event); void RecordE2ELatency(const FrameEvent& frame_event); void RecordPacketSentTime(const PacketEvent& packet_event); void ErasePacketSentTime(const PacketEvent& packet_event); void RecordPacketRelatedLatencies(const PacketEvent& packet_event); void UpdateLastResponseTime(base::TimeTicks receiver_time); void PopulateFpsStat(base::TimeTicks now, CastLoggingEvent event, CastStat stat, StatsMap* stats_map) const; void PopulateFrameCountStat(CastLoggingEvent event, CastStat stat, StatsMap* stats_map) const; void PopulatePacketCountStat(CastLoggingEvent event, CastStat stat, 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; 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_capture_latency_; int capture_latency_datapoints_; base::TimeDelta total_encode_time_; int encode_time_datapoints_; base::TimeDelta total_queueing_latency_; int queueing_latency_datapoints_; base::TimeDelta total_network_latency_; int network_latency_datapoints_; base::TimeDelta total_packet_latency_; int packet_latency_datapoints_; base::TimeDelta total_frame_latency_; int frame_latency_datapoints_; base::TimeDelta total_e2e_latency_; int e2e_latency_datapoints_; base::TimeTicks last_response_received_time_; int num_frames_dropped_by_encoder_; int num_frames_late_; // Fixed size map to record when recent frames were captured and other info. FrameInfoMap recent_frame_infos_; // 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::TimeTicks first_event_time_; base::TimeTicks last_event_time_; HistogramMap histograms_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(StatsEventSubscriber); }; } // namespace cast } // namespace media #endif // MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_