blob: c6f48e21a853a3b254a6eb0c92a43f39c04af930 [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
13#include <map>
14
pbos@webrtc.org49096de2015-02-24 22:37:52 +000015#include "webrtc/base/checks.h"
16
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000017#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org273a4142014-12-01 15:23:21 +000018#include "webrtc/system_wrappers/interface/logging.h"
Åsa Persson24b4eda2015-06-16 10:17:01 +020019#include "webrtc/system_wrappers/interface/metrics.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000020
21namespace webrtc {
22
pbos@webrtc.org273a4142014-12-01 15:23:21 +000023const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
24
25SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
26 const VideoSendStream::Config& config)
Åsa Persson24b4eda2015-06-16 10:17:01 +020027 : clock_(clock), config_(config), last_sent_frame_timestamp_(0) {
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +000028}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000029
Åsa Persson24b4eda2015-06-16 10:17:01 +020030SendStatisticsProxy::~SendStatisticsProxy() {
31 UpdateHistograms();
32}
33
34void SendStatisticsProxy::UpdateHistograms() {
35 int input_fps =
36 static_cast<int>(input_frame_rate_tracker_total_.units_second());
37 int sent_fps =
38 static_cast<int>(sent_frame_rate_tracker_total_.units_second());
39
40 if (input_fps > 0)
41 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.InputFramesPerSecond", input_fps);
42 if (sent_fps > 0)
43 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.SentFramesPerSecond", sent_fps);
44}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000045
46void SendStatisticsProxy::OutgoingRate(const int video_channel,
47 const unsigned int framerate,
48 const unsigned int bitrate) {
Peter Boströmf2f82832015-05-01 13:00:41 +020049 rtc::CritScope lock(&crit_);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000050 stats_.encode_frame_rate = framerate;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +000051 stats_.media_bitrate_bps = bitrate;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000052}
53
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000054void SendStatisticsProxy::CpuOveruseMetricsUpdated(
55 const CpuOveruseMetrics& metrics) {
Peter Boströmf2f82832015-05-01 13:00:41 +020056 rtc::CritScope lock(&crit_);
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +000057 stats_.avg_encode_time_ms = metrics.avg_encode_time_ms;
58 stats_.encode_usage_percent = metrics.encode_usage_percent;
59}
60
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +000061void SendStatisticsProxy::SuspendChange(int video_channel, bool is_suspended) {
Peter Boströmf2f82832015-05-01 13:00:41 +020062 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +000063 stats_.suspended = is_suspended;
64}
65
pbos@webrtc.org273a4142014-12-01 15:23:21 +000066VideoSendStream::Stats SendStatisticsProxy::GetStats() {
Peter Boströmf2f82832015-05-01 13:00:41 +020067 rtc::CritScope lock(&crit_);
pbos@webrtc.org273a4142014-12-01 15:23:21 +000068 PurgeOldStats();
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +000069 stats_.input_frame_rate =
70 static_cast<int>(input_frame_rate_tracker_.units_second());
stefan@webrtc.org168f23f2014-07-11 13:44:02 +000071 return stats_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000072}
73
pbos@webrtc.org273a4142014-12-01 15:23:21 +000074void SendStatisticsProxy::PurgeOldStats() {
Peter Boström20f3f942015-05-15 11:33:39 +020075 int64_t old_stats_ms = clock_->TimeInMilliseconds() - kStatsTimeoutMs;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +000076 for (std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
77 stats_.substreams.begin();
pbos@webrtc.org273a4142014-12-01 15:23:21 +000078 it != stats_.substreams.end(); ++it) {
79 uint32_t ssrc = it->first;
Peter Boström20f3f942015-05-15 11:33:39 +020080 if (update_times_[ssrc].resolution_update_ms <= old_stats_ms) {
81 it->second.width = 0;
82 it->second.height = 0;
83 }
pbos@webrtc.org273a4142014-12-01 15:23:21 +000084 }
85}
86
pbos@webrtc.org09c77b92015-02-25 10:42:16 +000087VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry(
88 uint32_t ssrc) {
89 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
90 stats_.substreams.find(ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000091 if (it != stats_.substreams.end())
92 return &it->second;
93
94 if (std::find(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc) ==
stefan@webrtc.org58e2d262014-08-14 15:10:49 +000095 config_.rtp.ssrcs.end() &&
96 std::find(config_.rtp.rtx.ssrcs.begin(),
97 config_.rtp.rtx.ssrcs.end(),
98 ssrc) == config_.rtp.rtx.ssrcs.end()) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000099 return nullptr;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000100 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000101
102 return &stats_.substreams[ssrc]; // Insert new entry and return ptr.
103}
104
Peter Boström20f3f942015-05-15 11:33:39 +0200105void SendStatisticsProxy::OnInactiveSsrc(uint32_t ssrc) {
106 rtc::CritScope lock(&crit_);
107 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
108 if (stats == nullptr)
109 return;
110
111 stats->total_bitrate_bps = 0;
112 stats->retransmit_bitrate_bps = 0;
113 stats->height = 0;
114 stats->width = 0;
115}
116
pbos@webrtc.org891d4832015-02-26 13:15:22 +0000117void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200118 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +0000119 stats_.target_media_bitrate_bps = bitrate_bps;
120}
121
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000122void SendStatisticsProxy::OnSendEncodedImage(
123 const EncodedImage& encoded_image,
124 const RTPVideoHeader* rtp_video_header) {
125 size_t simulcast_idx =
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000126 rtp_video_header != nullptr ? rtp_video_header->simulcastIdx : 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000127 if (simulcast_idx >= config_.rtp.ssrcs.size()) {
128 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
129 << " >= " << config_.rtp.ssrcs.size() << ").";
130 return;
131 }
132 uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx];
133
Peter Boströmf2f82832015-05-01 13:00:41 +0200134 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000135 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000136 if (stats == nullptr)
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000137 return;
138
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000139 stats->width = encoded_image._encodedWidth;
140 stats->height = encoded_image._encodedHeight;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000141 update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
Åsa Persson24b4eda2015-06-16 10:17:01 +0200142 if (encoded_image._timeStamp != last_sent_frame_timestamp_) {
143 last_sent_frame_timestamp_ = encoded_image._timeStamp;
144 sent_frame_rate_tracker_total_.Update(1);
145 }
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000146}
147
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000148void SendStatisticsProxy::OnIncomingFrame() {
Peter Boströmf2f82832015-05-01 13:00:41 +0200149 rtc::CritScope lock(&crit_);
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000150 input_frame_rate_tracker_.Update(1);
Åsa Persson24b4eda2015-06-16 10:17:01 +0200151 input_frame_rate_tracker_total_.Update(1);
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000152}
153
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000154void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
155 uint32_t ssrc,
156 const RtcpPacketTypeCounter& packet_counter) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200157 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000158 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000159 if (stats == nullptr)
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000160 return;
161
162 stats->rtcp_packet_type_counts = packet_counter;
163}
164
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000165void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
166 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200167 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000168 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000169 if (stats == nullptr)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000170 return;
171
172 stats->rtcp_stats = statistics;
173}
174
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000175void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
176}
177
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000178void SendStatisticsProxy::DataCountersUpdated(
179 const StreamDataCounters& counters,
180 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200181 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000182 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000183 DCHECK(stats != nullptr) << "DataCountersUpdated reported for unknown ssrc: "
184 << ssrc;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000185
186 stats->rtp_stats = counters;
187}
188
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000189void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
190 const BitrateStatistics& retransmit_stats,
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000191 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200192 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000193 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000194 if (stats == nullptr)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000195 return;
196
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000197 stats->total_bitrate_bps = total_stats.bitrate_bps;
198 stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000199}
200
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000201void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
202 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200203 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000204 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000205 if (stats == nullptr)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000206 return;
207
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000208 stats->frame_counts = frame_counts;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000209}
210
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000211void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
212 int max_delay_ms,
213 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200214 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000215 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000216 if (stats == nullptr)
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000217 return;
218 stats->avg_delay_ms = avg_delay_ms;
219 stats->max_delay_ms = max_delay_ms;
220}
221
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000222} // namespace webrtc