diff --git a/common_types.h b/common_types.h index 9545284801..f41903ab8d 100644 --- a/common_types.h +++ b/common_types.h @@ -496,9 +496,7 @@ union VideoCodecUnion { VideoCodecH264 H264; }; -// Simulcast is when the same stream is encoded multiple times with different -// settings such as resolution. -struct SimulcastStream { +struct SpatialLayer { unsigned short width; unsigned short height; unsigned char numberOfTemporalLayers; @@ -509,12 +507,9 @@ struct SimulcastStream { bool active; // encoded and sent. }; -struct SpatialLayer { - int scaling_factor_num; - int scaling_factor_den; - int target_bitrate_bps; - // TODO(ivica): Add max_quantizer and min_quantizer? -}; +// Simulcast is when the same stream is encoded multiple times with different +// settings such as resolution. +typedef SpatialLayer SimulcastStream; enum VideoCodecMode { kRealtimeVideo, kScreensharing }; 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 e43be9e702..442e02886f 100644 --- a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc +++ b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc @@ -202,4 +202,41 @@ TEST_F(TestVp9Impl, EncoderRetainsRtpStateAfterRelease) { 1); } +TEST_F(TestVp9Impl, EncoderExplicitLayering) { + // Override default settings. + codec_settings_.VP9()->numberOfTemporalLayers = 1; + codec_settings_.VP9()->numberOfSpatialLayers = 2; + + codec_settings_.width = 960; + codec_settings_.height = 540; + codec_settings_.spatialLayers[0].targetBitrate = 500; + codec_settings_.spatialLayers[1].targetBitrate = 1000; + + codec_settings_.spatialLayers[0].width = codec_settings_.width / 2; + codec_settings_.spatialLayers[0].height = codec_settings_.height / 2; + codec_settings_.spatialLayers[1].width = codec_settings_.width; + codec_settings_.spatialLayers[1].height = codec_settings_.height; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + encoder_->InitEncode(&codec_settings_, 1 /* number of cores */, + 0 /* max payload size (unused) */)); + + // Ensure it fails if scaling factors in horz/vert dimentions are different. + codec_settings_.spatialLayers[0].width = codec_settings_.width; + codec_settings_.spatialLayers[0].height = codec_settings_.height / 2; + codec_settings_.spatialLayers[1].width = codec_settings_.width; + codec_settings_.spatialLayers[1].height = codec_settings_.height; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_PARAMETER, + encoder_->InitEncode(&codec_settings_, 1 /* number of cores */, + 0 /* max payload size (unused) */)); + + // Ensure it fails if scaling factor is not power of two. + codec_settings_.spatialLayers[0].width = codec_settings_.width / 3; + codec_settings_.spatialLayers[0].height = codec_settings_.height / 3; + codec_settings_.spatialLayers[1].width = codec_settings_.width; + codec_settings_.spatialLayers[1].height = codec_settings_.height; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERR_PARAMETER, + encoder_->InitEncode(&codec_settings_, 1 /* number of cores */, + 0 /* max payload size (unused) */)); +} + } // namespace webrtc diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc index 2fb6e55aff..c7c6247837 100644 --- a/modules/video_coding/codecs/vp9/vp9_impl.cc +++ b/modules/video_coding/codecs/vp9/vp9_impl.cc @@ -124,8 +124,7 @@ int VP9EncoderImpl::Release() { bool VP9EncoderImpl::ExplicitlyConfiguredSpatialLayers() const { // We check target_bitrate_bps of the 0th layer to see if the spatial layers // (i.e. bitrates) were explicitly configured. - return num_spatial_layers_ > 1 && - codec_.spatialLayers[0].target_bitrate_bps > 0; + return num_spatial_layers_ > 1 && codec_.spatialLayers[0].targetBitrate > 0; } bool VP9EncoderImpl::SetSvcRates() { @@ -139,13 +138,13 @@ bool VP9EncoderImpl::SetSvcRates() { } int total_bitrate_bps = 0; for (i = 0; i < num_spatial_layers_; ++i) - total_bitrate_bps += codec_.spatialLayers[i].target_bitrate_bps; + total_bitrate_bps += codec_.spatialLayers[i].targetBitrate * 1000; // If total bitrate differs now from what has been specified at the // beginning, update the bitrates in the same ratio as before. for (i = 0; i < num_spatial_layers_; ++i) { config_->ss_target_bitrate[i] = config_->layer_target_bitrate[i] = static_cast(static_cast(config_->rc_target_bitrate) * - codec_.spatialLayers[i].target_bitrate_bps / + codec_.spatialLayers[i].targetBitrate * 1000 / total_bitrate_bps); } } else { @@ -412,8 +411,27 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { if (ExplicitlyConfiguredSpatialLayers()) { for (int i = 0; i < num_spatial_layers_; ++i) { const auto& layer = codec_.spatialLayers[i]; - svc_params_.scaling_factor_num[i] = layer.scaling_factor_num; - svc_params_.scaling_factor_den[i] = layer.scaling_factor_den; + const int scale_factor = codec_.width / layer.width; + RTC_DCHECK_GT(scale_factor, 0); + + // Ensure scaler factor is integer. + if (scale_factor * layer.width != codec_.width) { + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; + } + + // Ensure scale factor is the same in both dimensions. + if (scale_factor * layer.height != codec_.height) { + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; + } + + // Ensure scale factor is power of two. + const bool is_pow_of_two = (scale_factor & (scale_factor - 1)) == 0; + if (!is_pow_of_two) { + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; + } + + svc_params_.scaling_factor_num[i] = 1; + svc_params_.scaling_factor_den[i] = scale_factor; } } else { int scaling_factor_num = 256; diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc index 661363d6c0..8e1990c603 100644 --- a/video/video_quality_test.cc +++ b/video/video_quality_test.cc @@ -1326,12 +1326,18 @@ void VideoQualityTest::FillScalabilitySettings( if (descriptor.empty()) continue; std::vector v = VideoQualityTest::ParseCSV(descriptor); - RTC_CHECK_GT(v[2], 0); + RTC_CHECK_EQ(v.size(), 7); + + SpatialLayer layer = {0}; + layer.width = v[0]; + layer.height = v[1]; + layer.numberOfTemporalLayers = v[2]; + layer.maxBitrate = v[3]; + layer.minBitrate = v[4]; + layer.targetBitrate = v[5]; + layer.qpMax = v[6]; + layer.active = true; - SpatialLayer layer; - layer.scaling_factor_num = v[0] == -1 ? 1 : v[0]; - layer.scaling_factor_den = v[1] == -1 ? 1 : v[1]; - layer.target_bitrate_bps = v[2]; params->ss[video_idx].spatial_layers.push_back(layer); } }