Add separate send-side UMA stats for screenshare and video.
This CL duplicates all the histograms in SendStatisticsProxy. Might be overkill, but we don't know which stats will be interesting and it makes the change easier. BUG= Review URL: https://codereview.webrtc.org/1433393002 Cr-Commit-Position: refs/heads/master@{#10885}
This commit is contained in:
@ -81,7 +81,7 @@ class EndToEndTest : public test::CallTest {
|
|||||||
void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
|
void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
|
||||||
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
|
||||||
void TestRtpStatePreservation(bool use_rtx);
|
void TestRtpStatePreservation(bool use_rtx);
|
||||||
void VerifyHistogramStats(bool use_rtx, bool use_red);
|
void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare);
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
|
TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
|
||||||
@ -1877,13 +1877,16 @@ TEST_F(EndToEndTest, VerifyNackStats) {
|
|||||||
"WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
|
"WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
void EndToEndTest::VerifyHistogramStats(bool use_rtx,
|
||||||
|
bool use_red,
|
||||||
|
bool screenshare) {
|
||||||
class StatsObserver : public test::EndToEndTest {
|
class StatsObserver : public test::EndToEndTest {
|
||||||
public:
|
public:
|
||||||
StatsObserver(bool use_rtx, bool use_red)
|
StatsObserver(bool use_rtx, bool use_red, bool screenshare)
|
||||||
: EndToEndTest(kLongTimeoutMs),
|
: EndToEndTest(kLongTimeoutMs),
|
||||||
use_rtx_(use_rtx),
|
use_rtx_(use_rtx),
|
||||||
use_red_(use_red),
|
use_red_(use_red),
|
||||||
|
screenshare_(screenshare),
|
||||||
sender_call_(nullptr),
|
sender_call_(nullptr),
|
||||||
receiver_call_(nullptr),
|
receiver_call_(nullptr),
|
||||||
start_runtime_ms_(-1) {}
|
start_runtime_ms_(-1) {}
|
||||||
@ -1934,6 +1937,9 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
(*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
|
(*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
|
||||||
kSendRtxPayloadType;
|
kSendRtxPayloadType;
|
||||||
}
|
}
|
||||||
|
encoder_config->content_type =
|
||||||
|
screenshare_ ? VideoEncoderConfig::ContentType::kScreen
|
||||||
|
: VideoEncoderConfig::ContentType::kRealtimeVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
|
void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
|
||||||
@ -1946,12 +1952,13 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
<< "Timed out waiting for packet to be NACKed.";
|
<< "Timed out waiting for packet to be NACKed.";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_rtx_;
|
const bool use_rtx_;
|
||||||
bool use_red_;
|
const bool use_red_;
|
||||||
|
const bool screenshare_;
|
||||||
Call* sender_call_;
|
Call* sender_call_;
|
||||||
Call* receiver_call_;
|
Call* receiver_call_;
|
||||||
int64_t start_runtime_ms_;
|
int64_t start_runtime_ms_;
|
||||||
} test(use_rtx, use_red);
|
} test(use_rtx, use_red, screenshare);
|
||||||
|
|
||||||
test::ClearHistograms();
|
test::ClearHistograms();
|
||||||
RunBaseTest(&test, FakeNetworkPipe::Config());
|
RunBaseTest(&test, FakeNetworkPipe::Config());
|
||||||
@ -1960,6 +1967,9 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
sender_call_.reset();
|
sender_call_.reset();
|
||||||
receiver_call_.reset();
|
receiver_call_.reset();
|
||||||
|
|
||||||
|
std::string video_prefix =
|
||||||
|
screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
|
||||||
|
|
||||||
// Verify that stats have been updated once.
|
// Verify that stats have been updated once.
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
|
1, test::NumHistogramSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
|
||||||
@ -1983,8 +1993,8 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(1, test::NumHistogramSamples(
|
||||||
"WebRTC.Video.PliPacketsReceivedPerMinute"));
|
"WebRTC.Video.PliPacketsReceivedPerMinute"));
|
||||||
|
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(
|
||||||
"WebRTC.Video.KeyFramesSentInPermille"));
|
1, test::NumHistogramSamples(video_prefix + "KeyFramesSentInPermille"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(1, test::NumHistogramSamples(
|
||||||
"WebRTC.Video.KeyFramesReceivedInPermille"));
|
"WebRTC.Video.KeyFramesReceivedInPermille"));
|
||||||
|
|
||||||
@ -1993,29 +2003,30 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(1, test::NumHistogramSamples(
|
||||||
"WebRTC.Video.ReceivedPacketsLostInPercent"));
|
"WebRTC.Video.ReceivedPacketsLostInPercent"));
|
||||||
|
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputWidthInPixels"));
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputWidthInPixels"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputHeightInPixels"));
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "InputHeightInPixels"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SentWidthInPixels"));
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentWidthInPixels"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SentHeightInPixels"));
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentHeightInPixels"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
|
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.ReceivedWidthInPixels"));
|
||||||
EXPECT_EQ(1,
|
EXPECT_EQ(1,
|
||||||
test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
|
test::NumHistogramSamples("WebRTC.Video.ReceivedHeightInPixels"));
|
||||||
|
|
||||||
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
|
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
|
||||||
test::LastHistogramSample("WebRTC.Video.InputWidthInPixels"));
|
test::LastHistogramSample(video_prefix + "InputWidthInPixels"));
|
||||||
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
|
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
|
||||||
test::LastHistogramSample("WebRTC.Video.InputHeightInPixels"));
|
test::LastHistogramSample(video_prefix + "InputHeightInPixels"));
|
||||||
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
|
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
|
||||||
test::LastHistogramSample("WebRTC.Video.SentWidthInPixels"));
|
test::LastHistogramSample(video_prefix + "SentWidthInPixels"));
|
||||||
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
|
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
|
||||||
test::LastHistogramSample("WebRTC.Video.SentHeightInPixels"));
|
test::LastHistogramSample(video_prefix + "SentHeightInPixels"));
|
||||||
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
|
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].width),
|
||||||
test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
|
test::LastHistogramSample("WebRTC.Video.ReceivedWidthInPixels"));
|
||||||
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
|
EXPECT_EQ(static_cast<int>(encoder_config_.streams[0].height),
|
||||||
test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
|
test::LastHistogramSample("WebRTC.Video.ReceivedHeightInPixels"));
|
||||||
|
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputFramesPerSecond"));
|
EXPECT_EQ(1,
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SentFramesPerSecond"));
|
test::NumHistogramSamples(video_prefix + "InputFramesPerSecond"));
|
||||||
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SentFramesPerSecond"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(1, test::NumHistogramSamples(
|
||||||
"WebRTC.Video.DecodedFramesPerSecond"));
|
"WebRTC.Video.DecodedFramesPerSecond"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
|
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.RenderFramesPerSecond"));
|
||||||
@ -2024,7 +2035,7 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
|
1, test::NumHistogramSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
|
||||||
|
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.EncodeTimeInMs"));
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "EncodeTimeInMs"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
|
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.DecodeTimeInMs"));
|
||||||
|
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(1, test::NumHistogramSamples(
|
||||||
@ -2044,8 +2055,9 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
EXPECT_EQ(1, test::NumHistogramSamples(
|
EXPECT_EQ(1, test::NumHistogramSamples(
|
||||||
"WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
|
"WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
|
||||||
|
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SendSideDelayInMs"));
|
EXPECT_EQ(1, test::NumHistogramSamples(video_prefix + "SendSideDelayInMs"));
|
||||||
EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.SendSideDelayMaxInMs"));
|
EXPECT_EQ(1,
|
||||||
|
test::NumHistogramSamples(video_prefix + "SendSideDelayMaxInMs"));
|
||||||
|
|
||||||
int num_rtx_samples = use_rtx ? 1 : 0;
|
int num_rtx_samples = use_rtx ? 1 : 0;
|
||||||
EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
|
EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
|
||||||
@ -2065,13 +2077,22 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
|
|||||||
TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
|
TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
|
||||||
const bool kEnabledRtx = true;
|
const bool kEnabledRtx = true;
|
||||||
const bool kEnabledRed = false;
|
const bool kEnabledRed = false;
|
||||||
VerifyHistogramStats(kEnabledRtx, kEnabledRed);
|
const bool kScreenshare = false;
|
||||||
|
VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
|
TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
|
||||||
const bool kEnabledRtx = false;
|
const bool kEnabledRtx = false;
|
||||||
const bool kEnabledRed = true;
|
const bool kEnabledRed = true;
|
||||||
VerifyHistogramStats(kEnabledRtx, kEnabledRed);
|
const bool kScreenshare = false;
|
||||||
|
VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) {
|
||||||
|
const bool kEnabledRtx = false;
|
||||||
|
const bool kEnabledRed = false;
|
||||||
|
const bool kScreenshare = true;
|
||||||
|
VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
|
void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
|
||||||
|
@ -31,6 +31,17 @@ enum HistogramCodecType {
|
|||||||
kVideoMax = 64,
|
kVideoMax = 64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
HistogramCodecType PayloadNameToHistogramCodecType(
|
HistogramCodecType PayloadNameToHistogramCodecType(
|
||||||
const std::string& payload_name) {
|
const std::string& payload_name) {
|
||||||
if (payload_name == "VP8") {
|
if (payload_name == "VP8") {
|
||||||
@ -53,78 +64,98 @@ void UpdateCodecTypeHistogram(const std::string& payload_name) {
|
|||||||
|
|
||||||
const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
|
const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
|
||||||
|
|
||||||
SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
|
SendStatisticsProxy::SendStatisticsProxy(
|
||||||
const VideoSendStream::Config& config)
|
Clock* clock,
|
||||||
|
const VideoSendStream::Config& config,
|
||||||
|
VideoEncoderConfig::ContentType content_type)
|
||||||
: clock_(clock),
|
: clock_(clock),
|
||||||
config_(config),
|
config_(config),
|
||||||
input_frame_rate_tracker_(100u, 10u),
|
content_type_(content_type),
|
||||||
sent_frame_rate_tracker_(100u, 10u),
|
|
||||||
last_sent_frame_timestamp_(0),
|
last_sent_frame_timestamp_(0),
|
||||||
max_sent_width_per_timestamp_(0),
|
uma_container_(new UmaSamplesContainer(GetUmaPrefix(content_type_))) {
|
||||||
max_sent_height_per_timestamp_(0) {
|
|
||||||
UpdateCodecTypeHistogram(config_.encoder_settings.payload_name);
|
UpdateCodecTypeHistogram(config_.encoder_settings.payload_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendStatisticsProxy::~SendStatisticsProxy() {
|
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() {
|
||||||
UpdateHistograms();
|
UpdateHistograms();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendStatisticsProxy::UpdateHistograms() {
|
void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms() {
|
||||||
const int kMinRequiredSamples = 200;
|
const int kMinRequiredSamples = 200;
|
||||||
int in_width = input_width_counter_.Avg(kMinRequiredSamples);
|
int in_width = input_width_counter_.Avg(kMinRequiredSamples);
|
||||||
int in_height = input_height_counter_.Avg(kMinRequiredSamples);
|
int in_height = input_height_counter_.Avg(kMinRequiredSamples);
|
||||||
int in_fps = round(input_frame_rate_tracker_.ComputeTotalRate());
|
int in_fps = round(input_frame_rate_tracker_.ComputeTotalRate());
|
||||||
if (in_width != -1) {
|
if (in_width != -1) {
|
||||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InputWidthInPixels", in_width);
|
RTC_HISTOGRAM_COUNTS_10000(uma_prefix_ + "InputWidthInPixels", in_width);
|
||||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InputHeightInPixels", in_height);
|
RTC_HISTOGRAM_COUNTS_10000(uma_prefix_ + "InputHeightInPixels", in_height);
|
||||||
RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.InputFramesPerSecond", in_fps);
|
RTC_HISTOGRAM_COUNTS_100(uma_prefix_ + "InputFramesPerSecond", in_fps);
|
||||||
}
|
}
|
||||||
int sent_width = sent_width_counter_.Avg(kMinRequiredSamples);
|
int sent_width = sent_width_counter_.Avg(kMinRequiredSamples);
|
||||||
int sent_height = sent_height_counter_.Avg(kMinRequiredSamples);
|
int sent_height = sent_height_counter_.Avg(kMinRequiredSamples);
|
||||||
int sent_fps = round(sent_frame_rate_tracker_.ComputeTotalRate());
|
int sent_fps = round(sent_frame_rate_tracker_.ComputeTotalRate());
|
||||||
if (sent_width != -1) {
|
if (sent_width != -1) {
|
||||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SentWidthInPixels", sent_width);
|
RTC_HISTOGRAM_COUNTS_10000(uma_prefix_ + "SentWidthInPixels", sent_width);
|
||||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SentHeightInPixels", sent_height);
|
RTC_HISTOGRAM_COUNTS_10000(uma_prefix_ + "SentHeightInPixels", sent_height);
|
||||||
RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.SentFramesPerSecond", sent_fps);
|
RTC_HISTOGRAM_COUNTS_100(uma_prefix_ + "SentFramesPerSecond", sent_fps);
|
||||||
}
|
}
|
||||||
int encode_ms = encode_time_counter_.Avg(kMinRequiredSamples);
|
int encode_ms = encode_time_counter_.Avg(kMinRequiredSamples);
|
||||||
if (encode_ms != -1)
|
if (encode_ms != -1)
|
||||||
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.EncodeTimeInMs", encode_ms);
|
RTC_HISTOGRAM_COUNTS_1000(uma_prefix_ + "EncodeTimeInMs", encode_ms);
|
||||||
|
|
||||||
int key_frames_permille = key_frame_counter_.Permille(kMinRequiredSamples);
|
int key_frames_permille = key_frame_counter_.Permille(kMinRequiredSamples);
|
||||||
if (key_frames_permille != -1) {
|
if (key_frames_permille != -1) {
|
||||||
RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesSentInPermille",
|
RTC_HISTOGRAM_COUNTS_1000(uma_prefix_ + "KeyFramesSentInPermille",
|
||||||
key_frames_permille);
|
key_frames_permille);
|
||||||
}
|
}
|
||||||
int quality_limited =
|
int quality_limited =
|
||||||
quality_limited_frame_counter_.Percent(kMinRequiredSamples);
|
quality_limited_frame_counter_.Percent(kMinRequiredSamples);
|
||||||
if (quality_limited != -1) {
|
if (quality_limited != -1) {
|
||||||
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.QualityLimitedResolutionInPercent",
|
RTC_HISTOGRAM_PERCENTAGE(uma_prefix_ + "QualityLimitedResolutionInPercent",
|
||||||
quality_limited);
|
quality_limited);
|
||||||
}
|
}
|
||||||
int downscales = quality_downscales_counter_.Avg(kMinRequiredSamples);
|
int downscales = quality_downscales_counter_.Avg(kMinRequiredSamples);
|
||||||
if (downscales != -1) {
|
if (downscales != -1) {
|
||||||
RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.QualityLimitedResolutionDownscales",
|
RTC_HISTOGRAM_ENUMERATION(
|
||||||
downscales, 20);
|
uma_prefix_ + "QualityLimitedResolutionDownscales", downscales, 20);
|
||||||
}
|
}
|
||||||
int bw_limited = bw_limited_frame_counter_.Percent(kMinRequiredSamples);
|
int bw_limited = bw_limited_frame_counter_.Percent(kMinRequiredSamples);
|
||||||
if (bw_limited != -1) {
|
if (bw_limited != -1) {
|
||||||
RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BandwidthLimitedResolutionInPercent",
|
RTC_HISTOGRAM_PERCENTAGE(
|
||||||
bw_limited);
|
uma_prefix_ + "BandwidthLimitedResolutionInPercent", bw_limited);
|
||||||
}
|
}
|
||||||
int num_disabled = bw_resolutions_disabled_counter_.Avg(kMinRequiredSamples);
|
int num_disabled = bw_resolutions_disabled_counter_.Avg(kMinRequiredSamples);
|
||||||
if (num_disabled != -1) {
|
if (num_disabled != -1) {
|
||||||
RTC_HISTOGRAM_ENUMERATION(
|
RTC_HISTOGRAM_ENUMERATION(
|
||||||
"WebRTC.Video.BandwidthLimitedResolutionsDisabled", num_disabled, 10);
|
uma_prefix_ + "BandwidthLimitedResolutionsDisabled", num_disabled, 10);
|
||||||
}
|
}
|
||||||
int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
|
int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
|
||||||
if (delay_ms != -1)
|
if (delay_ms != -1)
|
||||||
RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.SendSideDelayInMs", delay_ms);
|
RTC_HISTOGRAM_COUNTS_100000(uma_prefix_ + "SendSideDelayInMs", delay_ms);
|
||||||
|
|
||||||
int max_delay_ms = max_delay_counter_.Avg(kMinRequiredSamples);
|
int max_delay_ms = max_delay_counter_.Avg(kMinRequiredSamples);
|
||||||
if (max_delay_ms != -1) {
|
if (max_delay_ms != -1) {
|
||||||
RTC_HISTOGRAM_COUNTS_100000(
|
RTC_HISTOGRAM_COUNTS_100000(uma_prefix_ + "SendSideDelayMaxInMs",
|
||||||
"WebRTC.Video.SendSideDelayMaxInMs", max_delay_ms);
|
max_delay_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendStatisticsProxy::SetContentType(
|
||||||
|
VideoEncoderConfig::ContentType content_type) {
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
if (content_type_ != content_type) {
|
||||||
|
uma_container_->UpdateHistograms();
|
||||||
|
uma_container_.reset(new UmaSamplesContainer(GetUmaPrefix(content_type)));
|
||||||
|
content_type_ = content_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +182,7 @@ VideoSendStream::Stats SendStatisticsProxy::GetStats() {
|
|||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
PurgeOldStats();
|
PurgeOldStats();
|
||||||
stats_.input_frame_rate =
|
stats_.input_frame_rate =
|
||||||
round(input_frame_rate_tracker_.ComputeRate());
|
round(uma_container_->input_frame_rate_tracker_.ComputeRate());
|
||||||
return stats_;
|
return stats_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,22 +255,23 @@ void SendStatisticsProxy::OnSendEncodedImage(
|
|||||||
stats->height = encoded_image._encodedHeight;
|
stats->height = encoded_image._encodedHeight;
|
||||||
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
|
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
|
||||||
|
|
||||||
key_frame_counter_.Add(encoded_image._frameType == kVideoFrameKey);
|
uma_container_->key_frame_counter_.Add(encoded_image._frameType ==
|
||||||
|
kVideoFrameKey);
|
||||||
|
|
||||||
if (encoded_image.adapt_reason_.quality_resolution_downscales != -1) {
|
if (encoded_image.adapt_reason_.quality_resolution_downscales != -1) {
|
||||||
bool downscaled =
|
bool downscaled =
|
||||||
encoded_image.adapt_reason_.quality_resolution_downscales > 0;
|
encoded_image.adapt_reason_.quality_resolution_downscales > 0;
|
||||||
quality_limited_frame_counter_.Add(downscaled);
|
uma_container_->quality_limited_frame_counter_.Add(downscaled);
|
||||||
if (downscaled) {
|
if (downscaled) {
|
||||||
quality_downscales_counter_.Add(
|
uma_container_->quality_downscales_counter_.Add(
|
||||||
encoded_image.adapt_reason_.quality_resolution_downscales);
|
encoded_image.adapt_reason_.quality_resolution_downscales);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) {
|
if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) {
|
||||||
bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
|
bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
|
||||||
bw_limited_frame_counter_.Add(bw_limited);
|
uma_container_->bw_limited_frame_counter_.Add(bw_limited);
|
||||||
if (bw_limited) {
|
if (bw_limited) {
|
||||||
bw_resolutions_disabled_counter_.Add(
|
uma_container_->bw_resolutions_disabled_counter_.Add(
|
||||||
encoded_image.adapt_reason_.bw_resolutions_disabled);
|
encoded_image.adapt_reason_.bw_resolutions_disabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,31 +281,33 @@ void SendStatisticsProxy::OnSendEncodedImage(
|
|||||||
// are encoded before the next start.
|
// are encoded before the next start.
|
||||||
if (last_sent_frame_timestamp_ > 0 &&
|
if (last_sent_frame_timestamp_ > 0 &&
|
||||||
encoded_image._timeStamp != last_sent_frame_timestamp_) {
|
encoded_image._timeStamp != last_sent_frame_timestamp_) {
|
||||||
sent_frame_rate_tracker_.AddSamples(1);
|
uma_container_->sent_frame_rate_tracker_.AddSamples(1);
|
||||||
sent_width_counter_.Add(max_sent_width_per_timestamp_);
|
uma_container_->sent_width_counter_.Add(
|
||||||
sent_height_counter_.Add(max_sent_height_per_timestamp_);
|
uma_container_->max_sent_width_per_timestamp_);
|
||||||
max_sent_width_per_timestamp_ = 0;
|
uma_container_->sent_height_counter_.Add(
|
||||||
max_sent_height_per_timestamp_ = 0;
|
uma_container_->max_sent_height_per_timestamp_);
|
||||||
|
uma_container_->max_sent_width_per_timestamp_ = 0;
|
||||||
|
uma_container_->max_sent_height_per_timestamp_ = 0;
|
||||||
}
|
}
|
||||||
last_sent_frame_timestamp_ = encoded_image._timeStamp;
|
last_sent_frame_timestamp_ = encoded_image._timeStamp;
|
||||||
max_sent_width_per_timestamp_ =
|
uma_container_->max_sent_width_per_timestamp_ =
|
||||||
std::max(max_sent_width_per_timestamp_,
|
std::max(uma_container_->max_sent_width_per_timestamp_,
|
||||||
static_cast<int>(encoded_image._encodedWidth));
|
static_cast<int>(encoded_image._encodedWidth));
|
||||||
max_sent_height_per_timestamp_ =
|
uma_container_->max_sent_height_per_timestamp_ =
|
||||||
std::max(max_sent_height_per_timestamp_,
|
std::max(uma_container_->max_sent_height_per_timestamp_,
|
||||||
static_cast<int>(encoded_image._encodedHeight));
|
static_cast<int>(encoded_image._encodedHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
|
void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
input_frame_rate_tracker_.AddSamples(1);
|
uma_container_->input_frame_rate_tracker_.AddSamples(1);
|
||||||
input_width_counter_.Add(width);
|
uma_container_->input_width_counter_.Add(width);
|
||||||
input_height_counter_.Add(height);
|
uma_container_->input_height_counter_.Add(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendStatisticsProxy::OnEncodedFrame(int encode_time_ms) {
|
void SendStatisticsProxy::OnEncodedFrame(int encode_time_ms) {
|
||||||
rtc::CritScope lock(&crit_);
|
rtc::CritScope lock(&crit_);
|
||||||
encode_time_counter_.Add(encode_time_ms);
|
uma_container_->encode_time_counter_.Add(encode_time_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
|
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
|
||||||
@ -343,8 +377,8 @@ void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
|
|||||||
stats->avg_delay_ms = avg_delay_ms;
|
stats->avg_delay_ms = avg_delay_ms;
|
||||||
stats->max_delay_ms = max_delay_ms;
|
stats->max_delay_ms = max_delay_ms;
|
||||||
|
|
||||||
delay_counter_.Add(avg_delay_ms);
|
uma_container_->delay_counter_.Add(avg_delay_ms);
|
||||||
max_delay_counter_.Add(max_delay_ms);
|
uma_container_->max_delay_counter_.Add(max_delay_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendStatisticsProxy::SampleCounter::Add(int sample) {
|
void SendStatisticsProxy::SampleCounter::Add(int sample) {
|
||||||
@ -380,5 +414,4 @@ int SendStatisticsProxy::BoolSampleCounter::Fraction(
|
|||||||
return -1;
|
return -1;
|
||||||
return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
|
return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -38,7 +38,9 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
|
|||||||
public:
|
public:
|
||||||
static const int kStatsTimeoutMs;
|
static const int kStatsTimeoutMs;
|
||||||
|
|
||||||
SendStatisticsProxy(Clock* clock, const VideoSendStream::Config& config);
|
SendStatisticsProxy(Clock* clock,
|
||||||
|
const VideoSendStream::Config& config,
|
||||||
|
VideoEncoderConfig::ContentType content_type);
|
||||||
virtual ~SendStatisticsProxy();
|
virtual ~SendStatisticsProxy();
|
||||||
|
|
||||||
VideoSendStream::Stats GetStats();
|
VideoSendStream::Stats GetStats();
|
||||||
@ -58,6 +60,10 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
|
|||||||
void OnSuspendChange(bool is_suspended);
|
void OnSuspendChange(bool is_suspended);
|
||||||
void OnInactiveSsrc(uint32_t ssrc);
|
void OnInactiveSsrc(uint32_t ssrc);
|
||||||
|
|
||||||
|
// Used to indicate change in content type, which may require a change in
|
||||||
|
// how stats are collected.
|
||||||
|
void SetContentType(VideoEncoderConfig::ContentType content_type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// From CpuOveruseMetricsObserver.
|
// From CpuOveruseMetricsObserver.
|
||||||
void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override;
|
void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override;
|
||||||
@ -112,38 +118,51 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
|
|||||||
int num_samples;
|
int num_samples;
|
||||||
};
|
};
|
||||||
struct StatsUpdateTimes {
|
struct StatsUpdateTimes {
|
||||||
StatsUpdateTimes() : resolution_update_ms(0) {}
|
StatsUpdateTimes() : resolution_update_ms(0), bitrate_update_ms(0) {}
|
||||||
int64_t resolution_update_ms;
|
int64_t resolution_update_ms;
|
||||||
int64_t bitrate_update_ms;
|
int64_t bitrate_update_ms;
|
||||||
};
|
};
|
||||||
void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||||
VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
|
VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||||
void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
|
||||||
|
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
const VideoSendStream::Config config_;
|
const VideoSendStream::Config config_;
|
||||||
mutable rtc::CriticalSection crit_;
|
mutable rtc::CriticalSection crit_;
|
||||||
|
VideoEncoderConfig::ContentType content_type_ GUARDED_BY(crit_);
|
||||||
VideoSendStream::Stats stats_ GUARDED_BY(crit_);
|
VideoSendStream::Stats stats_ GUARDED_BY(crit_);
|
||||||
rtc::RateTracker input_frame_rate_tracker_ GUARDED_BY(crit_);
|
|
||||||
rtc::RateTracker sent_frame_rate_tracker_ GUARDED_BY(crit_);
|
|
||||||
uint32_t last_sent_frame_timestamp_ GUARDED_BY(crit_);
|
uint32_t last_sent_frame_timestamp_ GUARDED_BY(crit_);
|
||||||
std::map<uint32_t, StatsUpdateTimes> update_times_ GUARDED_BY(crit_);
|
std::map<uint32_t, StatsUpdateTimes> update_times_ GUARDED_BY(crit_);
|
||||||
|
|
||||||
int max_sent_width_per_timestamp_ GUARDED_BY(crit_);
|
// Contains stats used for UMA histograms. These stats will be reset if
|
||||||
int max_sent_height_per_timestamp_ GUARDED_BY(crit_);
|
// content type changes between real-time video and screenshare, since these
|
||||||
SampleCounter input_width_counter_ GUARDED_BY(crit_);
|
// will be reported separately.
|
||||||
SampleCounter input_height_counter_ GUARDED_BY(crit_);
|
struct UmaSamplesContainer {
|
||||||
SampleCounter sent_width_counter_ GUARDED_BY(crit_);
|
explicit UmaSamplesContainer(const char* prefix);
|
||||||
SampleCounter sent_height_counter_ GUARDED_BY(crit_);
|
~UmaSamplesContainer();
|
||||||
SampleCounter encode_time_counter_ GUARDED_BY(crit_);
|
|
||||||
BoolSampleCounter key_frame_counter_ GUARDED_BY(crit_);
|
void UpdateHistograms();
|
||||||
BoolSampleCounter quality_limited_frame_counter_ GUARDED_BY(crit_);
|
|
||||||
SampleCounter quality_downscales_counter_ GUARDED_BY(crit_);
|
const std::string uma_prefix_;
|
||||||
BoolSampleCounter bw_limited_frame_counter_ GUARDED_BY(crit_);
|
int max_sent_width_per_timestamp_;
|
||||||
SampleCounter bw_resolutions_disabled_counter_ GUARDED_BY(crit_);
|
int max_sent_height_per_timestamp_;
|
||||||
SampleCounter delay_counter_ GUARDED_BY(crit_);
|
SampleCounter input_width_counter_;
|
||||||
SampleCounter max_delay_counter_ GUARDED_BY(crit_);
|
SampleCounter input_height_counter_;
|
||||||
|
SampleCounter sent_width_counter_;
|
||||||
|
SampleCounter sent_height_counter_;
|
||||||
|
SampleCounter encode_time_counter_;
|
||||||
|
BoolSampleCounter key_frame_counter_;
|
||||||
|
BoolSampleCounter quality_limited_frame_counter_;
|
||||||
|
SampleCounter quality_downscales_counter_;
|
||||||
|
BoolSampleCounter bw_limited_frame_counter_;
|
||||||
|
SampleCounter bw_resolutions_disabled_counter_;
|
||||||
|
SampleCounter delay_counter_;
|
||||||
|
SampleCounter max_delay_counter_;
|
||||||
|
rtc::RateTracker input_frame_rate_tracker_;
|
||||||
|
rtc::RateTracker sent_frame_rate_tracker_;
|
||||||
|
};
|
||||||
|
|
||||||
|
rtc::scoped_ptr<UmaSamplesContainer> uma_container_ GUARDED_BY(crit_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -28,8 +28,9 @@ class SendStatisticsProxyTest : public ::testing::Test {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
statistics_proxy_.reset(
|
statistics_proxy_.reset(new SendStatisticsProxy(
|
||||||
new SendStatisticsProxy(&fake_clock_, GetTestConfig()));
|
&fake_clock_, GetTestConfig(),
|
||||||
|
VideoEncoderConfig::ContentType::kRealtimeVideo));
|
||||||
expected_ = VideoSendStream::Stats();
|
expected_ = VideoSendStream::Stats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ class VideoCaptureInputTest : public ::testing::Test {
|
|||||||
mock_frame_callback_(new NiceMock<MockVideoCaptureCallback>),
|
mock_frame_callback_(new NiceMock<MockVideoCaptureCallback>),
|
||||||
output_frame_event_(EventWrapper::Create()),
|
output_frame_event_(EventWrapper::Create()),
|
||||||
stats_proxy_(Clock::GetRealTimeClock(),
|
stats_proxy_(Clock::GetRealTimeClock(),
|
||||||
webrtc::VideoSendStream::Config(nullptr)) {}
|
webrtc::VideoSendStream::Config(nullptr),
|
||||||
|
webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo) {}
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
EXPECT_CALL(*mock_frame_callback_, DeliverFrame(_))
|
EXPECT_CALL(*mock_frame_callback_, DeliverFrame(_))
|
||||||
|
@ -117,7 +117,9 @@ VideoSendStream::VideoSendStream(
|
|||||||
const VideoSendStream::Config& config,
|
const VideoSendStream::Config& config,
|
||||||
const VideoEncoderConfig& encoder_config,
|
const VideoEncoderConfig& encoder_config,
|
||||||
const std::map<uint32_t, RtpState>& suspended_ssrcs)
|
const std::map<uint32_t, RtpState>& suspended_ssrcs)
|
||||||
: stats_proxy_(Clock::GetRealTimeClock(), config),
|
: stats_proxy_(Clock::GetRealTimeClock(),
|
||||||
|
config,
|
||||||
|
encoder_config.content_type),
|
||||||
transport_adapter_(config.send_transport),
|
transport_adapter_(config.send_transport),
|
||||||
encoded_frame_proxy_(config.post_encode_callback),
|
encoded_frame_proxy_(config.post_encode_callback),
|
||||||
config_(config),
|
config_(config),
|
||||||
@ -435,6 +437,8 @@ bool VideoSendStream::ReconfigureVideoEncoder(
|
|||||||
stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]);
|
stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stats_proxy_.SetContentType(config.content_type);
|
||||||
|
|
||||||
RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
|
RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
|
||||||
vie_encoder_->SetMinTransmitBitrate(config.min_transmit_bitrate_bps / 1000);
|
vie_encoder_->SetMinTransmitBitrate(config.min_transmit_bitrate_bps / 1000);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user