| // 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, 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); |
| |
| 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; |
| }; |
| |
| 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. |
| 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, |
| // 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 had their retransmission cancelled. |
| NUM_PACKETS_RTX_REJECTED, |
| }; |
| |
| struct FrameInfo { |
| explicit FrameInfo(base::TimeTicks capture_time); |
| ~FrameInfo(); |
| |
| base::TimeTicks capture_time; |
| bool encoded; |
| }; |
| |
| typedef std::map<CastStat, double> StatsMap; |
| typedef std::map<RtpTimestamp, FrameInfo> FrameInfoMap; |
| 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 RecordFrameCaptureTime(const FrameEvent& frame_event); |
| void MarkAsEncoded(RtpTimestamp rtp_timestamp); |
| 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 PopulateFrameCountStat(CastLoggingEvent event, |
| CastStat stat, |
| StatsMap* stats_map) const; |
| void PopulatePacketCountStat(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_; |
| |
| 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_captured_frames_; |
| |
| // 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_ |