blob: 206c70570de569805652c34936e53ac72a6367fd [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"
Danil Chapovalov99b71df2018-10-26 15:57:48 +020018#include "api/test/video/function_video_decoder_factory.h"
19#include "api/test/video/function_video_encoder_factory.h"
Magnus Jedvertdf4883d2017-11-17 14:44:55 +010020#include "api/video_codecs/sdp_video_format.h"
21#include "api/video_codecs/video_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "common_video/include/video_frame_buffer.h"
Jonathan Yu9a5da492018-10-19 00:51:18 -070023#include "media/base/mediaconstants.h"
Magnus Jedvert46a27652017-11-13 14:10:02 +010024#include "media/engine/internalencoderfactory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "media/engine/simulcast_encoder_adapter.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020026#include "modules/video_coding/codecs/vp8/include/vp8.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "modules/video_coding/include/video_codec_interface.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020028#include "modules/video_coding/utility/simulcast_test_fixture_impl.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "test/gmock.h"
Rasmus Brandt0cedc052018-05-31 12:53:00 +020030#include "test/gtest.h"
31
32using ::testing::_;
33using ::testing::Return;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000034
35namespace webrtc {
Rasmus Brandt0cedc052018-05-31 12:53:00 +020036namespace test {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000037
Rasmus Brandt0cedc052018-05-31 12:53:00 +020038namespace {
philipelcce46fc2015-12-21 03:04:49 -080039
Rasmus Brandt0cedc052018-05-31 12:53:00 +020040constexpr int kDefaultWidth = 1280;
41constexpr int kDefaultHeight = 720;
magjed6cc25612017-07-10 03:26:36 -070042
Rasmus Brandt0cedc052018-05-31 12:53:00 +020043std::unique_ptr<SimulcastTestFixture> CreateSpecificSimulcastTestFixture(
44 VideoEncoderFactory* internal_encoder_factory) {
45 std::unique_ptr<VideoEncoderFactory> encoder_factory =
Karl Wiberg918f50c2018-07-05 11:40:33 +020046 absl::make_unique<FunctionVideoEncoderFactory>(
Rasmus Brandt0cedc052018-05-31 12:53:00 +020047 [internal_encoder_factory]() {
Karl Wiberg918f50c2018-07-05 11:40:33 +020048 return absl::make_unique<SimulcastEncoderAdapter>(
Rasmus Brandt0cedc052018-05-31 12:53:00 +020049 internal_encoder_factory,
50 SdpVideoFormat(cricket::kVp8CodecName));
51 });
52 std::unique_ptr<VideoDecoderFactory> decoder_factory =
Karl Wiberg918f50c2018-07-05 11:40:33 +020053 absl::make_unique<FunctionVideoDecoderFactory>(
Rasmus Brandt0cedc052018-05-31 12:53:00 +020054 []() { return VP8Decoder::Create(); });
55 return CreateSimulcastTestFixture(std::move(encoder_factory),
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020056 std::move(decoder_factory),
57 SdpVideoFormat(cricket::kVp8CodecName));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000058}
59
Rasmus Brandt0cedc052018-05-31 12:53:00 +020060} // namespace
61
62TEST(SimulcastEncoderAdapterSimulcastTest, TestKeyFrameRequestsOnAllStreams) {
63 InternalEncoderFactory internal_encoder_factory;
64 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
65 fixture->TestKeyFrameRequestsOnAllStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000066}
67
Rasmus Brandt0cedc052018-05-31 12:53:00 +020068TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingAllStreams) {
69 InternalEncoderFactory internal_encoder_factory;
70 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
71 fixture->TestPaddingAllStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000072}
73
Rasmus Brandt0cedc052018-05-31 12:53:00 +020074TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingTwoStreams) {
75 InternalEncoderFactory internal_encoder_factory;
76 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
77 fixture->TestPaddingTwoStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000078}
79
Rasmus Brandt0cedc052018-05-31 12:53:00 +020080TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingTwoStreamsOneMaxedOut) {
81 InternalEncoderFactory internal_encoder_factory;
82 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
83 fixture->TestPaddingTwoStreamsOneMaxedOut();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000084}
85
Rasmus Brandt0cedc052018-05-31 12:53:00 +020086TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingOneStream) {
87 InternalEncoderFactory internal_encoder_factory;
88 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
89 fixture->TestPaddingOneStream();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000090}
91
Rasmus Brandt0cedc052018-05-31 12:53:00 +020092TEST(SimulcastEncoderAdapterSimulcastTest, TestPaddingOneStreamTwoMaxedOut) {
93 InternalEncoderFactory internal_encoder_factory;
94 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
95 fixture->TestPaddingOneStreamTwoMaxedOut();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +000096}
97
Rasmus Brandt0cedc052018-05-31 12:53:00 +020098TEST(SimulcastEncoderAdapterSimulcastTest, TestSendAllStreams) {
99 InternalEncoderFactory internal_encoder_factory;
100 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
101 fixture->TestSendAllStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000102}
103
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200104TEST(SimulcastEncoderAdapterSimulcastTest, TestDisablingStreams) {
105 InternalEncoderFactory internal_encoder_factory;
106 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
107 fixture->TestDisablingStreams();
Seth Hampson46e31ba2018-01-18 10:39:54 -0800108}
109
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200110TEST(SimulcastEncoderAdapterSimulcastTest, TestActiveStreams) {
111 InternalEncoderFactory internal_encoder_factory;
112 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
113 fixture->TestActiveStreams();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000114}
115
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200116TEST(SimulcastEncoderAdapterSimulcastTest, TestSwitchingToOneStream) {
117 InternalEncoderFactory internal_encoder_factory;
118 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
119 fixture->TestSwitchingToOneStream();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000120}
121
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200122TEST(SimulcastEncoderAdapterSimulcastTest, TestSwitchingToOneOddStream) {
123 InternalEncoderFactory internal_encoder_factory;
124 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
125 fixture->TestSwitchingToOneOddStream();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000126}
127
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200128TEST(SimulcastEncoderAdapterSimulcastTest, TestStrideEncodeDecode) {
129 InternalEncoderFactory internal_encoder_factory;
130 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
131 fixture->TestStrideEncodeDecode();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000132}
133
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200134TEST(SimulcastEncoderAdapterSimulcastTest,
135 TestSpatioTemporalLayers333PatternEncoder) {
136 InternalEncoderFactory internal_encoder_factory;
137 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
138 fixture->TestSpatioTemporalLayers333PatternEncoder();
139}
140
141TEST(SimulcastEncoderAdapterSimulcastTest,
142 TestSpatioTemporalLayers321PatternEncoder) {
143 InternalEncoderFactory internal_encoder_factory;
144 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
145 fixture->TestSpatioTemporalLayers321PatternEncoder();
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000146}
147
Per Kjellander841c9122018-10-04 18:40:28 +0200148TEST(SimulcastEncoderAdapterSimulcastTest, TestDecodeWidthHeightSet) {
149 InternalEncoderFactory internal_encoder_factory;
150 auto fixture = CreateSpecificSimulcastTestFixture(&internal_encoder_factory);
151 fixture->TestDecodeWidthHeightSet();
152}
153
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100154class MockVideoEncoder;
155
156class MockVideoEncoderFactory : public VideoEncoderFactory {
157 public:
158 std::vector<SdpVideoFormat> GetSupportedFormats() const override;
159
160 std::unique_ptr<VideoEncoder> CreateVideoEncoder(
161 const SdpVideoFormat& format) override;
162
163 CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
164
165 const std::vector<MockVideoEncoder*>& encoders() const;
166 void SetEncoderNames(const std::vector<const char*>& encoder_names);
167 void set_init_encode_return_value(int32_t value);
168
169 void DestroyVideoEncoder(VideoEncoder* encoder);
170
171 private:
172 int32_t init_encode_return_value_ = 0;
173 std::vector<MockVideoEncoder*> encoders_;
174 std::vector<const char*> encoder_names_;
175};
176
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000177class MockVideoEncoder : public VideoEncoder {
178 public:
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100179 explicit MockVideoEncoder(MockVideoEncoderFactory* factory)
Erik Språng82fad3d2018-03-21 09:57:23 +0100180 : factory_(factory), callback_(nullptr) {}
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100181
nisseef8b61e2016-04-29 06:09:15 -0700182 // TODO(nisse): Valid overrides commented out, because the gmock
183 // methods don't use any override declarations, and we want to avoid
184 // warnings from -Winconsistent-missing-override. See
185 // http://crbug.com/428099.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000186 int32_t InitEncode(const VideoCodec* codecSettings,
187 int32_t numberOfCores,
nisseef8b61e2016-04-29 06:09:15 -0700188 size_t maxPayloadSize) /* override */ {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000189 codec_ = *codecSettings;
noahrice5ba75a2016-12-12 13:08:27 -0800190 return init_encode_return_value_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000191 }
192
noahricfe3654d2016-07-01 09:05:54 -0700193 MOCK_METHOD3(
194 Encode,
195 int32_t(const VideoFrame& inputImage,
196 const CodecSpecificInfo* codecSpecificInfo,
197 const std::vector<FrameType>* frame_types) /* override */);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000198
pbos65e15ba2015-10-15 10:52:15 -0700199 int32_t RegisterEncodeCompleteCallback(
nisseef8b61e2016-04-29 06:09:15 -0700200 EncodedImageCallback* callback) /* override */ {
Noah Richards41ee1ea2015-04-15 09:24:26 -0700201 callback_ = callback;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000202 return 0;
203 }
204
brandtr5e171752017-05-23 03:32:16 -0700205 MOCK_METHOD0(Release, int32_t());
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000206
Erik Språng566124a2018-04-23 12:32:22 +0200207 int32_t SetRateAllocation(const VideoBitrateAllocation& bitrate_allocation,
Erik Språng08127a92016-11-16 16:41:30 +0100208 uint32_t framerate) {
209 last_set_bitrate_ = bitrate_allocation;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000210 return 0;
211 }
212
philipelcce46fc2015-12-21 03:04:49 -0800213 MOCK_METHOD2(SetChannelParameters, int32_t(uint32_t packetLoss, int64_t rtt));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000214
Erik Språng9b5b0702018-11-01 14:52:30 +0100215 EncoderInfo GetEncoderInfo() const override {
216 EncoderInfo info;
217 info.supports_native_handle = supports_native_handle_;
218 info.implementation_name = implementation_name_;
219 return info;
nisseef8b61e2016-04-29 06:09:15 -0700220 }
pbos65e15ba2015-10-15 10:52:15 -0700221
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100222 virtual ~MockVideoEncoder() { factory_->DestroyVideoEncoder(this); }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000223
224 const VideoCodec& codec() const { return codec_; }
225
Noah Richards41ee1ea2015-04-15 09:24:26 -0700226 void SendEncodedImage(int width, int height) {
227 // Sends a fake image of the given width/height.
228 EncodedImage image;
229 image._encodedWidth = width;
230 image._encodedHeight = height;
sergeyu2cb155a2016-11-04 11:39:29 -0700231 CodecSpecificInfo codec_specific_info;
232 memset(&codec_specific_info, 0, sizeof(codec_specific_info));
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200233 codec_specific_info.codecType = webrtc::kVideoCodecVP8;
brandtr5e171752017-05-23 03:32:16 -0700234 callback_->OnEncodedImage(image, &codec_specific_info, nullptr);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700235 }
236
pbos65e15ba2015-10-15 10:52:15 -0700237 void set_supports_native_handle(bool enabled) {
238 supports_native_handle_ = enabled;
239 }
noahrice5ba75a2016-12-12 13:08:27 -0800240
Erik Språng9b5b0702018-11-01 14:52:30 +0100241 void set_implementation_name(const std::string& name) {
242 implementation_name_ = name;
243 }
244
noahrice5ba75a2016-12-12 13:08:27 -0800245 void set_init_encode_return_value(int32_t value) {
246 init_encode_return_value_ = value;
247 }
248
Erik Språng566124a2018-04-23 12:32:22 +0200249 VideoBitrateAllocation last_set_bitrate() const { return last_set_bitrate_; }
pbos65e15ba2015-10-15 10:52:15 -0700250
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000251 private:
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100252 MockVideoEncoderFactory* const factory_;
pbos65e15ba2015-10-15 10:52:15 -0700253 bool supports_native_handle_ = false;
Erik Språng9b5b0702018-11-01 14:52:30 +0100254 std::string implementation_name_ = "unknown";
noahrice5ba75a2016-12-12 13:08:27 -0800255 int32_t init_encode_return_value_ = 0;
Erik Språng566124a2018-04-23 12:32:22 +0200256 VideoBitrateAllocation last_set_bitrate_;
noahricfac0ff02016-09-09 10:27:15 -0700257
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000258 VideoCodec codec_;
Noah Richards41ee1ea2015-04-15 09:24:26 -0700259 EncodedImageCallback* callback_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000260};
261
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100262std::vector<SdpVideoFormat> MockVideoEncoderFactory::GetSupportedFormats()
263 const {
264 std::vector<SdpVideoFormat> formats = {SdpVideoFormat("VP8")};
265 return formats;
266}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000267
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100268std::unique_ptr<VideoEncoder> MockVideoEncoderFactory::CreateVideoEncoder(
269 const SdpVideoFormat& format) {
270 std::unique_ptr<MockVideoEncoder> encoder(
271 new ::testing::NiceMock<MockVideoEncoder>(this));
272 encoder->set_init_encode_return_value(init_encode_return_value_);
273 const char* encoder_name = encoder_names_.empty()
274 ? "codec_implementation_name"
275 : encoder_names_[encoders_.size()];
Erik Språng9b5b0702018-11-01 14:52:30 +0100276 encoder->set_implementation_name(encoder_name);
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100277 encoders_.push_back(encoder.get());
278 return encoder;
279}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000280
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100281void MockVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder* encoder) {
282 for (size_t i = 0; i < encoders_.size(); ++i) {
283 if (encoders_[i] == encoder) {
284 encoders_.erase(encoders_.begin() + i);
285 break;
Zhi Huangaea84f52017-11-16 18:46:27 +0000286 }
Zhi Huangaea84f52017-11-16 18:46:27 +0000287 }
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100288}
Zhi Huangaea84f52017-11-16 18:46:27 +0000289
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100290VideoEncoderFactory::CodecInfo MockVideoEncoderFactory::QueryVideoEncoder(
291 const SdpVideoFormat& format) const {
292 return CodecInfo();
293}
Zhi Huangaea84f52017-11-16 18:46:27 +0000294
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100295const std::vector<MockVideoEncoder*>& MockVideoEncoderFactory::encoders()
296 const {
297 return encoders_;
298}
299void MockVideoEncoderFactory::SetEncoderNames(
300 const std::vector<const char*>& encoder_names) {
301 encoder_names_ = encoder_names;
302}
303void MockVideoEncoderFactory::set_init_encode_return_value(int32_t value) {
304 init_encode_return_value_ = value;
305}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000306
307class TestSimulcastEncoderAdapterFakeHelper {
308 public:
309 TestSimulcastEncoderAdapterFakeHelper()
310 : factory_(new MockVideoEncoderFactory()) {}
311
312 // Can only be called once as the SimulcastEncoderAdapter will take the
313 // ownership of |factory_|.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200314 VideoEncoder* CreateMockEncoderAdapter() {
Ilya Nikolaevskiy97b4ee52018-05-28 10:24:22 +0200315 return new SimulcastEncoderAdapter(factory_.get(), SdpVideoFormat("VP8"));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000316 }
317
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000318 void ExpectCallSetChannelParameters(uint32_t packetLoss, int64_t rtt) {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000319 EXPECT_TRUE(!factory_->encoders().empty());
320 for (size_t i = 0; i < factory_->encoders().size(); ++i) {
321 EXPECT_CALL(*factory_->encoders()[i],
philipelcce46fc2015-12-21 03:04:49 -0800322 SetChannelParameters(packetLoss, rtt))
323 .Times(1);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000324 }
325 }
326
magjed6cc25612017-07-10 03:26:36 -0700327 MockVideoEncoderFactory* factory() { return factory_.get(); }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000328
329 private:
magjed6cc25612017-07-10 03:26:36 -0700330 std::unique_ptr<MockVideoEncoderFactory> factory_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000331};
332
333static const int kTestTemporalLayerProfile[3] = {3, 2, 1};
334
Noah Richards41ee1ea2015-04-15 09:24:26 -0700335class TestSimulcastEncoderAdapterFake : public ::testing::Test,
336 public EncodedImageCallback {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000337 public:
338 TestSimulcastEncoderAdapterFake()
Noah Richards41ee1ea2015-04-15 09:24:26 -0700339 : helper_(new TestSimulcastEncoderAdapterFakeHelper()),
340 adapter_(helper_->CreateMockEncoderAdapter()),
341 last_encoded_image_width_(-1),
342 last_encoded_image_height_(-1),
343 last_encoded_image_simulcast_index_(-1) {}
brandtr5e171752017-05-23 03:32:16 -0700344 virtual ~TestSimulcastEncoderAdapterFake() {
345 if (adapter_) {
346 adapter_->Release();
347 }
348 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000349
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700350 Result OnEncodedImage(const EncodedImage& encoded_image,
351 const CodecSpecificInfo* codec_specific_info,
352 const RTPFragmentationHeader* fragmentation) override {
353 last_encoded_image_width_ = encoded_image._encodedWidth;
354 last_encoded_image_height_ = encoded_image._encodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200355 last_encoded_image_simulcast_index_ =
356 encoded_image.SpatialIndex().value_or(-1);
357
Niels Möller72bc8d62018-09-12 10:03:51 +0200358 return Result(Result::OK, encoded_image.Timestamp());
Noah Richards41ee1ea2015-04-15 09:24:26 -0700359 }
360
361 bool GetLastEncodedImageInfo(int* out_width,
362 int* out_height,
363 int* out_simulcast_index) {
364 if (last_encoded_image_width_ == -1) {
365 return false;
366 }
367 *out_width = last_encoded_image_width_;
368 *out_height = last_encoded_image_height_;
369 *out_simulcast_index = last_encoded_image_simulcast_index_;
370 return true;
371 }
372
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000373 void SetupCodec() {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200374 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200375 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
376 kVideoCodecVP8);
Erik Språng82fad3d2018-03-21 09:57:23 +0100377 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000378 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Noah Richards41ee1ea2015-04-15 09:24:26 -0700379 adapter_->RegisterEncodeCompleteCallback(this);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000380 }
381
382 void VerifyCodec(const VideoCodec& ref, int stream_index) {
383 const VideoCodec& target =
384 helper_->factory()->encoders()[stream_index]->codec();
385 EXPECT_EQ(ref.codecType, target.codecType);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000386 EXPECT_EQ(ref.plType, target.plType);
387 EXPECT_EQ(ref.width, target.width);
388 EXPECT_EQ(ref.height, target.height);
389 EXPECT_EQ(ref.startBitrate, target.startBitrate);
390 EXPECT_EQ(ref.maxBitrate, target.maxBitrate);
391 EXPECT_EQ(ref.minBitrate, target.minBitrate);
392 EXPECT_EQ(ref.maxFramerate, target.maxFramerate);
hta257dc392016-10-25 09:05:06 -0700393 EXPECT_EQ(ref.VP8().complexity, target.VP8().complexity);
hta257dc392016-10-25 09:05:06 -0700394 EXPECT_EQ(ref.VP8().numberOfTemporalLayers,
395 target.VP8().numberOfTemporalLayers);
396 EXPECT_EQ(ref.VP8().denoisingOn, target.VP8().denoisingOn);
hta257dc392016-10-25 09:05:06 -0700397 EXPECT_EQ(ref.VP8().automaticResizeOn, target.VP8().automaticResizeOn);
398 EXPECT_EQ(ref.VP8().frameDroppingOn, target.VP8().frameDroppingOn);
399 EXPECT_EQ(ref.VP8().keyFrameInterval, target.VP8().keyFrameInterval);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000400 EXPECT_EQ(ref.qpMax, target.qpMax);
401 EXPECT_EQ(0, target.numberOfSimulcastStreams);
402 EXPECT_EQ(ref.mode, target.mode);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000403
404 // No need to compare simulcastStream as numberOfSimulcastStreams should
405 // always be 0.
406 }
407
408 void InitRefCodec(int stream_index, VideoCodec* ref_codec) {
409 *ref_codec = codec_;
hta257dc392016-10-25 09:05:06 -0700410 ref_codec->VP8()->numberOfTemporalLayers =
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000411 kTestTemporalLayerProfile[stream_index];
412 ref_codec->width = codec_.simulcastStream[stream_index].width;
413 ref_codec->height = codec_.simulcastStream[stream_index].height;
414 ref_codec->maxBitrate = codec_.simulcastStream[stream_index].maxBitrate;
415 ref_codec->minBitrate = codec_.simulcastStream[stream_index].minBitrate;
416 ref_codec->qpMax = codec_.simulcastStream[stream_index].qpMax;
417 }
418
419 void VerifyCodecSettings() {
420 EXPECT_EQ(3u, helper_->factory()->encoders().size());
421 VideoCodec ref_codec;
422
423 // stream 0, the lowest resolution stream.
424 InitRefCodec(0, &ref_codec);
425 ref_codec.qpMax = 45;
Niels Möllere3cf3d02018-06-13 11:52:16 +0200426 ref_codec.VP8()->complexity =
427 webrtc::VideoCodecComplexity::kComplexityHigher;
hta257dc392016-10-25 09:05:06 -0700428 ref_codec.VP8()->denoisingOn = false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000429 ref_codec.startBitrate = 100; // Should equal to the target bitrate.
430 VerifyCodec(ref_codec, 0);
431
432 // stream 1
433 InitRefCodec(1, &ref_codec);
hta257dc392016-10-25 09:05:06 -0700434 ref_codec.VP8()->denoisingOn = false;
Noah Richards67b635a2015-05-22 14:12:10 -0700435 // The start bitrate (300kbit) minus what we have for the lower layers
436 // (100kbit).
437 ref_codec.startBitrate = 200;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000438 VerifyCodec(ref_codec, 1);
439
440 // stream 2, the biggest resolution stream.
441 InitRefCodec(2, &ref_codec);
Noah Richards67b635a2015-05-22 14:12:10 -0700442 // We don't have enough bits to send this, so the adapter should have
443 // configured it to use the min bitrate for this layer (600kbit) but turn
444 // off sending.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000445 ref_codec.startBitrate = 600;
446 VerifyCodec(ref_codec, 2);
447 }
448
449 protected:
kwiberg3f55dea2016-02-29 05:51:59 -0800450 std::unique_ptr<TestSimulcastEncoderAdapterFakeHelper> helper_;
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200451 std::unique_ptr<VideoEncoder> adapter_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000452 VideoCodec codec_;
Noah Richards41ee1ea2015-04-15 09:24:26 -0700453 int last_encoded_image_width_;
454 int last_encoded_image_height_;
455 int last_encoded_image_simulcast_index_;
Erik Språng08127a92016-11-16 16:41:30 +0100456 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000457};
458
459TEST_F(TestSimulcastEncoderAdapterFake, InitEncode) {
460 SetupCodec();
461 VerifyCodecSettings();
462}
463
brandtr5e171752017-05-23 03:32:16 -0700464TEST_F(TestSimulcastEncoderAdapterFake, ReleaseWithoutInitEncode) {
465 EXPECT_EQ(0, adapter_->Release());
466}
467
468TEST_F(TestSimulcastEncoderAdapterFake, Reinit) {
469 SetupCodec();
470 EXPECT_EQ(0, adapter_->Release());
471
472 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
473}
474
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000475TEST_F(TestSimulcastEncoderAdapterFake, SetChannelParameters) {
476 SetupCodec();
477 const uint32_t packetLoss = 5;
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000478 const int64_t rtt = 30;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000479 helper_->ExpectCallSetChannelParameters(packetLoss, rtt);
480 adapter_->SetChannelParameters(packetLoss, rtt);
481}
482
Noah Richards41ee1ea2015-04-15 09:24:26 -0700483TEST_F(TestSimulcastEncoderAdapterFake, EncodedCallbackForDifferentEncoders) {
484 SetupCodec();
485
Peter Boström5d0379d2015-10-06 14:04:51 +0200486 // Set bitrates so that we send all layers.
Erik Språng08127a92016-11-16 16:41:30 +0100487 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
Peter Boström5d0379d2015-10-06 14:04:51 +0200488
Noah Richards41ee1ea2015-04-15 09:24:26 -0700489 // At this point, the simulcast encoder adapter should have 3 streams: HD,
490 // quarter HD, and quarter quarter HD. We're going to mostly ignore the exact
491 // resolutions, to test that the adapter forwards on the correct resolution
492 // and simulcast index values, going only off the encoder that generates the
493 // image.
brandtr5e171752017-05-23 03:32:16 -0700494 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
495 ASSERT_EQ(3u, encoders.size());
496 encoders[0]->SendEncodedImage(1152, 704);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700497 int width;
498 int height;
499 int simulcast_index;
500 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
501 EXPECT_EQ(1152, width);
502 EXPECT_EQ(704, height);
503 EXPECT_EQ(0, simulcast_index);
504
brandtr5e171752017-05-23 03:32:16 -0700505 encoders[1]->SendEncodedImage(300, 620);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700506 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
507 EXPECT_EQ(300, width);
508 EXPECT_EQ(620, height);
509 EXPECT_EQ(1, simulcast_index);
510
brandtr5e171752017-05-23 03:32:16 -0700511 encoders[2]->SendEncodedImage(120, 240);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700512 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
513 EXPECT_EQ(120, width);
514 EXPECT_EQ(240, height);
515 EXPECT_EQ(2, simulcast_index);
516}
517
brandtr5e171752017-05-23 03:32:16 -0700518// This test verifies that the underlying encoders are reused, when the adapter
519// is reinited with different number of simulcast streams. It further checks
520// that the allocated encoders are reused in the same order as before, starting
521// with the lowest stream.
522TEST_F(TestSimulcastEncoderAdapterFake, ReusesEncodersInOrder) {
523 // Set up common settings for three streams.
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200524 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200525 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
526 kVideoCodecVP8);
Erik Språng82fad3d2018-03-21 09:57:23 +0100527 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
brandtr5e171752017-05-23 03:32:16 -0700528 adapter_->RegisterEncodeCompleteCallback(this);
Erik Språng7d687b12018-09-12 17:04:10 +0200529 const uint32_t target_bitrate =
530 1000 * (codec_.simulcastStream[0].targetBitrate +
531 codec_.simulcastStream[1].targetBitrate +
532 codec_.simulcastStream[2].minBitrate);
brandtr5e171752017-05-23 03:32:16 -0700533
534 // Input data.
535 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
536 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
537 std::vector<FrameType> frame_types;
538
539 // Encode with three streams.
540 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
541 VerifyCodecSettings();
Erik Språng7d687b12018-09-12 17:04:10 +0200542 adapter_->SetRateAllocation(
543 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
544
brandtr5e171752017-05-23 03:32:16 -0700545 std::vector<MockVideoEncoder*> original_encoders =
546 helper_->factory()->encoders();
547 ASSERT_EQ(3u, original_encoders.size());
548 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
549 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
550 EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
551 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
552 EXPECT_CALL(*original_encoders[2], Encode(_, _, _))
553 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
554 frame_types.resize(3, kVideoFrameKey);
555 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
556 EXPECT_CALL(*original_encoders[0], Release())
557 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
558 EXPECT_CALL(*original_encoders[1], Release())
559 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
560 EXPECT_CALL(*original_encoders[2], Release())
561 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
562 EXPECT_EQ(0, adapter_->Release());
563
564 // Encode with two streams.
565 codec_.width /= 2;
566 codec_.height /= 2;
567 codec_.numberOfSimulcastStreams = 2;
568 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200569 adapter_->SetRateAllocation(
570 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700571 std::vector<MockVideoEncoder*> new_encoders = helper_->factory()->encoders();
572 ASSERT_EQ(2u, new_encoders.size());
573 ASSERT_EQ(original_encoders[0], new_encoders[0]);
574 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
575 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
576 ASSERT_EQ(original_encoders[1], new_encoders[1]);
577 EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
578 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
579 frame_types.resize(2, kVideoFrameKey);
580 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
581 EXPECT_CALL(*original_encoders[0], Release())
582 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
583 EXPECT_CALL(*original_encoders[1], Release())
584 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
585 EXPECT_EQ(0, adapter_->Release());
586
587 // Encode with single stream.
588 codec_.width /= 2;
589 codec_.height /= 2;
590 codec_.numberOfSimulcastStreams = 1;
591 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200592 adapter_->SetRateAllocation(
593 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700594 new_encoders = helper_->factory()->encoders();
595 ASSERT_EQ(1u, new_encoders.size());
596 ASSERT_EQ(original_encoders[0], new_encoders[0]);
597 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
598 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
599 frame_types.resize(1, kVideoFrameKey);
600 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
601 EXPECT_CALL(*original_encoders[0], Release())
602 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
603 EXPECT_EQ(0, adapter_->Release());
604
605 // Encode with three streams, again.
606 codec_.width *= 4;
607 codec_.height *= 4;
608 codec_.numberOfSimulcastStreams = 3;
609 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200610 adapter_->SetRateAllocation(
611 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700612 new_encoders = helper_->factory()->encoders();
613 ASSERT_EQ(3u, new_encoders.size());
614 // The first encoder is reused.
615 ASSERT_EQ(original_encoders[0], new_encoders[0]);
616 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
617 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
618 // The second and third encoders are new.
619 EXPECT_CALL(*new_encoders[1], Encode(_, _, _))
620 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
621 EXPECT_CALL(*new_encoders[2], Encode(_, _, _))
622 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
623 frame_types.resize(3, kVideoFrameKey);
624 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
625 EXPECT_CALL(*original_encoders[0], Release())
626 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
627 EXPECT_CALL(*new_encoders[1], Release())
628 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
629 EXPECT_CALL(*new_encoders[2], Release())
630 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
631 EXPECT_EQ(0, adapter_->Release());
632}
633
634TEST_F(TestSimulcastEncoderAdapterFake, DoesNotLeakEncoders) {
635 SetupCodec();
636 VerifyCodecSettings();
637
638 EXPECT_EQ(3u, helper_->factory()->encoders().size());
639
640 // The adapter should destroy all encoders it has allocated. Since
641 // |helper_->factory()| is owned by |adapter_|, however, we need to rely on
642 // lsan to find leaks here.
643 EXPECT_EQ(0, adapter_->Release());
644 adapter_.reset();
645}
646
647// This test verifies that an adapter reinit with the same codec settings as
648// before does not change the underlying encoder codec settings.
649TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderEncoderSettings) {
650 SetupCodec();
651 VerifyCodecSettings();
652
653 // Capture current codec settings.
654 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
655 ASSERT_EQ(3u, encoders.size());
656 std::array<VideoCodec, 3> codecs_before;
657 for (int i = 0; i < 3; ++i) {
658 codecs_before[i] = encoders[i]->codec();
659 }
660
661 // Reinitialize and verify that the new codec settings are the same.
662 EXPECT_EQ(0, adapter_->Release());
663 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
664 for (int i = 0; i < 3; ++i) {
665 const VideoCodec& codec_before = codecs_before[i];
666 const VideoCodec& codec_after = encoders[i]->codec();
667
668 // webrtc::VideoCodec does not implement operator==.
669 EXPECT_EQ(codec_before.codecType, codec_after.codecType);
670 EXPECT_EQ(codec_before.plType, codec_after.plType);
671 EXPECT_EQ(codec_before.width, codec_after.width);
672 EXPECT_EQ(codec_before.height, codec_after.height);
673 EXPECT_EQ(codec_before.startBitrate, codec_after.startBitrate);
674 EXPECT_EQ(codec_before.maxBitrate, codec_after.maxBitrate);
675 EXPECT_EQ(codec_before.minBitrate, codec_after.minBitrate);
676 EXPECT_EQ(codec_before.targetBitrate, codec_after.targetBitrate);
677 EXPECT_EQ(codec_before.maxFramerate, codec_after.maxFramerate);
678 EXPECT_EQ(codec_before.qpMax, codec_after.qpMax);
679 EXPECT_EQ(codec_before.numberOfSimulcastStreams,
680 codec_after.numberOfSimulcastStreams);
681 EXPECT_EQ(codec_before.mode, codec_after.mode);
682 EXPECT_EQ(codec_before.expect_encode_from_texture,
683 codec_after.expect_encode_from_texture);
684 }
685}
686
687// This test is similar to the one above, except that it tests the simulcastIdx
688// from the CodecSpecificInfo that is connected to an encoded frame. The
689// PayloadRouter demuxes the incoming encoded frames on different RTP modules
690// using the simulcastIdx, so it's important that there is no corresponding
691// encoder reordering in between adapter reinits as this would lead to PictureID
692// discontinuities.
693TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderFrameSimulcastIdx) {
694 SetupCodec();
695 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
696 VerifyCodecSettings();
697
698 // Send frames on all streams.
699 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
700 ASSERT_EQ(3u, encoders.size());
701 encoders[0]->SendEncodedImage(1152, 704);
702 int width;
703 int height;
704 int simulcast_index;
705 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
706 EXPECT_EQ(0, simulcast_index);
707
708 encoders[1]->SendEncodedImage(300, 620);
709 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
710 EXPECT_EQ(1, simulcast_index);
711
712 encoders[2]->SendEncodedImage(120, 240);
713 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
714 EXPECT_EQ(2, simulcast_index);
715
716 // Reinitialize.
717 EXPECT_EQ(0, adapter_->Release());
718 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
719 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
720
721 // Verify that the same encoder sends out frames on the same simulcast index.
722 encoders[0]->SendEncodedImage(1152, 704);
723 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
724 EXPECT_EQ(0, simulcast_index);
725
726 encoders[1]->SendEncodedImage(300, 620);
727 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
728 EXPECT_EQ(1, simulcast_index);
729
730 encoders[2]->SendEncodedImage(120, 240);
731 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
732 EXPECT_EQ(2, simulcast_index);
733}
734
pbos65e15ba2015-10-15 10:52:15 -0700735TEST_F(TestSimulcastEncoderAdapterFake, SupportsNativeHandleForSingleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200736 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200737 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
738 kVideoCodecVP8);
pbos65e15ba2015-10-15 10:52:15 -0700739 codec_.numberOfSimulcastStreams = 1;
740 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
741 adapter_->RegisterEncodeCompleteCallback(this);
742 ASSERT_EQ(1u, helper_->factory()->encoders().size());
743 helper_->factory()->encoders()[0]->set_supports_native_handle(true);
Erik Språnge2fd86a2018-10-24 11:32:39 +0200744 EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
pbos65e15ba2015-10-15 10:52:15 -0700745 helper_->factory()->encoders()[0]->set_supports_native_handle(false);
Erik Språnge2fd86a2018-10-24 11:32:39 +0200746 EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle);
pbos65e15ba2015-10-15 10:52:15 -0700747}
748
noahricfac0ff02016-09-09 10:27:15 -0700749TEST_F(TestSimulcastEncoderAdapterFake, SetRatesUnderMinBitrate) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200750 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200751 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
752 kVideoCodecVP8);
noahricfac0ff02016-09-09 10:27:15 -0700753 codec_.minBitrate = 50;
754 codec_.numberOfSimulcastStreams = 1;
755 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng82fad3d2018-03-21 09:57:23 +0100756 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
noahricfac0ff02016-09-09 10:27:15 -0700757
758 // Above min should be respected.
Erik Språng566124a2018-04-23 12:32:22 +0200759 VideoBitrateAllocation target_bitrate =
Erik Språng08127a92016-11-16 16:41:30 +0100760 rate_allocator_->GetAllocation(codec_.minBitrate * 1000, 30);
761 adapter_->SetRateAllocation(target_bitrate, 30);
762 EXPECT_EQ(target_bitrate,
763 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700764
765 // Below min but non-zero should be replaced with the min bitrate.
Erik Språng566124a2018-04-23 12:32:22 +0200766 VideoBitrateAllocation too_low_bitrate =
Erik Språng08127a92016-11-16 16:41:30 +0100767 rate_allocator_->GetAllocation((codec_.minBitrate - 1) * 1000, 30);
768 adapter_->SetRateAllocation(too_low_bitrate, 30);
769 EXPECT_EQ(target_bitrate,
770 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700771
772 // Zero should be passed on as is, since it means "pause".
Erik Språng566124a2018-04-23 12:32:22 +0200773 adapter_->SetRateAllocation(VideoBitrateAllocation(), 30);
774 EXPECT_EQ(VideoBitrateAllocation(),
Erik Språng08127a92016-11-16 16:41:30 +0100775 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700776}
777
Peter Boströma5dec162016-01-20 15:53:55 +0100778TEST_F(TestSimulcastEncoderAdapterFake, SupportsImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +0200779 EXPECT_EQ("SimulcastEncoderAdapter",
780 adapter_->GetEncoderInfo().implementation_name);
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200781 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200782 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
783 kVideoCodecVP8);
Peter Boströma5dec162016-01-20 15:53:55 +0100784 std::vector<const char*> encoder_names;
785 encoder_names.push_back("codec1");
786 encoder_names.push_back("codec2");
787 encoder_names.push_back("codec3");
788 helper_->factory()->SetEncoderNames(encoder_names);
789 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språnge2fd86a2018-10-24 11:32:39 +0200790 EXPECT_EQ("SimulcastEncoderAdapter (codec1, codec2, codec3)",
791 adapter_->GetEncoderInfo().implementation_name);
Peter Boströmd53c3892016-03-30 17:03:52 +0200792
793 // Single streams should not expose "SimulcastEncoderAdapter" in name.
brandtr5e171752017-05-23 03:32:16 -0700794 EXPECT_EQ(0, adapter_->Release());
Peter Boströmd53c3892016-03-30 17:03:52 +0200795 codec_.numberOfSimulcastStreams = 1;
796 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
797 adapter_->RegisterEncodeCompleteCallback(this);
798 ASSERT_EQ(1u, helper_->factory()->encoders().size());
Erik Språnge2fd86a2018-10-24 11:32:39 +0200799 EXPECT_EQ("codec1", adapter_->GetEncoderInfo().implementation_name);
Peter Boströma5dec162016-01-20 15:53:55 +0100800}
801
pbos65e15ba2015-10-15 10:52:15 -0700802TEST_F(TestSimulcastEncoderAdapterFake,
noahricfe3654d2016-07-01 09:05:54 -0700803 SupportsNativeHandleForMultipleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200804 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200805 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
806 kVideoCodecVP8);
pbos65e15ba2015-10-15 10:52:15 -0700807 codec_.numberOfSimulcastStreams = 3;
808 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
809 adapter_->RegisterEncodeCompleteCallback(this);
810 ASSERT_EQ(3u, helper_->factory()->encoders().size());
811 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
812 encoder->set_supports_native_handle(true);
noahricfe3654d2016-07-01 09:05:54 -0700813 // If one encoder doesn't support it, then overall support is disabled.
814 helper_->factory()->encoders()[0]->set_supports_native_handle(false);
Erik Språnge2fd86a2018-10-24 11:32:39 +0200815 EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle);
noahricfe3654d2016-07-01 09:05:54 -0700816 // Once all do, then the adapter claims support.
817 helper_->factory()->encoders()[0]->set_supports_native_handle(true);
Erik Språnge2fd86a2018-10-24 11:32:39 +0200818 EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
noahricfe3654d2016-07-01 09:05:54 -0700819}
820
nisseaf916892017-01-10 07:44:26 -0800821// TODO(nisse): Reuse definition in webrtc/test/fake_texture_handle.h.
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200822class FakeNativeBufferNoI420 : public VideoFrameBuffer {
noahricfe3654d2016-07-01 09:05:54 -0700823 public:
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200824 FakeNativeBufferNoI420(int width, int height)
825 : width_(width), height_(height) {}
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000826
827 Type type() const override { return Type::kNative; }
828 int width() const override { return width_; }
829 int height() const override { return height_; }
830
831 rtc::scoped_refptr<I420BufferInterface> ToI420() override {
noahricfe3654d2016-07-01 09:05:54 -0700832 RTC_NOTREACHED();
833 return nullptr;
834 }
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000835
836 private:
837 const int width_;
838 const int height_;
noahricfe3654d2016-07-01 09:05:54 -0700839};
840
841TEST_F(TestSimulcastEncoderAdapterFake,
842 NativeHandleForwardingForMultipleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200843 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200844 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
845 kVideoCodecVP8);
noahricfe3654d2016-07-01 09:05:54 -0700846 codec_.numberOfSimulcastStreams = 3;
847 // High start bitrate, so all streams are enabled.
848 codec_.startBitrate = 3000;
849 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
850 adapter_->RegisterEncodeCompleteCallback(this);
851 ASSERT_EQ(3u, helper_->factory()->encoders().size());
852 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
853 encoder->set_supports_native_handle(true);
Erik Språnge2fd86a2018-10-24 11:32:39 +0200854 EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
noahricfe3654d2016-07-01 09:05:54 -0700855
856 rtc::scoped_refptr<VideoFrameBuffer> buffer(
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200857 new rtc::RefCountedObject<FakeNativeBufferNoI420>(1280, 720));
noahricfe3654d2016-07-01 09:05:54 -0700858 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
859 // Expect calls with the given video frame verbatim, since it's a texture
860 // frame and can't otherwise be modified/resized.
861 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
862 EXPECT_CALL(*encoder, Encode(::testing::Ref(input_frame), _, _)).Times(1);
863 std::vector<FrameType> frame_types(3, kVideoFrameKey);
brandtr5e171752017-05-23 03:32:16 -0700864 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
pbos65e15ba2015-10-15 10:52:15 -0700865}
866
noahric57779102016-05-25 06:48:46 -0700867TEST_F(TestSimulcastEncoderAdapterFake, TestFailureReturnCodesFromEncodeCalls) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200868 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200869 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
870 kVideoCodecVP8);
noahric57779102016-05-25 06:48:46 -0700871 codec_.numberOfSimulcastStreams = 3;
872 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
873 adapter_->RegisterEncodeCompleteCallback(this);
874 ASSERT_EQ(3u, helper_->factory()->encoders().size());
875 // Tell the 2nd encoder to request software fallback.
noahricfe3654d2016-07-01 09:05:54 -0700876 EXPECT_CALL(*helper_->factory()->encoders()[1], Encode(_, _, _))
877 .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
noahric57779102016-05-25 06:48:46 -0700878
879 // Send a fake frame and assert the return is software fallback.
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000880 rtc::scoped_refptr<I420Buffer> input_buffer =
881 I420Buffer::Create(kDefaultWidth, kDefaultHeight);
nisse64ec8f82016-09-27 00:17:25 -0700882 input_buffer->InitializeData();
883 VideoFrame input_frame(input_buffer, 0, 0, webrtc::kVideoRotation_0);
noahric57779102016-05-25 06:48:46 -0700884 std::vector<FrameType> frame_types(3, kVideoFrameKey);
885 EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
886 adapter_->Encode(input_frame, nullptr, &frame_types));
887}
888
noahrice5ba75a2016-12-12 13:08:27 -0800889TEST_F(TestSimulcastEncoderAdapterFake, TestInitFailureCleansUpEncoders) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200890 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200891 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
892 kVideoCodecVP8);
noahrice5ba75a2016-12-12 13:08:27 -0800893 codec_.numberOfSimulcastStreams = 3;
894 helper_->factory()->set_init_encode_return_value(
895 WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
896 EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
897 adapter_->InitEncode(&codec_, 1, 1200));
898 EXPECT_TRUE(helper_->factory()->encoders().empty());
899}
900
Erik Språng8d2995b2018-08-09 11:18:17 +0200901TEST_F(TestSimulcastEncoderAdapterFake, DoesNotAlterMaxQpForScreenshare) {
902 const int kHighMaxQp = 56;
903 const int kLowMaxQp = 46;
904
905 SimulcastTestFixtureImpl::DefaultSettings(
906 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
907 kVideoCodecVP8);
908 codec_.numberOfSimulcastStreams = 3;
909 codec_.simulcastStream[0].qpMax = kHighMaxQp;
910 codec_.mode = VideoCodecMode::kScreensharing;
911
912 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
913 EXPECT_EQ(3u, helper_->factory()->encoders().size());
914
915 // Just check the lowest stream, which is the one that where the adapter
916 // might alter the max qp setting.
917 VideoCodec ref_codec;
918 InitRefCodec(0, &ref_codec);
919 ref_codec.qpMax = kHighMaxQp;
920 ref_codec.VP8()->complexity = webrtc::VideoCodecComplexity::kComplexityHigher;
921 ref_codec.VP8()->denoisingOn = false;
922 ref_codec.startBitrate = 100; // Should equal to the target bitrate.
923 VerifyCodec(ref_codec, 0);
924
925 // Change the max qp and try again.
926 codec_.simulcastStream[0].qpMax = kLowMaxQp;
927 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
928 EXPECT_EQ(3u, helper_->factory()->encoders().size());
929 ref_codec.qpMax = kLowMaxQp;
930 VerifyCodec(ref_codec, 0);
931}
Erik Språng7d687b12018-09-12 17:04:10 +0200932
933TEST_F(TestSimulcastEncoderAdapterFake, ActivatesCorrectStreamsInInitEncode) {
934 // Set up common settings for three streams.
935 SimulcastTestFixtureImpl::DefaultSettings(
936 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
937 kVideoCodecVP8);
938 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
939 adapter_->RegisterEncodeCompleteCallback(this);
940
941 // Only enough start bitrate for the lowest stream.
942 ASSERT_EQ(3u, codec_.numberOfSimulcastStreams);
943 codec_.startBitrate = codec_.simulcastStream[0].targetBitrate +
944 codec_.simulcastStream[1].minBitrate - 1;
945
946 // Input data.
947 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
948 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
949
950 // Encode with three streams.
951 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
952 std::vector<MockVideoEncoder*> original_encoders =
953 helper_->factory()->encoders();
954 ASSERT_EQ(3u, original_encoders.size());
955 // Only first encoder will be active and called.
956 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
957 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
958 EXPECT_CALL(*original_encoders[1], Encode(_, _, _)).Times(0);
959 EXPECT_CALL(*original_encoders[2], Encode(_, _, _)).Times(0);
960
961 std::vector<FrameType> frame_types;
962 frame_types.resize(3, kVideoFrameKey);
963 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
964}
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200965} // namespace test
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000966} // namespace webrtc