blob: 6c249f70a97629eec33192ace3e11432449f0322 [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
11#include "webrtc/video/send_statistics_proxy.h"
12
asaperssond89920b2015-07-22 06:52:00 -070013#include <algorithm>
Tim Psiakiad13d2f2015-11-10 16:34:50 -080014#include <cmath>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000015#include <map>
asapersson58d992e2016-03-29 02:15:06 -070016#include <vector>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000017
pbos@webrtc.org49096de2015-02-24 22:37:52 +000018#include "webrtc/base/checks.h"
Peter Boström415d2cd2015-10-26 11:35:17 +010019#include "webrtc/base/logging.h"
kjellander02b3d272016-04-20 05:05:54 -070020#include "webrtc/modules/video_coding/include/video_codec_interface.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010021#include "webrtc/system_wrappers/include/metrics.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000022
23namespace webrtc {
asapersson2a0a2a42015-10-27 01:32:00 -070024namespace {
asapersson1aa420b2015-12-07 03:12:22 -080025const float kEncodeTimeWeigthFactor = 0.5f;
26
asapersson2a0a2a42015-10-27 01:32:00 -070027// Used by histograms. Values of entries should not be changed.
28enum HistogramCodecType {
29 kVideoUnknown = 0,
30 kVideoVp8 = 1,
31 kVideoVp9 = 2,
32 kVideoH264 = 3,
33 kVideoMax = 64,
34};
35
asaperssonc2148a52016-02-04 00:33:21 -080036const char* kRealtimePrefix = "WebRTC.Video.";
37const char* kScreenPrefix = "WebRTC.Video.Screenshare.";
38
sprangb4a1ae52015-12-03 08:10:08 -080039const char* GetUmaPrefix(VideoEncoderConfig::ContentType content_type) {
40 switch (content_type) {
41 case VideoEncoderConfig::ContentType::kRealtimeVideo:
asaperssonc2148a52016-02-04 00:33:21 -080042 return kRealtimePrefix;
sprangb4a1ae52015-12-03 08:10:08 -080043 case VideoEncoderConfig::ContentType::kScreen:
asaperssonc2148a52016-02-04 00:33:21 -080044 return kScreenPrefix;
sprangb4a1ae52015-12-03 08:10:08 -080045 }
46 RTC_NOTREACHED();
47 return nullptr;
48}
49
asapersson2a0a2a42015-10-27 01:32:00 -070050HistogramCodecType PayloadNameToHistogramCodecType(
51 const std::string& payload_name) {
52 if (payload_name == "VP8") {
53 return kVideoVp8;
54 } else if (payload_name == "VP9") {
55 return kVideoVp9;
56 } else if (payload_name == "H264") {
57 return kVideoH264;
58 } else {
59 return kVideoUnknown;
60 }
61}
62
63void UpdateCodecTypeHistogram(const std::string& payload_name) {
asapersson28ba9272016-01-25 05:58:23 -080064 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.Encoder.CodecType",
65 PayloadNameToHistogramCodecType(payload_name),
66 kVideoMax);
asapersson2a0a2a42015-10-27 01:32:00 -070067}
68} // namespace
69
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000070
pbos@webrtc.org273a4142014-12-01 15:23:21 +000071const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
72
sprangb4a1ae52015-12-03 08:10:08 -080073SendStatisticsProxy::SendStatisticsProxy(
74 Clock* clock,
75 const VideoSendStream::Config& config,
76 VideoEncoderConfig::ContentType content_type)
asaperssond89920b2015-07-22 06:52:00 -070077 : clock_(clock),
perkj26091b12016-09-01 01:17:40 -070078 payload_name_(config.encoder_settings.payload_name),
79 rtp_config_(config.rtp),
sprangb4a1ae52015-12-03 08:10:08 -080080 content_type_(content_type),
asapersson4374a092016-07-27 00:39:09 -070081 start_ms_(clock->TimeInMilliseconds()),
asaperssond89920b2015-07-22 06:52:00 -070082 last_sent_frame_timestamp_(0),
asapersson1aa420b2015-12-07 03:12:22 -080083 encode_time_(kEncodeTimeWeigthFactor),
sprang07fb9be2016-02-24 07:55:00 -080084 uma_container_(
85 new UmaSamplesContainer(GetUmaPrefix(content_type_), stats_, clock)) {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +000086}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000087
sprang07fb9be2016-02-24 07:55:00 -080088SendStatisticsProxy::~SendStatisticsProxy() {
89 rtc::CritScope lock(&crit_);
perkj26091b12016-09-01 01:17:40 -070090 uma_container_->UpdateHistograms(rtp_config_, stats_);
asapersson4374a092016-07-27 00:39:09 -070091
92 int64_t elapsed_sec = (clock_->TimeInMilliseconds() - start_ms_) / 1000;
asapersson1d02d3e2016-09-09 22:40:25 -070093 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.SendStreamLifetimeInSeconds",
94 elapsed_sec);
asapersson4374a092016-07-27 00:39:09 -070095
96 if (elapsed_sec >= metrics::kMinRunTimeInSeconds)
perkj26091b12016-09-01 01:17:40 -070097 UpdateCodecTypeHistogram(payload_name_);
sprang07fb9be2016-02-24 07:55:00 -080098}
sprangb4a1ae52015-12-03 08:10:08 -080099
100SendStatisticsProxy::UmaSamplesContainer::UmaSamplesContainer(
sprang07fb9be2016-02-24 07:55:00 -0800101 const char* prefix,
102 const VideoSendStream::Stats& stats,
103 Clock* const clock)
sprangb4a1ae52015-12-03 08:10:08 -0800104 : uma_prefix_(prefix),
sprang07fb9be2016-02-24 07:55:00 -0800105 clock_(clock),
sprangb4a1ae52015-12-03 08:10:08 -0800106 max_sent_width_per_timestamp_(0),
107 max_sent_height_per_timestamp_(0),
Honghai Zhang82d78622016-05-06 11:29:15 -0700108 input_frame_rate_tracker_(100, 10u),
asapersson320e45a2016-11-29 01:40:35 -0800109 input_fps_counter_(clock, nullptr, true),
110 sent_fps_counter_(clock, nullptr, true),
sprang07fb9be2016-02-24 07:55:00 -0800111 first_rtcp_stats_time_ms_(-1),
Erik Språng22c2b482016-03-01 09:40:42 +0100112 first_rtp_stats_time_ms_(-1),
sprang07fb9be2016-02-24 07:55:00 -0800113 start_stats_(stats) {}
sprangb4a1ae52015-12-03 08:10:08 -0800114
sprang07fb9be2016-02-24 07:55:00 -0800115SendStatisticsProxy::UmaSamplesContainer::~UmaSamplesContainer() {}
Åsa Persson24b4eda2015-06-16 10:17:01 +0200116
perkj26091b12016-09-01 01:17:40 -0700117void AccumulateRtxStats(const VideoSendStream::Stats& stats,
118 const std::vector<uint32_t>& rtx_ssrcs,
Erik Språng22c2b482016-03-01 09:40:42 +0100119 StreamDataCounters* total_rtp_stats,
120 StreamDataCounters* rtx_stats) {
121 for (auto it : stats.substreams) {
Erik Språng22c2b482016-03-01 09:40:42 +0100122 if (std::find(rtx_ssrcs.begin(), rtx_ssrcs.end(), it.first) !=
123 rtx_ssrcs.end()) {
124 rtx_stats->Add(it.second.rtp_stats);
125 } else {
126 total_rtp_stats->Add(it.second.rtp_stats);
127 }
128 }
129}
130
sprang07fb9be2016-02-24 07:55:00 -0800131void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
perkj26091b12016-09-01 01:17:40 -0700132 const VideoSendStream::Config::Rtp& rtp_config,
sprang07fb9be2016-02-24 07:55:00 -0800133 const VideoSendStream::Stats& current_stats) {
asaperssonc2148a52016-02-04 00:33:21 -0800134 RTC_DCHECK(uma_prefix_ == kRealtimePrefix || uma_prefix_ == kScreenPrefix);
135 const int kIndex = uma_prefix_ == kScreenPrefix ? 1 : 0;
asapersson320e45a2016-11-29 01:40:35 -0800136 const int kMinRequiredPeriodicSamples = 6;
perkj803d97f2016-11-01 11:45:46 -0700137 int in_width = input_width_counter_.Avg(kMinRequiredMetricsSamples);
138 int in_height = input_height_counter_.Avg(kMinRequiredMetricsSamples);
asaperssond89920b2015-07-22 06:52:00 -0700139 if (in_width != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700140 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "InputWidthInPixels",
141 in_width);
142 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "InputHeightInPixels",
143 in_height);
asaperssond89920b2015-07-22 06:52:00 -0700144 }
asapersson320e45a2016-11-29 01:40:35 -0800145 AggregatedStats in_fps = input_fps_counter_.GetStats();
146 if (in_fps.num_samples >= kMinRequiredPeriodicSamples) {
147 RTC_HISTOGRAMS_COUNTS_100(kIndex, uma_prefix_ + "InputFramesPerSecond",
148 in_fps.average);
149 LOG(LS_INFO) << uma_prefix_ + "InputFramesPerSecond, " << in_fps.ToString();
150 }
151
perkj803d97f2016-11-01 11:45:46 -0700152 int sent_width = sent_width_counter_.Avg(kMinRequiredMetricsSamples);
153 int sent_height = sent_height_counter_.Avg(kMinRequiredMetricsSamples);
asaperssond89920b2015-07-22 06:52:00 -0700154 if (sent_width != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700155 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "SentWidthInPixels",
156 sent_width);
157 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "SentHeightInPixels",
158 sent_height);
asaperssond89920b2015-07-22 06:52:00 -0700159 }
asapersson320e45a2016-11-29 01:40:35 -0800160 AggregatedStats sent_fps = sent_fps_counter_.GetStats();
161 if (sent_fps.num_samples >= kMinRequiredPeriodicSamples) {
162 RTC_HISTOGRAMS_COUNTS_100(kIndex, uma_prefix_ + "SentFramesPerSecond",
163 sent_fps.average);
164 LOG(LS_INFO) << uma_prefix_ + "SentFramesPerSecond, "
165 << sent_fps.ToString();
166 }
167
perkj803d97f2016-11-01 11:45:46 -0700168 int encode_ms = encode_time_counter_.Avg(kMinRequiredMetricsSamples);
asaperssonc2148a52016-02-04 00:33:21 -0800169 if (encode_ms != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700170 RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "EncodeTimeInMs",
171 encode_ms);
asaperssonc2148a52016-02-04 00:33:21 -0800172 }
perkj803d97f2016-11-01 11:45:46 -0700173 int key_frames_permille =
174 key_frame_counter_.Permille(kMinRequiredMetricsSamples);
asaperssondec5ebf2015-10-05 02:36:17 -0700175 if (key_frames_permille != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700176 RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "KeyFramesSentInPermille",
177 key_frames_permille);
asaperssondec5ebf2015-10-05 02:36:17 -0700178 }
asapersson4306fc72015-10-19 00:35:21 -0700179 int quality_limited =
perkj803d97f2016-11-01 11:45:46 -0700180 quality_limited_frame_counter_.Percent(kMinRequiredMetricsSamples);
asapersson4306fc72015-10-19 00:35:21 -0700181 if (quality_limited != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700182 RTC_HISTOGRAMS_PERCENTAGE(kIndex,
183 uma_prefix_ + "QualityLimitedResolutionInPercent",
184 quality_limited);
asapersson4306fc72015-10-19 00:35:21 -0700185 }
perkj803d97f2016-11-01 11:45:46 -0700186 int downscales = quality_downscales_counter_.Avg(kMinRequiredMetricsSamples);
asapersson4306fc72015-10-19 00:35:21 -0700187 if (downscales != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700188 RTC_HISTOGRAMS_ENUMERATION(
asaperssonc2148a52016-02-04 00:33:21 -0800189 kIndex, uma_prefix_ + "QualityLimitedResolutionDownscales", downscales,
190 20);
asapersson4306fc72015-10-19 00:35:21 -0700191 }
perkj803d97f2016-11-01 11:45:46 -0700192 int cpu_limited =
193 cpu_limited_frame_counter_.Percent(kMinRequiredMetricsSamples);
194 if (cpu_limited != -1) {
195 RTC_HISTOGRAMS_PERCENTAGE(
196 kIndex, uma_prefix_ + "CpuLimitedResolutionInPercent", cpu_limited);
197 }
198 int bw_limited =
199 bw_limited_frame_counter_.Percent(kMinRequiredMetricsSamples);
asaperssonda535c42015-10-19 23:32:41 -0700200 if (bw_limited != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700201 RTC_HISTOGRAMS_PERCENTAGE(
asaperssonc2148a52016-02-04 00:33:21 -0800202 kIndex, uma_prefix_ + "BandwidthLimitedResolutionInPercent",
203 bw_limited);
asaperssonda535c42015-10-19 23:32:41 -0700204 }
perkj803d97f2016-11-01 11:45:46 -0700205 int num_disabled =
206 bw_resolutions_disabled_counter_.Avg(kMinRequiredMetricsSamples);
asaperssonda535c42015-10-19 23:32:41 -0700207 if (num_disabled != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700208 RTC_HISTOGRAMS_ENUMERATION(
asaperssonc2148a52016-02-04 00:33:21 -0800209 kIndex, uma_prefix_ + "BandwidthLimitedResolutionsDisabled",
210 num_disabled, 10);
asaperssonda535c42015-10-19 23:32:41 -0700211 }
perkj803d97f2016-11-01 11:45:46 -0700212 int delay_ms = delay_counter_.Avg(kMinRequiredMetricsSamples);
asaperssonf040b232015-11-04 00:59:03 -0800213 if (delay_ms != -1)
asapersson1d02d3e2016-09-09 22:40:25 -0700214 RTC_HISTOGRAMS_COUNTS_100000(kIndex, uma_prefix_ + "SendSideDelayInMs",
215 delay_ms);
asaperssonf040b232015-11-04 00:59:03 -0800216
perkj803d97f2016-11-01 11:45:46 -0700217 int max_delay_ms = max_delay_counter_.Avg(kMinRequiredMetricsSamples);
asaperssonf040b232015-11-04 00:59:03 -0800218 if (max_delay_ms != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700219 RTC_HISTOGRAMS_COUNTS_100000(kIndex, uma_prefix_ + "SendSideDelayMaxInMs",
220 max_delay_ms);
sprangb4a1ae52015-12-03 08:10:08 -0800221 }
sprang07fb9be2016-02-24 07:55:00 -0800222
asapersson118ef002016-03-31 00:00:19 -0700223 for (const auto& it : qp_counters_) {
perkj803d97f2016-11-01 11:45:46 -0700224 int qp_vp8 = it.second.vp8.Avg(kMinRequiredMetricsSamples);
asapersson5265fed2016-04-18 02:58:47 -0700225 if (qp_vp8 != -1) {
asapersson118ef002016-03-31 00:00:19 -0700226 int spatial_idx = it.first;
227 if (spatial_idx == -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700228 RTC_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8",
229 qp_vp8);
asapersson118ef002016-03-31 00:00:19 -0700230 } else if (spatial_idx == 0) {
asapersson1d02d3e2016-09-09 22:40:25 -0700231 RTC_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8.S0",
232 qp_vp8);
asapersson118ef002016-03-31 00:00:19 -0700233 } else if (spatial_idx == 1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700234 RTC_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8.S1",
235 qp_vp8);
asapersson118ef002016-03-31 00:00:19 -0700236 } else if (spatial_idx == 2) {
asapersson1d02d3e2016-09-09 22:40:25 -0700237 RTC_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8.S2",
238 qp_vp8);
asapersson118ef002016-03-31 00:00:19 -0700239 } else {
240 LOG(LS_WARNING) << "QP stats not recorded for VP8 spatial idx "
241 << spatial_idx;
242 }
243 }
perkj803d97f2016-11-01 11:45:46 -0700244 int qp_vp9 = it.second.vp9.Avg(kMinRequiredMetricsSamples);
asapersson5265fed2016-04-18 02:58:47 -0700245 if (qp_vp9 != -1) {
246 int spatial_idx = it.first;
247 if (spatial_idx == -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700248 RTC_HISTOGRAMS_COUNTS_500(kIndex, uma_prefix_ + "Encoded.Qp.Vp9",
249 qp_vp9);
asapersson5265fed2016-04-18 02:58:47 -0700250 } else if (spatial_idx == 0) {
asapersson1d02d3e2016-09-09 22:40:25 -0700251 RTC_HISTOGRAMS_COUNTS_500(kIndex, uma_prefix_ + "Encoded.Qp.Vp9.S0",
252 qp_vp9);
asapersson5265fed2016-04-18 02:58:47 -0700253 } else if (spatial_idx == 1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700254 RTC_HISTOGRAMS_COUNTS_500(kIndex, uma_prefix_ + "Encoded.Qp.Vp9.S1",
255 qp_vp9);
asapersson5265fed2016-04-18 02:58:47 -0700256 } else if (spatial_idx == 2) {
asapersson1d02d3e2016-09-09 22:40:25 -0700257 RTC_HISTOGRAMS_COUNTS_500(kIndex, uma_prefix_ + "Encoded.Qp.Vp9.S2",
258 qp_vp9);
asapersson5265fed2016-04-18 02:58:47 -0700259 } else {
260 LOG(LS_WARNING) << "QP stats not recorded for VP9 spatial layer "
261 << spatial_idx;
262 }
263 }
asapersson827cab32016-11-02 09:08:47 -0700264 int qp_h264 = it.second.h264.Avg(kMinRequiredMetricsSamples);
265 if (qp_h264 != -1) {
266 int spatial_idx = it.first;
267 RTC_DCHECK_EQ(-1, spatial_idx);
268 RTC_HISTOGRAMS_COUNTS_100(kIndex, uma_prefix_ + "Encoded.Qp.H264",
269 qp_h264);
270 }
asapersson118ef002016-03-31 00:00:19 -0700271 }
272
sprange2d83d62016-02-19 09:03:26 -0800273 if (first_rtcp_stats_time_ms_ != -1) {
sprang07fb9be2016-02-24 07:55:00 -0800274 int64_t elapsed_sec =
275 (clock_->TimeInMilliseconds() - first_rtcp_stats_time_ms_) / 1000;
276 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
277 int fraction_lost = report_block_stats_.FractionLostInPercent();
278 if (fraction_lost != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700279 RTC_HISTOGRAMS_PERCENTAGE(
sprang07fb9be2016-02-24 07:55:00 -0800280 kIndex, uma_prefix_ + "SentPacketsLostInPercent", fraction_lost);
281 }
282
283 // The RTCP packet type counters, delivered via the
284 // RtcpPacketTypeCounterObserver interface, are aggregates over the entire
285 // life of the send stream and are not reset when switching content type.
286 // For the purpose of these statistics though, we want new counts when
287 // switching since we switch histogram name. On every reset of the
288 // UmaSamplesContainer, we save the initial state of the counters, so that
289 // we can calculate the delta here and aggregate over all ssrcs.
290 RtcpPacketTypeCounter counters;
perkj26091b12016-09-01 01:17:40 -0700291 for (uint32_t ssrc : rtp_config.ssrcs) {
sprang07fb9be2016-02-24 07:55:00 -0800292 auto kv = current_stats.substreams.find(ssrc);
293 if (kv == current_stats.substreams.end())
294 continue;
295
296 RtcpPacketTypeCounter stream_counters =
297 kv->second.rtcp_packet_type_counts;
298 kv = start_stats_.substreams.find(ssrc);
299 if (kv != start_stats_.substreams.end())
300 stream_counters.Subtract(kv->second.rtcp_packet_type_counts);
301
302 counters.Add(stream_counters);
303 }
asapersson1d02d3e2016-09-09 22:40:25 -0700304 RTC_HISTOGRAMS_COUNTS_10000(kIndex,
305 uma_prefix_ + "NackPacketsReceivedPerMinute",
306 counters.nack_packets * 60 / elapsed_sec);
307 RTC_HISTOGRAMS_COUNTS_10000(kIndex,
308 uma_prefix_ + "FirPacketsReceivedPerMinute",
309 counters.fir_packets * 60 / elapsed_sec);
310 RTC_HISTOGRAMS_COUNTS_10000(kIndex,
311 uma_prefix_ + "PliPacketsReceivedPerMinute",
312 counters.pli_packets * 60 / elapsed_sec);
sprang07fb9be2016-02-24 07:55:00 -0800313 if (counters.nack_requests > 0) {
asapersson1d02d3e2016-09-09 22:40:25 -0700314 RTC_HISTOGRAMS_PERCENTAGE(
sprang07fb9be2016-02-24 07:55:00 -0800315 kIndex, uma_prefix_ + "UniqueNackRequestsReceivedInPercent",
316 counters.UniqueNackRequestsInPercent());
317 }
sprange2d83d62016-02-19 09:03:26 -0800318 }
319 }
Erik Språng22c2b482016-03-01 09:40:42 +0100320
321 if (first_rtp_stats_time_ms_ != -1) {
322 int64_t elapsed_sec =
323 (clock_->TimeInMilliseconds() - first_rtp_stats_time_ms_) / 1000;
324 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
325 StreamDataCounters rtp;
326 StreamDataCounters rtx;
perkj26091b12016-09-01 01:17:40 -0700327 AccumulateRtxStats(current_stats, rtp_config.rtx.ssrcs, &rtp, &rtx);
Erik Språng22c2b482016-03-01 09:40:42 +0100328 StreamDataCounters start_rtp;
329 StreamDataCounters start_rtx;
perkj26091b12016-09-01 01:17:40 -0700330 AccumulateRtxStats(start_stats_, rtp_config.rtx.ssrcs, &start_rtp,
331 &start_rtx);
Erik Språng22c2b482016-03-01 09:40:42 +0100332 rtp.Subtract(start_rtp);
333 rtx.Subtract(start_rtx);
334 StreamDataCounters rtp_rtx = rtp;
335 rtp_rtx.Add(rtx);
336
asapersson1d02d3e2016-09-09 22:40:25 -0700337 RTC_HISTOGRAMS_COUNTS_10000(
Erik Språng22c2b482016-03-01 09:40:42 +0100338 kIndex, uma_prefix_ + "BitrateSentInKbps",
339 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
340 1000));
asapersson1d02d3e2016-09-09 22:40:25 -0700341 RTC_HISTOGRAMS_COUNTS_10000(
Erik Språng22c2b482016-03-01 09:40:42 +0100342 kIndex, uma_prefix_ + "MediaBitrateSentInKbps",
343 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000));
asapersson1d02d3e2016-09-09 22:40:25 -0700344 RTC_HISTOGRAMS_COUNTS_10000(
Erik Språng22c2b482016-03-01 09:40:42 +0100345 kIndex, uma_prefix_ + "PaddingBitrateSentInKbps",
346 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec /
347 1000));
asapersson1d02d3e2016-09-09 22:40:25 -0700348 RTC_HISTOGRAMS_COUNTS_10000(
Erik Språng22c2b482016-03-01 09:40:42 +0100349 kIndex, uma_prefix_ + "RetransmittedBitrateSentInKbps",
350 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 /
351 elapsed_sec / 1000));
perkj26091b12016-09-01 01:17:40 -0700352 if (!rtp_config.rtx.ssrcs.empty()) {
asapersson1d02d3e2016-09-09 22:40:25 -0700353 RTC_HISTOGRAMS_COUNTS_10000(
Erik Språng22c2b482016-03-01 09:40:42 +0100354 kIndex, uma_prefix_ + "RtxBitrateSentInKbps",
355 static_cast<int>(rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
356 1000));
357 }
brandtrcd188f62016-11-15 08:21:52 -0800358 if (rtp_config.flexfec.flexfec_payload_type != -1 ||
359 rtp_config.ulpfec.red_payload_type != -1) {
asapersson1d02d3e2016-09-09 22:40:25 -0700360 RTC_HISTOGRAMS_COUNTS_10000(kIndex,
361 uma_prefix_ + "FecBitrateSentInKbps",
362 static_cast<int>(rtp_rtx.fec.TotalBytes() *
363 8 / elapsed_sec / 1000));
Erik Språng22c2b482016-03-01 09:40:42 +0100364 }
365 }
366 }
sprangb4a1ae52015-12-03 08:10:08 -0800367}
368
Pera48ddb72016-09-29 11:48:50 +0200369void SendStatisticsProxy::OnEncoderReconfigured(
370 const VideoEncoderConfig& config,
371 uint32_t preferred_bitrate_bps) {
sprangb4a1ae52015-12-03 08:10:08 -0800372 rtc::CritScope lock(&crit_);
Pera48ddb72016-09-29 11:48:50 +0200373 stats_.preferred_media_bitrate_bps = preferred_bitrate_bps;
374
375 if (content_type_ != config.content_type) {
perkj26091b12016-09-01 01:17:40 -0700376 uma_container_->UpdateHistograms(rtp_config_, stats_);
Pera48ddb72016-09-29 11:48:50 +0200377 uma_container_.reset(new UmaSamplesContainer(
378 GetUmaPrefix(config.content_type), stats_, clock_));
379 content_type_ = config.content_type;
asaperssonf040b232015-11-04 00:59:03 -0800380 }
Åsa Persson24b4eda2015-06-16 10:17:01 +0200381}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000382
perkj275afc52016-09-01 00:21:16 -0700383void SendStatisticsProxy::OnEncoderStatsUpdate(uint32_t framerate,
384 uint32_t bitrate) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200385 rtc::CritScope lock(&crit_);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000386 stats_.encode_frame_rate = framerate;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000387 stats_.media_bitrate_bps = bitrate;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000388}
389
Peter Boströme4499152016-02-05 11:13:28 +0100390void SendStatisticsProxy::OnEncodedFrameTimeMeasured(
391 int encode_time_ms,
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000392 const CpuOveruseMetrics& metrics) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200393 rtc::CritScope lock(&crit_);
Peter Boströme4499152016-02-05 11:13:28 +0100394 uma_container_->encode_time_counter_.Add(encode_time_ms);
395 encode_time_.Apply(1.0f, encode_time_ms);
396 stats_.avg_encode_time_ms = round(encode_time_.filtered());
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000397 stats_.encode_usage_percent = metrics.encode_usage_percent;
398}
399
Peter Boström7083e112015-09-22 16:28:51 +0200400void SendStatisticsProxy::OnSuspendChange(bool is_suspended) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200401 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000402 stats_.suspended = is_suspended;
asapersson320e45a2016-11-29 01:40:35 -0800403 // Pause framerate stats.
404 if (is_suspended) {
405 uma_container_->input_fps_counter_.ProcessAndPause();
406 uma_container_->sent_fps_counter_.ProcessAndPause();
407 }
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000408}
409
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000410VideoSendStream::Stats SendStatisticsProxy::GetStats() {
Peter Boströmf2f82832015-05-01 13:00:41 +0200411 rtc::CritScope lock(&crit_);
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000412 PurgeOldStats();
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000413 stats_.input_frame_rate =
sprangb4a1ae52015-12-03 08:10:08 -0800414 round(uma_container_->input_frame_rate_tracker_.ComputeRate());
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000415 return stats_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000416}
417
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000418void SendStatisticsProxy::PurgeOldStats() {
Peter Boström20f3f942015-05-15 11:33:39 +0200419 int64_t old_stats_ms = clock_->TimeInMilliseconds() - kStatsTimeoutMs;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000420 for (std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
421 stats_.substreams.begin();
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000422 it != stats_.substreams.end(); ++it) {
423 uint32_t ssrc = it->first;
Peter Boström20f3f942015-05-15 11:33:39 +0200424 if (update_times_[ssrc].resolution_update_ms <= old_stats_ms) {
425 it->second.width = 0;
426 it->second.height = 0;
427 }
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000428 }
429}
430
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000431VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry(
432 uint32_t ssrc) {
433 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
434 stats_.substreams.find(ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000435 if (it != stats_.substreams.end())
436 return &it->second;
437
brandtrcd188f62016-11-15 08:21:52 -0800438 bool is_media = std::find(rtp_config_.ssrcs.begin(), rtp_config_.ssrcs.end(),
439 ssrc) != rtp_config_.ssrcs.end();
440 bool is_flexfec = rtp_config_.flexfec.flexfec_payload_type != -1 &&
441 ssrc == rtp_config_.flexfec.flexfec_ssrc;
442 bool is_rtx =
443 std::find(rtp_config_.rtx.ssrcs.begin(), rtp_config_.rtx.ssrcs.end(),
444 ssrc) != rtp_config_.rtx.ssrcs.end();
445 if (!is_media && !is_flexfec && !is_rtx)
446 return nullptr;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000447
asapersson2e5cfcd2016-08-11 08:41:18 -0700448 // Insert new entry and return ptr.
449 VideoSendStream::StreamStats* entry = &stats_.substreams[ssrc];
450 entry->is_rtx = is_rtx;
asaperssona6a699a2016-11-25 03:52:46 -0800451 entry->is_flexfec = is_flexfec;
asapersson2e5cfcd2016-08-11 08:41:18 -0700452
453 return entry;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000454}
455
Peter Boström20f3f942015-05-15 11:33:39 +0200456void SendStatisticsProxy::OnInactiveSsrc(uint32_t ssrc) {
457 rtc::CritScope lock(&crit_);
458 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200459 if (!stats)
Peter Boström20f3f942015-05-15 11:33:39 +0200460 return;
461
462 stats->total_bitrate_bps = 0;
463 stats->retransmit_bitrate_bps = 0;
464 stats->height = 0;
465 stats->width = 0;
466}
467
perkjf5b2e512016-07-05 08:34:04 -0700468void SendStatisticsProxy::OnSetEncoderTargetRate(uint32_t bitrate_bps) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200469 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +0000470 stats_.target_media_bitrate_bps = bitrate_bps;
471}
472
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000473void SendStatisticsProxy::OnSendEncodedImage(
474 const EncodedImage& encoded_image,
kjellander02b3d272016-04-20 05:05:54 -0700475 const CodecSpecificInfo* codec_info) {
476 size_t simulcast_idx = 0;
477
perkj275afc52016-09-01 00:21:16 -0700478 rtc::CritScope lock(&crit_);
sakal43536c32016-10-24 01:46:43 -0700479 ++stats_.frames_encoded;
kjellander02b3d272016-04-20 05:05:54 -0700480 if (codec_info) {
481 if (codec_info->codecType == kVideoCodecVP8) {
482 simulcast_idx = codec_info->codecSpecific.VP8.simulcastIdx;
483 } else if (codec_info->codecType == kVideoCodecGeneric) {
484 simulcast_idx = codec_info->codecSpecific.generic.simulcast_idx;
485 }
perkj275afc52016-09-01 00:21:16 -0700486 if (codec_info->codec_name) {
487 stats_.encoder_implementation_name = codec_info->codec_name;
488 }
kjellander02b3d272016-04-20 05:05:54 -0700489 }
490
perkj26091b12016-09-01 01:17:40 -0700491 if (simulcast_idx >= rtp_config_.ssrcs.size()) {
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000492 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
perkj26091b12016-09-01 01:17:40 -0700493 << " >= " << rtp_config_.ssrcs.size() << ").";
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000494 return;
495 }
perkj26091b12016-09-01 01:17:40 -0700496 uint32_t ssrc = rtp_config_.ssrcs[simulcast_idx];
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000497
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000498 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200499 if (!stats)
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000500 return;
501
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000502 stats->width = encoded_image._encodedWidth;
503 stats->height = encoded_image._encodedHeight;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000504 update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
asaperssond89920b2015-07-22 06:52:00 -0700505
sprangb4a1ae52015-12-03 08:10:08 -0800506 uma_container_->key_frame_counter_.Add(encoded_image._frameType ==
507 kVideoFrameKey);
asapersson17821db2015-12-14 02:08:12 -0800508 stats_.bw_limited_resolution =
kthelgason0cd27ba2016-12-19 06:32:16 -0800509 encoded_image.adapt_reason_.bw_resolutions_disabled > 0 ||
510 quality_downscales_ > 0;
asapersson17821db2015-12-14 02:08:12 -0800511
kthelgason0cd27ba2016-12-19 06:32:16 -0800512 if (quality_downscales_ != -1) {
513 uma_container_->quality_limited_frame_counter_.Add(quality_downscales_ > 0);
514 if (quality_downscales_ > 0)
515 uma_container_->quality_downscales_counter_.Add(quality_downscales_);
asapersson4306fc72015-10-19 00:35:21 -0700516 }
asaperssonda535c42015-10-19 23:32:41 -0700517 if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) {
518 bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
sprangb4a1ae52015-12-03 08:10:08 -0800519 uma_container_->bw_limited_frame_counter_.Add(bw_limited);
asaperssonda535c42015-10-19 23:32:41 -0700520 if (bw_limited) {
sprangb4a1ae52015-12-03 08:10:08 -0800521 uma_container_->bw_resolutions_disabled_counter_.Add(
522 encoded_image.adapt_reason_.bw_resolutions_disabled);
asaperssonda535c42015-10-19 23:32:41 -0700523 }
524 }
asapersson4306fc72015-10-19 00:35:21 -0700525
sakal87da4042016-10-31 06:53:47 -0700526 if (encoded_image.qp_ != -1) {
527 if (!stats_.qp_sum)
528 stats_.qp_sum = rtc::Optional<uint64_t>(0);
529 *stats_.qp_sum += encoded_image.qp_;
530
531 if (codec_info) {
532 if (codec_info->codecType == kVideoCodecVP8) {
533 int spatial_idx = (rtp_config_.ssrcs.size() == 1)
534 ? -1
535 : static_cast<int>(simulcast_idx);
536 uma_container_->qp_counters_[spatial_idx].vp8.Add(encoded_image.qp_);
537 } else if (codec_info->codecType == kVideoCodecVP9) {
538 int spatial_idx =
539 (codec_info->codecSpecific.VP9.num_spatial_layers == 1)
540 ? -1
541 : codec_info->codecSpecific.VP9.spatial_idx;
542 uma_container_->qp_counters_[spatial_idx].vp9.Add(encoded_image.qp_);
asapersson827cab32016-11-02 09:08:47 -0700543 } else if (codec_info->codecType == kVideoCodecH264) {
544 int spatial_idx = -1;
545 uma_container_->qp_counters_[spatial_idx].h264.Add(encoded_image.qp_);
sakal87da4042016-10-31 06:53:47 -0700546 }
asapersson5265fed2016-04-18 02:58:47 -0700547 }
asapersson118ef002016-03-31 00:00:19 -0700548 }
549
asaperssond89920b2015-07-22 06:52:00 -0700550 // TODO(asapersson): This is incorrect if simulcast layers are encoded on
551 // different threads and there is no guarantee that one frame of all layers
552 // are encoded before the next start.
553 if (last_sent_frame_timestamp_ > 0 &&
554 encoded_image._timeStamp != last_sent_frame_timestamp_) {
asapersson320e45a2016-11-29 01:40:35 -0800555 uma_container_->sent_fps_counter_.Add(1);
sprangb4a1ae52015-12-03 08:10:08 -0800556 uma_container_->sent_width_counter_.Add(
557 uma_container_->max_sent_width_per_timestamp_);
558 uma_container_->sent_height_counter_.Add(
559 uma_container_->max_sent_height_per_timestamp_);
560 uma_container_->max_sent_width_per_timestamp_ = 0;
561 uma_container_->max_sent_height_per_timestamp_ = 0;
Åsa Persson24b4eda2015-06-16 10:17:01 +0200562 }
asaperssond89920b2015-07-22 06:52:00 -0700563 last_sent_frame_timestamp_ = encoded_image._timeStamp;
sprangb4a1ae52015-12-03 08:10:08 -0800564 uma_container_->max_sent_width_per_timestamp_ =
565 std::max(uma_container_->max_sent_width_per_timestamp_,
asaperssond89920b2015-07-22 06:52:00 -0700566 static_cast<int>(encoded_image._encodedWidth));
sprangb4a1ae52015-12-03 08:10:08 -0800567 uma_container_->max_sent_height_per_timestamp_ =
568 std::max(uma_container_->max_sent_height_per_timestamp_,
asaperssond89920b2015-07-22 06:52:00 -0700569 static_cast<int>(encoded_image._encodedHeight));
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000570}
571
Per69b332d2016-06-02 15:45:42 +0200572int SendStatisticsProxy::GetSendFrameRate() const {
573 rtc::CritScope lock(&crit_);
574 return stats_.encode_frame_rate;
575}
576
asaperssond89920b2015-07-22 06:52:00 -0700577void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200578 rtc::CritScope lock(&crit_);
sprangb4a1ae52015-12-03 08:10:08 -0800579 uma_container_->input_frame_rate_tracker_.AddSamples(1);
asapersson320e45a2016-11-29 01:40:35 -0800580 uma_container_->input_fps_counter_.Add(1);
sprangb4a1ae52015-12-03 08:10:08 -0800581 uma_container_->input_width_counter_.Add(width);
582 uma_container_->input_height_counter_.Add(height);
perkj803d97f2016-11-01 11:45:46 -0700583 uma_container_->cpu_limited_frame_counter_.Add(stats_.cpu_limited_resolution);
584}
585
kthelgason0cd27ba2016-12-19 06:32:16 -0800586void SendStatisticsProxy::SetResolutionRestrictionStats(
587 bool scaling_enabled,
588 bool cpu_restricted,
589 int num_quality_downscales) {
perkj803d97f2016-11-01 11:45:46 -0700590 rtc::CritScope lock(&crit_);
kthelgason0cd27ba2016-12-19 06:32:16 -0800591 if (scaling_enabled) {
592 quality_downscales_ = num_quality_downscales;
593 stats_.bw_limited_resolution = quality_downscales_ > 0;
594 stats_.cpu_limited_resolution = cpu_restricted;
595 } else {
596 stats_.bw_limited_resolution = false;
597 stats_.cpu_limited_resolution = false;
598 quality_downscales_ = -1;
599 }
perkj803d97f2016-11-01 11:45:46 -0700600}
601
602void SendStatisticsProxy::OnCpuRestrictedResolutionChanged(
603 bool cpu_restricted_resolution) {
604 rtc::CritScope lock(&crit_);
605 stats_.cpu_limited_resolution = cpu_restricted_resolution;
606 ++stats_.number_of_cpu_adapt_changes;
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000607}
608
kthelgason876222f2016-11-29 01:44:11 -0800609void SendStatisticsProxy::OnQualityRestrictedResolutionChanged(
kthelgason0cd27ba2016-12-19 06:32:16 -0800610 int num_quality_downscales) {
kthelgason876222f2016-11-29 01:44:11 -0800611 rtc::CritScope lock(&crit_);
kthelgason0cd27ba2016-12-19 06:32:16 -0800612 quality_downscales_ = num_quality_downscales;
613 stats_.bw_limited_resolution = quality_downscales_ > 0;
kthelgason876222f2016-11-29 01:44:11 -0800614}
615
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000616void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
617 uint32_t ssrc,
618 const RtcpPacketTypeCounter& packet_counter) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200619 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000620 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200621 if (!stats)
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000622 return;
623
624 stats->rtcp_packet_type_counts = packet_counter;
sprang07fb9be2016-02-24 07:55:00 -0800625 if (uma_container_->first_rtcp_stats_time_ms_ == -1)
626 uma_container_->first_rtcp_stats_time_ms_ = clock_->TimeInMilliseconds();
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000627}
628
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000629void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
630 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200631 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000632 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200633 if (!stats)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000634 return;
635
636 stats->rtcp_stats = statistics;
sprange2d83d62016-02-19 09:03:26 -0800637 uma_container_->report_block_stats_.Store(statistics, 0, ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000638}
639
Peter Boströmd1d66ba2016-02-08 14:07:14 +0100640void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {}
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000641
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000642void SendStatisticsProxy::DataCountersUpdated(
643 const StreamDataCounters& counters,
644 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200645 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000646 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200647 RTC_DCHECK(stats) << "DataCountersUpdated reported for unknown ssrc: "
648 << ssrc;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000649
asaperssona6a699a2016-11-25 03:52:46 -0800650 if (stats->is_flexfec) {
651 // The same counters are reported for both the media ssrc and flexfec ssrc.
652 // Bitrate stats are summed for all SSRCs. Use fec stats from media update.
653 return;
654 }
655
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000656 stats->rtp_stats = counters;
Erik Språng22c2b482016-03-01 09:40:42 +0100657 if (uma_container_->first_rtp_stats_time_ms_ == -1)
658 uma_container_->first_rtp_stats_time_ms_ = clock_->TimeInMilliseconds();
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000659}
660
sprangcd349d92016-07-13 09:11:28 -0700661void SendStatisticsProxy::Notify(uint32_t total_bitrate_bps,
662 uint32_t retransmit_bitrate_bps,
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000663 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200664 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000665 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200666 if (!stats)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000667 return;
668
sprangcd349d92016-07-13 09:11:28 -0700669 stats->total_bitrate_bps = total_bitrate_bps;
670 stats->retransmit_bitrate_bps = retransmit_bitrate_bps;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000671}
672
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000673void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
674 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200675 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000676 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200677 if (!stats)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000678 return;
679
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000680 stats->frame_counts = frame_counts;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000681}
682
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000683void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
684 int max_delay_ms,
685 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200686 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000687 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
Peter Boström74f6e9e2016-04-04 17:56:10 +0200688 if (!stats)
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000689 return;
690 stats->avg_delay_ms = avg_delay_ms;
691 stats->max_delay_ms = max_delay_ms;
asaperssonf040b232015-11-04 00:59:03 -0800692
sprangb4a1ae52015-12-03 08:10:08 -0800693 uma_container_->delay_counter_.Add(avg_delay_ms);
694 uma_container_->max_delay_counter_.Add(max_delay_ms);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000695}
696
asaperssond89920b2015-07-22 06:52:00 -0700697void SendStatisticsProxy::SampleCounter::Add(int sample) {
698 sum += sample;
699 ++num_samples;
700}
701
702int SendStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
703 if (num_samples < min_required_samples || num_samples == 0)
704 return -1;
asaperssonda535c42015-10-19 23:32:41 -0700705 return (sum + (num_samples / 2)) / num_samples;
asaperssond89920b2015-07-22 06:52:00 -0700706}
707
asaperssondec5ebf2015-10-05 02:36:17 -0700708void SendStatisticsProxy::BoolSampleCounter::Add(bool sample) {
709 if (sample)
710 ++sum;
711 ++num_samples;
712}
713
714int SendStatisticsProxy::BoolSampleCounter::Percent(
715 int min_required_samples) const {
716 return Fraction(min_required_samples, 100.0f);
717}
718
719int SendStatisticsProxy::BoolSampleCounter::Permille(
720 int min_required_samples) const {
721 return Fraction(min_required_samples, 1000.0f);
722}
723
724int SendStatisticsProxy::BoolSampleCounter::Fraction(
725 int min_required_samples, float multiplier) const {
726 if (num_samples < min_required_samples || num_samples == 0)
727 return -1;
728 return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
729}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000730} // namespace webrtc