Skip to content

Commit

Permalink
M110 Merge: Make sure VP9 encoders are reconfigured on layer activation.
Browse files Browse the repository at this point in the history
When disabling a spatial layer, reconfiguration of the encoder is not
necessary (bitrate will never be assigned to the inactive layer anway).
This CL however makes sure we reconfigure the encoder when a spatial
layer is activated. Some encoder implementations may encoder the wrong
number of spatial layers if the active layers have not beens set
correctly.

(cherry picked from commit 17043b8)

Bug: webrtc:14809, b/261097903, chromium:1310794
Change-Id: I8d34aaec95eb50a9717c06ea38f25088e5a96429
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290560
Commit-Queue: Philip Eliasson <[email protected]>
Auto-Submit: Erik Språng <[email protected]>
Reviewed-by: Philip Eliasson <[email protected]>
Cr-Original-Commit-Position: refs/heads/main@{#38999}
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290780
Commit-Queue: Erik Språng <[email protected]>
Cr-Commit-Position: refs/branch-heads/5481@{#1}
Cr-Branched-From: 2e1a9a4-refs/heads/main@{#38901}
  • Loading branch information
Erik Språng authored and WebRTC LUCI CQ committed Jan 10, 2023
1 parent 2e1a9a4 commit dc7333f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
7 changes: 6 additions & 1 deletion video/video_stream_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,19 @@ bool RequiresEncoderReset(const VideoCodec& prev_send_codec,
if (new_send_codec.codecType == kVideoCodecVP9) {
size_t num_spatial_layers = new_send_codec.VP9().numberOfSpatialLayers;
for (unsigned char i = 0; i < num_spatial_layers; ++i) {
if (!new_send_codec.spatialLayers[i].active) {
// No need to reset when layer is inactive.
continue;
}
if (new_send_codec.spatialLayers[i].width !=
prev_send_codec.spatialLayers[i].width ||
new_send_codec.spatialLayers[i].height !=
prev_send_codec.spatialLayers[i].height ||
new_send_codec.spatialLayers[i].numberOfTemporalLayers !=
prev_send_codec.spatialLayers[i].numberOfTemporalLayers ||
new_send_codec.spatialLayers[i].qpMax !=
prev_send_codec.spatialLayers[i].qpMax) {
prev_send_codec.spatialLayers[i].qpMax ||
!prev_send_codec.spatialLayers[i].active) {
return true;
}
}
Expand Down
58 changes: 58 additions & 0 deletions video/video_stream_encoder_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8649,6 +8649,64 @@ TEST_F(VideoStreamEncoderTest,
video_stream_encoder_->Stop();
}

TEST_F(VideoStreamEncoderTest, RecreatesEncoderWhenEnableVp9SpatialLayer) {
// Set up encoder to use VP9 SVC using two spatial layers.
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
/* num_streams*/ 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
video_encoder_config.content_type =
VideoEncoderConfig::ContentType::kRealtimeVideo;
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
vp9_settings.numberOfSpatialLayers = 2;
vp9_settings.numberOfTemporalLayers = 2;
vp9_settings.interLayerPred = InterLayerPredMode::kOn;
vp9_settings.automaticResizeOn = false;
video_encoder_config.encoder_specific_settings =
rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
vp9_settings);
video_encoder_config.spatial_layers = GetSvcConfig(1280, 720,
/*fps=*/30.0,
/*first_active_layer=*/0,
/*num_spatial_layers=*/2,
/*num_temporal_layers=*/3,
/*is_screenshare=*/false);
ConfigureEncoder(video_encoder_config.Copy(),
VideoStreamEncoder::BitrateAllocationCallbackType::
kVideoLayersAllocation);

video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);

video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(fake_encoder_.GetNumInitializations(), 1);

// Turn off the top spatial layer. This does not require an encoder reset.
video_encoder_config.spatial_layers[1].active = false;
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength, nullptr);

time_controller_.AdvanceTime(TimeDelta::Millis(33));
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(fake_encoder_.GetNumInitializations(), 1);

// Turn on the top spatial layer again, this does require an encoder reset.
video_encoder_config.spatial_layers[1].active = true;
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength, nullptr);

time_controller_.AdvanceTime(TimeDelta::Millis(33));
video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
WaitForEncodedFrame(CurrentTimeMs());
EXPECT_EQ(fake_encoder_.GetNumInitializations(), 2);

video_stream_encoder_->Stop();
}

#endif // !defined(WEBRTC_IOS)

// Test parameters: (VideoCodecType codec, bool allow_i420_conversion)
Expand Down

0 comments on commit dc7333f

Please sign in to comment.