1 /* 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 11 #include <vector> 12 13 #include "testing/gmock/include/gmock/gmock.h" 14 #include "webrtc/modules/video_coding/include/video_codec_interface.h" 15 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" 16 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h" 17 #include "webrtc/modules/video_coding/codecs/vp8/vp8_factory.h" 18 19 namespace webrtc { 20 namespace testing { 21 22 static VP8Encoder* CreateTestEncoderAdapter() { 23 VP8EncoderFactoryConfig::set_use_simulcast_adapter(true); 24 return VP8Encoder::Create(); 25 } 26 27 class TestSimulcastEncoderAdapter : public TestVp8Simulcast { 28 public: 29 TestSimulcastEncoderAdapter() 30 : TestVp8Simulcast(CreateTestEncoderAdapter(), VP8Decoder::Create()) {} 31 32 protected: 33 virtual void SetUp() { TestVp8Simulcast::SetUp(); } 34 virtual void TearDown() { 35 TestVp8Simulcast::TearDown(); 36 VP8EncoderFactoryConfig::set_use_simulcast_adapter(false); 37 } 38 }; 39 40 TEST_F(TestSimulcastEncoderAdapter, TestKeyFrameRequestsOnAllStreams) { 41 TestVp8Simulcast::TestKeyFrameRequestsOnAllStreams(); 42 } 43 44 TEST_F(TestSimulcastEncoderAdapter, TestPaddingAllStreams) { 45 TestVp8Simulcast::TestPaddingAllStreams(); 46 } 47 48 TEST_F(TestSimulcastEncoderAdapter, TestPaddingTwoStreams) { 49 TestVp8Simulcast::TestPaddingTwoStreams(); 50 } 51 52 TEST_F(TestSimulcastEncoderAdapter, TestPaddingTwoStreamsOneMaxedOut) { 53 TestVp8Simulcast::TestPaddingTwoStreamsOneMaxedOut(); 54 } 55 56 TEST_F(TestSimulcastEncoderAdapter, TestPaddingOneStream) { 57 TestVp8Simulcast::TestPaddingOneStream(); 58 } 59 60 TEST_F(TestSimulcastEncoderAdapter, TestPaddingOneStreamTwoMaxedOut) { 61 TestVp8Simulcast::TestPaddingOneStreamTwoMaxedOut(); 62 } 63 64 TEST_F(TestSimulcastEncoderAdapter, TestSendAllStreams) { 65 TestVp8Simulcast::TestSendAllStreams(); 66 } 67 68 TEST_F(TestSimulcastEncoderAdapter, TestDisablingStreams) { 69 TestVp8Simulcast::TestDisablingStreams(); 70 } 71 72 TEST_F(TestSimulcastEncoderAdapter, TestSwitchingToOneStream) { 73 TestVp8Simulcast::TestSwitchingToOneStream(); 74 } 75 76 TEST_F(TestSimulcastEncoderAdapter, TestSwitchingToOneOddStream) { 77 TestVp8Simulcast::TestSwitchingToOneOddStream(); 78 } 79 80 TEST_F(TestSimulcastEncoderAdapter, TestRPSIEncodeDecode) { 81 TestVp8Simulcast::TestRPSIEncodeDecode(); 82 } 83 84 TEST_F(TestSimulcastEncoderAdapter, TestStrideEncodeDecode) { 85 TestVp8Simulcast::TestStrideEncodeDecode(); 86 } 87 88 TEST_F(TestSimulcastEncoderAdapter, TestSaptioTemporalLayers333PatternEncoder) { 89 TestVp8Simulcast::TestSaptioTemporalLayers333PatternEncoder(); 90 } 91 92 TEST_F(TestSimulcastEncoderAdapter, TestSpatioTemporalLayers321PatternEncoder) { 93 TestVp8Simulcast::TestSpatioTemporalLayers321PatternEncoder(); 94 } 95 96 // TODO(ronghuawu): Enable this test when SkipEncodingUnusedStreams option is 97 // implemented for SimulcastEncoderAdapter. 98 TEST_F(TestSimulcastEncoderAdapter, DISABLED_TestSkipEncodingUnusedStreams) { 99 TestVp8Simulcast::TestSkipEncodingUnusedStreams(); 100 } 101 102 TEST_F(TestSimulcastEncoderAdapter, DISABLED_TestRPSIEncoder) { 103 TestVp8Simulcast::TestRPSIEncoder(); 104 } 105 106 class MockVideoEncoder : public VideoEncoder { 107 public: 108 int32_t InitEncode(const VideoCodec* codecSettings, 109 int32_t numberOfCores, 110 size_t maxPayloadSize) override { 111 codec_ = *codecSettings; 112 return 0; 113 } 114 115 int32_t Encode(const VideoFrame& inputImage, 116 const CodecSpecificInfo* codecSpecificInfo, 117 const std::vector<FrameType>* frame_types) override { 118 return 0; 119 } 120 121 int32_t RegisterEncodeCompleteCallback( 122 EncodedImageCallback* callback) override { 123 callback_ = callback; 124 return 0; 125 } 126 127 int32_t Release() override { return 0; } 128 129 int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) override { 130 return 0; 131 } 132 133 MOCK_METHOD2(SetChannelParameters, int32_t(uint32_t packetLoss, int64_t rtt)); 134 135 bool SupportsNativeHandle() const override { return supports_native_handle_; } 136 137 virtual ~MockVideoEncoder() {} 138 139 const VideoCodec& codec() const { return codec_; } 140 141 void SendEncodedImage(int width, int height) { 142 // Sends a fake image of the given width/height. 143 EncodedImage image; 144 image._encodedWidth = width; 145 image._encodedHeight = height; 146 CodecSpecificInfo codecSpecificInfo; 147 memset(&codecSpecificInfo, 0, sizeof(codecSpecificInfo)); 148 callback_->Encoded(image, &codecSpecificInfo, NULL); 149 } 150 151 void set_supports_native_handle(bool enabled) { 152 supports_native_handle_ = enabled; 153 } 154 155 private: 156 bool supports_native_handle_ = false; 157 VideoCodec codec_; 158 EncodedImageCallback* callback_; 159 }; 160 161 class MockVideoEncoderFactory : public VideoEncoderFactory { 162 public: 163 VideoEncoder* Create() override { 164 MockVideoEncoder* encoder = new MockVideoEncoder(); 165 encoders_.push_back(encoder); 166 return encoder; 167 } 168 169 void Destroy(VideoEncoder* encoder) override { delete encoder; } 170 171 virtual ~MockVideoEncoderFactory() {} 172 173 const std::vector<MockVideoEncoder*>& encoders() const { return encoders_; } 174 175 private: 176 std::vector<MockVideoEncoder*> encoders_; 177 }; 178 179 class TestSimulcastEncoderAdapterFakeHelper { 180 public: 181 TestSimulcastEncoderAdapterFakeHelper() 182 : factory_(new MockVideoEncoderFactory()) {} 183 184 // Can only be called once as the SimulcastEncoderAdapter will take the 185 // ownership of |factory_|. 186 VP8Encoder* CreateMockEncoderAdapter() { 187 return new SimulcastEncoderAdapter(factory_); 188 } 189 190 void ExpectCallSetChannelParameters(uint32_t packetLoss, int64_t rtt) { 191 EXPECT_TRUE(!factory_->encoders().empty()); 192 for (size_t i = 0; i < factory_->encoders().size(); ++i) { 193 EXPECT_CALL(*factory_->encoders()[i], 194 SetChannelParameters(packetLoss, rtt)) 195 .Times(1); 196 } 197 } 198 199 MockVideoEncoderFactory* factory() { return factory_; } 200 201 private: 202 MockVideoEncoderFactory* factory_; 203 }; 204 205 static const int kTestTemporalLayerProfile[3] = {3, 2, 1}; 206 207 class TestSimulcastEncoderAdapterFake : public ::testing::Test, 208 public EncodedImageCallback { 209 public: 210 TestSimulcastEncoderAdapterFake() 211 : helper_(new TestSimulcastEncoderAdapterFakeHelper()), 212 adapter_(helper_->CreateMockEncoderAdapter()), 213 last_encoded_image_width_(-1), 214 last_encoded_image_height_(-1), 215 last_encoded_image_simulcast_index_(-1) {} 216 virtual ~TestSimulcastEncoderAdapterFake() {} 217 218 int32_t Encoded(const EncodedImage& encodedImage, 219 const CodecSpecificInfo* codecSpecificInfo = NULL, 220 const RTPFragmentationHeader* fragmentation = NULL) override { 221 last_encoded_image_width_ = encodedImage._encodedWidth; 222 last_encoded_image_height_ = encodedImage._encodedHeight; 223 if (codecSpecificInfo) { 224 last_encoded_image_simulcast_index_ = 225 codecSpecificInfo->codecSpecific.VP8.simulcastIdx; 226 } 227 return 0; 228 } 229 230 bool GetLastEncodedImageInfo(int* out_width, 231 int* out_height, 232 int* out_simulcast_index) { 233 if (last_encoded_image_width_ == -1) { 234 return false; 235 } 236 *out_width = last_encoded_image_width_; 237 *out_height = last_encoded_image_height_; 238 *out_simulcast_index = last_encoded_image_simulcast_index_; 239 return true; 240 } 241 242 void SetupCodec() { 243 TestVp8Simulcast::DefaultSettings( 244 &codec_, static_cast<const int*>(kTestTemporalLayerProfile)); 245 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); 246 adapter_->RegisterEncodeCompleteCallback(this); 247 } 248 249 void VerifyCodec(const VideoCodec& ref, int stream_index) { 250 const VideoCodec& target = 251 helper_->factory()->encoders()[stream_index]->codec(); 252 EXPECT_EQ(ref.codecType, target.codecType); 253 EXPECT_EQ(0, strcmp(ref.plName, target.plName)); 254 EXPECT_EQ(ref.plType, target.plType); 255 EXPECT_EQ(ref.width, target.width); 256 EXPECT_EQ(ref.height, target.height); 257 EXPECT_EQ(ref.startBitrate, target.startBitrate); 258 EXPECT_EQ(ref.maxBitrate, target.maxBitrate); 259 EXPECT_EQ(ref.minBitrate, target.minBitrate); 260 EXPECT_EQ(ref.maxFramerate, target.maxFramerate); 261 EXPECT_EQ(ref.codecSpecific.VP8.pictureLossIndicationOn, 262 target.codecSpecific.VP8.pictureLossIndicationOn); 263 EXPECT_EQ(ref.codecSpecific.VP8.feedbackModeOn, 264 target.codecSpecific.VP8.feedbackModeOn); 265 EXPECT_EQ(ref.codecSpecific.VP8.complexity, 266 target.codecSpecific.VP8.complexity); 267 EXPECT_EQ(ref.codecSpecific.VP8.resilience, 268 target.codecSpecific.VP8.resilience); 269 EXPECT_EQ(ref.codecSpecific.VP8.numberOfTemporalLayers, 270 target.codecSpecific.VP8.numberOfTemporalLayers); 271 EXPECT_EQ(ref.codecSpecific.VP8.denoisingOn, 272 target.codecSpecific.VP8.denoisingOn); 273 EXPECT_EQ(ref.codecSpecific.VP8.errorConcealmentOn, 274 target.codecSpecific.VP8.errorConcealmentOn); 275 EXPECT_EQ(ref.codecSpecific.VP8.automaticResizeOn, 276 target.codecSpecific.VP8.automaticResizeOn); 277 EXPECT_EQ(ref.codecSpecific.VP8.frameDroppingOn, 278 target.codecSpecific.VP8.frameDroppingOn); 279 EXPECT_EQ(ref.codecSpecific.VP8.keyFrameInterval, 280 target.codecSpecific.VP8.keyFrameInterval); 281 EXPECT_EQ(ref.qpMax, target.qpMax); 282 EXPECT_EQ(0, target.numberOfSimulcastStreams); 283 EXPECT_EQ(ref.mode, target.mode); 284 EXPECT_EQ(ref.extra_options, target.extra_options); 285 286 // No need to compare simulcastStream as numberOfSimulcastStreams should 287 // always be 0. 288 } 289 290 void InitRefCodec(int stream_index, VideoCodec* ref_codec) { 291 *ref_codec = codec_; 292 ref_codec->codecSpecific.VP8.numberOfTemporalLayers = 293 kTestTemporalLayerProfile[stream_index]; 294 ref_codec->width = codec_.simulcastStream[stream_index].width; 295 ref_codec->height = codec_.simulcastStream[stream_index].height; 296 ref_codec->maxBitrate = codec_.simulcastStream[stream_index].maxBitrate; 297 ref_codec->minBitrate = codec_.simulcastStream[stream_index].minBitrate; 298 ref_codec->qpMax = codec_.simulcastStream[stream_index].qpMax; 299 } 300 301 void VerifyCodecSettings() { 302 EXPECT_EQ(3u, helper_->factory()->encoders().size()); 303 VideoCodec ref_codec; 304 305 // stream 0, the lowest resolution stream. 306 InitRefCodec(0, &ref_codec); 307 ref_codec.qpMax = 45; 308 ref_codec.codecSpecific.VP8.complexity = webrtc::kComplexityHigher; 309 ref_codec.codecSpecific.VP8.denoisingOn = false; 310 ref_codec.startBitrate = 100; // Should equal to the target bitrate. 311 VerifyCodec(ref_codec, 0); 312 313 // stream 1 314 InitRefCodec(1, &ref_codec); 315 ref_codec.codecSpecific.VP8.denoisingOn = false; 316 // The start bitrate (300kbit) minus what we have for the lower layers 317 // (100kbit). 318 ref_codec.startBitrate = 200; 319 VerifyCodec(ref_codec, 1); 320 321 // stream 2, the biggest resolution stream. 322 InitRefCodec(2, &ref_codec); 323 // We don't have enough bits to send this, so the adapter should have 324 // configured it to use the min bitrate for this layer (600kbit) but turn 325 // off sending. 326 ref_codec.startBitrate = 600; 327 VerifyCodec(ref_codec, 2); 328 } 329 330 protected: 331 rtc::scoped_ptr<TestSimulcastEncoderAdapterFakeHelper> helper_; 332 rtc::scoped_ptr<VP8Encoder> adapter_; 333 VideoCodec codec_; 334 int last_encoded_image_width_; 335 int last_encoded_image_height_; 336 int last_encoded_image_simulcast_index_; 337 }; 338 339 TEST_F(TestSimulcastEncoderAdapterFake, InitEncode) { 340 SetupCodec(); 341 VerifyCodecSettings(); 342 } 343 344 TEST_F(TestSimulcastEncoderAdapterFake, SetChannelParameters) { 345 SetupCodec(); 346 const uint32_t packetLoss = 5; 347 const int64_t rtt = 30; 348 helper_->ExpectCallSetChannelParameters(packetLoss, rtt); 349 adapter_->SetChannelParameters(packetLoss, rtt); 350 } 351 352 TEST_F(TestSimulcastEncoderAdapterFake, EncodedCallbackForDifferentEncoders) { 353 SetupCodec(); 354 355 // Set bitrates so that we send all layers. 356 adapter_->SetRates(1200, 30); 357 358 // At this point, the simulcast encoder adapter should have 3 streams: HD, 359 // quarter HD, and quarter quarter HD. We're going to mostly ignore the exact 360 // resolutions, to test that the adapter forwards on the correct resolution 361 // and simulcast index values, going only off the encoder that generates the 362 // image. 363 EXPECT_EQ(3u, helper_->factory()->encoders().size()); 364 helper_->factory()->encoders()[0]->SendEncodedImage(1152, 704); 365 int width; 366 int height; 367 int simulcast_index; 368 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index)); 369 EXPECT_EQ(1152, width); 370 EXPECT_EQ(704, height); 371 EXPECT_EQ(0, simulcast_index); 372 373 helper_->factory()->encoders()[1]->SendEncodedImage(300, 620); 374 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index)); 375 EXPECT_EQ(300, width); 376 EXPECT_EQ(620, height); 377 EXPECT_EQ(1, simulcast_index); 378 379 helper_->factory()->encoders()[2]->SendEncodedImage(120, 240); 380 EXPECT_TRUE(GetLastEncodedImageInfo(&width, &height, &simulcast_index)); 381 EXPECT_EQ(120, width); 382 EXPECT_EQ(240, height); 383 EXPECT_EQ(2, simulcast_index); 384 } 385 386 TEST_F(TestSimulcastEncoderAdapterFake, SupportsNativeHandleForSingleStreams) { 387 TestVp8Simulcast::DefaultSettings( 388 &codec_, static_cast<const int*>(kTestTemporalLayerProfile)); 389 codec_.numberOfSimulcastStreams = 1; 390 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); 391 adapter_->RegisterEncodeCompleteCallback(this); 392 ASSERT_EQ(1u, helper_->factory()->encoders().size()); 393 helper_->factory()->encoders()[0]->set_supports_native_handle(true); 394 EXPECT_TRUE(adapter_->SupportsNativeHandle()); 395 helper_->factory()->encoders()[0]->set_supports_native_handle(false); 396 EXPECT_FALSE(adapter_->SupportsNativeHandle()); 397 } 398 399 TEST_F(TestSimulcastEncoderAdapterFake, 400 SupportsNativeHandleDisabledForMultipleStreams) { 401 // TODO(pbos): Implement actual test (verify that it works) when implemented 402 // for multiple streams. 403 TestVp8Simulcast::DefaultSettings( 404 &codec_, static_cast<const int*>(kTestTemporalLayerProfile)); 405 codec_.numberOfSimulcastStreams = 3; 406 EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); 407 adapter_->RegisterEncodeCompleteCallback(this); 408 ASSERT_EQ(3u, helper_->factory()->encoders().size()); 409 for (MockVideoEncoder* encoder : helper_->factory()->encoders()) 410 encoder->set_supports_native_handle(true); 411 EXPECT_FALSE(adapter_->SupportsNativeHandle()); 412 } 413 414 } // namespace testing 415 } // namespace webrtc 416