1 /*
2  *  Copyright (c) 2018 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_VIDEO_QUALITY_OBSERVER_H_
12 #define VIDEO_VIDEO_QUALITY_OBSERVER_H_
13 
14 #include <stdint.h>
15 
16 #include <set>
17 #include <vector>
18 
19 #include "absl/types/optional.h"
20 #include "api/video/video_codec_type.h"
21 #include "api/video/video_content_type.h"
22 #include "api/video/video_frame.h"
23 #include "rtc_base/numerics/moving_average.h"
24 #include "rtc_base/numerics/sample_counter.h"
25 
26 namespace webrtc {
27 
28 // Calculates spatial and temporal quality metrics and reports them to UMA
29 // stats.
30 class VideoQualityObserver {
31  public:
32   // Use either VideoQualityObserver::kBlockyQpThresholdVp8 or
33   // VideoQualityObserver::kBlockyQpThresholdVp9.
34   explicit VideoQualityObserver(VideoContentType content_type);
35   ~VideoQualityObserver() = default;
36 
37   void OnDecodedFrame(const VideoFrame& frame,
38                       absl::optional<uint8_t> qp,
39                       VideoCodecType codec);
40 
41   void OnRenderedFrame(const VideoFrame& frame, int64_t now_ms);
42 
43   void OnStreamInactive();
44 
45   uint32_t NumFreezes() const;
46   uint32_t NumPauses() const;
47   uint32_t TotalFreezesDurationMs() const;
48   uint32_t TotalPausesDurationMs() const;
49   uint32_t TotalFramesDurationMs() const;
50   double SumSquaredFrameDurationsSec() const;
51 
52   void UpdateHistograms();
53 
54   static const uint32_t kMinFrameSamplesToDetectFreeze;
55   static const uint32_t kMinIncreaseForFreezeMs;
56   static const uint32_t kAvgInterframeDelaysWindowSizeFrames;
57 
58  private:
59   enum Resolution {
60     Low = 0,
61     Medium = 1,
62     High = 2,
63   };
64 
65   int64_t last_frame_rendered_ms_;
66   int64_t num_frames_rendered_;
67   int64_t first_frame_rendered_ms_;
68   int64_t last_frame_pixels_;
69   bool is_last_frame_blocky_;
70   // Decoded timestamp of the last delayed frame.
71   int64_t last_unfreeze_time_ms_;
72   rtc::MovingAverage render_interframe_delays_;
73   double sum_squared_interframe_delays_secs_;
74   // An inter-frame delay is counted as a freeze if it's significantly longer
75   // than average inter-frame delay.
76   rtc::SampleCounter freezes_durations_;
77   rtc::SampleCounter pauses_durations_;
78   // Time between freezes.
79   rtc::SampleCounter smooth_playback_durations_;
80   // Counters for time spent in different resolutions. Time between each two
81   // Consecutive frames is counted to bin corresponding to the first frame
82   // resolution.
83   std::vector<int64_t> time_in_resolution_ms_;
84   // Resolution of the last decoded frame. Resolution enum is used as an index.
85   Resolution current_resolution_;
86   int num_resolution_downgrades_;
87   // Similar to resolution, time spent in high-QP video.
88   int64_t time_in_blocky_video_ms_;
89   // Content type of the last decoded frame.
90   VideoContentType content_type_;
91   bool is_paused_;
92 
93   // Set of decoded frames with high QP value.
94   std::set<int64_t> blocky_frames_;
95 };
96 
97 }  // namespace webrtc
98 
99 #endif  // VIDEO_VIDEO_QUALITY_OBSERVER_H_
100