2014-01-07 09:54:34 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "webrtc/video/send_statistics_proxy.h"
|
|
|
|
|
|
2015-07-22 06:52:00 -07:00
|
|
|
#include <algorithm>
|
2015-11-10 16:34:50 -08:00
|
|
|
#include <cmath>
|
2014-01-07 09:54:34 +00:00
|
|
|
#include <map>
|
|
|
|
|
|
2015-02-24 22:37:52 +00:00
|
|
|
#include "webrtc/base/checks.h"
|
2015-10-26 11:35:17 +01:00
|
|
|
#include "webrtc/base/logging.h"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/metrics.h"
|
2014-01-07 09:54:34 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
2015-10-27 01:32:00 -07:00
|
|
|
namespace {
|
2015-12-07 03:12:22 -08:00
|
|
|
const float kEncodeTimeWeigthFactor = 0.5f;
|
|
|
|
|
|
2015-10-27 01:32:00 -07:00
|
|
|
// Used by histograms. Values of entries should not be changed.
|
|
|
|
|
enum HistogramCodecType {
|
|
|
|
|
kVideoUnknown = 0,
|
|
|
|
|
kVideoVp8 = 1,
|
|
|
|
|
kVideoVp9 = 2,
|
|
|
|
|
kVideoH264 = 3,
|
|
|
|
|
kVideoMax = 64,
|
|
|
|
|
};
|
|
|
|
|
|
2015-12-03 08:10:08 -08:00
|
|
|
const char* GetUmaPrefix(VideoEncoderConfig::ContentType content_type) {
|
|
|
|
|
switch (content_type) {
|
|
|
|
|
case VideoEncoderConfig::ContentType::kRealtimeVideo:
|
|
|
|
|
return "WebRTC.Video.";
|
|
|
|
|
case VideoEncoderConfig::ContentType::kScreen:
|
|
|
|
|
return "WebRTC.Video.Screenshare.";
|
|
|
|
|
}
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 01:32:00 -07:00
|
|
|
HistogramCodecType PayloadNameToHistogramCodecType(
|
|
|
|
|
const std::string& payload_name) {
|
|
|
|
|
if (payload_name == "VP8") {
|
|
|
|
|
return kVideoVp8;
|
|
|
|
|
} else if (payload_name == "VP9") {
|
|
|
|
|
return kVideoVp9;
|
|
|
|
|
} else if (payload_name == "H264") {
|
|
|
|
|
return kVideoH264;
|
|
|
|
|
} else {
|
|
|
|
|
return kVideoUnknown;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UpdateCodecTypeHistogram(const std::string& payload_name) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE("WebRTC.Video.Encoder.CodecType",
|
2015-10-27 01:32:00 -07:00
|
|
|
PayloadNameToHistogramCodecType(payload_name), kVideoMax);
|
|
|
|
|
}
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2014-01-07 09:54:34 +00:00
|
|
|
|
2014-12-01 15:23:21 +00:00
|
|
|
const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
|
|
|
|
|
|
2015-12-03 08:10:08 -08:00
|
|
|
SendStatisticsProxy::SendStatisticsProxy(
|
|
|
|
|
Clock* clock,
|
|
|
|
|
const VideoSendStream::Config& config,
|
|
|
|
|
VideoEncoderConfig::ContentType content_type)
|
2015-07-22 06:52:00 -07:00
|
|
|
: clock_(clock),
|
|
|
|
|
config_(config),
|
2015-12-03 08:10:08 -08:00
|
|
|
content_type_(content_type),
|
2015-07-22 06:52:00 -07:00
|
|
|
last_sent_frame_timestamp_(0),
|
2015-12-07 03:12:22 -08:00
|
|
|
encode_time_(kEncodeTimeWeigthFactor),
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_(new UmaSamplesContainer(GetUmaPrefix(content_type_))) {
|
2015-10-27 01:32:00 -07:00
|
|
|
UpdateCodecTypeHistogram(config_.encoder_settings.payload_name);
|
2014-04-28 13:00:21 +00:00
|
|
|
}
|
2014-01-07 09:54:34 +00:00
|
|
|
|
2015-12-03 08:10:08 -08:00
|
|
|
SendStatisticsProxy::~SendStatisticsProxy() {}
|
|
|
|
|
|
|
|
|
|
SendStatisticsProxy::UmaSamplesContainer::UmaSamplesContainer(
|
|
|
|
|
const char* prefix)
|
|
|
|
|
: uma_prefix_(prefix),
|
|
|
|
|
max_sent_width_per_timestamp_(0),
|
|
|
|
|
max_sent_height_per_timestamp_(0),
|
|
|
|
|
input_frame_rate_tracker_(100u, 10u),
|
|
|
|
|
sent_frame_rate_tracker_(100u, 10u) {}
|
|
|
|
|
|
|
|
|
|
SendStatisticsProxy::UmaSamplesContainer::~UmaSamplesContainer() {
|
2015-06-16 10:17:01 +02:00
|
|
|
UpdateHistograms();
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-03 08:10:08 -08:00
|
|
|
void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms() {
|
2015-07-24 00:20:58 -07:00
|
|
|
const int kMinRequiredSamples = 200;
|
2015-07-22 06:52:00 -07:00
|
|
|
int in_width = input_width_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
int in_height = input_height_counter_.Avg(kMinRequiredSamples);
|
2015-11-16 00:40:49 -08:00
|
|
|
int in_fps = round(input_frame_rate_tracker_.ComputeTotalRate());
|
2015-07-22 06:52:00 -07:00
|
|
|
if (in_width != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(uma_prefix_ + "InputWidthInPixels",
|
|
|
|
|
in_width);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(uma_prefix_ + "InputHeightInPixels",
|
|
|
|
|
in_height);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_100(uma_prefix_ + "InputFramesPerSecond",
|
|
|
|
|
in_fps);
|
2015-07-22 06:52:00 -07:00
|
|
|
}
|
|
|
|
|
int sent_width = sent_width_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
int sent_height = sent_height_counter_.Avg(kMinRequiredSamples);
|
2015-11-16 00:40:49 -08:00
|
|
|
int sent_fps = round(sent_frame_rate_tracker_.ComputeTotalRate());
|
2015-07-22 06:52:00 -07:00
|
|
|
if (sent_width != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(uma_prefix_ + "SentWidthInPixels",
|
|
|
|
|
sent_width);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_10000(uma_prefix_ + "SentHeightInPixels",
|
|
|
|
|
sent_height);
|
|
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_100(uma_prefix_ + "SentFramesPerSecond",
|
|
|
|
|
sent_fps);
|
2015-07-22 06:52:00 -07:00
|
|
|
}
|
2015-07-24 00:20:58 -07:00
|
|
|
int encode_ms = encode_time_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (encode_ms != -1)
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_1000(uma_prefix_ + "EncodeTimeInMs", encode_ms);
|
2015-10-05 02:36:17 -07:00
|
|
|
|
|
|
|
|
int key_frames_permille = key_frame_counter_.Permille(kMinRequiredSamples);
|
|
|
|
|
if (key_frames_permille != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_1000(uma_prefix_ + "KeyFramesSentInPermille",
|
|
|
|
|
key_frames_permille);
|
2015-10-05 02:36:17 -07:00
|
|
|
}
|
2015-10-19 00:35:21 -07:00
|
|
|
int quality_limited =
|
|
|
|
|
quality_limited_frame_counter_.Percent(kMinRequiredSamples);
|
|
|
|
|
if (quality_limited != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_PERCENTAGE_SPARSE(
|
|
|
|
|
uma_prefix_ + "QualityLimitedResolutionInPercent", quality_limited);
|
2015-10-19 00:35:21 -07:00
|
|
|
}
|
|
|
|
|
int downscales = quality_downscales_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (downscales != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_prefix_ + "QualityLimitedResolutionDownscales", downscales, 20);
|
2015-10-19 00:35:21 -07:00
|
|
|
}
|
2015-10-19 23:32:41 -07:00
|
|
|
int bw_limited = bw_limited_frame_counter_.Percent(kMinRequiredSamples);
|
|
|
|
|
if (bw_limited != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_PERCENTAGE_SPARSE(
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_prefix_ + "BandwidthLimitedResolutionInPercent", bw_limited);
|
2015-10-19 23:32:41 -07:00
|
|
|
}
|
|
|
|
|
int num_disabled = bw_resolutions_disabled_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (num_disabled != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_prefix_ + "BandwidthLimitedResolutionsDisabled", num_disabled, 10);
|
2015-10-19 23:32:41 -07:00
|
|
|
}
|
2015-11-04 00:59:03 -08:00
|
|
|
int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (delay_ms != -1)
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_100000(uma_prefix_ + "SendSideDelayInMs",
|
|
|
|
|
delay_ms);
|
2015-11-04 00:59:03 -08:00
|
|
|
|
|
|
|
|
int max_delay_ms = max_delay_counter_.Avg(kMinRequiredSamples);
|
|
|
|
|
if (max_delay_ms != -1) {
|
2015-12-21 01:46:20 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_SPARSE_100000(uma_prefix_ + "SendSideDelayMaxInMs",
|
|
|
|
|
max_delay_ms);
|
2015-12-03 08:10:08 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SendStatisticsProxy::SetContentType(
|
|
|
|
|
VideoEncoderConfig::ContentType content_type) {
|
|
|
|
|
rtc::CritScope lock(&crit_);
|
|
|
|
|
if (content_type_ != content_type) {
|
|
|
|
|
uma_container_.reset(new UmaSamplesContainer(GetUmaPrefix(content_type)));
|
|
|
|
|
content_type_ = content_type;
|
2015-11-04 00:59:03 -08:00
|
|
|
}
|
2015-06-16 10:17:01 +02:00
|
|
|
}
|
2014-01-07 09:54:34 +00:00
|
|
|
|
2015-12-18 16:01:11 +01:00
|
|
|
void SendStatisticsProxy::OnEncoderImplementationName(
|
|
|
|
|
const char* implementation_name) {
|
|
|
|
|
rtc::CritScope lock(&crit_);
|
|
|
|
|
stats_.encoder_implementation_name = implementation_name;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-22 16:28:51 +02:00
|
|
|
void SendStatisticsProxy::OnOutgoingRate(uint32_t framerate, uint32_t bitrate) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2014-01-07 09:54:34 +00:00
|
|
|
stats_.encode_frame_rate = framerate;
|
2014-11-05 14:05:29 +00:00
|
|
|
stats_.media_bitrate_bps = bitrate;
|
2014-01-07 09:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
2015-02-26 12:19:31 +00:00
|
|
|
void SendStatisticsProxy::CpuOveruseMetricsUpdated(
|
|
|
|
|
const CpuOveruseMetrics& metrics) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-26 12:19:31 +00:00
|
|
|
stats_.encode_usage_percent = metrics.encode_usage_percent;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-22 16:28:51 +02:00
|
|
|
void SendStatisticsProxy::OnSuspendChange(bool is_suspended) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2014-03-13 13:31:21 +00:00
|
|
|
stats_.suspended = is_suspended;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 15:23:21 +00:00
|
|
|
VideoSendStream::Stats SendStatisticsProxy::GetStats() {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2014-12-01 15:23:21 +00:00
|
|
|
PurgeOldStats();
|
2015-03-18 09:51:05 +00:00
|
|
|
stats_.input_frame_rate =
|
2015-12-03 08:10:08 -08:00
|
|
|
round(uma_container_->input_frame_rate_tracker_.ComputeRate());
|
2014-07-11 13:44:02 +00:00
|
|
|
return stats_;
|
2014-01-07 09:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
2014-12-01 15:23:21 +00:00
|
|
|
void SendStatisticsProxy::PurgeOldStats() {
|
2015-05-15 11:33:39 +02:00
|
|
|
int64_t old_stats_ms = clock_->TimeInMilliseconds() - kStatsTimeoutMs;
|
2015-02-25 10:42:16 +00:00
|
|
|
for (std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
|
|
|
|
|
stats_.substreams.begin();
|
2014-12-01 15:23:21 +00:00
|
|
|
it != stats_.substreams.end(); ++it) {
|
|
|
|
|
uint32_t ssrc = it->first;
|
2015-05-15 11:33:39 +02:00
|
|
|
if (update_times_[ssrc].resolution_update_ms <= old_stats_ms) {
|
|
|
|
|
it->second.width = 0;
|
|
|
|
|
it->second.height = 0;
|
|
|
|
|
}
|
2014-12-01 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry(
|
|
|
|
|
uint32_t ssrc) {
|
|
|
|
|
std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
|
|
|
|
|
stats_.substreams.find(ssrc);
|
2014-01-07 09:54:34 +00:00
|
|
|
if (it != stats_.substreams.end())
|
|
|
|
|
return &it->second;
|
|
|
|
|
|
|
|
|
|
if (std::find(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc) ==
|
2014-08-14 15:10:49 +00:00
|
|
|
config_.rtp.ssrcs.end() &&
|
|
|
|
|
std::find(config_.rtp.rtx.ssrcs.begin(),
|
|
|
|
|
config_.rtp.rtx.ssrcs.end(),
|
|
|
|
|
ssrc) == config_.rtp.rtx.ssrcs.end()) {
|
2015-03-23 13:12:24 +00:00
|
|
|
return nullptr;
|
2014-08-14 15:10:49 +00:00
|
|
|
}
|
2014-01-07 09:54:34 +00:00
|
|
|
|
|
|
|
|
return &stats_.substreams[ssrc]; // Insert new entry and return ptr.
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 11:33:39 +02:00
|
|
|
void SendStatisticsProxy::OnInactiveSsrc(uint32_t ssrc) {
|
|
|
|
|
rtc::CritScope lock(&crit_);
|
|
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
|
|
|
if (stats == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
stats->total_bitrate_bps = 0;
|
|
|
|
|
stats->retransmit_bitrate_bps = 0;
|
|
|
|
|
stats->height = 0;
|
|
|
|
|
stats->width = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-26 13:15:22 +00:00
|
|
|
void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-26 13:15:22 +00:00
|
|
|
stats_.target_media_bitrate_bps = bitrate_bps;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-01 15:23:21 +00:00
|
|
|
void SendStatisticsProxy::OnSendEncodedImage(
|
|
|
|
|
const EncodedImage& encoded_image,
|
|
|
|
|
const RTPVideoHeader* rtp_video_header) {
|
|
|
|
|
size_t simulcast_idx =
|
2015-03-23 13:12:24 +00:00
|
|
|
rtp_video_header != nullptr ? rtp_video_header->simulcastIdx : 0;
|
2014-12-01 15:23:21 +00:00
|
|
|
if (simulcast_idx >= config_.rtp.ssrcs.size()) {
|
|
|
|
|
LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
|
|
|
|
|
<< " >= " << config_.rtp.ssrcs.size() << ").";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx];
|
|
|
|
|
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-03-23 13:12:24 +00:00
|
|
|
if (stats == nullptr)
|
2014-12-01 15:23:21 +00:00
|
|
|
return;
|
|
|
|
|
|
2015-02-25 10:42:16 +00:00
|
|
|
stats->width = encoded_image._encodedWidth;
|
|
|
|
|
stats->height = encoded_image._encodedHeight;
|
2014-12-01 15:23:21 +00:00
|
|
|
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
|
2015-07-22 06:52:00 -07:00
|
|
|
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->key_frame_counter_.Add(encoded_image._frameType ==
|
|
|
|
|
kVideoFrameKey);
|
2015-10-05 02:36:17 -07:00
|
|
|
|
2015-12-14 02:08:12 -08:00
|
|
|
stats_.bw_limited_resolution =
|
|
|
|
|
encoded_image.adapt_reason_.quality_resolution_downscales > 0 ||
|
|
|
|
|
encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
|
|
|
|
|
|
2015-10-19 00:35:21 -07:00
|
|
|
if (encoded_image.adapt_reason_.quality_resolution_downscales != -1) {
|
|
|
|
|
bool downscaled =
|
|
|
|
|
encoded_image.adapt_reason_.quality_resolution_downscales > 0;
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->quality_limited_frame_counter_.Add(downscaled);
|
2015-10-19 00:35:21 -07:00
|
|
|
if (downscaled) {
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->quality_downscales_counter_.Add(
|
2015-10-19 00:35:21 -07:00
|
|
|
encoded_image.adapt_reason_.quality_resolution_downscales);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-19 23:32:41 -07:00
|
|
|
if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) {
|
|
|
|
|
bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->bw_limited_frame_counter_.Add(bw_limited);
|
2015-10-19 23:32:41 -07:00
|
|
|
if (bw_limited) {
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->bw_resolutions_disabled_counter_.Add(
|
|
|
|
|
encoded_image.adapt_reason_.bw_resolutions_disabled);
|
2015-10-19 23:32:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
2015-10-19 00:35:21 -07:00
|
|
|
|
2015-07-22 06:52:00 -07:00
|
|
|
// TODO(asapersson): This is incorrect if simulcast layers are encoded on
|
|
|
|
|
// different threads and there is no guarantee that one frame of all layers
|
|
|
|
|
// are encoded before the next start.
|
|
|
|
|
if (last_sent_frame_timestamp_ > 0 &&
|
|
|
|
|
encoded_image._timeStamp != last_sent_frame_timestamp_) {
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->sent_frame_rate_tracker_.AddSamples(1);
|
|
|
|
|
uma_container_->sent_width_counter_.Add(
|
|
|
|
|
uma_container_->max_sent_width_per_timestamp_);
|
|
|
|
|
uma_container_->sent_height_counter_.Add(
|
|
|
|
|
uma_container_->max_sent_height_per_timestamp_);
|
|
|
|
|
uma_container_->max_sent_width_per_timestamp_ = 0;
|
|
|
|
|
uma_container_->max_sent_height_per_timestamp_ = 0;
|
2015-06-16 10:17:01 +02:00
|
|
|
}
|
2015-07-22 06:52:00 -07:00
|
|
|
last_sent_frame_timestamp_ = encoded_image._timeStamp;
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->max_sent_width_per_timestamp_ =
|
|
|
|
|
std::max(uma_container_->max_sent_width_per_timestamp_,
|
2015-07-22 06:52:00 -07:00
|
|
|
static_cast<int>(encoded_image._encodedWidth));
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->max_sent_height_per_timestamp_ =
|
|
|
|
|
std::max(uma_container_->max_sent_height_per_timestamp_,
|
2015-07-22 06:52:00 -07:00
|
|
|
static_cast<int>(encoded_image._encodedHeight));
|
2014-12-01 15:23:21 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-22 06:52:00 -07:00
|
|
|
void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->input_frame_rate_tracker_.AddSamples(1);
|
|
|
|
|
uma_container_->input_width_counter_.Add(width);
|
|
|
|
|
uma_container_->input_height_counter_.Add(height);
|
2015-03-18 09:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-24 00:20:58 -07:00
|
|
|
void SendStatisticsProxy::OnEncodedFrame(int encode_time_ms) {
|
|
|
|
|
rtc::CritScope lock(&crit_);
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->encode_time_counter_.Add(encode_time_ms);
|
2015-12-07 03:12:22 -08:00
|
|
|
encode_time_.Apply(1.0f, encode_time_ms);
|
|
|
|
|
stats_.avg_encode_time_ms = round(encode_time_.filtered());
|
2015-07-24 00:20:58 -07:00
|
|
|
}
|
|
|
|
|
|
2015-02-19 12:47:00 +00:00
|
|
|
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
|
|
|
|
|
uint32_t ssrc,
|
|
|
|
|
const RtcpPacketTypeCounter& packet_counter) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-03-23 13:12:24 +00:00
|
|
|
if (stats == nullptr)
|
2015-02-19 12:47:00 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
stats->rtcp_packet_type_counts = packet_counter;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-07 09:54:34 +00:00
|
|
|
void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
|
|
|
|
|
uint32_t ssrc) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-03-23 13:12:24 +00:00
|
|
|
if (stats == nullptr)
|
2014-01-07 09:54:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
stats->rtcp_stats = statistics;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-18 13:50:16 +00:00
|
|
|
void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-07 09:54:34 +00:00
|
|
|
void SendStatisticsProxy::DataCountersUpdated(
|
|
|
|
|
const StreamDataCounters& counters,
|
|
|
|
|
uint32_t ssrc) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_DCHECK(stats != nullptr)
|
|
|
|
|
<< "DataCountersUpdated reported for unknown ssrc: " << ssrc;
|
2014-01-07 09:54:34 +00:00
|
|
|
|
|
|
|
|
stats->rtp_stats = counters;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 14:05:29 +00:00
|
|
|
void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
|
|
|
|
|
const BitrateStatistics& retransmit_stats,
|
2014-01-07 09:54:34 +00:00
|
|
|
uint32_t ssrc) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-03-23 13:12:24 +00:00
|
|
|
if (stats == nullptr)
|
2014-01-07 09:54:34 +00:00
|
|
|
return;
|
|
|
|
|
|
2014-11-05 14:05:29 +00:00
|
|
|
stats->total_bitrate_bps = total_stats.bitrate_bps;
|
|
|
|
|
stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
|
2014-01-07 09:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
2014-12-18 13:50:16 +00:00
|
|
|
void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
|
|
|
|
|
uint32_t ssrc) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-03-23 13:12:24 +00:00
|
|
|
if (stats == nullptr)
|
2014-01-07 09:54:34 +00:00
|
|
|
return;
|
|
|
|
|
|
2014-12-18 13:50:16 +00:00
|
|
|
stats->frame_counts = frame_counts;
|
2014-01-07 09:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
2014-07-11 13:44:02 +00:00
|
|
|
void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
|
|
|
|
|
int max_delay_ms,
|
|
|
|
|
uint32_t ssrc) {
|
2015-05-01 13:00:41 +02:00
|
|
|
rtc::CritScope lock(&crit_);
|
2015-02-25 10:42:16 +00:00
|
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
2015-03-23 13:12:24 +00:00
|
|
|
if (stats == nullptr)
|
2014-07-11 13:44:02 +00:00
|
|
|
return;
|
|
|
|
|
stats->avg_delay_ms = avg_delay_ms;
|
|
|
|
|
stats->max_delay_ms = max_delay_ms;
|
2015-11-04 00:59:03 -08:00
|
|
|
|
2015-12-03 08:10:08 -08:00
|
|
|
uma_container_->delay_counter_.Add(avg_delay_ms);
|
|
|
|
|
uma_container_->max_delay_counter_.Add(max_delay_ms);
|
2014-07-11 13:44:02 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-22 06:52:00 -07:00
|
|
|
void SendStatisticsProxy::SampleCounter::Add(int sample) {
|
|
|
|
|
sum += sample;
|
|
|
|
|
++num_samples;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SendStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
|
|
|
|
|
if (num_samples < min_required_samples || num_samples == 0)
|
|
|
|
|
return -1;
|
2015-10-19 23:32:41 -07:00
|
|
|
return (sum + (num_samples / 2)) / num_samples;
|
2015-07-22 06:52:00 -07:00
|
|
|
}
|
|
|
|
|
|
2015-10-05 02:36:17 -07:00
|
|
|
void SendStatisticsProxy::BoolSampleCounter::Add(bool sample) {
|
|
|
|
|
if (sample)
|
|
|
|
|
++sum;
|
|
|
|
|
++num_samples;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SendStatisticsProxy::BoolSampleCounter::Percent(
|
|
|
|
|
int min_required_samples) const {
|
|
|
|
|
return Fraction(min_required_samples, 100.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SendStatisticsProxy::BoolSampleCounter::Permille(
|
|
|
|
|
int min_required_samples) const {
|
|
|
|
|
return Fraction(min_required_samples, 1000.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SendStatisticsProxy::BoolSampleCounter::Fraction(
|
|
|
|
|
int min_required_samples, float multiplier) const {
|
|
|
|
|
if (num_samples < min_required_samples || num_samples == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
|
|
|
|
|
}
|
2014-01-07 09:54:34 +00:00
|
|
|
} // namespace webrtc
|