blob: bd39595f0c387e742f6b0027edf54bbd897f3580 [file] [log] [blame]
pbos@webrtc.org9115cde2014-12-09 10:36:40 +00001/*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
brandtr5e171752017-05-23 03:32:16 -070011#include <array>
kwiberg3f55dea2016-02-29 05:51:59 -080012#include <memory>
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000013#include <vector>
14
Karl Wiberg918f50c2018-07-05 11:40:33 +020015#include "absl/memory/memory.h"
Rasmus Brandt0cedc052018-05-31 12:53:00 +020016#include "api/test/create_simulcast_test_fixture.h"
17#include "api/test/simulcast_test_fixture.h"
Magnus Jedvertdf4883d2017-11-17 14:44:55 +010018#include "api/video_codecs/sdp_video_format.h"
19#include "api/video_codecs/video_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "common_video/include/video_frame_buffer.h"
Magnus Jedvert46a27652017-11-13 14:10:02 +010021#include "media/engine/internalencoderfactory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "media/engine/simulcast_encoder_adapter.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020023#include "modules/video_coding/codecs/vp8/include/vp8.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/video_coding/include/video_codec_interface.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020025#include "modules/video_coding/utility/simulcast_test_fixture_impl.h"
Rasmus Brandt0cedc052018-05-31 12:53:00 +020026#include "test/function_video_decoder_factory.h"
27#include "test/function_video_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gmock.h"
Rasmus Brandt0cedc052018-05-31 12:53:00 +020029#include "test/gtest.h"
30
31using ::testing::_;
32using ::testing::Return;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000033
34namespace webrtc {
Rasmus Brandt0cedc052018-05-31 12:53:00 +020035namespace test {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000036
Rasmus Brandt0cedc052018-05-31 12:53:00 +020037namespace {
philipelcce46fc2015-12-21 03:04:49 -080038
Rasmus Brandt0cedc052018-05-31 12:53:00 +020039constexpr int kDefaultWidth = 1280;
40constexpr int kDefaultHeight = 720;
magjed6cc25612017-07-10 03:26:36 -070041
Rasmus Brandt0cedc052018-05-31 12:53:00 +020042std::unique_ptr<SimulcastTestFixture> CreateSpecificSimulcastTestFixture(
43 VideoEncoderFactory* internal_encoder_factory) {
44 std::unique_ptr<VideoEncoderFactory> encoder_factory =
Karl Wiberg918f50c2018-07-05 11:40:33 +020045 absl::make_unique<FunctionVideoEncoderFactory>(
Rasmus Brandt0cedc052018-05-31 12:53:00 +020046 [internal_encoder_factory]() {
Karl Wiberg918f50c2018-07-05 11:40:33 +020047 return absl::make_unique<SimulcastEncoderAdapter>(
Rasmus Brandt0cedc052018-05-31 12:53:00 +020048 internal_encoder_factory,
49 SdpVideoFormat(cricket::kVp8CodecName));
50 });
51 std::unique_ptr<VideoDecoderFactory> decoder_factory =
Karl Wiberg918f50c2018-07-05 11:40:33 +020052 absl::make_unique<FunctionVideoDecoderFactory>(
Rasmus Brandt0cedc052018-05-31 12:53:00 +020053 []() { return VP8Decoder::Create(); });
54 return CreateSimulcastTestFixture(std::move(encoder_factory),
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020055 std::move(decoder_factory),
56 SdpVideoFormat(cricket::kVp8CodecName));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000057}
58
Rasmus Brandt0cedc052018-05-31 12:53:00 +020059} // namespace
60
61TEST(SimulcastEncoderAdapterSimulcastTest, TestKeyFrameRequestsOnAllStreams) {
62 InternalEncoderFactory internal_encoder_factory;
63 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
64 fixture->TestKeyFrameRequestsOnAllStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000065}
66
Rasmus Brandt0cedc052018-05-31 12:53:00 +020067TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingAllStreams) {
68 InternalEncoderFactory internal_encoder_factory;
69 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
70 fixture->TestPaddingAllStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000071}
72
Rasmus Brandt0cedc052018-05-31 12:53:00 +020073TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingTwoStreams) {
74 InternalEncoderFactory internal_encoder_factory;
75 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
76 fixture->TestPaddingTwoStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000077}
78
Rasmus Brandt0cedc052018-05-31 12:53:00 +020079TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingTwoStreamsOneMaxedOut) {
80 InternalEncoderFactory internal_encoder_factory;
81 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
82 fixture->TestPaddingTwoStreamsOneMaxedOut();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000083}
84
Rasmus Brandt0cedc052018-05-31 12:53:00 +020085TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingOneStream) {
86 InternalEncoderFactory internal_encoder_factory;
87 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
88 fixture->TestPaddingOneStream();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000089}
90
Rasmus Brandt0cedc052018-05-31 12:53:00 +020091TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingOneStreamTwoMaxedOut) {
92 InternalEncoderFactory internal_encoder_factory;
93 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
94 fixture->TestPaddingOneStreamTwoMaxedOut();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000095}
96
Rasmus Brandt0cedc052018-05-31 12:53:00 +020097TEST(SimulcastEncoderAdapterSimulcastTest, TestSendAllStreams) {
98 InternalEncoderFactory internal_encoder_factory;
99 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
100 fixture->TestSendAllStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000101}
102
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200103TEST(SimulcastEncoderAdapterSimulcastTest, TestDisablingStreams) {
104 InternalEncoderFactory internal_encoder_factory;
105 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
106 fixture->TestDisablingStreams();
Seth Hampson46e31ba2018-01-18 10:39:54 -0800107}
108
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200109TEST(SimulcastEncoderAdapterSimulcastTest, TestActiveStreams) {
110 InternalEncoderFactory internal_encoder_factory;
111 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
112 fixture->TestActiveStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000113}
114
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200115TEST(SimulcastEncoderAdapterSimulcastTest, TestSwitchingToOneStream) {
116 InternalEncoderFactory internal_encoder_factory;
117 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
118 fixture->TestSwitchingToOneStream();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000119}
120
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200121TEST(SimulcastEncoderAdapterSimulcastTest, TestSwitchingToOneOddStream) {
122 InternalEncoderFactory internal_encoder_factory;
123 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
124 fixture->TestSwitchingToOneOddStream();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000125}
126
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200127TEST(SimulcastEncoderAdapterSimulcastTest, TestStrideEncodeDecode) {
128 InternalEncoderFactory internal_encoder_factory;
129 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
130 fixture->TestStrideEncodeDecode();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000131}
132
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200133TEST(SimulcastEncoderAdapterSimulcastTest,
134 TestSpatioTemporalLayers333PatternEncoder) {
135 InternalEncoderFactory internal_encoder_factory;
136 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
137 fixture->TestSpatioTemporalLayers333PatternEncoder();
138}
139
140TEST(SimulcastEncoderAdapterSimulcastTest,
141 TestSpatioTemporalLayers321PatternEncoder) {
142 InternalEncoderFactory internal_encoder_factory;
143 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
144 fixture->TestSpatioTemporalLayers321PatternEncoder();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000145}
146
Per Kjellander841c9122018-10-04 18:40:28 +0200147TEST(SimulcastEncoderAdapterSimulcastTest, TestDecodeWidthHeightSet) {
148 InternalEncoderFactory internal_encoder_factory;
149 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
150 fixture->TestDecodeWidthHeightSet();
151}
152
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100153class MockVideoEncoder;
154
155class MockVideoEncoderFactory : public VideoEncoderFactory {
156 public:
157 std::vector<SdpVideoFormat> GetSupportedFormats() const override;
158
159 std::unique_ptr<VideoEncoder> CreateVideoEncoder(
160 const SdpVideoFormat& format) override;
161
162 CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
163
164 const std::vector<MockVideoEncoder*>& encoders() const;
165 void SetEncoderNames(const std::vector<const char*>& encoder_names);
166 void set_init_encode_return_value(int32_t value);
167
168 void DestroyVideoEncoder(VideoEncoder* encoder);
169
170 private:
171 int32_t init_encode_return_value_ = 0;
172 std::vector<MockVideoEncoder*> encoders_;
173 std::vector<const char*> encoder_names_;
174};
175
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000176class MockVideoEncoder : public VideoEncoder {
177 public:
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100178 explicit MockVideoEncoder(MockVideoEncoderFactory* factory)
Erik Språng82fad3d2018-03-21 09:57:23 +0100179 : factory_(factory), callback_(nullptr) {}
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100180
nisseef8b61e2016-04-29 06:09:15 -0700181 // TODO(nisse): Valid overrides commented out, because the gmock
182 // methods don't use any override declarations, and we want to avoid
183 // warnings from -Winconsistent-missing-override. See
184 // http://crbug.com/428099.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000185 int32_t InitEncode(const VideoCodec* codecSettings,
186 int32_t numberOfCores,
nisseef8b61e2016-04-29 06:09:15 -0700187 size_t maxPayloadSize) /* override */ {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000188 codec_ = *codecSettings;
noahrice5ba75a2016-12-12 13:08:27 -0800189 return init_encode_return_value_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000190 }
191
noahricfe3654d2016-07-01 09:05:54 -0700192 MOCK_METHOD3(
193 Encode,
194 int32_t(const VideoFrame& inputImage,
195 const CodecSpecificInfo* codecSpecificInfo,
196 const std::vector<FrameType>* frame_types) /* override */);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000197
pbos65e15ba2015-10-15 10:52:15 -0700198 int32_t RegisterEncodeCompleteCallback(
nisseef8b61e2016-04-29 06:09:15 -0700199 EncodedImageCallback* callback) /* override */ {
Noah Richards41ee1ea2015-04-15 09:24:26 -0700200 callback_ = callback;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000201 return 0;
202 }
203
brandtr5e171752017-05-23 03:32:16 -0700204 MOCK_METHOD0(Release, int32_t());
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000205
Erik Språng566124a2018-04-23 12:32:22 +0200206 int32_t SetRateAllocation(const VideoBitrateAllocation& bitrate_allocation,
Erik Språng08127a92016-11-16 16:41:30 +0100207 uint32_t framerate) {
208 last_set_bitrate_ = bitrate_allocation;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000209 return 0;
210 }
211
philipelcce46fc2015-12-21 03:04:49 -0800212 MOCK_METHOD2(SetChannelParameters, int32_t(uint32_t packetLoss, int64_t rtt));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000213
nisseef8b61e2016-04-29 06:09:15 -0700214 bool SupportsNativeHandle() const /* override */ {
215 return supports_native_handle_;
216 }
pbos65e15ba2015-10-15 10:52:15 -0700217
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100218 virtual ~MockVideoEncoder() { factory_->DestroyVideoEncoder(this); }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000219
220 const VideoCodec& codec() const { return codec_; }
221
Noah Richards41ee1ea2015-04-15 09:24:26 -0700222 void SendEncodedImage(int width, int height) {
223 // Sends a fake image of the given width/height.
224 EncodedImage image;
225 image._encodedWidth = width;
226 image._encodedHeight = height;
sergeyu2cb155a2016-11-04 11:39:29 -0700227 CodecSpecificInfo codec_specific_info;
228 memset(&codec_specific_info, 0, sizeof(codec_specific_info));
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200229 codec_specific_info.codecType = webrtc::kVideoCodecVP8;
brandtr5e171752017-05-23 03:32:16 -0700230 callback_->OnEncodedImage(image, &codec_specific_info, nullptr);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700231 }
232
pbos65e15ba2015-10-15 10:52:15 -0700233 void set_supports_native_handle(bool enabled) {
234 supports_native_handle_ = enabled;
235 }
noahrice5ba75a2016-12-12 13:08:27 -0800236
237 void set_init_encode_return_value(int32_t value) {
238 init_encode_return_value_ = value;
239 }
240
Erik Språng566124a2018-04-23 12:32:22 +0200241 VideoBitrateAllocation last_set_bitrate() const { return last_set_bitrate_; }
pbos65e15ba2015-10-15 10:52:15 -0700242
Peter Boströma5dec162016-01-20 15:53:55 +0100243 MOCK_CONST_METHOD0(ImplementationName, const char*());
244
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000245 private:
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100246 MockVideoEncoderFactory* const factory_;
pbos65e15ba2015-10-15 10:52:15 -0700247 bool supports_native_handle_ = false;
noahrice5ba75a2016-12-12 13:08:27 -0800248 int32_t init_encode_return_value_ = 0;
Erik Språng566124a2018-04-23 12:32:22 +0200249 VideoBitrateAllocation last_set_bitrate_;
noahricfac0ff02016-09-09 10:27:15 -0700250
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000251 VideoCodec codec_;
Noah Richards41ee1ea2015-04-15 09:24:26 -0700252 EncodedImageCallback* callback_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000253};
254
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100255std::vector<SdpVideoFormat> MockVideoEncoderFactory::GetSupportedFormats()
256 const {
257 std::vector<SdpVideoFormat> formats = {SdpVideoFormat("VP8")};
258 return formats;
259}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000260
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100261std::unique_ptr<VideoEncoder> MockVideoEncoderFactory::CreateVideoEncoder(
262 const SdpVideoFormat& format) {
263 std::unique_ptr<MockVideoEncoder> encoder(
264 new ::testing::NiceMock<MockVideoEncoder>(this));
265 encoder->set_init_encode_return_value(init_encode_return_value_);
266 const char* encoder_name = encoder_names_.empty()
267 ? "codec_implementation_name"
268 : encoder_names_[encoders_.size()];
269 ON_CALL(*encoder, ImplementationName()).WillByDefault(Return(encoder_name));
270 encoders_.push_back(encoder.get());
271 return encoder;
272}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000273
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100274void MockVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder* encoder) {
275 for (size_t i = 0; i < encoders_.size(); ++i) {
276 if (encoders_[i] == encoder) {
277 encoders_.erase(encoders_.begin() + i);
278 break;
Zhi Huangaea84f52017-11-16 18:46:27 +0000279 }
Zhi Huangaea84f52017-11-16 18:46:27 +0000280 }
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100281}
Zhi Huangaea84f52017-11-16 18:46:27 +0000282
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100283VideoEncoderFactory::CodecInfo MockVideoEncoderFactory::QueryVideoEncoder(
284 const SdpVideoFormat& format) const {
285 return CodecInfo();
286}
Zhi Huangaea84f52017-11-16 18:46:27 +0000287
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100288const std::vector<MockVideoEncoder*>& MockVideoEncoderFactory::encoders()
289 const {
290 return encoders_;
291}
292void MockVideoEncoderFactory::SetEncoderNames(
293 const std::vector<const char*>& encoder_names) {
294 encoder_names_ = encoder_names;
295}
296void MockVideoEncoderFactory::set_init_encode_return_value(int32_t value) {
297 init_encode_return_value_ = value;
298}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000299
300class TestSimulcastEncoderAdapterFakeHelper {
301 public:
302 TestSimulcastEncoderAdapterFakeHelper()
303 : factory_(new MockVideoEncoderFactory()) {}
304
305 // Can only be called once as the SimulcastEncoderAdapter will take the
306 // ownership of |factory_|.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200307 VideoEncoder* CreateMockEncoderAdapter() {
Ilya Nikolaevskiy97b4ee52018-05-28 10:24:22 +0200308 return new SimulcastEncoderAdapter(factory_.get(), SdpVideoFormat("VP8"));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000309 }
310
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000311 void ExpectCallSetChannelParameters(uint32_t packetLoss, int64_t rtt) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000312 EXPECT_TRUE(!factory_->encoders().empty());
313 for (size_t i = 0; i < factory_->encoders().size(); ++i) {
314 EXPECT_CALL(*factory_->encoders()[i],
philipelcce46fc2015-12-21 03:04:49 -0800315 SetChannelParameters(packetLoss, rtt))
316 .Times(1);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000317 }
318 }
319
magjed6cc25612017-07-10 03:26:36 -0700320 MockVideoEncoderFactory* factory() { return factory_.get(); }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000321
322 private:
magjed6cc25612017-07-10 03:26:36 -0700323 std::unique_ptr<MockVideoEncoderFactory> factory_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000324};
325
326static const int kTestTemporalLayerProfile[3] = {3, 2, 1};
327
Noah Richards41ee1ea2015-04-15 09:24:26 -0700328class TestSimulcastEncoderAdapterFake : public ::testing::Test,
329 public EncodedImageCallback {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000330 public:
331 TestSimulcastEncoderAdapterFake()
Noah Richards41ee1ea2015-04-15 09:24:26 -0700332 : helper_(new TestSimulcastEncoderAdapterFakeHelper()),
333 adapter_(helper_->CreateMockEncoderAdapter()),
334 last_encoded_image_width_(-1),
335 last_encoded_image_height_(-1),
336 last_encoded_image_simulcast_index_(-1) {}
brandtr5e171752017-05-23 03:32:16 -0700337 virtual ~TestSimulcastEncoderAdapterFake() {
338 if (adapter_) {
339 adapter_->Release();
340 }
341 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000342
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700343 Result OnEncodedImage(const EncodedImage& encoded_image,
344 const CodecSpecificInfo* codec_specific_info,
345 const RTPFragmentationHeader* fragmentation) override {
346 last_encoded_image_width_ = encoded_image._encodedWidth;
347 last_encoded_image_height_ = encoded_image._encodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200348 last_encoded_image_simulcast_index_ =
349 encoded_image.SpatialIndex().value_or(-1);
350
Niels Möller72bc8d62018-09-12 10:03:51 +0200351 return Result(Result::OK, encoded_image.Timestamp());
Noah Richards41ee1ea2015-04-15 09:24:26 -0700352 }
353
354 bool GetLastEncodedImageInfo(int* out_width,
355 int* out_height,
356 int* out_simulcast_index) {
357 if (last_encoded_image_width_ == -1) {
358 return false;
359 }
360 *out_width = last_encoded_image_width_;
361 *out_height = last_encoded_image_height_;
362 *out_simulcast_index = last_encoded_image_simulcast_index_;
363 return true;
364 }
365
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000366 void SetupCodec() {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200367 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200368 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
369 kVideoCodecVP8);
Erik Språng82fad3d2018-03-21 09:57:23 +0100370 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000371 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Noah Richards41ee1ea2015-04-15 09:24:26 -0700372 adapter_->RegisterEncodeCompleteCallback(this);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000373 }
374
375 void VerifyCodec(const VideoCodec& ref, int stream_index) {
376 const VideoCodec& target =
377 helper_->factory()->encoders()[stream_index]->codec();
378 EXPECT_EQ(ref.codecType, target.codecType);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000379 EXPECT_EQ(ref.plType, target.plType);
380 EXPECT_EQ(ref.width, target.width);
381 EXPECT_EQ(ref.height, target.height);
382 EXPECT_EQ(ref.startBitrate, target.startBitrate);
383 EXPECT_EQ(ref.maxBitrate, target.maxBitrate);
384 EXPECT_EQ(ref.minBitrate, target.minBitrate);
385 EXPECT_EQ(ref.maxFramerate, target.maxFramerate);
hta257dc392016-10-25 09:05:06 -0700386 EXPECT_EQ(ref.VP8().complexity, target.VP8().complexity);
hta257dc392016-10-25 09:05:06 -0700387 EXPECT_EQ(ref.VP8().numberOfTemporalLayers,
388 target.VP8().numberOfTemporalLayers);
389 EXPECT_EQ(ref.VP8().denoisingOn, target.VP8().denoisingOn);
hta257dc392016-10-25 09:05:06 -0700390 EXPECT_EQ(ref.VP8().automaticResizeOn, target.VP8().automaticResizeOn);
391 EXPECT_EQ(ref.VP8().frameDroppingOn, target.VP8().frameDroppingOn);
392 EXPECT_EQ(ref.VP8().keyFrameInterval, target.VP8().keyFrameInterval);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000393 EXPECT_EQ(ref.qpMax, target.qpMax);
394 EXPECT_EQ(0, target.numberOfSimulcastStreams);
395 EXPECT_EQ(ref.mode, target.mode);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000396
397 // No need to compare simulcastStream as numberOfSimulcastStreams should
398 // always be 0.
399 }
400
401 void InitRefCodec(int stream_index, VideoCodec* ref_codec) {
402 *ref_codec = codec_;
hta257dc392016-10-25 09:05:06 -0700403 ref_codec->VP8()->numberOfTemporalLayers =
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000404 kTestTemporalLayerProfile[stream_index];
405 ref_codec->width = codec_.simulcastStream[stream_index].width;
406 ref_codec->height = codec_.simulcastStream[stream_index].height;
407 ref_codec->maxBitrate = codec_.simulcastStream[stream_index].maxBitrate;
408 ref_codec->minBitrate = codec_.simulcastStream[stream_index].minBitrate;
409 ref_codec->qpMax = codec_.simulcastStream[stream_index].qpMax;
410 }
411
412 void VerifyCodecSettings() {
413 EXPECT_EQ(3u, helper_->factory()->encoders().size());
414 VideoCodec ref_codec;
415
416 // stream 0, the lowest resolution stream.
417 InitRefCodec(0, &ref_codec);
418 ref_codec.qpMax = 45;
Niels Möllere3cf3d02018-06-13 11:52:16 +0200419 ref_codec.VP8()->complexity =
420 webrtc::VideoCodecComplexity::kComplexityHigher;
hta257dc392016-10-25 09:05:06 -0700421 ref_codec.VP8()->denoisingOn = false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000422 ref_codec.startBitrate = 100; // Should equal to the target bitrate.
423 VerifyCodec(ref_codec, 0);
424
425 // stream 1
426 InitRefCodec(1, &ref_codec);
hta257dc392016-10-25 09:05:06 -0700427 ref_codec.VP8()->denoisingOn = false;
Noah Richards67b635a2015-05-22 14:12:10 -0700428 // The start bitrate (300kbit) minus what we have for the lower layers
429 // (100kbit).
430 ref_codec.startBitrate = 200;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000431 VerifyCodec(ref_codec, 1);
432
433 // stream 2, the biggest resolution stream.
434 InitRefCodec(2, &ref_codec);
Noah Richards67b635a2015-05-22 14:12:10 -0700435 // We don't have enough bits to send this, so the adapter should have
436 // configured it to use the min bitrate for this layer (600kbit) but turn
437 // off sending.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000438 ref_codec.startBitrate = 600;
439 VerifyCodec(ref_codec, 2);
440 }
441
442 protected:
kwiberg3f55dea2016-02-29 05:51:59 -0800443 std::unique_ptr<TestSimulcastEncoderAdapterFakeHelper> helper_;
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200444 std::unique_ptr<VideoEncoder> adapter_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000445 VideoCodec codec_;
Noah Richards41ee1ea2015-04-15 09:24:26 -0700446 int last_encoded_image_width_;
447 int last_encoded_image_height_;
448 int last_encoded_image_simulcast_index_;
Erik Språng08127a92016-11-16 16:41:30 +0100449 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000450};
451
452TEST_F(TestSimulcastEncoderAdapterFake, InitEncode) {
453 SetupCodec();
454 VerifyCodecSettings();
455}
456
brandtr5e171752017-05-23 03:32:16 -0700457TEST_F(TestSimulcastEncoderAdapterFake, ReleaseWithoutInitEncode) {
458 EXPECT_EQ(0, adapter_->Release());
459}
460
461TEST_F(TestSimulcastEncoderAdapterFake, Reinit) {
462 SetupCodec();
463 EXPECT_EQ(0, adapter_->Release());
464
465 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
466}
467
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000468TEST_F(TestSimulcastEncoderAdapterFake, SetChannelParameters) {
469 SetupCodec();
470 const uint32_t packetLoss = 5;
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000471 const int64_t rtt = 30;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000472 helper_->ExpectCallSetChannelParameters(packetLoss, rtt);
473 adapter_->SetChannelParameters(packetLoss, rtt);
474}
475
Noah Richards41ee1ea2015-04-15 09:24:26 -0700476TEST_F(TestSimulcastEncoderAdapterFake, EncodedCallbackForDifferentEncoders) {
477 SetupCodec();
478
Peter Boström5d0379d2015-10-06 14:04:51 +0200479 // Set bitrates so that we send all layers.
Erik Språng08127a92016-11-16 16:41:30 +0100480 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
Peter Boström5d0379d2015-10-06 14:04:51 +0200481
Noah Richards41ee1ea2015-04-15 09:24:26 -0700482 // At this point, the simulcast encoder adapter should have 3 streams: HD,
483 // quarter HD, and quarter quarter HD. We're going to mostly ignore the exact
484 // resolutions, to test that the adapter forwards on the correct resolution
485 // and simulcast index values, going only off the encoder that generates the
486 // image.
brandtr5e171752017-05-23 03:32:16 -0700487 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
488 ASSERT_EQ(3u, encoders.size());
489 encoders[0]->SendEncodedImage(1152, 704);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700490 int width;
491 int height;
492 int simulcast_index;
493 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
494 EXPECT_EQ(1152, width);
495 EXPECT_EQ(704, height);
496 EXPECT_EQ(0, simulcast_index);
497
brandtr5e171752017-05-23 03:32:16 -0700498 encoders[1]->SendEncodedImage(300, 620);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700499 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
500 EXPECT_EQ(300, width);
501 EXPECT_EQ(620, height);
502 EXPECT_EQ(1, simulcast_index);
503
brandtr5e171752017-05-23 03:32:16 -0700504 encoders[2]->SendEncodedImage(120, 240);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700505 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
506 EXPECT_EQ(120, width);
507 EXPECT_EQ(240, height);
508 EXPECT_EQ(2, simulcast_index);
509}
510
brandtr5e171752017-05-23 03:32:16 -0700511// This test verifies that the underlying encoders are reused, when the adapter
512// is reinited with different number of simulcast streams. It further checks
513// that the allocated encoders are reused in the same order as before, starting
514// with the lowest stream.
515TEST_F(TestSimulcastEncoderAdapterFake, ReusesEncodersInOrder) {
516 // Set up common settings for three streams.
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200517 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200518 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
519 kVideoCodecVP8);
Erik Språng82fad3d2018-03-21 09:57:23 +0100520 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
brandtr5e171752017-05-23 03:32:16 -0700521 adapter_->RegisterEncodeCompleteCallback(this);
Erik Språng7d687b12018-09-12 17:04:10 +0200522 const uint32_t target_bitrate =
523 1000 * (codec_.simulcastStream[0].targetBitrate +
524 codec_.simulcastStream[1].targetBitrate +
525 codec_.simulcastStream[2].minBitrate);
brandtr5e171752017-05-23 03:32:16 -0700526
527 // Input data.
528 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
529 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
530 std::vector<FrameType> frame_types;
531
532 // Encode with three streams.
533 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
534 VerifyCodecSettings();
Erik Språng7d687b12018-09-12 17:04:10 +0200535 adapter_->SetRateAllocation(
536 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
537
brandtr5e171752017-05-23 03:32:16 -0700538 std::vector<MockVideoEncoder*> original_encoders =
539 helper_->factory()->encoders();
540 ASSERT_EQ(3u, original_encoders.size());
541 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
542 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
543 EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
544 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
545 EXPECT_CALL(*original_encoders[2], Encode(_, _, _))
546 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
547 frame_types.resize(3, kVideoFrameKey);
548 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
549 EXPECT_CALL(*original_encoders[0], Release())
550 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
551 EXPECT_CALL(*original_encoders[1], Release())
552 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
553 EXPECT_CALL(*original_encoders[2], Release())
554 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
555 EXPECT_EQ(0, adapter_->Release());
556
557 // Encode with two streams.
558 codec_.width /= 2;
559 codec_.height /= 2;
560 codec_.numberOfSimulcastStreams = 2;
561 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200562 adapter_->SetRateAllocation(
563 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700564 std::vector<MockVideoEncoder*> new_encoders = helper_->factory()->encoders();
565 ASSERT_EQ(2u, new_encoders.size());
566 ASSERT_EQ(original_encoders[0], new_encoders[0]);
567 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
568 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
569 ASSERT_EQ(original_encoders[1], new_encoders[1]);
570 EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
571 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
572 frame_types.resize(2, kVideoFrameKey);
573 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
574 EXPECT_CALL(*original_encoders[0], Release())
575 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
576 EXPECT_CALL(*original_encoders[1], Release())
577 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
578 EXPECT_EQ(0, adapter_->Release());
579
580 // Encode with single stream.
581 codec_.width /= 2;
582 codec_.height /= 2;
583 codec_.numberOfSimulcastStreams = 1;
584 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200585 adapter_->SetRateAllocation(
586 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700587 new_encoders = helper_->factory()->encoders();
588 ASSERT_EQ(1u, new_encoders.size());
589 ASSERT_EQ(original_encoders[0], new_encoders[0]);
590 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
591 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
592 frame_types.resize(1, kVideoFrameKey);
593 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
594 EXPECT_CALL(*original_encoders[0], Release())
595 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
596 EXPECT_EQ(0, adapter_->Release());
597
598 // Encode with three streams, again.
599 codec_.width *= 4;
600 codec_.height *= 4;
601 codec_.numberOfSimulcastStreams = 3;
602 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200603 adapter_->SetRateAllocation(
604 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700605 new_encoders = helper_->factory()->encoders();
606 ASSERT_EQ(3u, new_encoders.size());
607 // The first encoder is reused.
608 ASSERT_EQ(original_encoders[0], new_encoders[0]);
609 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
610 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
611 // The second and third encoders are new.
612 EXPECT_CALL(*new_encoders[1], Encode(_, _, _))
613 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
614 EXPECT_CALL(*new_encoders[2], Encode(_, _, _))
615 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
616 frame_types.resize(3, kVideoFrameKey);
617 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
618 EXPECT_CALL(*original_encoders[0], Release())
619 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
620 EXPECT_CALL(*new_encoders[1], Release())
621 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
622 EXPECT_CALL(*new_encoders[2], Release())
623 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
624 EXPECT_EQ(0, adapter_->Release());
625}
626
627TEST_F(TestSimulcastEncoderAdapterFake, DoesNotLeakEncoders) {
628 SetupCodec();
629 VerifyCodecSettings();
630
631 EXPECT_EQ(3u, helper_->factory()->encoders().size());
632
633 // The adapter should destroy all encoders it has allocated. Since
634 // |helper_->factory()| is owned by |adapter_|, however, we need to rely on
635 // lsan to find leaks here.
636 EXPECT_EQ(0, adapter_->Release());
637 adapter_.reset();
638}
639
640// This test verifies that an adapter reinit with the same codec settings as
641// before does not change the underlying encoder codec settings.
642TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderEncoderSettings) {
643 SetupCodec();
644 VerifyCodecSettings();
645
646 // Capture current codec settings.
647 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
648 ASSERT_EQ(3u, encoders.size());
649 std::array<VideoCodec, 3> codecs_before;
650 for (int i = 0; i < 3; ++i) {
651 codecs_before[i] = encoders[i]->codec();
652 }
653
654 // Reinitialize and verify that the new codec settings are the same.
655 EXPECT_EQ(0, adapter_->Release());
656 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
657 for (int i = 0; i < 3; ++i) {
658 const VideoCodec& codec_before = codecs_before[i];
659 const VideoCodec& codec_after = encoders[i]->codec();
660
661 // webrtc::VideoCodec does not implement operator==.
662 EXPECT_EQ(codec_before.codecType, codec_after.codecType);
663 EXPECT_EQ(codec_before.plType, codec_after.plType);
664 EXPECT_EQ(codec_before.width, codec_after.width);
665 EXPECT_EQ(codec_before.height, codec_after.height);
666 EXPECT_EQ(codec_before.startBitrate, codec_after.startBitrate);
667 EXPECT_EQ(codec_before.maxBitrate, codec_after.maxBitrate);
668 EXPECT_EQ(codec_before.minBitrate, codec_after.minBitrate);
669 EXPECT_EQ(codec_before.targetBitrate, codec_after.targetBitrate);
670 EXPECT_EQ(codec_before.maxFramerate, codec_after.maxFramerate);
671 EXPECT_EQ(codec_before.qpMax, codec_after.qpMax);
672 EXPECT_EQ(codec_before.numberOfSimulcastStreams,
673 codec_after.numberOfSimulcastStreams);
674 EXPECT_EQ(codec_before.mode, codec_after.mode);
675 EXPECT_EQ(codec_before.expect_encode_from_texture,
676 codec_after.expect_encode_from_texture);
677 }
678}
679
680// This test is similar to the one above, except that it tests the simulcastIdx
681// from the CodecSpecificInfo that is connected to an encoded frame. The
682// PayloadRouter demuxes the incoming encoded frames on different RTP modules
683// using the simulcastIdx, so it's important that there is no corresponding
684// encoder reordering in between adapter reinits as this would lead to PictureID
685// discontinuities.
686TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderFrameSimulcastIdx) {
687 SetupCodec();
688 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
689 VerifyCodecSettings();
690
691 // Send frames on all streams.
692 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
693 ASSERT_EQ(3u, encoders.size());
694 encoders[0]->SendEncodedImage(1152, 704);
695 int width;
696 int height;
697 int simulcast_index;
698 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
699 EXPECT_EQ(0, simulcast_index);
700
701 encoders[1]->SendEncodedImage(300, 620);
702 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
703 EXPECT_EQ(1, simulcast_index);
704
705 encoders[2]->SendEncodedImage(120, 240);
706 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
707 EXPECT_EQ(2, simulcast_index);
708
709 // Reinitialize.
710 EXPECT_EQ(0, adapter_->Release());
711 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
712 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
713
714 // Verify that the same encoder sends out frames on the same simulcast index.
715 encoders[0]->SendEncodedImage(1152, 704);
716 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
717 EXPECT_EQ(0, simulcast_index);
718
719 encoders[1]->SendEncodedImage(300, 620);
720 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
721 EXPECT_EQ(1, simulcast_index);
722
723 encoders[2]->SendEncodedImage(120, 240);
724 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
725 EXPECT_EQ(2, simulcast_index);
726}
727
pbos65e15ba2015-10-15 10:52:15 -0700728TEST_F(TestSimulcastEncoderAdapterFake, SupportsNativeHandleForSingleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200729 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200730 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
731 kVideoCodecVP8);
pbos65e15ba2015-10-15 10:52:15 -0700732 codec_.numberOfSimulcastStreams = 1;
733 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
734 adapter_->RegisterEncodeCompleteCallback(this);
735 ASSERT_EQ(1u, helper_->factory()->encoders().size());
736 helper_->factory()->encoders()[0]->set_supports_native_handle(true);
737 EXPECT_TRUE(adapter_->SupportsNativeHandle());
738 helper_->factory()->encoders()[0]->set_supports_native_handle(false);
739 EXPECT_FALSE(adapter_->SupportsNativeHandle());
740}
741
noahricfac0ff02016-09-09 10:27:15 -0700742TEST_F(TestSimulcastEncoderAdapterFake, SetRatesUnderMinBitrate) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200743 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200744 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
745 kVideoCodecVP8);
noahricfac0ff02016-09-09 10:27:15 -0700746 codec_.minBitrate = 50;
747 codec_.numberOfSimulcastStreams = 1;
748 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng82fad3d2018-03-21 09:57:23 +0100749 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
noahricfac0ff02016-09-09 10:27:15 -0700750
751 // Above min should be respected.
Erik Språng566124a2018-04-23 12:32:22 +0200752 VideoBitrateAllocation target_bitrate =
Erik Språng08127a92016-11-16 16:41:30 +0100753 rate_allocator_->GetAllocation(codec_.minBitrate * 1000, 30);
754 adapter_->SetRateAllocation(target_bitrate, 30);
755 EXPECT_EQ(target_bitrate,
756 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700757
758 // Below min but non-zero should be replaced with the min bitrate.
Erik Språng566124a2018-04-23 12:32:22 +0200759 VideoBitrateAllocation too_low_bitrate =
Erik Språng08127a92016-11-16 16:41:30 +0100760 rate_allocator_->GetAllocation((codec_.minBitrate - 1) * 1000, 30);
761 adapter_->SetRateAllocation(too_low_bitrate, 30);
762 EXPECT_EQ(target_bitrate,
763 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700764
765 // Zero should be passed on as is, since it means "pause".
Erik Språng566124a2018-04-23 12:32:22 +0200766 adapter_->SetRateAllocation(VideoBitrateAllocation(), 30);
767 EXPECT_EQ(VideoBitrateAllocation(),
Erik Språng08127a92016-11-16 16:41:30 +0100768 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700769}
770
Peter Boströma5dec162016-01-20 15:53:55 +0100771TEST_F(TestSimulcastEncoderAdapterFake, SupportsImplementationName) {
772 EXPECT_STREQ("SimulcastEncoderAdapter", adapter_->ImplementationName());
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200773 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200774 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
775 kVideoCodecVP8);
Peter Boströma5dec162016-01-20 15:53:55 +0100776 std::vector<const char*> encoder_names;
777 encoder_names.push_back("codec1");
778 encoder_names.push_back("codec2");
779 encoder_names.push_back("codec3");
780 helper_->factory()->SetEncoderNames(encoder_names);
781 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
782 EXPECT_STREQ("SimulcastEncoderAdapter (codec1, codec2, codec3)",
783 adapter_->ImplementationName());
Peter Boströmd53c3892016-03-30 17:03:52 +0200784
785 // Single streams should not expose "SimulcastEncoderAdapter" in name.
brandtr5e171752017-05-23 03:32:16 -0700786 EXPECT_EQ(0, adapter_->Release());
Peter Boströmd53c3892016-03-30 17:03:52 +0200787 codec_.numberOfSimulcastStreams = 1;
788 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
789 adapter_->RegisterEncodeCompleteCallback(this);
790 ASSERT_EQ(1u, helper_->factory()->encoders().size());
791 EXPECT_STREQ("codec1", adapter_->ImplementationName());
Peter Boströma5dec162016-01-20 15:53:55 +0100792}
793
pbos65e15ba2015-10-15 10:52:15 -0700794TEST_F(TestSimulcastEncoderAdapterFake,
noahricfe3654d2016-07-01 09:05:54 -0700795 SupportsNativeHandleForMultipleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200796 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200797 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
798 kVideoCodecVP8);
pbos65e15ba2015-10-15 10:52:15 -0700799 codec_.numberOfSimulcastStreams = 3;
800 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
801 adapter_->RegisterEncodeCompleteCallback(this);
802 ASSERT_EQ(3u, helper_->factory()->encoders().size());
803 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
804 encoder->set_supports_native_handle(true);
noahricfe3654d2016-07-01 09:05:54 -0700805 // If one encoder doesn't support it, then overall support is disabled.
806 helper_->factory()->encoders()[0]->set_supports_native_handle(false);
pbos65e15ba2015-10-15 10:52:15 -0700807 EXPECT_FALSE(adapter_->SupportsNativeHandle());
noahricfe3654d2016-07-01 09:05:54 -0700808 // Once all do, then the adapter claims support.
809 helper_->factory()->encoders()[0]->set_supports_native_handle(true);
810 EXPECT_TRUE(adapter_->SupportsNativeHandle());
811}
812
nisseaf916892017-01-10 07:44:26 -0800813// TODO(nisse): Reuse definition in webrtc/test/fake_texture_handle.h.
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200814class FakeNativeBufferNoI420 : public VideoFrameBuffer {
noahricfe3654d2016-07-01 09:05:54 -0700815 public:
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200816 FakeNativeBufferNoI420(int width, int height)
817 : width_(width), height_(height) {}
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000818
819 Type type() const override { return Type::kNative; }
820 int width() const override { return width_; }
821 int height() const override { return height_; }
822
823 rtc::scoped_refptr<I420BufferInterface> ToI420() override {
noahricfe3654d2016-07-01 09:05:54 -0700824 RTC_NOTREACHED();
825 return nullptr;
826 }
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000827
828 private:
829 const int width_;
830 const int height_;
noahricfe3654d2016-07-01 09:05:54 -0700831};
832
833TEST_F(TestSimulcastEncoderAdapterFake,
834 NativeHandleForwardingForMultipleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200835 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200836 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
837 kVideoCodecVP8);
noahricfe3654d2016-07-01 09:05:54 -0700838 codec_.numberOfSimulcastStreams = 3;
839 // High start bitrate, so all streams are enabled.
840 codec_.startBitrate = 3000;
841 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
842 adapter_->RegisterEncodeCompleteCallback(this);
843 ASSERT_EQ(3u, helper_->factory()->encoders().size());
844 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
845 encoder->set_supports_native_handle(true);
846 EXPECT_TRUE(adapter_->SupportsNativeHandle());
847
848 rtc::scoped_refptr<VideoFrameBuffer> buffer(
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200849 new rtc::RefCountedObject<FakeNativeBufferNoI420>(1280, 720));
noahricfe3654d2016-07-01 09:05:54 -0700850 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
851 // Expect calls with the given video frame verbatim, since it's a texture
852 // frame and can't otherwise be modified/resized.
853 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
854 EXPECT_CALL(*encoder, Encode(::testing::Ref(input_frame), _, _)).Times(1);
855 std::vector<FrameType> frame_types(3, kVideoFrameKey);
brandtr5e171752017-05-23 03:32:16 -0700856 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
pbos65e15ba2015-10-15 10:52:15 -0700857}
858
noahric57779102016-05-25 06:48:46 -0700859TEST_F(TestSimulcastEncoderAdapterFake, TestFailureReturnCodesFromEncodeCalls) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200860 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200861 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
862 kVideoCodecVP8);
noahric57779102016-05-25 06:48:46 -0700863 codec_.numberOfSimulcastStreams = 3;
864 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
865 adapter_->RegisterEncodeCompleteCallback(this);
866 ASSERT_EQ(3u, helper_->factory()->encoders().size());
867 // Tell the 2nd encoder to request software fallback.
noahricfe3654d2016-07-01 09:05:54 -0700868 EXPECT_CALL(*helper_->factory()->encoders()[1], Encode(_, _, _))
869 .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
noahric57779102016-05-25 06:48:46 -0700870
871 // Send a fake frame and assert the return is software fallback.
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000872 rtc::scoped_refptr<I420Buffer> input_buffer =
873 I420Buffer::Create(kDefaultWidth, kDefaultHeight);
nisse64ec8f82016-09-27 00:17:25 -0700874 input_buffer->InitializeData();
875 VideoFrame input_frame(input_buffer, 0, 0, webrtc::kVideoRotation_0);
noahric57779102016-05-25 06:48:46 -0700876 std::vector<FrameType> frame_types(3, kVideoFrameKey);
877 EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
878 adapter_->Encode(input_frame, nullptr, &frame_types));
879}
880
noahrice5ba75a2016-12-12 13:08:27 -0800881TEST_F(TestSimulcastEncoderAdapterFake, TestInitFailureCleansUpEncoders) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200882 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200883 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
884 kVideoCodecVP8);
noahrice5ba75a2016-12-12 13:08:27 -0800885 codec_.numberOfSimulcastStreams = 3;
886 helper_->factory()->set_init_encode_return_value(
887 WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
888 EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
889 adapter_->InitEncode(&codec_, 1, 1200));
890 EXPECT_TRUE(helper_->factory()->encoders().empty());
891}
892
Erik Språng8d2995b2018-08-09 11:18:17 +0200893TEST_F(TestSimulcastEncoderAdapterFake, DoesNotAlterMaxQpForScreenshare) {
894 const int kHighMaxQp = 56;
895 const int kLowMaxQp = 46;
896
897 SimulcastTestFixtureImpl::DefaultSettings(
898 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
899 kVideoCodecVP8);
900 codec_.numberOfSimulcastStreams = 3;
901 codec_.simulcastStream[0].qpMax = kHighMaxQp;
902 codec_.mode = VideoCodecMode::kScreensharing;
903
904 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
905 EXPECT_EQ(3u, helper_->factory()->encoders().size());
906
907 // Just check the lowest stream, which is the one that where the adapter
908 // might alter the max qp setting.
909 VideoCodec ref_codec;
910 InitRefCodec(0, &ref_codec);
911 ref_codec.qpMax = kHighMaxQp;
912 ref_codec.VP8()->complexity = webrtc::VideoCodecComplexity::kComplexityHigher;
913 ref_codec.VP8()->denoisingOn = false;
914 ref_codec.startBitrate = 100; // Should equal to the target bitrate.
915 VerifyCodec(ref_codec, 0);
916
917 // Change the max qp and try again.
918 codec_.simulcastStream[0].qpMax = kLowMaxQp;
919 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
920 EXPECT_EQ(3u, helper_->factory()->encoders().size());
921 ref_codec.qpMax = kLowMaxQp;
922 VerifyCodec(ref_codec, 0);
923}
Erik Språng7d687b12018-09-12 17:04:10 +0200924
925TEST_F(TestSimulcastEncoderAdapterFake, ActivatesCorrectStreamsInInitEncode) {
926 // Set up common settings for three streams.
927 SimulcastTestFixtureImpl::DefaultSettings(
928 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
929 kVideoCodecVP8);
930 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
931 adapter_->RegisterEncodeCompleteCallback(this);
932
933 // Only enough start bitrate for the lowest stream.
934 ASSERT_EQ(3u, codec_.numberOfSimulcastStreams);
935 codec_.startBitrate = codec_.simulcastStream[0].targetBitrate +
936 codec_.simulcastStream[1].minBitrate - 1;
937
938 // Input data.
939 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
940 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
941
942 // Encode with three streams.
943 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
944 std::vector<MockVideoEncoder*> original_encoders =
945 helper_->factory()->encoders();
946 ASSERT_EQ(3u, original_encoders.size());
947 // Only first encoder will be active and called.
948 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
949 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
950 EXPECT_CALL(*original_encoders[1], Encode(_, _, _)).Times(0);
951 EXPECT_CALL(*original_encoders[2], Encode(_, _, _)).Times(0);
952
953 std::vector<FrameType> frame_types;
954 frame_types.resize(3, kVideoFrameKey);
955 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
956}
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200957} // namespace test
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000958} // namespace webrtc