Reland: googBandwidthLimitedResolution stat is not always set depending on configuration.

TBR=brandtr@webrtc.org,stefan@webrtc.org

Currently |bw_resolutions_disabled| is set per VP8EncoderImpl instance and reported via
OnEncodedImage callback.

Instead move logic to SendStatisticsProxy to determine if resolution is bw limited or not based
on info that is reported to SendStatisticsProxy::OnEncodedImage.

Bug: webrtc:8643
Change-Id: I553cea30dcda34b753b5224f15094a1b7b70a750
Reviewed-on: https://webrtc-review.googlesource.com/31460
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Original-Commit-Position: refs/heads/master@{#21249}
Reviewed-on: https://webrtc-review.googlesource.com/33360
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21319}
This commit is contained in:
Åsa Persson
2017-12-15 15:54:44 +01:00
committed by Commit Bot
parent 570df8b123
commit aa329e7cc3
7 changed files with 210 additions and 88 deletions

View File

@ -28,10 +28,12 @@ const uint32_t kFirstRtxSsrc = 18;
const uint32_t kSecondRtxSsrc = 43;
const uint32_t kFlexFecSsrc = 55;
const int kFpsPeriodicIntervalMs = 2000;
const int kPreferredBps = 50000;
const int kWidth = 640;
const int kHeight = 480;
const int kQpIdx0 = 21;
const int kQpIdx1 = 39;
const int kRtpClockRateHz = 90000;
const CodecSpecificInfo kDefaultCodecInfo = []() {
CodecSpecificInfo codec_info;
codec_info.codecType = kVideoCodecVP8;
@ -322,12 +324,11 @@ TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
TEST_F(SendStatisticsProxyTest, OnEncoderReconfiguredChangePreferredBitrate) {
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(0, stats.preferred_media_bitrate_bps);
const int kPreferredMediaBitrateBps = 50;
VideoEncoderConfig config;
statistics_proxy_->OnEncoderReconfigured(config, kPreferredMediaBitrateBps);
statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
stats = statistics_proxy_->GetStats();
EXPECT_EQ(kPreferredMediaBitrateBps, stats.preferred_media_bitrate_bps);
EXPECT_EQ(kPreferredBps, stats.preferred_media_bitrate_bps);
}
TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
@ -753,7 +754,7 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
// Switch content type, real-time stats should be updated.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kScreen;
statistics_proxy_->OnEncoderReconfigured(config, 50);
statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
EXPECT_EQ(0,
@ -786,12 +787,12 @@ TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
// No switch, stats should not be updated.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
statistics_proxy_->OnEncoderReconfigured(config, 50);
statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
// Switch to screenshare, real-time stats should be updated.
config.content_type = VideoEncoderConfig::ContentType::kScreen;
statistics_proxy_->OnEncoderReconfigured(config, 50);
statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
}
@ -1179,11 +1180,30 @@ TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
}
TEST_F(SendStatisticsProxyTest,
BandwidthLimitedHistogramsNotUpdatedWhenDisabled) {
BandwidthLimitedHistogramsNotUpdatedForOneStream) {
// Configure one stream.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoStream stream1;
stream1.width = kWidth;
stream1.height = kHeight;
statistics_proxy_->OnEncoderReconfigured(config, {stream1}, kPreferredBps);
const int64_t kMaxEncodedFrameWindowMs = 800;
const int kFps = 20;
const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
const int kMinSamples = // Sample added when removed from EncodedFrameMap.
SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
// Stream encoded.
EncodedImage encoded_image;
// encoded_image.adapt_reason_.bw_resolutions_disabled by default: -1
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
encoded_image._encodedWidth = kWidth;
encoded_image._encodedHeight = kHeight;
for (int i = 0; i < kMinSamples; ++i) {
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
encoded_image._timeStamp += (kRtpClockRateHz / kFps);
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
}
// Histograms are updated when the statistics_proxy_ is deleted.
statistics_proxy_.reset();
@ -1194,12 +1214,37 @@ TEST_F(SendStatisticsProxyTest,
}
TEST_F(SendStatisticsProxyTest,
BandwidthLimitedHistogramsUpdatedWhenEnabled_NoResolutionDisabled) {
const int kResolutionsDisabled = 0;
BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
// Configure two streams.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoStream stream1;
stream1.width = kWidth / 2;
stream1.height = kHeight / 2;
VideoStream stream2;
stream2.width = kWidth;
stream2.height = kHeight;
statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
kPreferredBps);
const int64_t kMaxEncodedFrameWindowMs = 800;
const int kFps = 20;
const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
const int kMinSamples = // Sample added when removed from EncodedFrameMap.
SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
// Two streams encoded.
EncodedImage encoded_image;
encoded_image.adapt_reason_.bw_resolutions_disabled = kResolutionsDisabled;
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
for (int i = 0; i < kMinSamples; ++i) {
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
encoded_image._timeStamp += (kRtpClockRateHz / kFps);
encoded_image._encodedWidth = kWidth;
encoded_image._encodedHeight = kHeight;
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
encoded_image._encodedWidth = kWidth / 2;
encoded_image._encodedHeight = kHeight / 2;
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
}
// Histograms are updated when the statistics_proxy_ is deleted.
statistics_proxy_.reset();
@ -1213,12 +1258,34 @@ TEST_F(SendStatisticsProxyTest,
}
TEST_F(SendStatisticsProxyTest,
BandwidthLimitedHistogramsUpdatedWhenEnabled_OneResolutionDisabled) {
const int kResolutionsDisabled = 1;
BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
// Configure two streams.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoStream stream1;
stream1.width = kWidth / 2;
stream1.height = kHeight / 2;
VideoStream stream2;
stream2.width = kWidth;
stream2.height = kHeight;
statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
kPreferredBps);
const int64_t kMaxEncodedFrameWindowMs = 800;
const int kFps = 20;
const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
const int kMinSamples = // Sample added when removed from EncodedFrameMap.
SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
// One stream encoded.
EncodedImage encoded_image;
encoded_image.adapt_reason_.bw_resolutions_disabled = kResolutionsDisabled;
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
encoded_image._encodedWidth = kWidth / 2;
encoded_image._encodedHeight = kHeight / 2;
for (int i = 0; i < kMinSamples; ++i) {
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
encoded_image._timeStamp += (kRtpClockRateHz / kFps);
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
}
// Histograms are updated when the statistics_proxy_ is deleted.
statistics_proxy_.reset();
@ -1226,12 +1293,11 @@ TEST_F(SendStatisticsProxyTest,
"WebRTC.Video.BandwidthLimitedResolutionInPercent"));
EXPECT_EQ(1, metrics::NumEvents(
"WebRTC.Video.BandwidthLimitedResolutionInPercent", 100));
// Resolutions disabled.
// One resolution disabled.
EXPECT_EQ(1, metrics::NumSamples(
"WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
EXPECT_EQ(
1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
kResolutionsDisabled));
EXPECT_EQ(1, metrics::NumEvents(
"WebRTC.Video.BandwidthLimitedResolutionsDisabled", 1));
}
TEST_F(SendStatisticsProxyTest,
@ -1300,17 +1366,58 @@ TEST_F(SendStatisticsProxyTest,
TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
// Initially false.
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
// No resolution scale by default.
EncodedImage encoded_image;
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
// Simulcast disabled resolutions
encoded_image.adapt_reason_.bw_resolutions_disabled = 1;
// Configure two streams.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoStream stream1;
stream1.width = kWidth / 2;
stream1.height = kHeight / 2;
VideoStream stream2;
stream2.width = kWidth;
stream2.height = kHeight;
statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2},
kPreferredBps);
const int64_t kMaxEncodedFrameWindowMs = 800;
const int kFps = 20;
const int kMinSamples = // Sample added when removed from EncodedFrameMap.
kFps * kMaxEncodedFrameWindowMs / 1000;
// One stream encoded.
EncodedImage encoded_image;
encoded_image._encodedWidth = kWidth / 2;
encoded_image._encodedHeight = kHeight / 2;
for (int i = 0; i < kMinSamples; ++i) {
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
encoded_image._timeStamp += (kRtpClockRateHz / kFps);
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
}
// First frame removed from EncodedFrameMap, stats updated.
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
++encoded_image._timeStamp;
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
encoded_image.adapt_reason_.bw_resolutions_disabled = 0;
// Two streams encoded.
for (int i = 0; i < kMinSamples; ++i) {
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
encoded_image._timeStamp += (kRtpClockRateHz / kFps);
encoded_image._encodedWidth = kWidth;
encoded_image._encodedHeight = kHeight;
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
encoded_image._encodedWidth = kWidth / 2;
encoded_image._encodedHeight = kHeight / 2;
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
}
// First frame with two streams removed, expect no resolution limit.
fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
encoded_image._timeStamp += (kRtpClockRateHz / kFps);
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
@ -1473,7 +1580,7 @@ TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
// Changing content type causes histograms to be reported.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kScreen;
statistics_proxy_->OnEncoderReconfigured(config, 50);
statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
EXPECT_EQ(1,
metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
@ -1637,7 +1744,7 @@ TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
// Changing content type causes histograms to be reported.
VideoEncoderConfig config;
config.content_type = VideoEncoderConfig::ContentType::kScreen;
statistics_proxy_->OnEncoderReconfigured(config, 50000);
statistics_proxy_->OnEncoderReconfigured(config, {}, kPreferredBps);
// Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec = 56 kbps
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));