Index: webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h |
diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h b/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h |
index 32481cb152765ae0b56850c058999c2d4197b7c6..56ad3a710d29528e30ec6d65636bf2062d2c5b36 100644 |
--- a/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h |
+++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h |
@@ -12,7 +12,6 @@ |
#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_UNITTEST_H_ |
#include <algorithm> |
-#include <map> |
#include <memory> |
#include <vector> |
@@ -21,7 +20,6 @@ |
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" |
#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" |
#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h" |
-#include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" |
#include "webrtc/test/gtest.h" |
#include "webrtc/video_frame.h" |
@@ -149,6 +147,83 @@ |
int decoded_frames_; |
}; |
+class SkipEncodingUnusedStreamsTest { |
+ public: |
+ std::vector<unsigned int> RunTest(VP8Encoder* encoder, |
+ VideoCodec* settings, |
+ uint32_t target_bitrate) { |
+ SpyingTemporalLayersFactory spy_factory; |
+ settings->VP8()->tl_factory = &spy_factory; |
+ EXPECT_EQ(0, encoder->InitEncode(settings, 1, 1200)); |
+ |
+ encoder->SetRates(target_bitrate, 30); |
+ |
+ std::vector<unsigned int> configured_bitrates; |
+ for (std::vector<TemporalLayers*>::const_iterator it = |
+ spy_factory.spying_layers_.begin(); |
+ it != spy_factory.spying_layers_.end(); ++it) { |
+ configured_bitrates.push_back( |
+ static_cast<SpyingTemporalLayers*>(*it)->configured_bitrate_); |
+ } |
+ return configured_bitrates; |
+ } |
+ |
+ class SpyingTemporalLayers : public TemporalLayers { |
+ public: |
+ explicit SpyingTemporalLayers(TemporalLayers* layers) |
+ : configured_bitrate_(0), layers_(layers) {} |
+ |
+ virtual ~SpyingTemporalLayers() { delete layers_; } |
+ |
+ int EncodeFlags(uint32_t timestamp) override { |
+ return layers_->EncodeFlags(timestamp); |
+ } |
+ |
+ bool ConfigureBitrates(int bitrate_kbit, |
+ int max_bitrate_kbit, |
+ int framerate, |
+ vpx_codec_enc_cfg_t* cfg) override { |
+ configured_bitrate_ = bitrate_kbit; |
+ return layers_->ConfigureBitrates(bitrate_kbit, max_bitrate_kbit, |
+ framerate, cfg); |
+ } |
+ |
+ void PopulateCodecSpecific(bool base_layer_sync, |
+ CodecSpecificInfoVP8* vp8_info, |
+ uint32_t timestamp) override { |
+ layers_->PopulateCodecSpecific(base_layer_sync, vp8_info, timestamp); |
+ } |
+ |
+ void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override { |
+ layers_->FrameEncoded(size, timestamp, qp); |
+ } |
+ |
+ int CurrentLayerId() const override { return layers_->CurrentLayerId(); } |
+ |
+ bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override { |
+ return false; |
+ } |
+ |
+ int configured_bitrate_; |
+ TemporalLayers* layers_; |
+ }; |
+ |
+ class SpyingTemporalLayersFactory : public TemporalLayersFactory { |
+ public: |
+ virtual ~SpyingTemporalLayersFactory() {} |
+ TemporalLayers* Create(int temporal_layers, |
+ uint8_t initial_tl0_pic_idx) const override { |
+ SpyingTemporalLayers* layers = |
+ new SpyingTemporalLayers(TemporalLayersFactory::Create( |
+ temporal_layers, initial_tl0_pic_idx)); |
+ spying_layers_.push_back(layers); |
+ return layers; |
+ } |
+ |
+ mutable std::vector<TemporalLayers*> spying_layers_; |
+ }; |
+}; |
+ |
class TestVp8Simulcast : public ::testing::Test { |
public: |
TestVp8Simulcast(VP8Encoder* encoder, VP8Decoder* decoder) |
@@ -190,7 +265,7 @@ |
static void DefaultSettings(VideoCodec* settings, |
const int* temporal_layer_profile) { |
- RTC_CHECK(settings); |
+ assert(settings); |
memset(settings, 0, sizeof(VideoCodec)); |
strncpy(settings->plName, "VP8", 4); |
settings->codecType = kVideoCodecVP8; |
@@ -240,18 +315,12 @@ |
} |
protected: |
- void SetUp() override { SetUpCodec(kDefaultTemporalLayerProfile); } |
- |
- void TearDown() override { |
- encoder_->Release(); |
- decoder_->Release(); |
- } |
- |
- void SetUpCodec(const int* temporal_layer_profile) { |
+ virtual void SetUp() { SetUpCodec(kDefaultTemporalLayerProfile); } |
+ |
+ virtual void SetUpCodec(const int* temporal_layer_profile) { |
encoder_->RegisterEncodeCompleteCallback(&encoder_callback_); |
decoder_->RegisterDecodeCompleteCallback(&decoder_callback_); |
DefaultSettings(&settings_, temporal_layer_profile); |
- SetUpRateAllocator(); |
EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); |
EXPECT_EQ(0, decoder_->InitDecode(&settings_, 1)); |
int half_width = (kDefaultWidth + 1) / 2; |
@@ -262,16 +331,9 @@ |
new VideoFrame(input_buffer_, 0, 0, webrtc::kVideoRotation_0)); |
} |
- void SetUpRateAllocator() { |
- TemporalLayersFactory* tl_factory = new TemporalLayersFactory(); |
- rate_allocator_.reset(new SimulcastRateAllocator( |
- settings_, std::unique_ptr<TemporalLayersFactory>(tl_factory))); |
- settings_.codecSpecific.VP8.tl_factory = tl_factory; |
- } |
- |
- void SetRates(uint32_t bitrate_kbps, uint32_t fps) { |
- encoder_->SetRateAllocation( |
- rate_allocator_->GetAllocation(bitrate_kbps * 1000, fps), fps); |
+ virtual void TearDown() { |
+ encoder_->Release(); |
+ decoder_->Release(); |
} |
void ExpectStreams(FrameType frame_type, int expected_video_streams) { |
@@ -334,7 +396,7 @@ |
// We currently expect all active streams to generate a key frame even though |
// a key frame was only requested for some of them. |
void TestKeyFrameRequestsOnAllStreams() { |
- SetRates(kMaxBitrates[2], 30); // To get all three streams. |
+ encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, kNumberOfSimulcastStreams); |
@@ -369,7 +431,7 @@ |
void TestPaddingAllStreams() { |
// We should always encode the base layer. |
- SetRates(kMinBitrates[0] - 1, 30); |
+ encoder_->SetRates(kMinBitrates[0] - 1, 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 1); |
@@ -382,7 +444,7 @@ |
void TestPaddingTwoStreams() { |
// We have just enough to get only the first stream and padding for two. |
- SetRates(kMinBitrates[0], 30); |
+ encoder_->SetRates(kMinBitrates[0], 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 1); |
@@ -396,7 +458,7 @@ |
void TestPaddingTwoStreamsOneMaxedOut() { |
// We are just below limit of sending second stream, so we should get |
// the first stream maxed out (at |maxBitrate|), and padding for two. |
- SetRates(kTargetBitrates[0] + kMinBitrates[1] - 1, 30); |
+ encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] - 1, 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 1); |
@@ -409,7 +471,7 @@ |
void TestPaddingOneStream() { |
// We have just enough to send two streams, so padding for one stream. |
- SetRates(kTargetBitrates[0] + kMinBitrates[1], 30); |
+ encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1], 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 2); |
@@ -423,7 +485,8 @@ |
void TestPaddingOneStreamTwoMaxedOut() { |
// We are just below limit of sending third stream, so we should get |
// first stream's rate maxed out at |targetBitrate|, second at |maxBitrate|. |
- SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30); |
+ encoder_->SetRates( |
+ kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 2); |
@@ -436,7 +499,8 @@ |
void TestSendAllStreams() { |
// We have just enough to send all streams. |
- SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30); |
+ encoder_->SetRates( |
+ kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 3); |
@@ -449,7 +513,7 @@ |
void TestDisablingStreams() { |
// We should get three media streams. |
- SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30); |
+ encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
ExpectStreams(kVideoFrameKey, 3); |
@@ -460,33 +524,36 @@ |
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); |
// We should only get two streams and padding for one. |
- SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); |
+ encoder_->SetRates( |
+ kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); |
ExpectStreams(kVideoFrameDelta, 2); |
input_frame_->set_timestamp(input_frame_->timestamp() + 3000); |
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); |
// We should only get the first stream and padding for two. |
- SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30); |
+ encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30); |
ExpectStreams(kVideoFrameDelta, 1); |
input_frame_->set_timestamp(input_frame_->timestamp() + 3000); |
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); |
// We don't have enough bitrate for the thumbnail stream, but we should get |
// it anyway with current configuration. |
- SetRates(kTargetBitrates[0] - 1, 30); |
+ encoder_->SetRates(kTargetBitrates[0] - 1, 30); |
ExpectStreams(kVideoFrameDelta, 1); |
input_frame_->set_timestamp(input_frame_->timestamp() + 3000); |
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); |
// We should only get two streams and padding for one. |
- SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); |
+ encoder_->SetRates( |
+ kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); |
// We get a key frame because a new stream is being enabled. |
ExpectStreams(kVideoFrameKey, 2); |
input_frame_->set_timestamp(input_frame_->timestamp() + 3000); |
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); |
// We should get all three streams. |
- SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30); |
+ encoder_->SetRates( |
+ kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30); |
// We get a key frame because a new stream is being enabled. |
ExpectStreams(kVideoFrameKey, 3); |
input_frame_->set_timestamp(input_frame_->timestamp() + 3000); |
@@ -523,11 +590,10 @@ |
settings_.width; |
settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1].height = |
settings_.height; |
- SetUpRateAllocator(); |
EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); |
// Encode one frame and verify. |
- SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30); |
+ encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30); |
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
kVideoFrameDelta); |
EXPECT_CALL( |
@@ -545,9 +611,8 @@ |
DefaultSettings(&settings_, kDefaultTemporalLayerProfile); |
// Start at the lowest bitrate for enabling base stream. |
settings_.startBitrate = kMinBitrates[0]; |
- SetUpRateAllocator(); |
EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); |
- SetRates(settings_.startBitrate, 30); |
+ encoder_->SetRates(settings_.startBitrate, 30); |
ExpectStreams(kVideoFrameKey, 1); |
// Resize |input_frame_| to the new resolution. |
half_width = (settings_.width + 1) / 2; |
@@ -569,7 +634,7 @@ |
Vp8TestEncodedImageCallback encoder_callback; |
encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
- SetRates(kMaxBitrates[2], 30); // To get all three streams. |
+ encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); |
int picture_id = -1; |
@@ -638,7 +703,7 @@ |
encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
decoder_->RegisterDecodeCompleteCallback(&decoder_callback); |
- SetRates(kMaxBitrates[2], 30); // To get all three streams. |
+ encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
// Set color. |
int plane_offset[kNumOfPlanes]; |
@@ -712,7 +777,7 @@ |
void TestSaptioTemporalLayers333PatternEncoder() { |
Vp8TestEncodedImageCallback encoder_callback; |
encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
- SetRates(kMaxBitrates[2], 30); // To get all three streams. |
+ encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
int expected_temporal_idx[3] = {-1, -1, -1}; |
bool expected_layer_sync[3] = {false, false, false}; |
@@ -781,7 +846,7 @@ |
SetUpCodec(temporal_layer_profile); |
Vp8TestEncodedImageCallback encoder_callback; |
encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
- SetRates(kMaxBitrates[2], 30); // To get all three streams. |
+ encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
int expected_temporal_idx[3] = {-1, -1, -1}; |
bool expected_layer_sync[3] = {false, false, false}; |
@@ -840,7 +905,7 @@ |
encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
decoder_->RegisterDecodeCompleteCallback(&decoder_callback); |
- SetRates(kMaxBitrates[2], 30); // To get all three streams. |
+ encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
// Setting two (possibly) problematic use cases for stride: |
// 1. stride > width 2. stride_y != stride_uv/2 |
int stride_y = kDefaultWidth + 20; |
@@ -876,6 +941,30 @@ |
EXPECT_EQ(2, decoder_callback.DecodedFrames()); |
} |
+ void TestSkipEncodingUnusedStreams() { |
+ SkipEncodingUnusedStreamsTest test; |
+ std::vector<unsigned int> configured_bitrate = |
+ test.RunTest(encoder_.get(), &settings_, |
+ 1); // Target bit rate 1, to force all streams but the |
+ // base one to be exceeding bandwidth constraints. |
+ EXPECT_EQ(static_cast<size_t>(kNumberOfSimulcastStreams), |
+ configured_bitrate.size()); |
+ |
+ unsigned int min_bitrate = |
+ std::max(settings_.simulcastStream[0].minBitrate, settings_.minBitrate); |
+ int stream = 0; |
+ for (std::vector<unsigned int>::const_iterator it = |
+ configured_bitrate.begin(); |
+ it != configured_bitrate.end(); ++it) { |
+ if (stream == 0) { |
+ EXPECT_EQ(min_bitrate, *it); |
+ } else { |
+ EXPECT_EQ(0u, *it); |
+ } |
+ ++stream; |
+ } |
+ } |
+ |
std::unique_ptr<VP8Encoder> encoder_; |
MockEncodedImageCallback encoder_callback_; |
std::unique_ptr<VP8Decoder> decoder_; |
@@ -883,7 +972,6 @@ |
VideoCodec settings_; |
rtc::scoped_refptr<I420Buffer> input_buffer_; |
std::unique_ptr<VideoFrame> input_frame_; |
- std::unique_ptr<SimulcastRateAllocator> rate_allocator_; |
}; |
} // namespace testing |