Skip to content

Commit 50327a5

Browse files
Ilya NikolaevskiyCommit Bot
Ilya Nikolaevskiy
authored and
Commit Bot
committed
Wire up internal libvpx VP9 scaler to statistics proxy
Bug: webrtc:11396 Change-Id: I5ac69208b00cc75d4e5dbb3ab86f234b3e1f29f8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/169922 Reviewed-by: Niels Moller <[email protected]> Reviewed-by: Henrik Boström <[email protected]> Commit-Queue: Ilya Nikolaevskiy <[email protected]> Cr-Commit-Position: refs/heads/master@{#30725}
1 parent f87536c commit 50327a5

7 files changed

+71
-2
lines changed

api/video/video_stream_encoder_observer.h

+5
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ class VideoStreamEncoderObserver : public CpuOveruseMetricsObserver {
9595
const VideoCodec& codec,
9696
const VideoBitrateAllocation& allocation) {}
9797

98+
// Informes observer if an internal encoder scaler has reduced video
99+
// resolution or not. |is_scaled| is a flag indicating if the video is scaled
100+
// down.
101+
virtual void OnEncoderInternalScalerUpdate(bool is_scaled) {}
102+
98103
// TODO(nisse): VideoStreamEncoder wants to query the stats, which makes this
99104
// not a pure observer. GetInputFrameRate is needed for the cpu adaptation, so
100105
// can be deleted if that responsibility is moved out to a VideoStreamAdaptor

video/send_statistics_proxy.cc

+15-1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ SendStatisticsProxy::SendStatisticsProxy(
148148
last_num_simulcast_streams_(0),
149149
last_spatial_layer_use_{},
150150
bw_limited_layers_(false),
151+
internal_encoder_scaler_(false),
151152
uma_container_(
152153
new UmaSamplesContainer(GetUmaPrefix(content_type_), stats_, clock)) {
153154
}
@@ -1083,7 +1084,7 @@ void SendStatisticsProxy::UpdateAdaptationStats() {
10831084
cpu_counts_.num_framerate_reductions > 0;
10841085
bool is_bandwidth_limited = quality_counts_.num_resolution_reductions > 0 ||
10851086
quality_counts_.num_framerate_reductions > 0 ||
1086-
bw_limited_layers_;
1087+
bw_limited_layers_ || internal_encoder_scaler_;
10871088
if (is_bandwidth_limited) {
10881089
// We may be both CPU limited and bandwidth limited at the same time but
10891090
// there is no way to express this in standardized stats. Heuristically,
@@ -1117,6 +1118,10 @@ void SendStatisticsProxy::UpdateAdaptationStats() {
11171118
}
11181119
}
11191120
}
1121+
if (internal_encoder_scaler_) {
1122+
stats_.bw_limited_resolution = true;
1123+
}
1124+
11201125
stats_.quality_limitation_reason =
11211126
quality_limitation_reason_tracker_.current_reason();
11221127

@@ -1164,6 +1169,15 @@ void SendStatisticsProxy::OnBitrateAllocationUpdated(
11641169
last_num_simulcast_streams_ = num_simulcast_streams;
11651170
}
11661171

1172+
// Informes observer if an internal encoder scaler has reduced video
1173+
// resolution or not. |is_scaled| is a flag indicating if the video is scaled
1174+
// down.
1175+
void SendStatisticsProxy::OnEncoderInternalScalerUpdate(bool is_scaled) {
1176+
rtc::CritScope lock(&crit_);
1177+
internal_encoder_scaler_ = is_scaled;
1178+
UpdateAdaptationStats();
1179+
}
1180+
11671181
// TODO(asapersson): Include fps changes.
11681182
void SendStatisticsProxy::OnInitialQualityResolutionAdaptDown() {
11691183
rtc::CritScope lock(&crit_);

video/send_statistics_proxy.h

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
7878
const VideoCodec& codec,
7979
const VideoBitrateAllocation& allocation) override;
8080

81+
void OnEncoderInternalScalerUpdate(bool is_scaled) override;
82+
8183
void OnMinPixelLimitReached() override;
8284
void OnInitialQualityResolutionAdaptDown() override;
8385

@@ -264,6 +266,8 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
264266
// Indicates if the latest bitrate allocation had layers disabled by low
265267
// available bandwidth.
266268
bool bw_limited_layers_ RTC_GUARDED_BY(crit_);
269+
// Indicastes if the encoder internally downscales input image.
270+
bool internal_encoder_scaler_ RTC_GUARDED_BY(crit_);
267271
AdaptationSteps cpu_counts_ RTC_GUARDED_BY(crit_);
268272
AdaptationSteps quality_counts_ RTC_GUARDED_BY(crit_);
269273

video/send_statistics_proxy_unittest.cc

+9
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,15 @@ TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
21472147
allocation.set_bw_limited(true);
21482148
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
21492149
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2150+
2151+
// Revert for the next test.
2152+
allocation.set_bw_limited(false);
2153+
statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2154+
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2155+
2156+
// Internal encoder scaler reduced resolution.
2157+
statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2158+
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
21502159
}
21512160

21522161
TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {

video/video_quality_test.cc

+5-1
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
870870
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
871871
vp9_settings.denoisingOn = false;
872872
vp9_settings.frameDroppingOn = false;
873+
vp9_settings.automaticResizeOn = false;
873874
vp9_settings.numberOfTemporalLayers = static_cast<unsigned char>(
874875
params_.video[video_idx].num_temporal_layers);
875876
vp9_settings.numberOfSpatialLayers = static_cast<unsigned char>(
@@ -892,6 +893,7 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
892893
vp9_settings.numberOfSpatialLayers =
893894
static_cast<unsigned char>(params_.ss[video_idx].num_spatial_layers);
894895
vp9_settings.interLayerPred = params_.ss[video_idx].inter_layer_pred;
896+
vp9_settings.automaticResizeOn = false;
895897
video_encoder_configs_[video_idx].encoder_specific_settings =
896898
new rtc::RefCountedObject<
897899
VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
@@ -904,7 +906,9 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
904906
VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
905907
} else if (params_.video[video_idx].codec == "VP9") {
906908
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
907-
vp9_settings.automaticResizeOn = true;
909+
// Only enable quality scaler for single spatial layer.
910+
vp9_settings.automaticResizeOn =
911+
params_.ss[video_idx].num_spatial_layers == 1;
908912
video_encoder_configs_[video_idx].encoder_specific_settings =
909913
new rtc::RefCountedObject<
910914
VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);

video/video_send_stream_tests.cc

+1
Original file line numberDiff line numberDiff line change
@@ -3479,6 +3479,7 @@ void VideoSendStreamTest::TestVp9NonFlexMode(uint8_t num_temporal_layers,
34793479

34803480
vp9_settings_.flexibleMode = false;
34813481
vp9_settings_.frameDroppingOn = false;
3482+
vp9_settings_.automaticResizeOn = false;
34823483
vp9_settings_.keyFrameInterval = kKeyFrameInterval;
34833484
vp9_settings_.numberOfTemporalLayers = num_temporal_layers_;
34843485
vp9_settings_.numberOfSpatialLayers = num_spatial_layers_;

video/video_stream_encoder.cc

+32
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ VideoBitrateAllocation UpdateAllocationFromEncoderInfo(
169169
new_allocation.set_bw_limited(allocation.is_bw_limited());
170170
return new_allocation;
171171
}
172+
172173
} // namespace
173174

174175
const int VideoStreamEncoder::kDefaultLastFrameInfoWidth = 176;
@@ -1360,6 +1361,37 @@ EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage(
13601361
RTC_CHECK(videocontenttypehelpers::SetSimulcastId(
13611362
&image_copy.content_type_, static_cast<uint8_t>(spatial_idx + 1)));
13621363

1364+
// Currently internal quality scaler is used for VP9 instead of webrtc qp
1365+
// scaler (in no-svc case or if only a single spatial layer is encoded).
1366+
// It has to be explicitly detected and reported to adaptation metrics.
1367+
// Post a task because |send_codec_| requires |encoder_queue_| lock.
1368+
unsigned int image_width = image_copy._encodedWidth;
1369+
unsigned int image_height = image_copy._encodedHeight;
1370+
VideoCodecType codec = codec_specific_info
1371+
? codec_specific_info->codecType
1372+
: VideoCodecType::kVideoCodecGeneric;
1373+
encoder_queue_.PostTask([this, codec, image_width, image_height] {
1374+
RTC_DCHECK_RUN_ON(&encoder_queue_);
1375+
if (codec == VideoCodecType::kVideoCodecVP9 &&
1376+
send_codec_.VP9()->automaticResizeOn) {
1377+
unsigned int expected_width = send_codec_.width;
1378+
unsigned int expected_height = send_codec_.height;
1379+
int num_active_layers = 0;
1380+
for (int i = 0; i < send_codec_.VP9()->numberOfSpatialLayers; ++i) {
1381+
if (send_codec_.spatialLayers[i].active) {
1382+
++num_active_layers;
1383+
expected_width = send_codec_.spatialLayers[i].width;
1384+
expected_height = send_codec_.spatialLayers[i].height;
1385+
}
1386+
}
1387+
RTC_DCHECK_LE(num_active_layers, 1)
1388+
<< "VP9 quality scaling is enabled for "
1389+
"SVC with several active layers.";
1390+
encoder_stats_observer_->OnEncoderInternalScalerUpdate(
1391+
image_width < expected_width || image_height < expected_height);
1392+
}
1393+
});
1394+
13631395
// Encoded is called on whatever thread the real encoder implementation run
13641396
// on. In the case of hardware encoders, there might be several encoders
13651397
// running in parallel on different threads.

0 commit comments

Comments
 (0)