1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef VIDEO_RECEIVE_STATISTICS_PROXY_H_ 12 #define VIDEO_RECEIVE_STATISTICS_PROXY_H_ 13 14 #include <map> 15 #include <memory> 16 #include <string> 17 #include <vector> 18 19 #include "absl/types/optional.h" 20 #include "call/video_receive_stream.h" 21 #include "modules/include/module_common_types.h" 22 #include "modules/video_coding/include/video_coding_defines.h" 23 #include "rtc_base/numerics/histogram_percentile_counter.h" 24 #include "rtc_base/numerics/moving_max_counter.h" 25 #include "rtc_base/numerics/sample_counter.h" 26 #include "rtc_base/rate_statistics.h" 27 #include "rtc_base/rate_tracker.h" 28 #include "rtc_base/synchronization/mutex.h" 29 #include "rtc_base/thread_annotations.h" 30 #include "rtc_base/thread_checker.h" 31 #include "video/quality_threshold.h" 32 #include "video/stats_counter.h" 33 #include "video/video_quality_observer.h" 34 35 namespace webrtc { 36 37 class Clock; 38 struct CodecSpecificInfo; 39 40 class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, 41 public RtcpCnameCallback, 42 public RtcpPacketTypeCounterObserver, 43 public CallStatsObserver { 44 public: 45 ReceiveStatisticsProxy(const VideoReceiveStream::Config* config, 46 Clock* clock); 47 ~ReceiveStatisticsProxy() = default; 48 49 VideoReceiveStream::Stats GetStats() const; 50 51 void OnDecodedFrame(const VideoFrame& frame, 52 absl::optional<uint8_t> qp, 53 int32_t decode_time_ms, 54 VideoContentType content_type); 55 void OnSyncOffsetUpdated(int64_t video_playout_ntp_ms, 56 int64_t sync_offset_ms, 57 double estimated_freq_khz); 58 void OnRenderedFrame(const VideoFrame& frame); 59 void OnIncomingPayloadType(int payload_type); 60 void OnDecoderImplementationName(const char* implementation_name); 61 62 void OnPreDecode(VideoCodecType codec_type, int qp); 63 64 void OnUniqueFramesCounted(int num_unique_frames); 65 66 // Indicates video stream has been paused (no incoming packets). 67 void OnStreamInactive(); 68 69 // Overrides VCMReceiveStatisticsCallback. 70 void OnCompleteFrame(bool is_keyframe, 71 size_t size_bytes, 72 VideoContentType content_type) override; 73 void OnDroppedFrames(uint32_t frames_dropped) override; 74 void OnFrameBufferTimingsUpdated(int max_decode_ms, 75 int current_delay_ms, 76 int target_delay_ms, 77 int jitter_buffer_ms, 78 int min_playout_delay_ms, 79 int render_delay_ms) override; 80 81 void OnTimingFrameInfoUpdated(const TimingFrameInfo& info) override; 82 83 // Overrides RtcpCnameCallback. 84 void OnCname(uint32_t ssrc, absl::string_view cname) override; 85 86 // Overrides RtcpPacketTypeCounterObserver. 87 void RtcpPacketTypesCounterUpdated( 88 uint32_t ssrc, 89 const RtcpPacketTypeCounter& packet_counter) override; 90 91 // Implements CallStatsObserver. 92 void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; 93 94 // Notification methods that are used to check our internal state and validate 95 // threading assumptions. These are called by VideoReceiveStream. 96 void DecoderThreadStarting(); 97 void DecoderThreadStopped(); 98 99 // Produce histograms. Must be called after DecoderThreadStopped(), typically 100 // at the end of the call. 101 void UpdateHistograms(absl::optional<int> fraction_lost, 102 const StreamDataCounters& rtp_stats, 103 const StreamDataCounters* rtx_stats); 104 105 private: 106 struct QpCounters { 107 rtc::SampleCounter vp8; 108 }; 109 110 struct ContentSpecificStats { 111 ContentSpecificStats(); 112 ~ContentSpecificStats(); 113 114 void Add(const ContentSpecificStats& other); 115 116 rtc::SampleCounter e2e_delay_counter; 117 rtc::SampleCounter interframe_delay_counter; 118 int64_t flow_duration_ms = 0; 119 int64_t total_media_bytes = 0; 120 rtc::SampleCounter received_width; 121 rtc::SampleCounter received_height; 122 rtc::SampleCounter qp_counter; 123 FrameCounts frame_counts; 124 rtc::HistogramPercentileCounter interframe_delay_percentiles; 125 }; 126 127 void QualitySample() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 128 129 // Removes info about old frames and then updates the framerate. 130 void UpdateFramerate(int64_t now_ms) const 131 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 132 133 void UpdateDecodeTimeHistograms(int width, 134 int height, 135 int decode_time_ms) const 136 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 137 138 absl::optional<int64_t> GetCurrentEstimatedPlayoutNtpTimestampMs( 139 int64_t now_ms) const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 140 141 Clock* const clock_; 142 // Ownership of this object lies with the owner of the ReceiveStatisticsProxy 143 // instance. Lifetime is guaranteed to outlive |this|. 144 // TODO(tommi): In practice the config_ reference is only used for accessing 145 // config_.rtp.ulpfec.ulpfec_payload_type. Instead of holding a pointer back, 146 // we could just store the value of ulpfec_payload_type and change the 147 // ReceiveStatisticsProxy() ctor to accept a const& of Config (since we'll 148 // then no longer store a pointer to the object). 149 const VideoReceiveStream::Config& config_; 150 const int64_t start_ms_; 151 const bool enable_decode_time_histograms_; 152 153 mutable Mutex mutex_; 154 int64_t last_sample_time_ RTC_GUARDED_BY(mutex_); 155 QualityThreshold fps_threshold_ RTC_GUARDED_BY(mutex_); 156 QualityThreshold qp_threshold_ RTC_GUARDED_BY(mutex_); 157 QualityThreshold variance_threshold_ RTC_GUARDED_BY(mutex_); 158 rtc::SampleCounter qp_sample_ RTC_GUARDED_BY(mutex_); 159 int num_bad_states_ RTC_GUARDED_BY(mutex_); 160 int num_certain_states_ RTC_GUARDED_BY(mutex_); 161 // Note: The |stats_.rtp_stats| member is not used or populated by this class. 162 mutable VideoReceiveStream::Stats stats_ RTC_GUARDED_BY(mutex_); 163 RateStatistics decode_fps_estimator_ RTC_GUARDED_BY(mutex_); 164 RateStatistics renders_fps_estimator_ RTC_GUARDED_BY(mutex_); 165 rtc::RateTracker render_fps_tracker_ RTC_GUARDED_BY(mutex_); 166 rtc::RateTracker render_pixel_tracker_ RTC_GUARDED_BY(mutex_); 167 rtc::SampleCounter sync_offset_counter_ RTC_GUARDED_BY(mutex_); 168 rtc::SampleCounter decode_time_counter_ RTC_GUARDED_BY(mutex_); 169 rtc::SampleCounter jitter_buffer_delay_counter_ RTC_GUARDED_BY(mutex_); 170 rtc::SampleCounter target_delay_counter_ RTC_GUARDED_BY(mutex_); 171 rtc::SampleCounter current_delay_counter_ RTC_GUARDED_BY(mutex_); 172 rtc::SampleCounter delay_counter_ RTC_GUARDED_BY(mutex_); 173 std::unique_ptr<VideoQualityObserver> video_quality_observer_ 174 RTC_GUARDED_BY(mutex_); 175 mutable rtc::MovingMaxCounter<int> interframe_delay_max_moving_ 176 RTC_GUARDED_BY(mutex_); 177 std::map<VideoContentType, ContentSpecificStats> content_specific_stats_ 178 RTC_GUARDED_BY(mutex_); 179 MaxCounter freq_offset_counter_ RTC_GUARDED_BY(mutex_); 180 QpCounters qp_counters_ RTC_GUARDED_BY(decode_thread_); 181 int64_t avg_rtt_ms_ RTC_GUARDED_BY(mutex_); 182 mutable std::map<int64_t, size_t> frame_window_ RTC_GUARDED_BY(&mutex_); 183 VideoContentType last_content_type_ RTC_GUARDED_BY(&mutex_); 184 VideoCodecType last_codec_type_ RTC_GUARDED_BY(&mutex_); 185 absl::optional<int64_t> first_frame_received_time_ms_ RTC_GUARDED_BY(&mutex_); 186 absl::optional<int64_t> first_decoded_frame_time_ms_ RTC_GUARDED_BY(&mutex_); 187 absl::optional<int64_t> last_decoded_frame_time_ms_ RTC_GUARDED_BY(&mutex_); 188 size_t num_delayed_frames_rendered_ RTC_GUARDED_BY(&mutex_); 189 int64_t sum_missed_render_deadline_ms_ RTC_GUARDED_BY(&mutex_); 190 // Mutable because calling Max() on MovingMaxCounter is not const. Yet it is 191 // called from const GetStats(). 192 mutable rtc::MovingMaxCounter<TimingFrameInfo> timing_frame_info_counter_ 193 RTC_GUARDED_BY(&mutex_); 194 absl::optional<int> num_unique_frames_ RTC_GUARDED_BY(mutex_); 195 absl::optional<int64_t> last_estimated_playout_ntp_timestamp_ms_ 196 RTC_GUARDED_BY(&mutex_); 197 absl::optional<int64_t> last_estimated_playout_time_ms_ 198 RTC_GUARDED_BY(&mutex_); 199 rtc::ThreadChecker decode_thread_; 200 rtc::ThreadChecker network_thread_; 201 rtc::ThreadChecker main_thread_; 202 }; 203 204 } // namespace webrtc 205 #endif // VIDEO_RECEIVE_STATISTICS_PROXY_H_ 206