Use recommended min bitrate limit provided by encoder.

Also:
- DCHECK that bitrate limits recommended by encoder are reasonable.
- Restrict target bitrate such that it never exceed the max bitrate.

Bug: webrtc:10853
Change-Id: Ie43d30a7acfc8fa115deffd94165844248ce7945
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/148442
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28822}
This commit is contained in:
Sergey Silkin
2019-08-09 16:04:05 +02:00
committed by Commit Bot
parent 48b48e5cc9
commit 6b2cec17c2
2 changed files with 152 additions and 29 deletions

View File

@ -682,6 +682,11 @@ GetEncoderBitrateLimits(const VideoEncoder::EncoderInfo& encoder_info,
});
for (size_t i = 0; i < bitrate_limits.size(); ++i) {
RTC_DCHECK_GT(bitrate_limits[i].min_bitrate_bps, 0);
RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps,
bitrate_limits[i].min_bitrate_bps);
RTC_DCHECK_GT(bitrate_limits[i].max_bitrate_bps,
bitrate_limits[i].min_start_bitrate_bps);
if (i > 0) {
// The bitrate limits aren't expected to decrease with resolution.
RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps,
@ -754,11 +759,18 @@ void VideoStreamEncoder::ReconfigureEncoder() {
encoder_->GetEncoderInfo(),
last_frame_info_->width * last_frame_info_->height);
if (encoder_config_.max_bitrate_bps <= 0 && streams.size() == 1 &&
encoder_bitrate_limits_ && encoder_bitrate_limits_->max_bitrate_bps > 0) {
// If max video bitrate is not limited explicitly, set it equal to max
// bitrate recommended by encoder.
streams.back().max_bitrate_bps = encoder_bitrate_limits_->max_bitrate_bps;
if (streams.size() == 1 && encoder_bitrate_limits_) {
// Use bitrate limits recommended by encoder only if app didn't set any of
// them.
if (encoder_config_.max_bitrate_bps <= 0 &&
(encoder_config_.simulcast_layers.empty() ||
encoder_config_.simulcast_layers[0].min_bitrate_bps <= 0)) {
streams.back().min_bitrate_bps = encoder_bitrate_limits_->min_bitrate_bps;
streams.back().max_bitrate_bps = encoder_bitrate_limits_->max_bitrate_bps;
streams.back().target_bitrate_bps =
std::min(streams.back().target_bitrate_bps,
encoder_bitrate_limits_->max_bitrate_bps);
}
}
VideoCodec codec;

View File

@ -1342,50 +1342,106 @@ TEST_F(VideoStreamEncoderTest, BitrateLimitsChangeReconfigureRateAllocator) {
}
TEST_F(VideoStreamEncoderTest,
EncoderConfigMaxBitrateOverridesMaxBitrateRecommendedByEncoder) {
EncoderRecommendedBitrateLimitsDoNotOverrideAppBitrateLimits) {
video_stream_encoder_->OnBitrateUpdated(
DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
codec_width_ * codec_height_, 0, 0, kTargetBitrateBps + 123 * 1000);
fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 0;
video_encoder_config.simulcast_layers[0].min_bitrate_bps = 0;
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength);
video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
video_source_.IncomingCapturedFrame(CreateFrame(1, 360, 180));
WaitForEncodedFrame(1);
// VideoEncoderConfig::max_bitrate_bps is set to 0 - the max bitrate
// recommended by encoder should be used.
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
// Get the default bitrate limits and use them as baseline for custom
// application and encoder recommended limits.
const uint32_t kDefaultMinBitrateKbps =
bitrate_allocator_factory_.codec_config().minBitrate;
const uint32_t kDefaultMaxBitrateKbps =
bitrate_allocator_factory_.codec_config().maxBitrate;
const uint32_t kEncMinBitrateKbps = kDefaultMinBitrateKbps * 2;
const uint32_t kEncMaxBitrateKbps = kDefaultMaxBitrateKbps * 2;
const uint32_t kAppMinBitrateKbps = kDefaultMinBitrateKbps * 3;
const uint32_t kAppMaxBitrateKbps = kDefaultMaxBitrateKbps * 3;
const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
codec_width_ * codec_height_, kEncMinBitrateKbps * 1000,
kEncMinBitrateKbps * 1000, kEncMaxBitrateKbps * 1000);
fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
// Change resolution. This will trigger encoder re-configuration and video
// stream encoder will pick up the bitrate limits recommended by encoder.
video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
WaitForEncodedFrame(2);
video_source_.IncomingCapturedFrame(CreateFrame(3, 360, 180));
WaitForEncodedFrame(3);
// App bitrate limits are not set - bitrate limits recommended by encoder
// should be used.
EXPECT_EQ(kEncMaxBitrateKbps,
bitrate_allocator_factory_.codec_config().maxBitrate);
EXPECT_EQ(kEncMinBitrateKbps,
bitrate_allocator_factory_.codec_config().minBitrate);
video_encoder_config.max_bitrate_bps = kAppMaxBitrateKbps * 1000;
video_encoder_config.simulcast_layers[0].min_bitrate_bps = 0;
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength);
video_source_.IncomingCapturedFrame(CreateFrame(4, nullptr));
WaitForEncodedFrame(4);
// App limited the max bitrate - bitrate limits recommended by encoder should
// not be applied.
EXPECT_EQ(kAppMaxBitrateKbps,
bitrate_allocator_factory_.codec_config().maxBitrate);
EXPECT_EQ(kDefaultMinBitrateKbps,
bitrate_allocator_factory_.codec_config().minBitrate);
video_encoder_config.max_bitrate_bps = 0;
video_encoder_config.simulcast_layers[0].min_bitrate_bps =
kAppMinBitrateKbps * 1000;
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength);
video_source_.IncomingCapturedFrame(CreateFrame(5, nullptr));
WaitForEncodedFrame(5);
// App limited the min bitrate - bitrate limits recommended by encoder should
// not be applied.
EXPECT_EQ(kDefaultMaxBitrateKbps,
bitrate_allocator_factory_.codec_config().maxBitrate);
EXPECT_EQ(kAppMinBitrateKbps,
bitrate_allocator_factory_.codec_config().minBitrate);
video_encoder_config.max_bitrate_bps = kAppMaxBitrateKbps * 1000;
video_encoder_config.simulcast_layers[0].min_bitrate_bps =
kAppMinBitrateKbps * 1000;
video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
kMaxPayloadLength);
video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
WaitForEncodedFrame(2);
video_source_.IncomingCapturedFrame(CreateFrame(6, nullptr));
WaitForEncodedFrame(6);
// When VideoEncoderConfig::max_bitrate_bps is set it should override the max
// bitrate limits recommended by encoder.
EXPECT_EQ(kTargetBitrateBps,
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
// App limited both min and max bitrates - bitrate limits recommended by
// encoder should not be applied.
EXPECT_EQ(kAppMaxBitrateKbps,
bitrate_allocator_factory_.codec_config().maxBitrate);
EXPECT_EQ(kAppMinBitrateKbps,
bitrate_allocator_factory_.codec_config().minBitrate);
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
EncoderRecommendedMaxBitrateUsedForGivenResolution) {
EncoderRecommendedMaxAndMinBitratesUsedForGivenResolution) {
video_stream_encoder_->OnBitrateUpdated(
DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits_270p(
480 * 270, 0, 0, kTargetBitrateBps + 270 * 1000);
480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits_360p(
640 * 360, 0, 0, kTargetBitrateBps + 360 * 1000);
640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
fake_encoder_.SetResolutionBitrateLimits(
{encoder_bitrate_limits_270p, encoder_bitrate_limits_360p});
@ -1395,32 +1451,42 @@ TEST_F(VideoStreamEncoderTest,
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength);
// 270p. The max bitrate limit recommended by encoder for 270p should be used.
// 270p. The bitrate limits recommended by encoder for 270p should be used.
video_source_.IncomingCapturedFrame(CreateFrame(1, 480, 270));
WaitForEncodedFrame(1);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.min_bitrate_bps),
bitrate_allocator_factory_.codec_config().minBitrate * 1000);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
// 360p. The max bitrate limit recommended by encoder for 360p should be used.
// 360p. The bitrate limits recommended by encoder for 360p should be used.
video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
WaitForEncodedFrame(2);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.min_bitrate_bps),
bitrate_allocator_factory_.codec_config().minBitrate * 1000);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
// Resolution between 270p and 360p. The max bitrate limit recommended by
// Resolution between 270p and 360p. The bitrate limits recommended by
// encoder for 360p should be used.
video_source_.IncomingCapturedFrame(
CreateFrame(3, (640 + 480) / 2, (360 + 270) / 2));
WaitForEncodedFrame(3);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.min_bitrate_bps),
bitrate_allocator_factory_.codec_config().minBitrate * 1000);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
// Resolution higher than 360p. The caps recommenended by encoder should be
// Resolution higher than 360p. The caps recommended by encoder should be
// ignored.
video_source_.IncomingCapturedFrame(CreateFrame(4, 960, 540));
WaitForEncodedFrame(4);
EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_270p.min_bitrate_bps),
bitrate_allocator_factory_.codec_config().minBitrate * 1000);
EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_270p.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_360p.min_bitrate_bps),
bitrate_allocator_factory_.codec_config().minBitrate * 1000);
EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_360p.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
@ -1428,12 +1494,57 @@ TEST_F(VideoStreamEncoderTest,
// for 270p should be used.
video_source_.IncomingCapturedFrame(CreateFrame(5, 320, 180));
WaitForEncodedFrame(5);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.min_bitrate_bps),
bitrate_allocator_factory_.codec_config().minBitrate * 1000);
EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.max_bitrate_bps),
bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest, EncoderRecommendedMaxBitrateCapsTargetBitrate) {
video_stream_encoder_->OnBitrateUpdated(
DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
video_encoder_config.max_bitrate_bps = 0;
video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
kMaxPayloadLength);
// Encode 720p frame to get the default encoder target bitrate.
video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
WaitForEncodedFrame(1);
const uint32_t kDefaultTargetBitrateFor720pKbps =
bitrate_allocator_factory_.codec_config()
.simulcastStream[0]
.targetBitrate;
// Set the max recommended encoder bitrate to something lower than the default
// target bitrate.
const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
1280 * 720, 10 * 1000, 10 * 1000,
kDefaultTargetBitrateFor720pKbps / 2 * 1000);
fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
// Change resolution to trigger encoder reinitialization.
video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
WaitForEncodedFrame(2);
video_source_.IncomingCapturedFrame(CreateFrame(3, 1280, 720));
WaitForEncodedFrame(3);
// Ensure the target bitrate is capped by the max bitrate.
EXPECT_EQ(bitrate_allocator_factory_.codec_config().maxBitrate * 1000,
static_cast<uint32_t>(encoder_bitrate_limits.max_bitrate_bps));
EXPECT_EQ(bitrate_allocator_factory_.codec_config()
.simulcastStream[0]
.targetBitrate *
1000,
static_cast<uint32_t>(encoder_bitrate_limits.max_bitrate_bps));
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
EXPECT_TRUE(video_source_.has_sinks());
test::FrameForwarder new_video_source;