blob: 32e6e74497a158d35f37c7356f70220c39ad9536 [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}
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
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100162 const std::vector<MockVideoEncoder*>& encoders() const;
163 void SetEncoderNames(const std::vector<const char*>& encoder_names);
164 void set_init_encode_return_value(int32_t value);
165
166 void DestroyVideoEncoder(VideoEncoder* encoder);
167
168 private:
169 int32_t init_encode_return_value_ = 0;
170 std::vector<MockVideoEncoder*> encoders_;
171 std::vector<const char*> encoder_names_;
172};
173
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000174class MockVideoEncoder : public VideoEncoder {
175 public:
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100176 explicit MockVideoEncoder(MockVideoEncoderFactory* factory)
Erik Språng75de46a2018-11-07 14:53:32 +0100177 : factory_(factory),
178 scaling_settings_(VideoEncoder::ScalingSettings::kOff),
179 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
Erik Språng9b5b0702018-11-01 14:52:30 +0100212 EncoderInfo GetEncoderInfo() const override {
213 EncoderInfo info;
214 info.supports_native_handle = supports_native_handle_;
215 info.implementation_name = implementation_name_;
Erik Språng75de46a2018-11-07 14:53:32 +0100216 info.scaling_settings = scaling_settings_;
Erik Språngd3438aa2018-11-08 16:56:43 +0100217 info.has_trusted_rate_controller = has_trusted_rate_controller_;
Mirta Dvornicic897a9912018-11-30 13:12:21 +0100218 info.is_hardware_accelerated = is_hardware_accelerated_;
219 info.has_internal_source = has_internal_source_;
Erik Språng9b5b0702018-11-01 14:52:30 +0100220 return info;
nisseef8b61e2016-04-29 06:09:15 -0700221 }
pbos65e15ba2015-10-15 10:52:15 -0700222
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100223 virtual ~MockVideoEncoder() { factory_->DestroyVideoEncoder(this); }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000224
225 const VideoCodec& codec() const { return codec_; }
226
Noah Richards41ee1ea2015-04-15 09:24:26 -0700227 void SendEncodedImage(int width, int height) {
228 // Sends a fake image of the given width/height.
229 EncodedImage image;
230 image._encodedWidth = width;
231 image._encodedHeight = height;
sergeyu2cb155a2016-11-04 11:39:29 -0700232 CodecSpecificInfo codec_specific_info;
233 memset(&codec_specific_info, 0, sizeof(codec_specific_info));
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200234 codec_specific_info.codecType = webrtc::kVideoCodecVP8;
brandtr5e171752017-05-23 03:32:16 -0700235 callback_->OnEncodedImage(image, &codec_specific_info, nullptr);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700236 }
237
pbos65e15ba2015-10-15 10:52:15 -0700238 void set_supports_native_handle(bool enabled) {
239 supports_native_handle_ = enabled;
240 }
noahrice5ba75a2016-12-12 13:08:27 -0800241
Erik Språng9b5b0702018-11-01 14:52:30 +0100242 void set_implementation_name(const std::string& name) {
243 implementation_name_ = name;
244 }
245
noahrice5ba75a2016-12-12 13:08:27 -0800246 void set_init_encode_return_value(int32_t value) {
247 init_encode_return_value_ = value;
248 }
249
Erik Språng75de46a2018-11-07 14:53:32 +0100250 void set_scaling_settings(const VideoEncoder::ScalingSettings& settings) {
251 scaling_settings_ = settings;
252 }
253
Erik Språngd3438aa2018-11-08 16:56:43 +0100254 void set_has_trusted_rate_controller(bool trusted) {
255 has_trusted_rate_controller_ = trusted;
256 }
257
Mirta Dvornicic897a9912018-11-30 13:12:21 +0100258 void set_is_hardware_accelerated(bool is_hardware_accelerated) {
259 is_hardware_accelerated_ = is_hardware_accelerated;
260 }
261
262 void set_has_internal_source(bool has_internal_source) {
263 has_internal_source_ = has_internal_source;
264 }
265
Erik Språng566124a2018-04-23 12:32:22 +0200266 VideoBitrateAllocation last_set_bitrate() const { return last_set_bitrate_; }
pbos65e15ba2015-10-15 10:52:15 -0700267
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000268 private:
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100269 MockVideoEncoderFactory* const factory_;
pbos65e15ba2015-10-15 10:52:15 -0700270 bool supports_native_handle_ = false;
Erik Språng9b5b0702018-11-01 14:52:30 +0100271 std::string implementation_name_ = "unknown";
Erik Språng75de46a2018-11-07 14:53:32 +0100272 VideoEncoder::ScalingSettings scaling_settings_;
Erik Språngd3438aa2018-11-08 16:56:43 +0100273 bool has_trusted_rate_controller_ = false;
Mirta Dvornicic897a9912018-11-30 13:12:21 +0100274 bool is_hardware_accelerated_ = false;
275 bool has_internal_source_ = false;
noahrice5ba75a2016-12-12 13:08:27 -0800276 int32_t init_encode_return_value_ = 0;
Erik Språng566124a2018-04-23 12:32:22 +0200277 VideoBitrateAllocation last_set_bitrate_;
noahricfac0ff02016-09-09 10:27:15 -0700278
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000279 VideoCodec codec_;
Noah Richards41ee1ea2015-04-15 09:24:26 -0700280 EncodedImageCallback* callback_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000281};
282
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100283std::vector<SdpVideoFormat> MockVideoEncoderFactory::GetSupportedFormats()
284 const {
285 std::vector<SdpVideoFormat> formats = {SdpVideoFormat("VP8")};
286 return formats;
287}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000288
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100289std::unique_ptr<VideoEncoder> MockVideoEncoderFactory::CreateVideoEncoder(
290 const SdpVideoFormat& format) {
291 std::unique_ptr<MockVideoEncoder> encoder(
292 new ::testing::NiceMock<MockVideoEncoder>(this));
293 encoder->set_init_encode_return_value(init_encode_return_value_);
294 const char* encoder_name = encoder_names_.empty()
295 ? "codec_implementation_name"
296 : encoder_names_[encoders_.size()];
Erik Språng9b5b0702018-11-01 14:52:30 +0100297 encoder->set_implementation_name(encoder_name);
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100298 encoders_.push_back(encoder.get());
299 return encoder;
300}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000301
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100302void MockVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder* encoder) {
303 for (size_t i = 0; i < encoders_.size(); ++i) {
304 if (encoders_[i] == encoder) {
305 encoders_.erase(encoders_.begin() + i);
306 break;
Zhi Huangaea84f52017-11-16 18:46:27 +0000307 }
Zhi Huangaea84f52017-11-16 18:46:27 +0000308 }
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100309}
Zhi Huangaea84f52017-11-16 18:46:27 +0000310
Magnus Jedvertdf4883d2017-11-17 14:44:55 +0100311const std::vector<MockVideoEncoder*>& MockVideoEncoderFactory::encoders()
312 const {
313 return encoders_;
314}
315void MockVideoEncoderFactory::SetEncoderNames(
316 const std::vector<const char*>& encoder_names) {
317 encoder_names_ = encoder_names;
318}
319void MockVideoEncoderFactory::set_init_encode_return_value(int32_t value) {
320 init_encode_return_value_ = value;
321}
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000322
323class TestSimulcastEncoderAdapterFakeHelper {
324 public:
325 TestSimulcastEncoderAdapterFakeHelper()
326 : factory_(new MockVideoEncoderFactory()) {}
327
328 // Can only be called once as the SimulcastEncoderAdapter will take the
329 // ownership of |factory_|.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200330 VideoEncoder* CreateMockEncoderAdapter() {
Ilya Nikolaevskiy97b4ee52018-05-28 10:24:22 +0200331 return new SimulcastEncoderAdapter(factory_.get(), SdpVideoFormat("VP8"));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000332 }
333
magjed6cc25612017-07-10 03:26:36 -0700334 MockVideoEncoderFactory* factory() { return factory_.get(); }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000335
336 private:
magjed6cc25612017-07-10 03:26:36 -0700337 std::unique_ptr<MockVideoEncoderFactory> factory_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000338};
339
340static const int kTestTemporalLayerProfile[3] = {3, 2, 1};
341
Noah Richards41ee1ea2015-04-15 09:24:26 -0700342class TestSimulcastEncoderAdapterFake : public ::testing::Test,
343 public EncodedImageCallback {
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000344 public:
345 TestSimulcastEncoderAdapterFake()
Noah Richards41ee1ea2015-04-15 09:24:26 -0700346 : helper_(new TestSimulcastEncoderAdapterFakeHelper()),
347 adapter_(helper_->CreateMockEncoderAdapter()),
348 last_encoded_image_width_(-1),
349 last_encoded_image_height_(-1),
350 last_encoded_image_simulcast_index_(-1) {}
brandtr5e171752017-05-23 03:32:16 -0700351 virtual ~TestSimulcastEncoderAdapterFake() {
352 if (adapter_) {
353 adapter_->Release();
354 }
355 }
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000356
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700357 Result OnEncodedImage(const EncodedImage& encoded_image,
358 const CodecSpecificInfo* codec_specific_info,
359 const RTPFragmentationHeader* fragmentation) override {
360 last_encoded_image_width_ = encoded_image._encodedWidth;
361 last_encoded_image_height_ = encoded_image._encodedHeight;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200362 last_encoded_image_simulcast_index_ =
363 encoded_image.SpatialIndex().value_or(-1);
364
Niels Möller72bc8d62018-09-12 10:03:51 +0200365 return Result(Result::OK, encoded_image.Timestamp());
Noah Richards41ee1ea2015-04-15 09:24:26 -0700366 }
367
368 bool GetLastEncodedImageInfo(int* out_width,
369 int* out_height,
370 int* out_simulcast_index) {
371 if (last_encoded_image_width_ == -1) {
372 return false;
373 }
374 *out_width = last_encoded_image_width_;
375 *out_height = last_encoded_image_height_;
376 *out_simulcast_index = last_encoded_image_simulcast_index_;
377 return true;
378 }
379
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000380 void SetupCodec() {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200381 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200382 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
383 kVideoCodecVP8);
Erik Språng82fad3d2018-03-21 09:57:23 +0100384 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000385 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Noah Richards41ee1ea2015-04-15 09:24:26 -0700386 adapter_->RegisterEncodeCompleteCallback(this);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000387 }
388
389 void VerifyCodec(const VideoCodec& ref, int stream_index) {
390 const VideoCodec& target =
391 helper_->factory()->encoders()[stream_index]->codec();
392 EXPECT_EQ(ref.codecType, target.codecType);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000393 EXPECT_EQ(ref.plType, target.plType);
394 EXPECT_EQ(ref.width, target.width);
395 EXPECT_EQ(ref.height, target.height);
396 EXPECT_EQ(ref.startBitrate, target.startBitrate);
397 EXPECT_EQ(ref.maxBitrate, target.maxBitrate);
398 EXPECT_EQ(ref.minBitrate, target.minBitrate);
399 EXPECT_EQ(ref.maxFramerate, target.maxFramerate);
hta257dc392016-10-25 09:05:06 -0700400 EXPECT_EQ(ref.VP8().complexity, target.VP8().complexity);
hta257dc392016-10-25 09:05:06 -0700401 EXPECT_EQ(ref.VP8().numberOfTemporalLayers,
402 target.VP8().numberOfTemporalLayers);
403 EXPECT_EQ(ref.VP8().denoisingOn, target.VP8().denoisingOn);
hta257dc392016-10-25 09:05:06 -0700404 EXPECT_EQ(ref.VP8().automaticResizeOn, target.VP8().automaticResizeOn);
405 EXPECT_EQ(ref.VP8().frameDroppingOn, target.VP8().frameDroppingOn);
406 EXPECT_EQ(ref.VP8().keyFrameInterval, target.VP8().keyFrameInterval);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000407 EXPECT_EQ(ref.qpMax, target.qpMax);
408 EXPECT_EQ(0, target.numberOfSimulcastStreams);
409 EXPECT_EQ(ref.mode, target.mode);
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000410
411 // No need to compare simulcastStream as numberOfSimulcastStreams should
412 // always be 0.
413 }
414
415 void InitRefCodec(int stream_index, VideoCodec* ref_codec) {
416 *ref_codec = codec_;
hta257dc392016-10-25 09:05:06 -0700417 ref_codec->VP8()->numberOfTemporalLayers =
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000418 kTestTemporalLayerProfile[stream_index];
419 ref_codec->width = codec_.simulcastStream[stream_index].width;
420 ref_codec->height = codec_.simulcastStream[stream_index].height;
421 ref_codec->maxBitrate = codec_.simulcastStream[stream_index].maxBitrate;
422 ref_codec->minBitrate = codec_.simulcastStream[stream_index].minBitrate;
423 ref_codec->qpMax = codec_.simulcastStream[stream_index].qpMax;
424 }
425
426 void VerifyCodecSettings() {
427 EXPECT_EQ(3u, helper_->factory()->encoders().size());
428 VideoCodec ref_codec;
429
430 // stream 0, the lowest resolution stream.
431 InitRefCodec(0, &ref_codec);
432 ref_codec.qpMax = 45;
Niels Möllere3cf3d02018-06-13 11:52:16 +0200433 ref_codec.VP8()->complexity =
434 webrtc::VideoCodecComplexity::kComplexityHigher;
hta257dc392016-10-25 09:05:06 -0700435 ref_codec.VP8()->denoisingOn = false;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000436 ref_codec.startBitrate = 100; // Should equal to the target bitrate.
437 VerifyCodec(ref_codec, 0);
438
439 // stream 1
440 InitRefCodec(1, &ref_codec);
hta257dc392016-10-25 09:05:06 -0700441 ref_codec.VP8()->denoisingOn = false;
Noah Richards67b635a2015-05-22 14:12:10 -0700442 // The start bitrate (300kbit) minus what we have for the lower layers
443 // (100kbit).
444 ref_codec.startBitrate = 200;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000445 VerifyCodec(ref_codec, 1);
446
447 // stream 2, the biggest resolution stream.
448 InitRefCodec(2, &ref_codec);
Noah Richards67b635a2015-05-22 14:12:10 -0700449 // We don't have enough bits to send this, so the adapter should have
450 // configured it to use the min bitrate for this layer (600kbit) but turn
451 // off sending.
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000452 ref_codec.startBitrate = 600;
453 VerifyCodec(ref_codec, 2);
454 }
455
456 protected:
kwiberg3f55dea2016-02-29 05:51:59 -0800457 std::unique_ptr<TestSimulcastEncoderAdapterFakeHelper> helper_;
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200458 std::unique_ptr<VideoEncoder> adapter_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000459 VideoCodec codec_;
Noah Richards41ee1ea2015-04-15 09:24:26 -0700460 int last_encoded_image_width_;
461 int last_encoded_image_height_;
462 int last_encoded_image_simulcast_index_;
Erik Språng08127a92016-11-16 16:41:30 +0100463 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
pbos@webrtc.org9115cde2014-12-09 10:36:40 +0000464};
465
466TEST_F(TestSimulcastEncoderAdapterFake, InitEncode) {
467 SetupCodec();
468 VerifyCodecSettings();
469}
470
brandtr5e171752017-05-23 03:32:16 -0700471TEST_F(TestSimulcastEncoderAdapterFake, ReleaseWithoutInitEncode) {
472 EXPECT_EQ(0, adapter_->Release());
473}
474
475TEST_F(TestSimulcastEncoderAdapterFake, Reinit) {
476 SetupCodec();
477 EXPECT_EQ(0, adapter_->Release());
478
479 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
480}
481
Noah Richards41ee1ea2015-04-15 09:24:26 -0700482TEST_F(TestSimulcastEncoderAdapterFake, EncodedCallbackForDifferentEncoders) {
483 SetupCodec();
484
Peter Boström5d0379d2015-10-06 14:04:51 +0200485 // Set bitrates so that we send all layers.
Erik Språng08127a92016-11-16 16:41:30 +0100486 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
Peter Boström5d0379d2015-10-06 14:04:51 +0200487
Noah Richards41ee1ea2015-04-15 09:24:26 -0700488 // At this point, the simulcast encoder adapter should have 3 streams: HD,
489 // quarter HD, and quarter quarter HD. We're going to mostly ignore the exact
490 // resolutions, to test that the adapter forwards on the correct resolution
491 // and simulcast index values, going only off the encoder that generates the
492 // image.
brandtr5e171752017-05-23 03:32:16 -0700493 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
494 ASSERT_EQ(3u, encoders.size());
495 encoders[0]->SendEncodedImage(1152, 704);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700496 int width;
497 int height;
498 int simulcast_index;
499 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
500 EXPECT_EQ(1152, width);
501 EXPECT_EQ(704, height);
502 EXPECT_EQ(0, simulcast_index);
503
brandtr5e171752017-05-23 03:32:16 -0700504 encoders[1]->SendEncodedImage(300, 620);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700505 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
506 EXPECT_EQ(300, width);
507 EXPECT_EQ(620, height);
508 EXPECT_EQ(1, simulcast_index);
509
brandtr5e171752017-05-23 03:32:16 -0700510 encoders[2]->SendEncodedImage(120, 240);
Noah Richards41ee1ea2015-04-15 09:24:26 -0700511 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
512 EXPECT_EQ(120, width);
513 EXPECT_EQ(240, height);
514 EXPECT_EQ(2, simulcast_index);
515}
516
brandtr5e171752017-05-23 03:32:16 -0700517// This test verifies that the underlying encoders are reused, when the adapter
518// is reinited with different number of simulcast streams. It further checks
519// that the allocated encoders are reused in the same order as before, starting
520// with the lowest stream.
521TEST_F(TestSimulcastEncoderAdapterFake, ReusesEncodersInOrder) {
522 // Set up common settings for three streams.
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200523 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200524 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
525 kVideoCodecVP8);
Erik Språng82fad3d2018-03-21 09:57:23 +0100526 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
brandtr5e171752017-05-23 03:32:16 -0700527 adapter_->RegisterEncodeCompleteCallback(this);
Erik Språng7d687b12018-09-12 17:04:10 +0200528 const uint32_t target_bitrate =
529 1000 * (codec_.simulcastStream[0].targetBitrate +
530 codec_.simulcastStream[1].targetBitrate +
531 codec_.simulcastStream[2].minBitrate);
brandtr5e171752017-05-23 03:32:16 -0700532
533 // Input data.
534 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
535 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
536 std::vector<FrameType> frame_types;
537
538 // Encode with three streams.
539 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
540 VerifyCodecSettings();
Erik Språng7d687b12018-09-12 17:04:10 +0200541 adapter_->SetRateAllocation(
542 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
543
brandtr5e171752017-05-23 03:32:16 -0700544 std::vector<MockVideoEncoder*> original_encoders =
545 helper_->factory()->encoders();
546 ASSERT_EQ(3u, original_encoders.size());
547 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
548 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
549 EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
550 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
551 EXPECT_CALL(*original_encoders[2], Encode(_, _, _))
552 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
553 frame_types.resize(3, kVideoFrameKey);
554 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
555 EXPECT_CALL(*original_encoders[0], Release())
556 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
557 EXPECT_CALL(*original_encoders[1], Release())
558 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
559 EXPECT_CALL(*original_encoders[2], Release())
560 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
561 EXPECT_EQ(0, adapter_->Release());
562
563 // Encode with two streams.
564 codec_.width /= 2;
565 codec_.height /= 2;
566 codec_.numberOfSimulcastStreams = 2;
567 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200568 adapter_->SetRateAllocation(
569 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700570 std::vector<MockVideoEncoder*> new_encoders = helper_->factory()->encoders();
571 ASSERT_EQ(2u, new_encoders.size());
572 ASSERT_EQ(original_encoders[0], new_encoders[0]);
573 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
574 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
575 ASSERT_EQ(original_encoders[1], new_encoders[1]);
576 EXPECT_CALL(*original_encoders[1], Encode(_, _, _))
577 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
578 frame_types.resize(2, kVideoFrameKey);
579 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
580 EXPECT_CALL(*original_encoders[0], Release())
581 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
582 EXPECT_CALL(*original_encoders[1], Release())
583 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
584 EXPECT_EQ(0, adapter_->Release());
585
586 // Encode with single stream.
587 codec_.width /= 2;
588 codec_.height /= 2;
589 codec_.numberOfSimulcastStreams = 1;
590 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200591 adapter_->SetRateAllocation(
592 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700593 new_encoders = helper_->factory()->encoders();
594 ASSERT_EQ(1u, new_encoders.size());
595 ASSERT_EQ(original_encoders[0], new_encoders[0]);
596 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
597 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
598 frame_types.resize(1, kVideoFrameKey);
599 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
600 EXPECT_CALL(*original_encoders[0], Release())
601 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
602 EXPECT_EQ(0, adapter_->Release());
603
604 // Encode with three streams, again.
605 codec_.width *= 4;
606 codec_.height *= 4;
607 codec_.numberOfSimulcastStreams = 3;
608 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng7d687b12018-09-12 17:04:10 +0200609 adapter_->SetRateAllocation(
610 rate_allocator_->GetAllocation(target_bitrate, 30), 30);
brandtr5e171752017-05-23 03:32:16 -0700611 new_encoders = helper_->factory()->encoders();
612 ASSERT_EQ(3u, new_encoders.size());
613 // The first encoder is reused.
614 ASSERT_EQ(original_encoders[0], new_encoders[0]);
615 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
616 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
617 // The second and third encoders are new.
618 EXPECT_CALL(*new_encoders[1], Encode(_, _, _))
619 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
620 EXPECT_CALL(*new_encoders[2], Encode(_, _, _))
621 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
622 frame_types.resize(3, kVideoFrameKey);
623 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
624 EXPECT_CALL(*original_encoders[0], Release())
625 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
626 EXPECT_CALL(*new_encoders[1], Release())
627 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
628 EXPECT_CALL(*new_encoders[2], Release())
629 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
630 EXPECT_EQ(0, adapter_->Release());
631}
632
633TEST_F(TestSimulcastEncoderAdapterFake, DoesNotLeakEncoders) {
634 SetupCodec();
635 VerifyCodecSettings();
636
637 EXPECT_EQ(3u, helper_->factory()->encoders().size());
638
639 // The adapter should destroy all encoders it has allocated. Since
640 // |helper_->factory()| is owned by |adapter_|, however, we need to rely on
641 // lsan to find leaks here.
642 EXPECT_EQ(0, adapter_->Release());
643 adapter_.reset();
644}
645
646// This test verifies that an adapter reinit with the same codec settings as
647// before does not change the underlying encoder codec settings.
648TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderEncoderSettings) {
649 SetupCodec();
650 VerifyCodecSettings();
651
652 // Capture current codec settings.
653 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
654 ASSERT_EQ(3u, encoders.size());
655 std::array<VideoCodec, 3> codecs_before;
656 for (int i = 0; i < 3; ++i) {
657 codecs_before[i] = encoders[i]->codec();
658 }
659
660 // Reinitialize and verify that the new codec settings are the same.
661 EXPECT_EQ(0, adapter_->Release());
662 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
663 for (int i = 0; i < 3; ++i) {
664 const VideoCodec& codec_before = codecs_before[i];
665 const VideoCodec& codec_after = encoders[i]->codec();
666
667 // webrtc::VideoCodec does not implement operator==.
668 EXPECT_EQ(codec_before.codecType, codec_after.codecType);
669 EXPECT_EQ(codec_before.plType, codec_after.plType);
670 EXPECT_EQ(codec_before.width, codec_after.width);
671 EXPECT_EQ(codec_before.height, codec_after.height);
672 EXPECT_EQ(codec_before.startBitrate, codec_after.startBitrate);
673 EXPECT_EQ(codec_before.maxBitrate, codec_after.maxBitrate);
674 EXPECT_EQ(codec_before.minBitrate, codec_after.minBitrate);
675 EXPECT_EQ(codec_before.targetBitrate, codec_after.targetBitrate);
676 EXPECT_EQ(codec_before.maxFramerate, codec_after.maxFramerate);
677 EXPECT_EQ(codec_before.qpMax, codec_after.qpMax);
678 EXPECT_EQ(codec_before.numberOfSimulcastStreams,
679 codec_after.numberOfSimulcastStreams);
680 EXPECT_EQ(codec_before.mode, codec_after.mode);
681 EXPECT_EQ(codec_before.expect_encode_from_texture,
682 codec_after.expect_encode_from_texture);
683 }
684}
685
686// This test is similar to the one above, except that it tests the simulcastIdx
687// from the CodecSpecificInfo that is connected to an encoded frame. The
688// PayloadRouter demuxes the incoming encoded frames on different RTP modules
689// using the simulcastIdx, so it's important that there is no corresponding
690// encoder reordering in between adapter reinits as this would lead to PictureID
691// discontinuities.
692TEST_F(TestSimulcastEncoderAdapterFake, ReinitDoesNotReorderFrameSimulcastIdx) {
693 SetupCodec();
694 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
695 VerifyCodecSettings();
696
697 // Send frames on all streams.
698 std::vector<MockVideoEncoder*> encoders = helper_->factory()->encoders();
699 ASSERT_EQ(3u, encoders.size());
700 encoders[0]->SendEncodedImage(1152, 704);
701 int width;
702 int height;
703 int simulcast_index;
704 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
705 EXPECT_EQ(0, simulcast_index);
706
707 encoders[1]->SendEncodedImage(300, 620);
708 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
709 EXPECT_EQ(1, simulcast_index);
710
711 encoders[2]->SendEncodedImage(120, 240);
712 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
713 EXPECT_EQ(2, simulcast_index);
714
715 // Reinitialize.
716 EXPECT_EQ(0, adapter_->Release());
717 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
718 adapter_->SetRateAllocation(rate_allocator_->GetAllocation(1200, 30), 30);
719
720 // Verify that the same encoder sends out frames on the same simulcast index.
721 encoders[0]->SendEncodedImage(1152, 704);
722 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
723 EXPECT_EQ(0, simulcast_index);
724
725 encoders[1]->SendEncodedImage(300, 620);
726 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
727 EXPECT_EQ(1, simulcast_index);
728
729 encoders[2]->SendEncodedImage(120, 240);
730 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index));
731 EXPECT_EQ(2, simulcast_index);
732}
733
pbos65e15ba2015-10-15 10:52:15 -0700734TEST_F(TestSimulcastEncoderAdapterFake, SupportsNativeHandleForSingleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200735 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200736 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
737 kVideoCodecVP8);
pbos65e15ba2015-10-15 10:52:15 -0700738 codec_.numberOfSimulcastStreams = 1;
739 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
740 adapter_->RegisterEncodeCompleteCallback(this);
741 ASSERT_EQ(1u, helper_->factory()->encoders().size());
742 helper_->factory()->encoders()[0]->set_supports_native_handle(true);
Erik Språng75de46a2018-11-07 14:53:32 +0100743 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
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ång75de46a2018-11-07 14:53:32 +0100746 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språnge2fd86a2018-10-24 11:32:39 +0200747 EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle);
pbos65e15ba2015-10-15 10:52:15 -0700748}
749
noahricfac0ff02016-09-09 10:27:15 -0700750TEST_F(TestSimulcastEncoderAdapterFake, SetRatesUnderMinBitrate) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200751 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200752 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
753 kVideoCodecVP8);
noahricfac0ff02016-09-09 10:27:15 -0700754 codec_.minBitrate = 50;
755 codec_.numberOfSimulcastStreams = 1;
756 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språng82fad3d2018-03-21 09:57:23 +0100757 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
noahricfac0ff02016-09-09 10:27:15 -0700758
759 // Above min should be respected.
Erik Språng566124a2018-04-23 12:32:22 +0200760 VideoBitrateAllocation target_bitrate =
Erik Språng08127a92016-11-16 16:41:30 +0100761 rate_allocator_->GetAllocation(codec_.minBitrate * 1000, 30);
762 adapter_->SetRateAllocation(target_bitrate, 30);
763 EXPECT_EQ(target_bitrate,
764 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700765
766 // Below min but non-zero should be replaced with the min bitrate.
Erik Språng566124a2018-04-23 12:32:22 +0200767 VideoBitrateAllocation too_low_bitrate =
Erik Språng08127a92016-11-16 16:41:30 +0100768 rate_allocator_->GetAllocation((codec_.minBitrate - 1) * 1000, 30);
769 adapter_->SetRateAllocation(too_low_bitrate, 30);
770 EXPECT_EQ(target_bitrate,
771 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700772
773 // Zero should be passed on as is, since it means "pause".
Erik Språng566124a2018-04-23 12:32:22 +0200774 adapter_->SetRateAllocation(VideoBitrateAllocation(), 30);
775 EXPECT_EQ(VideoBitrateAllocation(),
Erik Språng08127a92016-11-16 16:41:30 +0100776 helper_->factory()->encoders()[0]->last_set_bitrate());
noahricfac0ff02016-09-09 10:27:15 -0700777}
778
Peter Boströma5dec162016-01-20 15:53:55 +0100779TEST_F(TestSimulcastEncoderAdapterFake, SupportsImplementationName) {
Erik Språnge2fd86a2018-10-24 11:32:39 +0200780 EXPECT_EQ("SimulcastEncoderAdapter",
781 adapter_->GetEncoderInfo().implementation_name);
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200782 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200783 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
784 kVideoCodecVP8);
Peter Boströma5dec162016-01-20 15:53:55 +0100785 std::vector<const char*> encoder_names;
786 encoder_names.push_back("codec1");
787 encoder_names.push_back("codec2");
788 encoder_names.push_back("codec3");
789 helper_->factory()->SetEncoderNames(encoder_names);
790 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språnge2fd86a2018-10-24 11:32:39 +0200791 EXPECT_EQ("SimulcastEncoderAdapter (codec1, codec2, codec3)",
792 adapter_->GetEncoderInfo().implementation_name);
Peter Boströmd53c3892016-03-30 17:03:52 +0200793
794 // Single streams should not expose "SimulcastEncoderAdapter" in name.
brandtr5e171752017-05-23 03:32:16 -0700795 EXPECT_EQ(0, adapter_->Release());
Peter Boströmd53c3892016-03-30 17:03:52 +0200796 codec_.numberOfSimulcastStreams = 1;
797 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
798 adapter_->RegisterEncodeCompleteCallback(this);
799 ASSERT_EQ(1u, helper_->factory()->encoders().size());
Erik Språnge2fd86a2018-10-24 11:32:39 +0200800 EXPECT_EQ("codec1", adapter_->GetEncoderInfo().implementation_name);
Peter Boströma5dec162016-01-20 15:53:55 +0100801}
802
pbos65e15ba2015-10-15 10:52:15 -0700803TEST_F(TestSimulcastEncoderAdapterFake,
noahricfe3654d2016-07-01 09:05:54 -0700804 SupportsNativeHandleForMultipleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200805 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200806 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
807 kVideoCodecVP8);
pbos65e15ba2015-10-15 10:52:15 -0700808 codec_.numberOfSimulcastStreams = 3;
809 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
810 adapter_->RegisterEncodeCompleteCallback(this);
811 ASSERT_EQ(3u, helper_->factory()->encoders().size());
812 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
813 encoder->set_supports_native_handle(true);
noahricfe3654d2016-07-01 09:05:54 -0700814 // If one encoder doesn't support it, then overall support is disabled.
815 helper_->factory()->encoders()[0]->set_supports_native_handle(false);
Erik Språnge2fd86a2018-10-24 11:32:39 +0200816 EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle);
noahricfe3654d2016-07-01 09:05:54 -0700817 // Once all do, then the adapter claims support.
818 helper_->factory()->encoders()[0]->set_supports_native_handle(true);
Erik Språng75de46a2018-11-07 14:53:32 +0100819 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språnge2fd86a2018-10-24 11:32:39 +0200820 EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
noahricfe3654d2016-07-01 09:05:54 -0700821}
822
nisseaf916892017-01-10 07:44:26 -0800823// TODO(nisse): Reuse definition in webrtc/test/fake_texture_handle.h.
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200824class FakeNativeBufferNoI420 : public VideoFrameBuffer {
noahricfe3654d2016-07-01 09:05:54 -0700825 public:
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200826 FakeNativeBufferNoI420(int width, int height)
827 : width_(width), height_(height) {}
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000828
829 Type type() const override { return Type::kNative; }
830 int width() const override { return width_; }
831 int height() const override { return height_; }
832
833 rtc::scoped_refptr<I420BufferInterface> ToI420() override {
noahricfe3654d2016-07-01 09:05:54 -0700834 RTC_NOTREACHED();
835 return nullptr;
836 }
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000837
838 private:
839 const int width_;
840 const int height_;
noahricfe3654d2016-07-01 09:05:54 -0700841};
842
843TEST_F(TestSimulcastEncoderAdapterFake,
844 NativeHandleForwardingForMultipleStreams) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200845 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200846 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
847 kVideoCodecVP8);
noahricfe3654d2016-07-01 09:05:54 -0700848 codec_.numberOfSimulcastStreams = 3;
849 // High start bitrate, so all streams are enabled.
850 codec_.startBitrate = 3000;
851 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
852 adapter_->RegisterEncodeCompleteCallback(this);
853 ASSERT_EQ(3u, helper_->factory()->encoders().size());
854 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
855 encoder->set_supports_native_handle(true);
Erik Språng75de46a2018-11-07 14:53:32 +0100856 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
Erik Språnge2fd86a2018-10-24 11:32:39 +0200857 EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle);
noahricfe3654d2016-07-01 09:05:54 -0700858
859 rtc::scoped_refptr<VideoFrameBuffer> buffer(
Mirko Bonadeid93a51d2018-07-17 15:47:51 +0200860 new rtc::RefCountedObject<FakeNativeBufferNoI420>(1280, 720));
noahricfe3654d2016-07-01 09:05:54 -0700861 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
862 // Expect calls with the given video frame verbatim, since it's a texture
863 // frame and can't otherwise be modified/resized.
864 for (MockVideoEncoder* encoder : helper_->factory()->encoders())
865 EXPECT_CALL(*encoder, Encode(::testing::Ref(input_frame), _, _)).Times(1);
866 std::vector<FrameType> frame_types(3, kVideoFrameKey);
brandtr5e171752017-05-23 03:32:16 -0700867 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
pbos65e15ba2015-10-15 10:52:15 -0700868}
869
noahric57779102016-05-25 06:48:46 -0700870TEST_F(TestSimulcastEncoderAdapterFake, TestFailureReturnCodesFromEncodeCalls) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200871 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200872 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
873 kVideoCodecVP8);
noahric57779102016-05-25 06:48:46 -0700874 codec_.numberOfSimulcastStreams = 3;
875 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
876 adapter_->RegisterEncodeCompleteCallback(this);
877 ASSERT_EQ(3u, helper_->factory()->encoders().size());
878 // Tell the 2nd encoder to request software fallback.
noahricfe3654d2016-07-01 09:05:54 -0700879 EXPECT_CALL(*helper_->factory()->encoders()[1], Encode(_, _, _))
880 .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE));
noahric57779102016-05-25 06:48:46 -0700881
882 // Send a fake frame and assert the return is software fallback.
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000883 rtc::scoped_refptr<I420Buffer> input_buffer =
884 I420Buffer::Create(kDefaultWidth, kDefaultHeight);
nisse64ec8f82016-09-27 00:17:25 -0700885 input_buffer->InitializeData();
886 VideoFrame input_frame(input_buffer, 0, 0, webrtc::kVideoRotation_0);
noahric57779102016-05-25 06:48:46 -0700887 std::vector<FrameType> frame_types(3, kVideoFrameKey);
888 EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
889 adapter_->Encode(input_frame, nullptr, &frame_types));
890}
891
noahrice5ba75a2016-12-12 13:08:27 -0800892TEST_F(TestSimulcastEncoderAdapterFake, TestInitFailureCleansUpEncoders) {
Rasmus Brandt0cedc052018-05-31 12:53:00 +0200893 SimulcastTestFixtureImpl::DefaultSettings(
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200894 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
895 kVideoCodecVP8);
noahrice5ba75a2016-12-12 13:08:27 -0800896 codec_.numberOfSimulcastStreams = 3;
897 helper_->factory()->set_init_encode_return_value(
898 WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
899 EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
900 adapter_->InitEncode(&codec_, 1, 1200));
901 EXPECT_TRUE(helper_->factory()->encoders().empty());
902}
903
Erik Språng8d2995b2018-08-09 11:18:17 +0200904TEST_F(TestSimulcastEncoderAdapterFake, DoesNotAlterMaxQpForScreenshare) {
905 const int kHighMaxQp = 56;
906 const int kLowMaxQp = 46;
907
908 SimulcastTestFixtureImpl::DefaultSettings(
909 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
910 kVideoCodecVP8);
911 codec_.numberOfSimulcastStreams = 3;
912 codec_.simulcastStream[0].qpMax = kHighMaxQp;
913 codec_.mode = VideoCodecMode::kScreensharing;
914
915 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
916 EXPECT_EQ(3u, helper_->factory()->encoders().size());
917
918 // Just check the lowest stream, which is the one that where the adapter
919 // might alter the max qp setting.
920 VideoCodec ref_codec;
921 InitRefCodec(0, &ref_codec);
922 ref_codec.qpMax = kHighMaxQp;
923 ref_codec.VP8()->complexity = webrtc::VideoCodecComplexity::kComplexityHigher;
924 ref_codec.VP8()->denoisingOn = false;
925 ref_codec.startBitrate = 100; // Should equal to the target bitrate.
926 VerifyCodec(ref_codec, 0);
927
928 // Change the max qp and try again.
929 codec_.simulcastStream[0].qpMax = kLowMaxQp;
930 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
931 EXPECT_EQ(3u, helper_->factory()->encoders().size());
932 ref_codec.qpMax = kLowMaxQp;
933 VerifyCodec(ref_codec, 0);
934}
Erik Språng7d687b12018-09-12 17:04:10 +0200935
936TEST_F(TestSimulcastEncoderAdapterFake, ActivatesCorrectStreamsInInitEncode) {
937 // Set up common settings for three streams.
938 SimulcastTestFixtureImpl::DefaultSettings(
939 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
940 kVideoCodecVP8);
941 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
942 adapter_->RegisterEncodeCompleteCallback(this);
943
944 // Only enough start bitrate for the lowest stream.
945 ASSERT_EQ(3u, codec_.numberOfSimulcastStreams);
946 codec_.startBitrate = codec_.simulcastStream[0].targetBitrate +
947 codec_.simulcastStream[1].minBitrate - 1;
948
949 // Input data.
950 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
951 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
952
953 // Encode with three streams.
954 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
955 std::vector<MockVideoEncoder*> original_encoders =
956 helper_->factory()->encoders();
957 ASSERT_EQ(3u, original_encoders.size());
958 // Only first encoder will be active and called.
959 EXPECT_CALL(*original_encoders[0], Encode(_, _, _))
960 .WillOnce(Return(WEBRTC_VIDEO_CODEC_OK));
961 EXPECT_CALL(*original_encoders[1], Encode(_, _, _)).Times(0);
962 EXPECT_CALL(*original_encoders[2], Encode(_, _, _)).Times(0);
963
964 std::vector<FrameType> frame_types;
965 frame_types.resize(3, kVideoFrameKey);
966 EXPECT_EQ(0, adapter_->Encode(input_frame, nullptr, &frame_types));
967}
Erik Språngd3438aa2018-11-08 16:56:43 +0100968
969TEST_F(TestSimulcastEncoderAdapterFake, TrustedRateControl) {
970 // Set up common settings for three streams.
971 SimulcastTestFixtureImpl::DefaultSettings(
972 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
973 kVideoCodecVP8);
974 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
975 adapter_->RegisterEncodeCompleteCallback(this);
976
977 // Only enough start bitrate for the lowest stream.
978 ASSERT_EQ(3u, codec_.numberOfSimulcastStreams);
979 codec_.startBitrate = codec_.simulcastStream[0].targetBitrate +
980 codec_.simulcastStream[1].minBitrate - 1;
981
982 // Input data.
983 rtc::scoped_refptr<VideoFrameBuffer> buffer(I420Buffer::Create(1280, 720));
984 VideoFrame input_frame(buffer, 100, 1000, kVideoRotation_180);
985
986 // No encoder trusted, so simulcast adapter should not be either.
987 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
988 EXPECT_FALSE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
989
990 // Encode with three streams.
991 std::vector<MockVideoEncoder*> original_encoders =
992 helper_->factory()->encoders();
993
994 // All encoders are trusted, so simulcast adapter should be too.
995 original_encoders[0]->set_has_trusted_rate_controller(true);
996 original_encoders[1]->set_has_trusted_rate_controller(true);
997 original_encoders[2]->set_has_trusted_rate_controller(true);
998 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
999 EXPECT_TRUE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
1000
1001 // One encoder not trusted, so simulcast adapter should not be either.
1002 original_encoders[2]->set_has_trusted_rate_controller(false);
1003 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1004 EXPECT_FALSE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
1005
1006 // No encoder trusted, so simulcast adapter should not be either.
1007 original_encoders[0]->set_has_trusted_rate_controller(false);
1008 original_encoders[1]->set_has_trusted_rate_controller(false);
1009 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1010 EXPECT_FALSE(adapter_->GetEncoderInfo().has_trusted_rate_controller);
1011}
1012
Mirta Dvornicic897a9912018-11-30 13:12:21 +01001013TEST_F(TestSimulcastEncoderAdapterFake, ReportsHardwareAccelerated) {
1014 SimulcastTestFixtureImpl::DefaultSettings(
1015 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
1016 kVideoCodecVP8);
1017 codec_.numberOfSimulcastStreams = 3;
1018 adapter_->RegisterEncodeCompleteCallback(this);
1019 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1020 ASSERT_EQ(3u, helper_->factory()->encoders().size());
1021
1022 // None of the encoders uses HW support, so simulcast adapter reports false.
1023 for (MockVideoEncoder* encoder : helper_->factory()->encoders()) {
1024 encoder->set_is_hardware_accelerated(false);
1025 }
1026 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1027 EXPECT_FALSE(adapter_->GetEncoderInfo().is_hardware_accelerated);
1028
1029 // One encoder uses HW support, so simulcast adapter reports true.
1030 helper_->factory()->encoders()[2]->set_is_hardware_accelerated(true);
1031 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1032 EXPECT_TRUE(adapter_->GetEncoderInfo().is_hardware_accelerated);
1033}
1034
1035TEST_F(TestSimulcastEncoderAdapterFake, ReportsInternalSource) {
1036 SimulcastTestFixtureImpl::DefaultSettings(
1037 &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
1038 kVideoCodecVP8);
1039 codec_.numberOfSimulcastStreams = 3;
1040 adapter_->RegisterEncodeCompleteCallback(this);
1041 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1042 ASSERT_EQ(3u, helper_->factory()->encoders().size());
1043
1044 // All encoders have internal source, simulcast adapter reports true.
1045 for (MockVideoEncoder* encoder : helper_->factory()->encoders()) {
1046 encoder->set_has_internal_source(true);
1047 }
1048 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1049 EXPECT_TRUE(adapter_->GetEncoderInfo().has_internal_source);
1050
1051 // One encoder does not have internal source, simulcast adapter reports false.
1052 helper_->factory()->encoders()[2]->set_has_internal_source(false);
1053 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
1054 EXPECT_FALSE(adapter_->GetEncoderInfo().has_internal_source);
1055}
1056
Rasmus Brandt0cedc052018-05-31 12:53:00 +02001057} // namespace test
pbos@webrtc.org9115cde2014-12-09 10:36:40 +00001058} // namespace webrtc