From 39fb817efdce6fa79e7f9f50772288459f1b2d98 Mon Sep 17 00:00:00 2001 From: Ilya Nikolaevskiy Date: Tue, 14 Apr 2020 10:28:19 +0200 Subject: [PATCH] [Video, Svc] Remove inactive spatial layers in codec initializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is more logical way to remove inactive lower layers. Current way is to notify the encoder that the layer is inactive, then renumber layers at the packatization level. This Cl will allow to simplify libvpx vp9 encoder, svcRateAllocator and vp9 packetizer. Bug: webrtc:11319 Change-Id: Idf0bb30b729f5ecc97e31454b32934546b681aa2 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/173182 Commit-Queue: Ilya Nikolaevskiy Reviewed-by: Henrik Boström Cr-Commit-Position: refs/heads/master@{#31058} --- .../test/videocodec_test_fixture_impl.cc | 2 +- modules/video_coding/codecs/vp9/svc_config.cc | 14 +++++----- modules/video_coding/codecs/vp9/svc_config.h | 2 +- .../codecs/vp9/svc_config_unittest.cc | 27 ++++++++++++++----- .../codecs/vp9/svc_rate_allocator_unittest.cc | 2 +- .../codecs/vp9/test/vp9_impl_unittest.cc | 2 +- .../video_coding/video_codec_initializer.cc | 9 +++---- 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc b/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc index fe42039468..7e92b360bd 100644 --- a/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc +++ b/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc @@ -85,7 +85,7 @@ void ConfigureSvc(VideoCodec* codec_settings) { const std::vector layers = GetSvcConfig( codec_settings->width, codec_settings->height, kMaxFramerateFps, - /*min_spatial_layers=*/1, codec_settings->VP9()->numberOfSpatialLayers, + /*first_active_layer=*/0, codec_settings->VP9()->numberOfSpatialLayers, codec_settings->VP9()->numberOfTemporalLayers, /* is_screen_sharing = */ false); ASSERT_EQ(codec_settings->VP9()->numberOfSpatialLayers, layers.size()) diff --git a/modules/video_coding/codecs/vp9/svc_config.cc b/modules/video_coding/codecs/vp9/svc_config.cc index 764c1a209d..e5d88bce21 100644 --- a/modules/video_coding/codecs/vp9/svc_config.cc +++ b/modules/video_coding/codecs/vp9/svc_config.cc @@ -61,10 +61,10 @@ std::vector ConfigureSvcScreenSharing(size_t input_width, std::vector ConfigureSvcNormalVideo(size_t input_width, size_t input_height, float max_framerate_fps, - size_t min_spatial_layers, + size_t first_active_layer, size_t num_spatial_layers, size_t num_temporal_layers) { - RTC_DCHECK_LE(min_spatial_layers, num_spatial_layers); + RTC_DCHECK_LT(first_active_layer, num_spatial_layers); std::vector spatial_layers; // Limit number of layers for given resolution. @@ -76,9 +76,11 @@ std::vector ConfigureSvcNormalVideo(size_t input_width, kMinVp9SpatialLayerHeight)))); num_spatial_layers = std::min({num_spatial_layers, num_layers_fit_horz, num_layers_fit_vert}); - num_spatial_layers = std::max(num_spatial_layers, min_spatial_layers); + // First active layer must be configured. + num_spatial_layers = std::max(num_spatial_layers, first_active_layer + 1); - for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) { + for (size_t sl_idx = first_active_layer; sl_idx < num_spatial_layers; + ++sl_idx) { SpatialLayer spatial_layer = {0}; spatial_layer.width = input_width >> (num_spatial_layers - sl_idx - 1); spatial_layer.height = input_height >> (num_spatial_layers - sl_idx - 1); @@ -112,7 +114,7 @@ std::vector ConfigureSvcNormalVideo(size_t input_width, std::vector GetSvcConfig(size_t input_width, size_t input_height, float max_framerate_fps, - size_t min_spatial_layers, + size_t first_active_layer, size_t num_spatial_layers, size_t num_temporal_layers, bool is_screen_sharing) { @@ -126,7 +128,7 @@ std::vector GetSvcConfig(size_t input_width, max_framerate_fps, num_spatial_layers); } else { return ConfigureSvcNormalVideo(input_width, input_height, max_framerate_fps, - min_spatial_layers, num_spatial_layers, + first_active_layer, num_spatial_layers, num_temporal_layers); } } diff --git a/modules/video_coding/codecs/vp9/svc_config.h b/modules/video_coding/codecs/vp9/svc_config.h index 3bc9ba7a34..9bd8b0e313 100644 --- a/modules/video_coding/codecs/vp9/svc_config.h +++ b/modules/video_coding/codecs/vp9/svc_config.h @@ -21,7 +21,7 @@ namespace webrtc { std::vector GetSvcConfig(size_t input_width, size_t input_height, float max_framerate_fps, - size_t min_spatial_layers, + size_t first_active_layer, size_t num_spatial_layers, size_t num_temporal_layers, bool is_screen_sharing); diff --git a/modules/video_coding/codecs/vp9/svc_config_unittest.cc b/modules/video_coding/codecs/vp9/svc_config_unittest.cc index 07a2ebe5ad..abc67a22ff 100644 --- a/modules/video_coding/codecs/vp9/svc_config_unittest.cc +++ b/modules/video_coding/codecs/vp9/svc_config_unittest.cc @@ -19,35 +19,48 @@ namespace webrtc { TEST(SvcConfig, NumSpatialLayers) { const size_t max_num_spatial_layers = 6; - const size_t min_spatial_layers = 1; + const size_t first_active_layer = 0; const size_t num_spatial_layers = 2; std::vector spatial_layers = GetSvcConfig(kMinVp9SpatialLayerWidth << (num_spatial_layers - 1), kMinVp9SpatialLayerHeight << (num_spatial_layers - 1), 30, - min_spatial_layers, max_num_spatial_layers, 1, false); + first_active_layer, max_num_spatial_layers, 1, false); EXPECT_EQ(spatial_layers.size(), num_spatial_layers); } -TEST(SvcConfig, NumSpatialLayersRespectsMinNumberOfLayers) { +TEST(SvcConfig, AlwaysSendsAtLeastOneLayer) { const size_t max_num_spatial_layers = 6; - const size_t min_spatial_layers = 2; + const size_t first_active_layer = 5; std::vector spatial_layers = GetSvcConfig(kMinVp9SpatialLayerWidth, kMinVp9SpatialLayerHeight, 30, - min_spatial_layers, max_num_spatial_layers, 1, false); + first_active_layer, max_num_spatial_layers, 1, false); + EXPECT_EQ(spatial_layers.size(), 1u); + EXPECT_EQ(spatial_layers.back().width, kMinVp9SpatialLayerWidth); +} +TEST(SvcConfig, SkipsInactiveLayers) { + const size_t num_spatial_layers = 4; + const size_t first_active_layer = 2; + + std::vector spatial_layers = + GetSvcConfig(kMinVp9SpatialLayerWidth << (num_spatial_layers - 1), + kMinVp9SpatialLayerHeight << (num_spatial_layers - 1), 30, + first_active_layer, num_spatial_layers, 1, false); EXPECT_EQ(spatial_layers.size(), 2u); + EXPECT_EQ(spatial_layers.back().width, + kMinVp9SpatialLayerWidth << (num_spatial_layers - 1)); } TEST(SvcConfig, BitrateThresholds) { - const size_t min_spatial_layers = 1; + const size_t first_active_layer = 0; const size_t num_spatial_layers = 3; std::vector spatial_layers = GetSvcConfig(kMinVp9SpatialLayerWidth << (num_spatial_layers - 1), kMinVp9SpatialLayerHeight << (num_spatial_layers - 1), 30, - min_spatial_layers, num_spatial_layers, 1, false); + first_active_layer, num_spatial_layers, 1, false); EXPECT_EQ(spatial_layers.size(), num_spatial_layers); diff --git a/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc b/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc index 7318592ac2..daa0c52e09 100644 --- a/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc +++ b/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc @@ -34,7 +34,7 @@ static VideoCodec Configure(size_t width, : VideoCodecMode::kRealtimeVideo; std::vector spatial_layers = - GetSvcConfig(width, height, 30, /*min_spatial_layers=*/1, + GetSvcConfig(width, height, 30, /*first_active_layer=*/0, num_spatial_layers, num_temporal_layers, is_screen_sharing); RTC_CHECK_LE(spatial_layers.size(), kMaxSpatialLayers); diff --git a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc index 58805934e6..d40cf23257 100644 --- a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc +++ b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc @@ -114,7 +114,7 @@ class TestVp9Impl : public VideoCodecUnitTest { std::vector layers = GetSvcConfig(codec_settings_.width, codec_settings_.height, - codec_settings_.maxFramerate, /*min_spatial_layers=*/1, + codec_settings_.maxFramerate, /*first_active_layer=*/0, num_spatial_layers, num_temporal_layers, false); for (size_t i = 0; i < layers.size(); ++i) { codec_settings_.spatialLayers[i] = layers[i]; diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc index bd40385a51..e8665b9557 100644 --- a/modules/video_coding/video_codec_initializer.cc +++ b/modules/video_coding/video_codec_initializer.cc @@ -179,19 +179,18 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec( // Layering is set explicitly. spatial_layers = config.spatial_layers; } else { - size_t min_required_layers = 0; - // Need at least enough layers for the first active one to be present. + size_t first_active_layer = 0; for (size_t spatial_idx = 0; spatial_idx < config.simulcast_layers.size(); ++spatial_idx) { if (config.simulcast_layers[spatial_idx].active) { - min_required_layers = spatial_idx + 1; + first_active_layer = spatial_idx; break; } } spatial_layers = GetSvcConfig( video_codec.width, video_codec.height, video_codec.maxFramerate, - min_required_layers, video_codec.VP9()->numberOfSpatialLayers, + first_active_layer, video_codec.VP9()->numberOfSpatialLayers, video_codec.VP9()->numberOfTemporalLayers, video_codec.mode == VideoCodecMode::kScreensharing); @@ -210,7 +209,7 @@ VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec( spatial_idx < config.simulcast_layers.size() && spatial_idx < spatial_layers.size(); ++spatial_idx) { - spatial_layers[spatial_idx].active = + spatial_layers[spatial_idx - first_active_layer].active = config.simulcast_layers[spatial_idx].active; } }