blob: 19c8ca7d62424b4d2e700d2c14ef2c691bc79d62 [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef VIDEO_SEND_STATISTICS_PROXY_H_
12#define VIDEO_SEND_STATISTICS_PROXY_H_
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000013
mflodmand1590b22015-12-09 07:07:59 -080014#include <map>
kwiberg27f982b2016-03-01 11:52:33 -080015#include <memory>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000016#include <string>
Pera48ddb72016-09-29 11:48:50 +020017#include <vector>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000018
Mirko Bonadei71207422017-09-15 13:58:09 +020019#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/video_coding/include/video_codec_interface.h"
21#include "modules/video_coding/include/video_coding_defines.h"
22#include "rtc_base/criticalsection.h"
23#include "rtc_base/numerics/exp_filter.h"
24#include "rtc_base/ratetracker.h"
25#include "rtc_base/thread_annotations.h"
26#include "system_wrappers/include/clock.h"
27#include "video/overuse_frame_detector.h"
28#include "video/report_block_stats.h"
29#include "video/stats_counter.h"
30#include "video/video_stream_encoder.h"
31#include "call/video_send_stream.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000032
33namespace webrtc {
34
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000035class SendStatisticsProxy : public CpuOveruseMetricsObserver,
36 public RtcpStatisticsCallback,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000037 public RtcpPacketTypeCounterObserver,
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000038 public StreamDataCountersCallback,
39 public BitrateStatisticsObserver,
40 public FrameCountObserver,
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000041 public SendSideDelayObserver {
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000042 public:
pbos@webrtc.org273a4142014-12-01 15:23:21 +000043 static const int kStatsTimeoutMs;
perkj803d97f2016-11-01 11:45:46 -070044 // Number of required samples to be collected before a metric is added
45 // to a rtc histogram.
46 static const int kMinRequiredMetricsSamples = 200;
pbos@webrtc.org273a4142014-12-01 15:23:21 +000047
sprangb4a1ae52015-12-03 08:10:08 -080048 SendStatisticsProxy(Clock* clock,
49 const VideoSendStream::Config& config,
50 VideoEncoderConfig::ContentType content_type);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000051 virtual ~SendStatisticsProxy();
52
sprangc5d62e22017-04-02 23:53:04 -070053 virtual VideoSendStream::Stats GetStats();
pbos@webrtc.org273a4142014-12-01 15:23:21 +000054
55 virtual void OnSendEncodedImage(const EncodedImage& encoded_image,
kjellander02b3d272016-04-20 05:05:54 -070056 const CodecSpecificInfo* codec_info);
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +000057 // Used to update incoming frame rate.
asaperssond89920b2015-07-22 06:52:00 -070058 void OnIncomingFrame(int width, int height);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000059
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +020060 // Dropped frame stats.
61 void OnFrameDroppedBySource();
62 void OnFrameDroppedInEncoderQueue();
63 void OnFrameDroppedByEncoder();
64 void OnFrameDroppedByMediaOptimizations();
65
asapersson09f05612017-05-15 23:40:18 -070066 // Adaptation stats.
mflodmancc3d4422017-08-03 08:27:51 -070067 void SetAdaptationStats(
68 const VideoStreamEncoder::AdaptCounts& cpu_counts,
69 const VideoStreamEncoder::AdaptCounts& quality_counts);
70 void OnCpuAdaptationChanged(
71 const VideoStreamEncoder::AdaptCounts& cpu_counts,
72 const VideoStreamEncoder::AdaptCounts& quality_counts);
asapersson09f05612017-05-15 23:40:18 -070073 void OnQualityAdaptationChanged(
mflodmancc3d4422017-08-03 08:27:51 -070074 const VideoStreamEncoder::AdaptCounts& cpu_counts,
75 const VideoStreamEncoder::AdaptCounts& quality_counts);
perkj803d97f2016-11-01 11:45:46 -070076
Peter Boström7083e112015-09-22 16:28:51 +020077 void OnSuspendChange(bool is_suspended);
Peter Boström20f3f942015-05-15 11:33:39 +020078 void OnInactiveSsrc(uint32_t ssrc);
79
sprangb4a1ae52015-12-03 08:10:08 -080080 // Used to indicate change in content type, which may require a change in
Pera48ddb72016-09-29 11:48:50 +020081 // how stats are collected and set the configured preferred media bitrate.
82 void OnEncoderReconfigured(const VideoEncoderConfig& encoder_config,
83 uint32_t preferred_bitrate_bps);
sprangb4a1ae52015-12-03 08:10:08 -080084
perkjf5b2e512016-07-05 08:34:04 -070085 // Used to update the encoder target rate.
86 void OnSetEncoderTargetRate(uint32_t bitrate_bps);
Peter Boströme4499152016-02-05 11:13:28 +010087
88 // Implements CpuOveruseMetricsObserver.
89 void OnEncodedFrameTimeMeasured(int encode_time_ms,
90 const CpuOveruseMetrics& metrics) override;
91
Per69b332d2016-06-02 15:45:42 +020092 int GetSendFrameRate() const;
93
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000094 protected:
95 // From RtcpStatisticsCallback.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000096 void StatisticsUpdated(const RtcpStatistics& statistics,
97 uint32_t ssrc) override;
98 void CNameChanged(const char* cname, uint32_t ssrc) override;
asaperssond89920b2015-07-22 06:52:00 -070099 // From RtcpPacketTypeCounterObserver.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000100 void RtcpPacketTypesCounterUpdated(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000101 uint32_t ssrc,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000102 const RtcpPacketTypeCounter& packet_counter) override;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000103 // From StreamDataCountersCallback.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000104 void DataCountersUpdated(const StreamDataCounters& counters,
105 uint32_t ssrc) override;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000106
107 // From BitrateStatisticsObserver.
sprangcd349d92016-07-13 09:11:28 -0700108 void Notify(uint32_t total_bitrate_bps,
109 uint32_t retransmit_bitrate_bps,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000110 uint32_t ssrc) override;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000111
112 // From FrameCountObserver.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000113 void FrameCountUpdated(const FrameCounts& frame_counts,
114 uint32_t ssrc) override;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000115
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000116 void SendSideDelayUpdated(int avg_delay_ms,
117 int max_delay_ms,
118 uint32_t ssrc) override;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000119
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000120 private:
asaperssonda535c42015-10-19 23:32:41 -0700121 class SampleCounter {
122 public:
asaperssond89920b2015-07-22 06:52:00 -0700123 SampleCounter() : sum(0), num_samples(0) {}
asaperssonda535c42015-10-19 23:32:41 -0700124 ~SampleCounter() {}
asaperssond89920b2015-07-22 06:52:00 -0700125 void Add(int sample);
asapersson66d4b372016-12-19 06:50:53 -0800126 int Avg(int64_t min_required_samples) const;
asaperssond89920b2015-07-22 06:52:00 -0700127
128 private:
asapersson66d4b372016-12-19 06:50:53 -0800129 int64_t sum;
130 int64_t num_samples;
asaperssond89920b2015-07-22 06:52:00 -0700131 };
asaperssonda535c42015-10-19 23:32:41 -0700132 class BoolSampleCounter {
133 public:
asaperssondec5ebf2015-10-05 02:36:17 -0700134 BoolSampleCounter() : sum(0), num_samples(0) {}
asaperssonda535c42015-10-19 23:32:41 -0700135 ~BoolSampleCounter() {}
asaperssondec5ebf2015-10-05 02:36:17 -0700136 void Add(bool sample);
asapersson66d4b372016-12-19 06:50:53 -0800137 void Add(bool sample, int64_t count);
138 int Percent(int64_t min_required_samples) const;
139 int Permille(int64_t min_required_samples) const;
asaperssondec5ebf2015-10-05 02:36:17 -0700140
141 private:
asapersson66d4b372016-12-19 06:50:53 -0800142 int Fraction(int64_t min_required_samples, float multiplier) const;
143 int64_t sum;
144 int64_t num_samples;
asaperssondec5ebf2015-10-05 02:36:17 -0700145 };
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000146 struct StatsUpdateTimes {
sprangb4a1ae52015-12-03 08:10:08 -0800147 StatsUpdateTimes() : resolution_update_ms(0), bitrate_update_ms(0) {}
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000148 int64_t resolution_update_ms;
Peter Boström20f3f942015-05-15 11:33:39 +0200149 int64_t bitrate_update_ms;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000150 };
asapersson66d4b372016-12-19 06:50:53 -0800151 struct TargetRateUpdates {
152 TargetRateUpdates()
153 : pause_resume_events(0), last_paused_or_resumed(false), last_ms(-1) {}
154 int pause_resume_events;
155 bool last_paused_or_resumed;
156 int64_t last_ms;
157 };
asapersson8d75ac72017-09-15 06:41:15 -0700158 struct FallbackEncoderInfo {
159 bool is_possible = true;
160 bool is_active = false;
161 int on_off_events = 0;
162 int64_t elapsed_ms = 0;
163 rtc::Optional<int64_t> last_update_ms;
164 const int max_frame_diff_ms = 2000;
165 };
asapersson6eca98b2017-04-04 23:40:50 -0700166 struct StatsTimer {
167 void Start(int64_t now_ms);
168 void Stop(int64_t now_ms);
169 void Restart(int64_t now_ms);
170 int64_t start_ms = -1;
171 int64_t total_ms = 0;
172 };
asapersson118ef002016-03-31 00:00:19 -0700173 struct QpCounters {
asapersson6eca98b2017-04-04 23:40:50 -0700174 SampleCounter vp8; // QP range: 0-127.
175 SampleCounter vp9; // QP range: 0-255.
176 SampleCounter h264; // QP range: 0-51.
asapersson118ef002016-03-31 00:00:19 -0700177 };
Åsa Persson0122e842017-10-16 12:19:23 +0200178
179 // Map holding encoded frames (mapped by timestamp).
180 // If simulcast layers are encoded on different threads, there is no guarantee
181 // that one frame of all layers are encoded before the next start.
182 struct TimestampOlderThan {
183 bool operator()(uint32_t ts1, uint32_t ts2) const {
184 return IsNewerTimestamp(ts2, ts1);
185 }
186 };
187 struct Frame {
188 Frame(int64_t send_ms, uint32_t width, uint32_t height)
189 : send_ms(send_ms), max_width(width), max_height(height) {}
190 const int64_t
191 send_ms; // Time when first frame with this timestamp is sent.
192 uint32_t max_width; // Max width with this timestamp.
193 uint32_t max_height; // Max height with this timestamp.
194 };
195 typedef std::map<uint32_t, Frame, TimestampOlderThan> EncodedFrameMap;
196
danilchapa37de392017-09-09 04:17:22 -0700197 void PurgeOldStats() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000198 VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
danilchapa37de392017-09-09 04:17:22 -0700199 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000200
mflodmancc3d4422017-08-03 08:27:51 -0700201 void SetAdaptTimer(const VideoStreamEncoder::AdaptCounts& counts,
danilchapa37de392017-09-09 04:17:22 -0700202 StatsTimer* timer) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
mflodmancc3d4422017-08-03 08:27:51 -0700203 void UpdateAdaptationStats(
204 const VideoStreamEncoder::AdaptCounts& cpu_counts,
205 const VideoStreamEncoder::AdaptCounts& quality_counts)
danilchapa37de392017-09-09 04:17:22 -0700206 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
asapersson09f05612017-05-15 23:40:18 -0700207
asapersson8d75ac72017-09-15 06:41:15 -0700208 void UpdateEncoderFallbackStats(const CodecSpecificInfo* codec_info)
209 RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
210
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000211 Clock* const clock_;
perkj26091b12016-09-01 01:17:40 -0700212 const std::string payload_name_;
213 const VideoSendStream::Config::Rtp rtp_config_;
asapersson8d75ac72017-09-15 06:41:15 -0700214 const rtc::Optional<int> min_first_fallback_interval_ms_;
pbos5ad935c2016-01-25 03:52:44 -0800215 rtc::CriticalSection crit_;
danilchapa37de392017-09-09 04:17:22 -0700216 VideoEncoderConfig::ContentType content_type_ RTC_GUARDED_BY(crit_);
asapersson4374a092016-07-27 00:39:09 -0700217 const int64_t start_ms_;
danilchapa37de392017-09-09 04:17:22 -0700218 VideoSendStream::Stats stats_ RTC_GUARDED_BY(crit_);
danilchapa37de392017-09-09 04:17:22 -0700219 std::map<uint32_t, StatsUpdateTimes> update_times_ RTC_GUARDED_BY(crit_);
220 rtc::ExpFilter encode_time_ RTC_GUARDED_BY(crit_);
221 int quality_downscales_ RTC_GUARDED_BY(crit_);
222 int cpu_downscales_ RTC_GUARDED_BY(crit_);
Åsa Persson0122e842017-10-16 12:19:23 +0200223 rtc::RateTracker media_byte_rate_tracker_ RTC_GUARDED_BY(crit_);
224 rtc::RateTracker encoded_frame_rate_tracker_ RTC_GUARDED_BY(crit_);
asaperssond89920b2015-07-22 06:52:00 -0700225
sprangb4a1ae52015-12-03 08:10:08 -0800226 // Contains stats used for UMA histograms. These stats will be reset if
227 // content type changes between real-time video and screenshare, since these
228 // will be reported separately.
229 struct UmaSamplesContainer {
sprang07fb9be2016-02-24 07:55:00 -0800230 UmaSamplesContainer(const char* prefix,
231 const VideoSendStream::Stats& start_stats,
232 Clock* clock);
sprangb4a1ae52015-12-03 08:10:08 -0800233 ~UmaSamplesContainer();
234
perkj26091b12016-09-01 01:17:40 -0700235 void UpdateHistograms(const VideoSendStream::Config::Rtp& rtp_config,
sprang07fb9be2016-02-24 07:55:00 -0800236 const VideoSendStream::Stats& current_stats);
sprangb4a1ae52015-12-03 08:10:08 -0800237
asapersson93e1e232017-02-06 05:18:35 -0800238 void InitializeBitrateCounters(const VideoSendStream::Stats& stats);
239
Åsa Persson0122e842017-10-16 12:19:23 +0200240 bool InsertEncodedFrame(const EncodedImage& encoded_frame);
241 void RemoveOld(int64_t now_ms);
242
sprangb4a1ae52015-12-03 08:10:08 -0800243 const std::string uma_prefix_;
sprang07fb9be2016-02-24 07:55:00 -0800244 Clock* const clock_;
sprangb4a1ae52015-12-03 08:10:08 -0800245 SampleCounter input_width_counter_;
246 SampleCounter input_height_counter_;
247 SampleCounter sent_width_counter_;
248 SampleCounter sent_height_counter_;
249 SampleCounter encode_time_counter_;
250 BoolSampleCounter key_frame_counter_;
251 BoolSampleCounter quality_limited_frame_counter_;
252 SampleCounter quality_downscales_counter_;
perkj803d97f2016-11-01 11:45:46 -0700253 BoolSampleCounter cpu_limited_frame_counter_;
sprangb4a1ae52015-12-03 08:10:08 -0800254 BoolSampleCounter bw_limited_frame_counter_;
255 SampleCounter bw_resolutions_disabled_counter_;
256 SampleCounter delay_counter_;
257 SampleCounter max_delay_counter_;
258 rtc::RateTracker input_frame_rate_tracker_;
asapersson320e45a2016-11-29 01:40:35 -0800259 RateCounter input_fps_counter_;
260 RateCounter sent_fps_counter_;
asapersson93e1e232017-02-06 05:18:35 -0800261 RateAccCounter total_byte_counter_;
262 RateAccCounter media_byte_counter_;
263 RateAccCounter rtx_byte_counter_;
264 RateAccCounter padding_byte_counter_;
265 RateAccCounter retransmit_byte_counter_;
266 RateAccCounter fec_byte_counter_;
sprange2d83d62016-02-19 09:03:26 -0800267 int64_t first_rtcp_stats_time_ms_;
Erik Språng22c2b482016-03-01 09:40:42 +0100268 int64_t first_rtp_stats_time_ms_;
asapersson09f05612017-05-15 23:40:18 -0700269 StatsTimer cpu_adapt_timer_;
270 StatsTimer quality_adapt_timer_;
asapersson66d4b372016-12-19 06:50:53 -0800271 BoolSampleCounter paused_time_counter_;
272 TargetRateUpdates target_rate_updates_;
asapersson8d75ac72017-09-15 06:41:15 -0700273 BoolSampleCounter fallback_active_counter_;
274 FallbackEncoderInfo fallback_info_;
sprange2d83d62016-02-19 09:03:26 -0800275 ReportBlockStats report_block_stats_;
sprang07fb9be2016-02-24 07:55:00 -0800276 const VideoSendStream::Stats start_stats_;
Åsa Persson0122e842017-10-16 12:19:23 +0200277 EncodedFrameMap encoded_frames_;
sprangc5d62e22017-04-02 23:53:04 -0700278
asapersson118ef002016-03-31 00:00:19 -0700279 std::map<int, QpCounters>
280 qp_counters_; // QP counters mapped by spatial idx.
sprangb4a1ae52015-12-03 08:10:08 -0800281 };
282
danilchapa37de392017-09-09 04:17:22 -0700283 std::unique_ptr<UmaSamplesContainer> uma_container_ RTC_GUARDED_BY(crit_);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000284};
285
286} // namespace webrtc
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200287#endif // VIDEO_SEND_STATISTICS_PROXY_H_