Refactor vp8 temporal layers with inferred sync and search order

This CL introduces a few changes to the default VP8 temporal layers:
* The pattern is now reset on keyframes
* The sync flag is inferred rather than hard-coded
* Support is added for buffer search order

Bug: webrtc:9012
Change-Id: Ice19d32413d20982368a01a7d2540d155e185ad4
Reviewed-on: https://webrtc-review.googlesource.com/91863
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24288}
This commit is contained in:
Erik Språng
2018-08-13 16:05:33 +02:00
committed by Commit Bot
parent fa4e185684
commit b75d6b8dc3
10 changed files with 813 additions and 284 deletions

View File

@ -68,7 +68,7 @@ class ScreenshareLayerTest : public ::testing::Test {
int EncodeFrame(bool base_sync) {
int flags = ConfigureFrame(base_sync);
if (flags != -1)
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
return flags;
}
@ -151,7 +151,7 @@ class ScreenshareLayerTest : public ::testing::Test {
timestamp_ += kTimestampDelta5Fps;
if (vp8_info_.temporalIdx != layer ||
(sync && *sync != vp8_info_.layerSync)) {
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
} else {
// Found frame from sought after layer.
return flags;
@ -216,9 +216,9 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
// Simulate TL1 being at least 8 qp steps better.
if (vp8_info_.temporalIdx == 0) {
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
} else {
layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp - 8);
}
if (vp8_info_.temporalIdx == 1 && vp8_info_.layerSync)
@ -242,9 +242,9 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
// Simulate TL1 being at least 8 qp steps better.
if (vp8_info_.temporalIdx == 0) {
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
} else {
layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp - 8);
}
if (vp8_info_.temporalIdx == 1 && vp8_info_.layerSync)
@ -260,10 +260,10 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
int flags = ConfigureFrame(false);
if (vp8_info_.temporalIdx == 0) {
// Bump TL0 to same quality as TL1.
layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp - 8);
bumped_tl0_quality = true;
} else {
layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp - 8);
if (bumped_tl0_quality) {
EXPECT_TRUE(vp8_info_.layerSync);
EXPECT_EQ(kTl1SyncFlags, flags);
@ -381,7 +381,7 @@ TEST_F(ScreenshareLayerTest, EncoderDrop) {
SkipUntilTl(0);
// Size 0 indicates dropped frame.
layers_->FrameEncoded(0, kDefaultQp);
layers_->FrameEncoded(timestamp_, 0, kDefaultQp);
// Re-encode frame (so don't advance timestamp).
int flags = EncodeFrame(false);
@ -393,18 +393,18 @@ TEST_F(ScreenshareLayerTest, EncoderDrop) {
SkipUntilTl(0);
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
timestamp_ += kTimestampDelta5Fps;
// ...then back to standard setup.
SkipUntilTl(0);
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
timestamp_ += kTimestampDelta5Fps;
EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
// Next drop in TL1.
SkipUntilTl(1);
layers_->FrameEncoded(0, kDefaultQp);
layers_->FrameEncoded(timestamp_, 0, kDefaultQp);
// Re-encode frame (so don't advance timestamp).
flags = EncodeFrame(false);
@ -416,13 +416,13 @@ TEST_F(ScreenshareLayerTest, EncoderDrop) {
SkipUntilTl(1);
EXPECT_TRUE(config_updated_);
EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
timestamp_ += kTimestampDelta5Fps;
// ...and back to normal.
SkipUntilTl(1);
EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
layers_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
timestamp_ += kTimestampDelta5Fps;
}
@ -437,7 +437,7 @@ TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
EXPECT_EQ(kTl0Flags,
LibvpxVp8Encoder::EncodeFlags(UpdateLayerConfig(kStartTimestamp)));
layers_->FrameEncoded(kLargeFrameSizeBytes, kDefaultQp);
layers_->FrameEncoded(timestamp_, kLargeFrameSizeBytes, kDefaultQp);
const uint32_t kTwoSecondsLater =
kStartTimestamp + (ScreenshareLayers::kMaxFrameIntervalMs * 90);
@ -479,20 +479,20 @@ TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) {
// Simulate one overshoot.
layers_->FrameEncoded(0, 0);
layers_->FrameEncoded(timestamp_, 0, 0);
overshoot = true;
}
if (flags == kTl0Flags) {
if (timestamp >= kTimestampDelta5Fps * 20 && !trigger_drop) {
// Simulate a too large frame, to cause frame drop.
layers_->FrameEncoded(frame_size_ * 10, kTl0Qp);
layers_->FrameEncoded(timestamp_, frame_size_ * 10, kTl0Qp);
trigger_drop = true;
} else {
layers_->FrameEncoded(frame_size_, kTl0Qp);
layers_->FrameEncoded(timestamp_, frame_size_, kTl0Qp);
}
} else if (flags == kTl1Flags || flags == kTl1SyncFlags) {
layers_->FrameEncoded(frame_size_, kTl1Qp);
layers_->FrameEncoded(timestamp_, frame_size_, kTl1Qp);
} else if (flags == -1) {
dropped_frame = true;
} else {
@ -558,7 +558,7 @@ TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
++num_discarded_frames;
} else {
size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
layers_->FrameEncoded(frame_size_bytes, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_bytes, kDefaultQp);
}
timestamp += kFrameIntervalsMs * 90;
clock_.AdvanceTimeMilliseconds(kFrameIntervalsMs);
@ -574,7 +574,7 @@ TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
++num_discarded_frames;
} else {
size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
layers_->FrameEncoded(frame_size_bytes, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_bytes, kDefaultQp);
}
timestamp += kFrameIntervalsMs * 90 / 2;
clock_.AdvanceTimeMilliseconds(kFrameIntervalsMs / 2);
@ -594,7 +594,7 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAtOvershootDrop) {
ASSERT_TRUE(vp8_info_.layerSync);
// Simulate overshoot of this frame.
layers_->FrameEncoded(0, -1);
layers_->FrameEncoded(timestamp_, 0, -1);
config_updated_ = layers_->UpdateConfiguration(&cfg_);
EXPECT_EQ(kTl1SyncFlags, LibvpxVp8Encoder::EncodeFlags(tl_config_));
@ -611,7 +611,7 @@ 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_->FrameEncoded(frame_size_, kDefaultQp);
layers_->FrameEncoded(timestamp_, frame_size_, kDefaultQp);
// Frame interval below 90% if desired time is not allowed, try inserting
// frame just before this limit.