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/codecs/interface/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 
CreateTestEncoderAdapter()22 static VP8Encoder* CreateTestEncoderAdapter() {
23   VP8EncoderFactoryConfig::set_use_simulcast_adapter(true);
24   return VP8Encoder::Create();
25 }
26 
27 class TestSimulcastEncoderAdapter : public TestVp8Simulcast {
28  public:
TestSimulcastEncoderAdapter()29   TestSimulcastEncoderAdapter()
30      : TestVp8Simulcast(CreateTestEncoderAdapter(),
31                         VP8Decoder::Create()) {}
32  protected:
SetUp()33   virtual void SetUp() {
34     TestVp8Simulcast::SetUp();
35   }
TearDown()36   virtual void TearDown() {
37     TestVp8Simulcast::TearDown();
38     VP8EncoderFactoryConfig::set_use_simulcast_adapter(false);
39   }
40 };
41 
TEST_F(TestSimulcastEncoderAdapter,TestKeyFrameRequestsOnAllStreams)42 TEST_F(TestSimulcastEncoderAdapter, TestKeyFrameRequestsOnAllStreams) {
43   TestVp8Simulcast::TestKeyFrameRequestsOnAllStreams();
44 }
45 
TEST_F(TestSimulcastEncoderAdapter,TestPaddingAllStreams)46 TEST_F(TestSimulcastEncoderAdapter, TestPaddingAllStreams) {
47   TestVp8Simulcast::TestPaddingAllStreams();
48 }
49 
TEST_F(TestSimulcastEncoderAdapter,TestPaddingTwoStreams)50 TEST_F(TestSimulcastEncoderAdapter, TestPaddingTwoStreams) {
51   TestVp8Simulcast::TestPaddingTwoStreams();
52 }
53 
TEST_F(TestSimulcastEncoderAdapter,TestPaddingTwoStreamsOneMaxedOut)54 TEST_F(TestSimulcastEncoderAdapter, TestPaddingTwoStreamsOneMaxedOut) {
55   TestVp8Simulcast::TestPaddingTwoStreamsOneMaxedOut();
56 }
57 
TEST_F(TestSimulcastEncoderAdapter,TestPaddingOneStream)58 TEST_F(TestSimulcastEncoderAdapter, TestPaddingOneStream) {
59   TestVp8Simulcast::TestPaddingOneStream();
60 }
61 
TEST_F(TestSimulcastEncoderAdapter,TestPaddingOneStreamTwoMaxedOut)62 TEST_F(TestSimulcastEncoderAdapter, TestPaddingOneStreamTwoMaxedOut) {
63   TestVp8Simulcast::TestPaddingOneStreamTwoMaxedOut();
64 }
65 
TEST_F(TestSimulcastEncoderAdapter,TestSendAllStreams)66 TEST_F(TestSimulcastEncoderAdapter, TestSendAllStreams) {
67   TestVp8Simulcast::TestSendAllStreams();
68 }
69 
TEST_F(TestSimulcastEncoderAdapter,TestDisablingStreams)70 TEST_F(TestSimulcastEncoderAdapter, TestDisablingStreams) {
71   TestVp8Simulcast::TestDisablingStreams();
72 }
73 
TEST_F(TestSimulcastEncoderAdapter,TestSwitchingToOneStream)74 TEST_F(TestSimulcastEncoderAdapter, TestSwitchingToOneStream) {
75   TestVp8Simulcast::TestSwitchingToOneStream();
76 }
77 
TEST_F(TestSimulcastEncoderAdapter,TestSwitchingToOneOddStream)78 TEST_F(TestSimulcastEncoderAdapter, TestSwitchingToOneOddStream) {
79   TestVp8Simulcast::TestSwitchingToOneOddStream();
80 }
81 
TEST_F(TestSimulcastEncoderAdapter,TestRPSIEncodeDecode)82 TEST_F(TestSimulcastEncoderAdapter, TestRPSIEncodeDecode) {
83   TestVp8Simulcast::TestRPSIEncodeDecode();
84 }
85 
TEST_F(TestSimulcastEncoderAdapter,TestStrideEncodeDecode)86 TEST_F(TestSimulcastEncoderAdapter, TestStrideEncodeDecode) {
87   TestVp8Simulcast::TestStrideEncodeDecode();
88 }
89 
TEST_F(TestSimulcastEncoderAdapter,TestSaptioTemporalLayers333PatternEncoder)90 TEST_F(TestSimulcastEncoderAdapter, TestSaptioTemporalLayers333PatternEncoder) {
91   TestVp8Simulcast::TestSaptioTemporalLayers333PatternEncoder();
92 }
93 
TEST_F(TestSimulcastEncoderAdapter,TestSpatioTemporalLayers321PatternEncoder)94 TEST_F(TestSimulcastEncoderAdapter, TestSpatioTemporalLayers321PatternEncoder) {
95   TestVp8Simulcast::TestSpatioTemporalLayers321PatternEncoder();
96 }
97 
98 // TODO(ronghuawu): Enable this test when SkipEncodingUnusedStreams option is
99 // implemented for SimulcastEncoderAdapter.
TEST_F(TestSimulcastEncoderAdapter,DISABLED_TestSkipEncodingUnusedStreams)100 TEST_F(TestSimulcastEncoderAdapter,
101     DISABLED_TestSkipEncodingUnusedStreams) {
102   TestVp8Simulcast::TestSkipEncodingUnusedStreams();
103 }
104 
TEST_F(TestSimulcastEncoderAdapter,DISABLED_TestRPSIEncoder)105 TEST_F(TestSimulcastEncoderAdapter, DISABLED_TestRPSIEncoder) {
106   TestVp8Simulcast::TestRPSIEncoder();
107 }
108 
109 class MockVideoEncoder : public VideoEncoder {
110  public:
InitEncode(const VideoCodec * codecSettings,int32_t numberOfCores,size_t maxPayloadSize)111   int32_t InitEncode(const VideoCodec* codecSettings,
112                      int32_t numberOfCores,
113                      size_t maxPayloadSize) {
114     codec_ = *codecSettings;
115     return 0;
116   }
117 
Encode(const I420VideoFrame & inputImage,const CodecSpecificInfo * codecSpecificInfo,const std::vector<VideoFrameType> * frame_types)118   int32_t Encode(const I420VideoFrame& inputImage,
119                  const CodecSpecificInfo* codecSpecificInfo,
120                  const std::vector<VideoFrameType>* frame_types) { return 0; }
121 
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)122   int32_t RegisterEncodeCompleteCallback(EncodedImageCallback* callback) {
123     return 0;
124   }
125 
Release()126   int32_t Release() {
127     return 0;
128   }
129 
SetRates(uint32_t newBitRate,uint32_t frameRate)130   int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) {
131     return 0;
132   }
133 
134   MOCK_METHOD2(SetChannelParameters,
135       int32_t(uint32_t packetLoss, int64_t rtt));
136 
~MockVideoEncoder()137   virtual ~MockVideoEncoder() {
138   }
139 
codec() const140   const VideoCodec& codec() const { return codec_; }
141 
142  private:
143   VideoCodec codec_;
144 };
145 
146 class MockVideoEncoderFactory : public VideoEncoderFactory {
147  public:
Create()148   VideoEncoder* Create() override {
149     MockVideoEncoder* encoder = new MockVideoEncoder();
150     encoders_.push_back(encoder);
151     return encoder;
152   }
153 
Destroy(VideoEncoder * encoder)154   void Destroy(VideoEncoder* encoder) override { delete encoder; }
155 
~MockVideoEncoderFactory()156   virtual ~MockVideoEncoderFactory() {}
157 
encoders() const158   const std::vector<MockVideoEncoder*>& encoders() const { return encoders_; }
159 
160  private:
161   std::vector<MockVideoEncoder*> encoders_;
162 };
163 
164 class TestSimulcastEncoderAdapterFakeHelper {
165  public:
TestSimulcastEncoderAdapterFakeHelper()166   TestSimulcastEncoderAdapterFakeHelper()
167       : factory_(new MockVideoEncoderFactory()) {}
168 
169   // Can only be called once as the SimulcastEncoderAdapter will take the
170   // ownership of |factory_|.
CreateMockEncoderAdapter()171   VP8Encoder* CreateMockEncoderAdapter() {
172     return new SimulcastEncoderAdapter(factory_);
173   }
174 
ExpectCallSetChannelParameters(uint32_t packetLoss,int64_t rtt)175   void ExpectCallSetChannelParameters(uint32_t packetLoss, int64_t rtt) {
176     EXPECT_TRUE(!factory_->encoders().empty());
177     for (size_t i = 0; i < factory_->encoders().size(); ++i) {
178       EXPECT_CALL(*factory_->encoders()[i],
179                   SetChannelParameters(packetLoss, rtt)).Times(1);
180     }
181   }
182 
factory()183   MockVideoEncoderFactory* factory() { return factory_; }
184 
185  private:
186   MockVideoEncoderFactory* factory_;
187 };
188 
189 static const int kTestTemporalLayerProfile[3] = {3, 2, 1};
190 
191 class TestSimulcastEncoderAdapterFake : public ::testing::Test {
192  public:
TestSimulcastEncoderAdapterFake()193   TestSimulcastEncoderAdapterFake()
194      : helper_(new TestSimulcastEncoderAdapterFakeHelper()),
195        adapter_(helper_->CreateMockEncoderAdapter()) {}
~TestSimulcastEncoderAdapterFake()196   virtual ~TestSimulcastEncoderAdapterFake() {}
197 
SetupCodec()198   void SetupCodec() {
199     TestVp8Simulcast::DefaultSettings(
200       &codec_,
201       static_cast<const int*>(kTestTemporalLayerProfile));
202     EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
203   }
204 
VerifyCodec(const VideoCodec & ref,int stream_index)205   void VerifyCodec(const VideoCodec& ref, int stream_index) {
206     const VideoCodec& target =
207         helper_->factory()->encoders()[stream_index]->codec();
208     EXPECT_EQ(ref.codecType, target.codecType);
209     EXPECT_EQ(0, strcmp(ref.plName, target.plName));
210     EXPECT_EQ(ref.plType, target.plType);
211     EXPECT_EQ(ref.width, target.width);
212     EXPECT_EQ(ref.height, target.height);
213     EXPECT_EQ(ref.startBitrate, target.startBitrate);
214     EXPECT_EQ(ref.maxBitrate, target.maxBitrate);
215     EXPECT_EQ(ref.minBitrate, target.minBitrate);
216     EXPECT_EQ(ref.maxFramerate, target.maxFramerate);
217     EXPECT_EQ(ref.codecSpecific.VP8.pictureLossIndicationOn,
218               target.codecSpecific.VP8.pictureLossIndicationOn);
219     EXPECT_EQ(ref.codecSpecific.VP8.feedbackModeOn,
220               target.codecSpecific.VP8.feedbackModeOn);
221     EXPECT_EQ(ref.codecSpecific.VP8.complexity,
222               target.codecSpecific.VP8.complexity);
223     EXPECT_EQ(ref.codecSpecific.VP8.resilience,
224               target.codecSpecific.VP8.resilience);
225     EXPECT_EQ(ref.codecSpecific.VP8.numberOfTemporalLayers,
226               target.codecSpecific.VP8.numberOfTemporalLayers);
227     EXPECT_EQ(ref.codecSpecific.VP8.denoisingOn,
228               target.codecSpecific.VP8.denoisingOn);
229     EXPECT_EQ(ref.codecSpecific.VP8.errorConcealmentOn,
230               target.codecSpecific.VP8.errorConcealmentOn);
231     EXPECT_EQ(ref.codecSpecific.VP8.automaticResizeOn,
232               target.codecSpecific.VP8.automaticResizeOn);
233     EXPECT_EQ(ref.codecSpecific.VP8.frameDroppingOn,
234               target.codecSpecific.VP8.frameDroppingOn);
235     EXPECT_EQ(ref.codecSpecific.VP8.keyFrameInterval,
236               target.codecSpecific.VP8.keyFrameInterval);
237     EXPECT_EQ(ref.qpMax, target.qpMax);
238     EXPECT_EQ(0, target.numberOfSimulcastStreams);
239     EXPECT_EQ(ref.mode, target.mode);
240     EXPECT_EQ(ref.extra_options, target.extra_options);
241 
242     // No need to compare simulcastStream as numberOfSimulcastStreams should
243     // always be 0.
244   }
245 
InitRefCodec(int stream_index,VideoCodec * ref_codec)246   void InitRefCodec(int stream_index, VideoCodec* ref_codec) {
247     *ref_codec = codec_;
248     ref_codec->codecSpecific.VP8.numberOfTemporalLayers =
249         kTestTemporalLayerProfile[stream_index];
250     ref_codec->width = codec_.simulcastStream[stream_index].width;
251     ref_codec->height = codec_.simulcastStream[stream_index].height;
252     ref_codec->maxBitrate = codec_.simulcastStream[stream_index].maxBitrate;
253     ref_codec->minBitrate = codec_.simulcastStream[stream_index].minBitrate;
254     ref_codec->qpMax = codec_.simulcastStream[stream_index].qpMax;
255   }
256 
VerifyCodecSettings()257   void VerifyCodecSettings() {
258     EXPECT_EQ(3u, helper_->factory()->encoders().size());
259     VideoCodec ref_codec;
260 
261     // stream 0, the lowest resolution stream.
262     InitRefCodec(0, &ref_codec);
263     ref_codec.qpMax = 45;
264     ref_codec.codecSpecific.VP8.complexity = webrtc::kComplexityHigher;
265     ref_codec.codecSpecific.VP8.denoisingOn = false;
266     ref_codec.startBitrate = 100;  // Should equal to the target bitrate.
267     VerifyCodec(ref_codec, 0);
268 
269     // stream 1
270     InitRefCodec(1, &ref_codec);
271     ref_codec.codecSpecific.VP8.denoisingOn = false;
272     ref_codec.startBitrate = 300;
273     VerifyCodec(ref_codec, 1);
274 
275     // stream 2, the biggest resolution stream.
276     InitRefCodec(2, &ref_codec);
277     ref_codec.startBitrate = 600;
278     VerifyCodec(ref_codec, 2);
279   }
280 
281  protected:
282   rtc::scoped_ptr<TestSimulcastEncoderAdapterFakeHelper> helper_;
283   rtc::scoped_ptr<VP8Encoder> adapter_;
284   VideoCodec codec_;
285 };
286 
TEST_F(TestSimulcastEncoderAdapterFake,InitEncode)287 TEST_F(TestSimulcastEncoderAdapterFake, InitEncode) {
288   SetupCodec();
289   VerifyCodecSettings();
290 }
291 
TEST_F(TestSimulcastEncoderAdapterFake,SetChannelParameters)292 TEST_F(TestSimulcastEncoderAdapterFake, SetChannelParameters) {
293   SetupCodec();
294   const uint32_t packetLoss = 5;
295   const int64_t rtt = 30;
296   helper_->ExpectCallSetChannelParameters(packetLoss, rtt);
297   adapter_->SetChannelParameters(packetLoss, rtt);
298 }
299 
300 }  // namespace testing
301 }  // namespace webrtc
302