blob: 879a33ded217cb870b975cfd412d26a795d66213 [file] [log] [blame]
sprang@webrtc.org09315702014-02-07 12:06:29 +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/receive_statistics_proxy.h"
12
asaperssonf839dcc2015-10-08 00:41:59 -070013#include <cmath>
14
15#include "webrtc/base/checks.h"
asapersson86b01602015-10-20 23:55:26 -070016#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010017#include "webrtc/system_wrappers/include/clock.h"
18#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
19#include "webrtc/system_wrappers/include/metrics.h"
sprang@webrtc.org09315702014-02-07 12:06:29 +000020
21namespace webrtc {
sprang@webrtc.org09315702014-02-07 12:06:29 +000022
pbos@webrtc.org55707692014-12-19 15:45:03 +000023ReceiveStatisticsProxy::ReceiveStatisticsProxy(uint32_t ssrc, Clock* clock)
24 : clock_(clock),
sprang@webrtc.org09315702014-02-07 12:06:29 +000025 // 1000ms window, scale 1000 for ms to s.
26 decode_fps_estimator_(1000, 1000),
Tim Psiaki63046262015-09-14 10:38:08 -070027 renders_fps_estimator_(1000, 1000),
asaperssonf839dcc2015-10-08 00:41:59 -070028 render_fps_tracker_(100u, 10u),
29 render_pixel_tracker_(100u, 10u) {
sprang@webrtc.org09315702014-02-07 12:06:29 +000030 stats_.ssrc = ssrc;
31}
32
Åsa Persson3c391cb2015-04-27 10:09:49 +020033ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
34 UpdateHistograms();
35}
36
asaperssond89920b2015-07-22 06:52:00 -070037void ReceiveStatisticsProxy::UpdateHistograms() {
38 int fraction_lost = report_block_stats_.FractionLostInPercent();
Åsa Persson3c391cb2015-04-27 10:09:49 +020039 if (fraction_lost != -1) {
40 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
41 fraction_lost);
42 }
asapersson6718e972015-07-24 00:20:58 -070043 const int kMinRequiredSamples = 200;
asaperssonf839dcc2015-10-08 00:41:59 -070044 int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount());
45 if (samples > kMinRequiredSamples) {
46 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond",
Tim Psiakiad13d2f2015-11-10 16:34:50 -080047 round(render_fps_tracker_.ComputeTotalRate()));
asaperssonf839dcc2015-10-08 00:41:59 -070048 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.RenderSqrtPixelsPerSecond",
Tim Psiakiad13d2f2015-11-10 16:34:50 -080049 round(render_pixel_tracker_.ComputeTotalRate()));
asaperssonf839dcc2015-10-08 00:41:59 -070050 }
asaperssond89920b2015-07-22 06:52:00 -070051 int width = render_width_counter_.Avg(kMinRequiredSamples);
52 int height = render_height_counter_.Avg(kMinRequiredSamples);
53 if (width != -1) {
54 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedWidthInPixels", width);
55 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedHeightInPixels", height);
56 }
asapersson86b01602015-10-20 23:55:26 -070057 int qp = qp_counters_.vp8.Avg(kMinRequiredSamples);
58 if (qp != -1)
59 RTC_HISTOGRAM_COUNTS_200("WebRTC.Video.Decoded.Vp8.Qp", qp);
60
asapersson6718e972015-07-24 00:20:58 -070061 // TODO(asapersson): DecoderTiming() is call periodically (each 1000ms) and
62 // not per frame. Change decode time to include every frame.
63 const int kMinRequiredDecodeSamples = 5;
64 int decode_ms = decode_time_counter_.Avg(kMinRequiredDecodeSamples);
65 if (decode_ms != -1)
66 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DecodeTimeInMs", decode_ms);
asapersson13c433c2015-10-06 04:08:15 -070067
68 int delay_ms = delay_counter_.Avg(kMinRequiredDecodeSamples);
69 if (delay_ms != -1)
70 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms);
Åsa Persson3c391cb2015-04-27 10:09:49 +020071}
sprang@webrtc.org09315702014-02-07 12:06:29 +000072
73VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
Peter Boströmf2f82832015-05-01 13:00:41 +020074 rtc::CritScope lock(&crit_);
pbos@webrtc.org55707692014-12-19 15:45:03 +000075 return stats_;
sprang@webrtc.org09315702014-02-07 12:06:29 +000076}
77
pbosf42376c2015-08-28 07:35:32 -070078void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) {
79 rtc::CritScope lock(&crit_);
80 stats_.current_payload_type = payload_type;
81}
82
83void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate,
84 unsigned int bitrate_bps) {
Peter Boströmf2f82832015-05-01 13:00:41 +020085 rtc::CritScope lock(&crit_);
sprang@webrtc.org09315702014-02-07 12:06:29 +000086 stats_.network_frame_rate = framerate;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +000087 stats_.total_bitrate_bps = bitrate_bps;
sprang@webrtc.org09315702014-02-07 12:06:29 +000088}
89
pbosf42376c2015-08-28 07:35:32 -070090void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms,
91 int max_decode_ms,
92 int current_delay_ms,
93 int target_delay_ms,
94 int jitter_buffer_ms,
95 int min_playout_delay_ms,
asapersson13c433c2015-10-06 04:08:15 -070096 int render_delay_ms,
97 int64_t rtt_ms) {
Peter Boströmf2f82832015-05-01 13:00:41 +020098 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +000099 stats_.decode_ms = decode_ms;
100 stats_.max_decode_ms = max_decode_ms;
101 stats_.current_delay_ms = current_delay_ms;
102 stats_.target_delay_ms = target_delay_ms;
103 stats_.jitter_buffer_ms = jitter_buffer_ms;
104 stats_.min_playout_delay_ms = min_playout_delay_ms;
105 stats_.render_delay_ms = render_delay_ms;
asapersson6718e972015-07-24 00:20:58 -0700106 decode_time_counter_.Add(decode_ms);
asapersson13c433c2015-10-06 04:08:15 -0700107 // Network delay (rtt/2) + target_delay_ms (jitter delay + decode time +
108 // render delay).
109 delay_counter_.Add(target_delay_ms + rtt_ms / 2);
pbos@webrtc.org98c04b32014-12-18 13:12:52 +0000110}
111
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000112void ReceiveStatisticsProxy::RtcpPacketTypesCounterUpdated(
113 uint32_t ssrc,
114 const RtcpPacketTypeCounter& packet_counter) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200115 rtc::CritScope lock(&crit_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000116 if (stats_.ssrc != ssrc)
117 return;
118 stats_.rtcp_packet_type_counts = packet_counter;
119}
120
sprang@webrtc.org09315702014-02-07 12:06:29 +0000121void ReceiveStatisticsProxy::StatisticsUpdated(
122 const webrtc::RtcpStatistics& statistics,
123 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200124 rtc::CritScope lock(&crit_);
henrikg91d6ede2015-09-17 00:24:34 -0700125 // TODO(pbos): Handle both local and remote ssrcs here and RTC_DCHECK that we
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000126 // receive stats from one of them.
127 if (stats_.ssrc != ssrc)
128 return;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000129 stats_.rtcp_stats = statistics;
Åsa Persson3c391cb2015-04-27 10:09:49 +0200130 report_block_stats_.Store(statistics, ssrc, 0);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000131}
132
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000133void ReceiveStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200134 rtc::CritScope lock(&crit_);
henrikg91d6ede2015-09-17 00:24:34 -0700135 // TODO(pbos): Handle both local and remote ssrcs here and RTC_DCHECK that we
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136 // receive stats from one of them.
137 if (stats_.ssrc != ssrc)
138 return;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000139 stats_.c_name = cname;
140}
141
sprang@webrtc.org09315702014-02-07 12:06:29 +0000142void ReceiveStatisticsProxy::DataCountersUpdated(
143 const webrtc::StreamDataCounters& counters,
144 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200145 rtc::CritScope lock(&crit_);
pbos@webrtc.org982cd2a2015-03-03 15:56:56 +0000146 if (stats_.ssrc != ssrc)
147 return;
sprang@webrtc.org09315702014-02-07 12:06:29 +0000148 stats_.rtp_stats = counters;
149}
150
151void ReceiveStatisticsProxy::OnDecodedFrame() {
152 uint64_t now = clock_->TimeInMilliseconds();
153
Peter Boströmf2f82832015-05-01 13:00:41 +0200154 rtc::CritScope lock(&crit_);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000155 decode_fps_estimator_.Update(1, now);
156 stats_.decode_frame_rate = decode_fps_estimator_.Rate(now);
157}
158
asaperssond89920b2015-07-22 06:52:00 -0700159void ReceiveStatisticsProxy::OnRenderedFrame(int width, int height) {
asaperssonf839dcc2015-10-08 00:41:59 -0700160 RTC_DCHECK_GT(width, 0);
161 RTC_DCHECK_GT(height, 0);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000162 uint64_t now = clock_->TimeInMilliseconds();
163
Peter Boströmf2f82832015-05-01 13:00:41 +0200164 rtc::CritScope lock(&crit_);
sprang@webrtc.org09315702014-02-07 12:06:29 +0000165 renders_fps_estimator_.Update(1, now);
166 stats_.render_frame_rate = renders_fps_estimator_.Rate(now);
asaperssond89920b2015-07-22 06:52:00 -0700167 render_width_counter_.Add(width);
168 render_height_counter_.Add(height);
Tim Psiaki63046262015-09-14 10:38:08 -0700169 render_fps_tracker_.AddSamples(1);
asaperssonf839dcc2015-10-08 00:41:59 -0700170 render_pixel_tracker_.AddSamples(sqrt(width * height));
sprang@webrtc.org09315702014-02-07 12:06:29 +0000171}
172
pbos@webrtc.org55707692014-12-19 15:45:03 +0000173void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate,
174 uint32_t frameRate) {
175}
176
177void ReceiveStatisticsProxy::OnFrameCountsUpdated(
178 const FrameCounts& frame_counts) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200179 rtc::CritScope lock(&crit_);
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000180 stats_.frame_counts = frame_counts;
181}
182
pbos@webrtc.org55707692014-12-19 15:45:03 +0000183void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200184 rtc::CritScope lock(&crit_);
pbos@webrtc.org55707692014-12-19 15:45:03 +0000185 stats_.discarded_packets = discarded_packets;
186}
187
asapersson86b01602015-10-20 23:55:26 -0700188void ReceiveStatisticsProxy::OnPreDecode(
189 const EncodedImage& encoded_image,
190 const CodecSpecificInfo* codec_specific_info) {
191 if (codec_specific_info == nullptr || encoded_image.qp_ == -1) {
192 return;
193 }
194 if (codec_specific_info->codecType == kVideoCodecVP8) {
195 qp_counters_.vp8.Add(encoded_image.qp_);
196 }
197}
198
asaperssond89920b2015-07-22 06:52:00 -0700199void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
200 sum += sample;
201 ++num_samples;
202}
203
204int ReceiveStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
205 if (num_samples < min_required_samples || num_samples == 0)
206 return -1;
207 return sum / num_samples;
208}
209
sprang@webrtc.org09315702014-02-07 12:06:29 +0000210} // namespace webrtc