Use single FrameBufferController in VP8, created by a factory.

This CL paves the way to making FrameBufferController injectable.

LibvpxVp8Encoder can manage multiple streams. Prior to this CL,
each stream had its own frame buffer controller, all of them held
in a vector by LibvpxVp8Encoder. This complicated the code and
produced some code duplication (cf. SetupTemporalLayers).

This CL:
1. Replaces CreateVp8TemporalLayers() by a factory. (Later CLs
   will make this factory injectable.)
2. Makes LibvpxVp8Encoder use a single controller. This single
   controller will, in the case of multiple streams, delegate
   its work to multiple controllers, but that fact is not visible
   to LibvpxVp8Encoder.

This CL also squashes CL #126046 (Send notifications of RTT and
PLR changes to Vp8FrameBufferController) into it.

Bug: webrtc:10382
Change-Id: Id9b55734bebb457acc276f34a7a9e52cc19c8eb9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/126483
Commit-Queue: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27206}
This commit is contained in:
Elad Alon
2019-03-20 11:56:20 +01:00
committed by Commit Bot
parent 98d85fe9a4
commit cde8ab265e
26 changed files with 581 additions and 362 deletions

View File

@ -79,13 +79,13 @@ class ScreenshareLayerTest : public ::testing::Test {
int flags = ConfigureFrame(base_sync);
if (flags != -1)
layers_->OnEncodeDone(timestamp_, frame_size_, base_sync, kDefaultQp,
layers_->OnEncodeDone(0, timestamp_, frame_size_, base_sync, kDefaultQp,
info);
return flags;
}
int ConfigureFrame(bool key_frame) {
tl_config_ = UpdateLayerConfig(timestamp_);
tl_config_ = UpdateLayerConfig(0, timestamp_);
EXPECT_EQ(0, tl_config_.encoder_layer_id)
<< "ScreenshareLayers always encodes using the bitrate allocator for "
"layer 0, but may reference different buffers and packetize "
@ -93,16 +93,16 @@ class ScreenshareLayerTest : public ::testing::Test {
if (tl_config_.drop_frame) {
return -1;
}
config_updated_ = layers_->UpdateConfiguration(&cfg_);
config_updated_ = layers_->UpdateConfiguration(0, &cfg_);
int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
EXPECT_NE(-1, frame_size_);
return flags;
}
Vp8FrameConfig UpdateLayerConfig(uint32_t timestamp) {
Vp8FrameConfig UpdateLayerConfig(size_t stream_index, uint32_t timestamp) {
int64_t timestamp_ms = timestamp / 90;
clock_.AdvanceTime(TimeDelta::ms(timestamp_ms - rtc::TimeMillis()));
return layers_->UpdateLayerConfig(timestamp);
return layers_->UpdateLayerConfig(stream_index, timestamp);
}
int FrameSizeForBitrate(int bitrate_kbps) {
@ -114,8 +114,8 @@ class ScreenshareLayerTest : public ::testing::Test {
memset(&vp8_cfg, 0, sizeof(Vp8EncoderConfig));
vp8_cfg.rc_min_quantizer = min_qp_;
vp8_cfg.rc_max_quantizer = max_qp_;
layers_->OnRatesUpdated(kDefault2TlBitratesBps, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(&vp8_cfg));
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(0, &vp8_cfg));
frame_size_ = FrameSizeForBitrate(vp8_cfg.rc_target_bitrate);
return vp8_cfg;
}
@ -162,7 +162,7 @@ class ScreenshareLayerTest : public ::testing::Test {
if (tl_config_.packetizer_temporal_idx != layer ||
(sync && *sync != tl_config_.layer_sync)) {
CodecSpecificInfo info;
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
&info);
timestamp_ += kTimestampDelta5Fps;
} else {
@ -238,14 +238,15 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
for (int i = 0; i < kNumFrames; ++i) {
CodecSpecificInfo info;
tl_config_ = UpdateLayerConfig(timestamp_);
config_updated_ = layers_->UpdateConfiguration(&cfg_);
tl_config_ = UpdateLayerConfig(0, timestamp_);
config_updated_ = layers_->UpdateConfiguration(0, &cfg_);
// Simulate TL1 being at least 8 qp steps better.
if (tl_config_.packetizer_temporal_idx == 0) {
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp, &info);
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
&info);
} else {
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp - 8,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
&info);
}
@ -273,9 +274,10 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
// Simulate TL1 being at least 8 qp steps better.
if (tl_config_.packetizer_temporal_idx == 0) {
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp, &info);
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
&info);
} else {
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp - 8,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
&info);
}
@ -293,7 +295,7 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
CodecSpecificInfo info;
int flags = ConfigureFrame(false);
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp - 8,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
&info);
if (info.codecSpecific.VP8.temporalIdx == 0) {
// Bump TL0 to same quality as TL1.
@ -384,8 +386,8 @@ TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) {
const int kTl1_kbps = 1000;
const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
(kTl1_kbps - kTl0_kbps) * 1000};
layers_->OnRatesUpdated(layer_rates, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
EXPECT_EQ(static_cast<unsigned int>(
ScreenshareLayers::kMaxTL0FpsReduction * kTl0_kbps + 0.5),
@ -397,8 +399,8 @@ TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) {
const int kTl1_kbps = 450;
const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
(kTl1_kbps - kTl0_kbps) * 1000};
layers_->OnRatesUpdated(layer_rates, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
EXPECT_EQ(static_cast<unsigned int>(
kTl1_kbps / ScreenshareLayers::kAcceptableTargetOvershoot),
@ -408,8 +410,8 @@ TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) {
TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) {
const int kTl0_kbps = 100;
const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000};
layers_->OnRatesUpdated(layer_rates, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
EXPECT_EQ(static_cast<uint32_t>(kTl0_kbps), cfg_.rc_target_bitrate);
}
@ -419,7 +421,7 @@ TEST_F(ScreenshareLayerTest, EncoderDrop) {
SkipUntilTl(0);
// Size 0 indicates dropped frame.
layers_->OnEncodeDone(timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
layers_->OnEncodeDone(0, timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
// Re-encode frame (so don't advance timestamp).
int flags = EncodeFrame(false);
@ -431,20 +433,20 @@ TEST_F(ScreenshareLayerTest, EncoderDrop) {
SkipUntilTl(0);
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
IgnoredCodecSpecificInfo());
timestamp_ += kTimestampDelta5Fps;
// ...then back to standard setup.
SkipUntilTl(0);
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
IgnoredCodecSpecificInfo());
timestamp_ += kTimestampDelta5Fps;
EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
// Next drop in TL1.
SkipUntilTl(1);
layers_->OnEncodeDone(timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
layers_->OnEncodeDone(0, timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
// Re-encode frame (so don't advance timestamp).
flags = EncodeFrame(false);
@ -456,14 +458,14 @@ TEST_F(ScreenshareLayerTest, EncoderDrop) {
SkipUntilTl(1);
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
IgnoredCodecSpecificInfo());
timestamp_ += kTimestampDelta5Fps;
// ...and back to normal.
SkipUntilTl(1);
EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
IgnoredCodecSpecificInfo());
timestamp_ += kTimestampDelta5Fps;
}
@ -474,12 +476,12 @@ TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
const uint32_t kStartTimestamp = 1234;
const std::vector<uint32_t> layer_rates = {kLowBitrateKbps * 1000};
layers_->OnRatesUpdated(layer_rates, kFrameRate);
layers_->UpdateConfiguration(&cfg_);
layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
layers_->UpdateConfiguration(0, &cfg_);
EXPECT_EQ(kTl0Flags,
LibvpxVp8Encoder::EncodeFlags(UpdateLayerConfig(kStartTimestamp)));
layers_->OnEncodeDone(kStartTimestamp, kLargeFrameSizeBytes, false,
EXPECT_EQ(kTl0Flags, LibvpxVp8Encoder::EncodeFlags(
UpdateLayerConfig(0, kStartTimestamp)));
layers_->OnEncodeDone(0, kStartTimestamp, kLargeFrameSizeBytes, false,
kDefaultQp, IgnoredCodecSpecificInfo());
const uint32_t kTwoSecondsLater =
@ -493,12 +495,12 @@ TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
// any later, the frame will be dropped anyway by the frame rate throttling
// logic.
EXPECT_TRUE(
UpdateLayerConfig(kTwoSecondsLater - kTimestampDelta5Fps).drop_frame);
UpdateLayerConfig(0, kTwoSecondsLater - kTimestampDelta5Fps).drop_frame);
// More than two seconds has passed since last frame, one should be emitted
// even if bitrate target is then exceeded.
EXPECT_EQ(kTl0Flags, LibvpxVp8Encoder::EncodeFlags(
UpdateLayerConfig(kTwoSecondsLater + 90)));
UpdateLayerConfig(0, kTwoSecondsLater + 90)));
}
TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
@ -511,33 +513,33 @@ TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
for (int64_t timestamp = 0;
timestamp < kTimestampDelta5Fps * 5 * metrics::kMinRunTimeInSeconds;
timestamp += kTimestampDelta5Fps) {
tl_config_ = UpdateLayerConfig(timestamp);
tl_config_ = UpdateLayerConfig(0, timestamp);
if (tl_config_.drop_frame) {
dropped_frame = true;
continue;
}
int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
if (flags != -1)
layers_->UpdateConfiguration(&cfg_);
layers_->UpdateConfiguration(0, &cfg_);
if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) {
// Simulate one overshoot.
layers_->OnEncodeDone(timestamp, 0, false, 0, nullptr);
layers_->OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
overshoot = true;
}
if (flags == kTl0Flags) {
if (timestamp >= kTimestampDelta5Fps * 20 && !trigger_drop) {
// Simulate a too large frame, to cause frame drop.
layers_->OnEncodeDone(timestamp, frame_size_ * 10, false, kTl0Qp,
layers_->OnEncodeDone(0, timestamp, frame_size_ * 10, false, kTl0Qp,
IgnoredCodecSpecificInfo());
trigger_drop = true;
} else {
layers_->OnEncodeDone(timestamp, frame_size_, false, kTl0Qp,
layers_->OnEncodeDone(0, timestamp, frame_size_, false, kTl0Qp,
IgnoredCodecSpecificInfo());
}
} else if (flags == kTl1Flags || flags == kTl1SyncFlags) {
layers_->OnEncodeDone(timestamp, frame_size_, false, kTl1Qp,
layers_->OnEncodeDone(0, timestamp, frame_size_, false, kTl1Qp,
IgnoredCodecSpecificInfo());
} else if (flags == -1) {
dropped_frame = true;
@ -587,7 +589,7 @@ TEST_F(ScreenshareLayerTest, AllowsUpdateConfigBeforeSetRates) {
layers_.reset(new ScreenshareLayers(2));
// New layer instance, OnRatesUpdated() never called.
// UpdateConfiguration() call should not cause crash.
layers_->UpdateConfiguration(&cfg_);
layers_->UpdateConfiguration(0, &cfg_);
}
TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
@ -600,11 +602,11 @@ TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
// Send at regular rate - no drops expected.
for (int64_t i = 0; i < kTestSpanMs; i += kFrameIntervalsMs) {
if (UpdateLayerConfig(timestamp).drop_frame) {
if (UpdateLayerConfig(0, timestamp).drop_frame) {
++num_discarded_frames;
} else {
size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
layers_->OnEncodeDone(timestamp, frame_size_bytes, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp, frame_size_bytes, false, kDefaultQp,
IgnoredCodecSpecificInfo());
}
timestamp += kFrameIntervalsMs * 90;
@ -618,11 +620,11 @@ TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
num_input_frames = 0;
num_discarded_frames = 0;
for (int64_t i = 0; i < kTestSpanMs; i += kFrameIntervalsMs / 2) {
if (UpdateLayerConfig(timestamp).drop_frame) {
if (UpdateLayerConfig(0, timestamp).drop_frame) {
++num_discarded_frames;
} else {
size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
layers_->OnEncodeDone(timestamp, frame_size_bytes, false, kDefaultQp,
layers_->OnEncodeDone(0, timestamp, frame_size_bytes, false, kDefaultQp,
IgnoredCodecSpecificInfo());
}
timestamp += kFrameIntervalsMs * 90 / 2;
@ -643,13 +645,14 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAtOvershootDrop) {
ASSERT_TRUE(tl_config_.layer_sync);
// Simulate overshoot of this frame.
layers_->OnEncodeDone(timestamp_, 0, false, 0, nullptr);
layers_->OnEncodeDone(0, timestamp_, 0, false, 0, nullptr);
config_updated_ = layers_->UpdateConfiguration(&cfg_);
config_updated_ = layers_->UpdateConfiguration(0, &cfg_);
EXPECT_EQ(kTl1SyncFlags, LibvpxVp8Encoder::EncodeFlags(tl_config_));
CodecSpecificInfo new_info;
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp, &new_info);
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
&new_info);
EXPECT_TRUE(new_info.codecSpecific.VP8.layerSync);
}
@ -659,26 +662,26 @@ TEST_F(ScreenshareLayerTest, DropOnTooShortFrameInterval) {
// Add a large gap, so there's plenty of room in the rate tracker.
timestamp_ += kTimestampDelta5Fps * 3;
EXPECT_FALSE(UpdateLayerConfig(timestamp_).drop_frame);
layers_->OnEncodeDone(timestamp_, frame_size_, false, kDefaultQp,
EXPECT_FALSE(UpdateLayerConfig(0, timestamp_).drop_frame);
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
IgnoredCodecSpecificInfo());
// Frame interval below 90% if desired time is not allowed, try inserting
// frame just before this limit.
const int64_t kMinFrameInterval = (kTimestampDelta5Fps * 85) / 100;
timestamp_ += kMinFrameInterval - 90;
EXPECT_TRUE(UpdateLayerConfig(timestamp_).drop_frame);
EXPECT_TRUE(UpdateLayerConfig(0, timestamp_).drop_frame);
// Try again at the limit, now it should pass.
timestamp_ += 90;
EXPECT_FALSE(UpdateLayerConfig(timestamp_).drop_frame);
EXPECT_FALSE(UpdateLayerConfig(0, timestamp_).drop_frame);
}
TEST_F(ScreenshareLayerTest, AdjustsBitrateWhenDroppingFrames) {
const uint32_t kTimestampDelta10Fps = kTimestampDelta5Fps / 2;
const int kNumFrames = 30;
uint32_t default_bitrate = cfg_.rc_target_bitrate;
layers_->OnRatesUpdated(kDefault2TlBitratesBps, 10);
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, 10);
int num_dropped_frames = 0;
for (int i = 0; i < kNumFrames; ++i) {
@ -686,7 +689,7 @@ TEST_F(ScreenshareLayerTest, AdjustsBitrateWhenDroppingFrames) {
++num_dropped_frames;
timestamp_ += kTimestampDelta10Fps;
}
layers_->UpdateConfiguration(&cfg_);
layers_->UpdateConfiguration(0, &cfg_);
EXPECT_EQ(num_dropped_frames, kNumFrames / 2);
EXPECT_EQ(cfg_.rc_target_bitrate, default_bitrate * 2);
@ -694,21 +697,21 @@ TEST_F(ScreenshareLayerTest, AdjustsBitrateWhenDroppingFrames) {
TEST_F(ScreenshareLayerTest, UpdatesConfigurationAfterRateChange) {
// Set inital rate again, no need to update configuration.
layers_->OnRatesUpdated(kDefault2TlBitratesBps, kFrameRate);
EXPECT_FALSE(layers_->UpdateConfiguration(&cfg_));
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
EXPECT_FALSE(layers_->UpdateConfiguration(0, &cfg_));
// Rate changed, now update config.
std::vector<uint32_t> bitrates = kDefault2TlBitratesBps;
bitrates[1] -= 100000;
layers_->OnRatesUpdated(bitrates, 5);
EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
layers_->OnRatesUpdated(0, bitrates, 5);
EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
// Changed rate, but then set changed rate again before trying to update
// configuration, update should still apply.
bitrates[1] -= 100000;
layers_->OnRatesUpdated(bitrates, 5);
layers_->OnRatesUpdated(bitrates, 5);
EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
layers_->OnRatesUpdated(0, bitrates, 5);
layers_->OnRatesUpdated(0, bitrates, 5);
EXPECT_TRUE(layers_->UpdateConfiguration(0, &cfg_));
}
// TODO(bugs.webrtc.org/10260): Fix.
@ -721,42 +724,42 @@ TEST_F(ScreenshareLayerTest, DISABLED_MaxQpRestoredAfterDoubleDrop) {
ASSERT_TRUE(tl_config_.layer_sync);
// Simulate overshoot of this frame.
layers_->OnEncodeDone(timestamp_, 0, false, -1, nullptr);
layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
// Simulate re-encoded frame.
layers_->OnEncodeDone(timestamp_, 1, false, max_qp_,
layers_->OnEncodeDone(0, timestamp_, 1, false, max_qp_,
IgnoredCodecSpecificInfo());
// Next frame, expect boosted quality.
// Slightly alter bitrate between each frame.
std::vector<uint32_t> kDefault2TlBitratesBpsAlt = kDefault2TlBitratesBps;
kDefault2TlBitratesBpsAlt[1] += 4000;
layers_->OnRatesUpdated(kDefault2TlBitratesBpsAlt, kFrameRate);
layers_->OnRatesUpdated(0, kDefault2TlBitratesBpsAlt, kFrameRate);
EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
uint32_t adjusted_qp = cfg_.rc_max_quantizer;
// Simulate overshoot of this frame.
layers_->OnEncodeDone(timestamp_, 0, false, -1, nullptr);
layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
// Simulate re-encoded frame.
layers_->OnEncodeDone(timestamp_, frame_size_, false, max_qp_,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, max_qp_,
IgnoredCodecSpecificInfo());
// A third frame, expect boosted quality.
layers_->OnRatesUpdated(kDefault2TlBitratesBps, kFrameRate);
layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
EXPECT_EQ(adjusted_qp, cfg_.rc_max_quantizer);
// Frame encoded.
layers_->OnEncodeDone(timestamp_, frame_size_, false, max_qp_,
layers_->OnEncodeDone(0, timestamp_, frame_size_, false, max_qp_,
IgnoredCodecSpecificInfo());
// A fourth frame, max qp should be restored.
layers_->OnRatesUpdated(kDefault2TlBitratesBpsAlt, kFrameRate);
layers_->OnRatesUpdated(0, kDefault2TlBitratesBpsAlt, kFrameRate);
EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
EXPECT_EQ(cfg_.rc_max_quantizer, max_qp_);
}