• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 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 <assert.h>
12 #include <math.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/modules/video_coding/codecs/test_framework/unit_test.h"
18 #include "webrtc/modules/video_coding/codecs/test_framework/video_source.h"
19 #include "webrtc/system_wrappers/interface/tick_util.h"
20 #include "webrtc/test/testsupport/fileutils.h"
21 
22 using namespace webrtc;
23 
UnitTest()24 UnitTest::UnitTest()
25 :
26 CodecTest("UnitTest", "Unit test"),
27 _tests(0),
28 _errors(0),
29 _source(NULL),
30 _refFrame(NULL),
31 _refEncFrame(NULL),
32 _refDecFrame(NULL),
33 _refEncFrameLength(0),
34 _sourceFile(NULL),
35 is_key_frame_(false),
36 _encodeCompleteCallback(NULL),
37 _decodeCompleteCallback(NULL)
38 {
39 }
40 
UnitTest(std::string name,std::string description)41 UnitTest::UnitTest(std::string name, std::string description)
42 :
43 CodecTest(name, description),
44 _tests(0),
45 _errors(0),
46 _source(NULL),
47 _refFrame(NULL),
48 _refEncFrame(NULL),
49 _refDecFrame(NULL),
50 _refEncFrameLength(0),
51 _sourceFile(NULL),
52 is_key_frame_(false),
53 _encodeCompleteCallback(NULL),
54 _decodeCompleteCallback(NULL)
55 {
56 }
57 
~UnitTest()58 UnitTest::~UnitTest()
59 {
60     if (_encodeCompleteCallback) {
61         delete _encodeCompleteCallback;
62     }
63 
64     if (_decodeCompleteCallback) {
65         delete _decodeCompleteCallback;
66     }
67 
68     if (_source) {
69         delete _source;
70     }
71 
72     if (_refFrame) {
73         delete [] _refFrame;
74     }
75 
76     if (_refDecFrame) {
77         delete [] _refDecFrame;
78     }
79 
80     if (_sourceBuffer) {
81         delete [] _sourceBuffer;
82     }
83 
84     if (_sourceFile) {
85         fclose(_sourceFile);
86     }
87 
88     if (_refEncFrame) {
89         delete [] _refEncFrame;
90     }
91 }
92 
93 int32_t
Encoded(EncodedImage & encodedImage,const webrtc::CodecSpecificInfo * codecSpecificInfo,const webrtc::RTPFragmentationHeader * fragmentation)94 UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
95                                         const webrtc::CodecSpecificInfo* codecSpecificInfo,
96                                         const webrtc::RTPFragmentationHeader*
97                                         fragmentation)
98 {
99     _encodedVideoBuffer->VerifyAndAllocate(encodedImage._size);
100     _encodedVideoBuffer->CopyFrame(encodedImage._size, encodedImage._buffer);
101     _encodedVideoBuffer->SetLength(encodedImage._length);
102     // TODO(mikhal): Update frame type API.
103     // _encodedVideoBuffer->SetFrameType(encodedImage._frameType);
104     _encodedVideoBuffer->SetWidth(
105         (uint16_t)encodedImage._encodedWidth);
106     _encodedVideoBuffer->SetHeight(
107         (uint16_t)encodedImage._encodedHeight);
108     _encodedVideoBuffer->SetTimeStamp(encodedImage._timeStamp);
109     _encodeComplete = true;
110     _encodedFrameType = encodedImage._frameType;
111     return 0;
112 }
113 
Decoded(I420VideoFrame & image)114 int32_t UnitTestDecodeCompleteCallback::Decoded(I420VideoFrame& image)
115 {
116     _decodedVideoBuffer->CopyFrame(image);
117     _decodeComplete = true;
118     return 0;
119 }
120 
121 bool
EncodeComplete()122 UnitTestEncodeCompleteCallback::EncodeComplete()
123 {
124     if (_encodeComplete)
125     {
126         _encodeComplete = false;
127         return true;
128     }
129     return false;
130 }
131 
132 VideoFrameType
EncodedFrameType() const133 UnitTestEncodeCompleteCallback::EncodedFrameType() const
134 {
135     return _encodedFrameType;
136 }
137 
138 bool
DecodeComplete()139 UnitTestDecodeCompleteCallback::DecodeComplete()
140 {
141     if (_decodeComplete)
142     {
143         _decodeComplete = false;
144         return true;
145     }
146     return false;
147 }
148 
149 uint32_t
WaitForEncodedFrame() const150 UnitTest::WaitForEncodedFrame() const
151 {
152     int64_t startTime = TickTime::MillisecondTimestamp();
153     while (TickTime::MillisecondTimestamp() - startTime < kMaxWaitEncTimeMs)
154     {
155         if (_encodeCompleteCallback->EncodeComplete())
156         {
157           return _encodedVideoBuffer.Length();
158         }
159     }
160     return 0;
161 }
162 
163 uint32_t
WaitForDecodedFrame() const164 UnitTest::WaitForDecodedFrame() const
165 {
166     int64_t startTime = TickTime::MillisecondTimestamp();
167     while (TickTime::MillisecondTimestamp() - startTime < kMaxWaitDecTimeMs)
168     {
169         if (_decodeCompleteCallback->DecodeComplete())
170         {
171           return webrtc::CalcBufferSize(kI420, _decodedVideoBuffer.width(),
172                                         _decodedVideoBuffer.height());
173         }
174     }
175     return 0;
176 }
177 
178 uint32_t
CodecSpecific_SetBitrate(uint32_t bitRate,uint32_t)179 UnitTest::CodecSpecific_SetBitrate(uint32_t bitRate,
180                                    uint32_t /* frameRate */)
181 {
182     return _encoder->SetRates(bitRate, _inst.maxFramerate);
183 }
184 
185 void
Setup()186 UnitTest::Setup()
187 {
188     // Use _sourceFile as a check to prevent multiple Setup() calls.
189     if (_sourceFile != NULL)
190     {
191         return;
192     }
193 
194     if (_encodeCompleteCallback == NULL)
195     {
196         _encodeCompleteCallback =
197             new UnitTestEncodeCompleteCallback(&_encodedVideoBuffer);
198     }
199     if (_decodeCompleteCallback == NULL)
200     {
201         _decodeCompleteCallback =
202             new UnitTestDecodeCompleteCallback(&_decodedVideoBuffer);
203     }
204 
205     _encoder->RegisterEncodeCompleteCallback(_encodeCompleteCallback);
206     _decoder->RegisterDecodeCompleteCallback(_decodeCompleteCallback);
207 
208     _source = new VideoSource(webrtc::test::ProjectRootPath() +
209                               "resources/foreman_cif.yuv", kCIF);
210 
211     _lengthSourceFrame = _source->GetFrameLength();
212     _refFrame = new unsigned char[_lengthSourceFrame];
213     _refDecFrame = new unsigned char[_lengthSourceFrame];
214     _sourceBuffer = new unsigned char [_lengthSourceFrame];
215     _sourceFile = fopen(_source->GetFileName().c_str(), "rb");
216     ASSERT_TRUE(_sourceFile != NULL);
217 
218     _inst.maxFramerate = _source->GetFrameRate();
219     _bitRate = 300;
220     _inst.startBitrate = 300;
221     _inst.maxBitrate = 4000;
222     _inst.width = _source->GetWidth();
223     _inst.height = _source->GetHeight();
224     _inst.qpMax = 56;
225     _inst.codecSpecific.VP8.denoisingOn = true;
226 
227     // Get input frame.
228     ASSERT_TRUE(fread(_refFrame, 1, _lengthSourceFrame, _sourceFile)
229                            == _lengthSourceFrame);
230     int size_y = _inst.width * _inst.height;
231     int size_uv = ((_inst.width + 1) / 2)  * ((_inst.height + 1) / 2);
232     _inputVideoBuffer.CreateFrame(size_y, _refFrame,
233                                   size_uv, _refFrame + size_y,
234                                   size_uv, _refFrame + size_y + size_uv,
235                                   _inst.width, _inst.height,
236                                   _inst.width,
237                                   (_inst.width + 1) / 2, (_inst.width + 1) / 2);
238     rewind(_sourceFile);
239 
240     // Get a reference encoded frame.
241     _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
242 
243     // Ensures our initial parameters are valid.
244     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
245     _encoder->Encode(_inputVideoBuffer, NULL, NULL);
246     _refEncFrameLength = WaitForEncodedFrame();
247     ASSERT_TRUE(_refEncFrameLength > 0);
248     _refEncFrame = new unsigned char[_refEncFrameLength];
249     memcpy(_refEncFrame, _encodedVideoBuffer.Buffer(), _refEncFrameLength);
250 
251     // Get a reference decoded frame.
252     _decodedVideoBuffer.CreateEmptyFrame(_inst.width, _inst.height, _inst.width,
253                                          (_inst.width + 1) / 2,
254                                          (_inst.width + 1) / 2);
255     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
256     ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
257 
258     unsigned int frameLength = 0;
259     int i = 0;
260     _inputVideoBuffer.CreateEmptyFrame(_inst.width, _inst.height, _inst.width,
261                                        (_inst.width + 1) / 2,
262                                        (_inst.width + 1) / 2);
263     while (frameLength == 0)
264     {
265          EncodedImage encodedImage;
266         if (i > 0)
267         {
268             // Insert yet another frame.
269             ASSERT_TRUE(fread(_refFrame, 1, _lengthSourceFrame,
270                 _sourceFile) == _lengthSourceFrame);
271             EXPECT_EQ(0, ConvertToI420(kI420, _refFrame, 0, 0, _width, _height,
272                           0, kRotateNone, &_inputVideoBuffer));
273             _encoder->Encode(_inputVideoBuffer, NULL, NULL);
274             ASSERT_TRUE(WaitForEncodedFrame() > 0);
275         } else {
276             // The first frame is always a key frame.
277             encodedImage._frameType = kKeyFrame;
278         }
279 
280         VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
281         ASSERT_TRUE(_decoder->Decode(encodedImage, 0, NULL)
282                                == WEBRTC_VIDEO_CODEC_OK);
283         frameLength = WaitForDecodedFrame();
284         _encodedVideoBuffer.SetLength(0);
285         i++;
286     }
287     rewind(_sourceFile);
288     EXPECT_TRUE(frameLength == _lengthSourceFrame);
289     ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame, _refDecFrame);
290 }
291 
292 void
Teardown()293 UnitTest::Teardown()
294 {
295     // Use _sourceFile as a check to prevent multiple Teardown() calls.
296     if (_sourceFile == NULL)
297     {
298         return;
299     }
300 
301     _encoder->Release();
302     _decoder->Release();
303 
304     fclose(_sourceFile);
305     _sourceFile = NULL;
306     delete [] _refFrame;
307     _refFrame = NULL;
308     delete [] _refEncFrame;
309     _refEncFrame = NULL;
310     delete [] _refDecFrame;
311     _refDecFrame = NULL;
312     delete [] _sourceBuffer;
313     _sourceBuffer = NULL;
314 }
315 
316 void
Print()317 UnitTest::Print()
318 {
319 }
320 
321 int
DecodeWithoutAssert()322 UnitTest::DecodeWithoutAssert()
323 {
324     EncodedImage encodedImage;
325     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
326     int ret = _decoder->Decode(encodedImage, 0, NULL);
327     int frameLength = WaitForDecodedFrame();
328     _encodedVideoBuffer.SetLength(0);
329     return ret == WEBRTC_VIDEO_CODEC_OK ? frameLength : ret;
330 }
331 
332 int
Decode()333 UnitTest::Decode()
334 {
335     EncodedImage encodedImage;
336     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
337     if (encodedImage._length == 0)
338     {
339         return WEBRTC_VIDEO_CODEC_OK;
340     }
341     if (is_key_frame_) {
342         encodedImage._frameType = kKeyFrame;
343     }
344 
345     int ret = _decoder->Decode(encodedImage, 0, NULL);
346     unsigned int frameLength = WaitForDecodedFrame();
347     assert(ret == WEBRTC_VIDEO_CODEC_OK && (frameLength == 0 || frameLength
348         == _lengthSourceFrame));
349     EXPECT_TRUE(ret == WEBRTC_VIDEO_CODEC_OK && (frameLength == 0 || frameLength
350         == _lengthSourceFrame));
351     _encodedVideoBuffer.SetLength(0);
352     return ret == WEBRTC_VIDEO_CODEC_OK ? frameLength : ret;
353 }
354 
355 // Test pure virtual VideoEncoder and VideoDecoder APIs.
356 void
Perform()357 UnitTest::Perform()
358 {
359     UnitTest::Setup();
360     int frameLength;
361     I420VideoFrame inputImage;
362     EncodedImage encodedImage;
363 
364     //----- Encoder parameter tests -----
365 
366     //-- Calls before InitEncode() --
367     // We want to revert the initialization done in Setup().
368     EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
369     EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL)
370                == WEBRTC_VIDEO_CODEC_UNINITIALIZED);
371 
372     //-- InitEncode() errors --
373     // Null pointer.
374     EXPECT_TRUE(_encoder->InitEncode(NULL, 1, 1440) ==
375         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
376     // bit rate exceeds max bit rate
377     int32_t tmpBitRate = _inst.startBitrate;
378     int32_t tmpMaxBitRate = _inst.maxBitrate;
379     _inst.startBitrate = 4000;
380     _inst.maxBitrate = 3000;
381     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440)  ==
382         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
383     _inst.startBitrate = tmpBitRate;
384     _inst.maxBitrate = tmpMaxBitRate; //unspecified value
385 
386     // Bad framerate.
387     _inst.maxFramerate = 0;
388     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
389         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
390     // Seems like we should allow any framerate in range [0, 255].
391     //_inst.frameRate = 100;
392     //EXPECT_TRUE(_encoder->InitEncode(&_inst, 1) == -1); // FAILS
393     _inst.maxFramerate = 30;
394 
395     // Bad bitrate.
396     _inst.startBitrate = -1;
397     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
398         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
399     _inst.maxBitrate = _inst.startBitrate - 1;
400     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
401         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
402     _inst.maxBitrate = 0;
403     _inst.startBitrate = 300;
404 
405     // Bad maxBitRate.
406     _inst.maxBitrate = 200;
407     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
408         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
409     _inst.maxBitrate = 4000;
410 
411     // Bad width.
412     _inst.width = 0;
413     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) < 0);
414     _inst.width = _source->GetWidth();
415 
416     // Bad height.
417     _inst.height = 0;
418     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) < 0);
419     _inst.height = _source->GetHeight();
420 
421     // Bad number of cores.
422     EXPECT_TRUE(_encoder->InitEncode(&_inst, -1, 1440) ==
423         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
424 
425     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
426 
427     //-- Encode() errors --
428     inputImage.ResetSize();
429     EXPECT_TRUE(_encoder->Encode(inputImage, NULL, NULL) ==
430         WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
431     int width = _source->GetWidth();
432     int half_width = (width + 1) / 2;
433     int height = _source->GetHeight();
434     int half_height = (height + 1) / 2;
435     int size_y = width * height;
436     int size_uv = half_width * half_height;
437     _inputVideoBuffer.CreateFrame(size_y, _refFrame,
438                                   size_uv, _refFrame + size_y,
439                                   size_uv, _refFrame + size_y + size_uv,
440                                   width, height,
441                                   width, half_width, half_width);
442     //----- Encoder stress tests -----
443 
444     // Vary frame rate and I-frame request.
445     for (int i = 1; i <= 60; i++)
446     {
447         VideoFrameType frame_type = !(i % 2) ? kKeyFrame : kDeltaFrame;
448         std::vector<VideoFrameType> frame_types(1, frame_type);
449         EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, &frame_types) ==
450             WEBRTC_VIDEO_CODEC_OK);
451         EXPECT_TRUE(WaitForEncodedFrame() > 0);
452     }
453 
454     // Init then encode.
455     _encodedVideoBuffer.SetLength(0);
456     EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
457         WEBRTC_VIDEO_CODEC_OK);
458     EXPECT_TRUE(WaitForEncodedFrame() > 0);
459 
460     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
461     _encoder->Encode(_inputVideoBuffer, NULL, NULL);
462     frameLength = WaitForEncodedFrame();
463     EXPECT_TRUE(frameLength > 0);
464     EXPECT_TRUE(CheckIfBitExact(_refEncFrame, _refEncFrameLength,
465             _encodedVideoBuffer.Buffer(), frameLength) == true);
466 
467     // Reset then encode.
468     _encodedVideoBuffer.SetLength(0);
469     EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
470         WEBRTC_VIDEO_CODEC_OK);
471     WaitForEncodedFrame();
472     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
473     _encoder->Encode(_inputVideoBuffer, NULL, NULL);
474     frameLength = WaitForEncodedFrame();
475     EXPECT_TRUE(frameLength > 0);
476     EXPECT_TRUE(CheckIfBitExact(_refEncFrame, _refEncFrameLength,
477         _encodedVideoBuffer.Buffer(), frameLength) == true);
478 
479     // Release then encode.
480     _encodedVideoBuffer.SetLength(0);
481     EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
482         WEBRTC_VIDEO_CODEC_OK);
483     WaitForEncodedFrame();
484     EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
485     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
486     _encoder->Encode(_inputVideoBuffer, NULL, NULL);
487     frameLength = WaitForEncodedFrame();
488     EXPECT_TRUE(frameLength > 0);
489     EXPECT_TRUE(CheckIfBitExact(_refEncFrame, _refEncFrameLength,
490         _encodedVideoBuffer.Buffer(), frameLength) == true);
491 
492     //----- Decoder parameter tests -----
493 
494     //-- Calls before InitDecode() --
495     // We want to revert the initialization done in Setup().
496     EXPECT_TRUE(_decoder->Release() == WEBRTC_VIDEO_CODEC_OK);
497     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
498     EXPECT_TRUE(_decoder->Decode(encodedImage, false, NULL) ==
499         WEBRTC_VIDEO_CODEC_UNINITIALIZED);
500     WaitForDecodedFrame();
501     EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_UNINITIALIZED);
502     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
503     ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
504 
505     //-- Decode() errors --
506     // Unallocated encodedVideoBuffer.
507     _encodedVideoBuffer.Free();
508     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
509     encodedImage._length = 10;  // Buffer NULL but length > 0
510     EXPECT_EQ(_decoder->Decode(encodedImage, false, NULL),
511               WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
512     _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
513 
514     //----- Decoder stress tests -----
515     unsigned char* tmpBuf = new unsigned char[_lengthSourceFrame];
516 
517     // "Random" and zero data.
518     // We either expect an error, or at the least, no output.
519     // This relies on the codec's ability to detect an erroneous bitstream.
520     EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
521     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
522     ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
523     for (int i = 0; i < 100; i++)
524     {
525         ASSERT_TRUE(fread(tmpBuf, 1, _refEncFrameLength, _sourceFile)
526             == _refEncFrameLength);
527         _encodedVideoBuffer.CopyFrame(_refEncFrameLength, tmpBuf);
528         VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
529         int ret = _decoder->Decode(encodedImage, false, NULL);
530         EXPECT_TRUE(ret <= 0);
531         if (ret == 0)
532         {
533             EXPECT_TRUE(WaitForDecodedFrame() == 0);
534         }
535 
536         memset(tmpBuf, 0, _refEncFrameLength);
537         _encodedVideoBuffer.CopyFrame(_refEncFrameLength, tmpBuf);
538         VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
539         if (i == 0) {
540             // First frame is a key frame.
541             is_key_frame_ = true;
542         }
543         ret = _decoder->Decode(encodedImage, false, NULL);
544         EXPECT_TRUE(ret <= 0);
545         if (ret == 0)
546         {
547             EXPECT_TRUE(WaitForDecodedFrame() == 0);
548         }
549     }
550     rewind(_sourceFile);
551 
552     _encodedVideoBuffer.SetLength(_refEncFrameLength);
553     _encodedVideoBuffer.CopyFrame(_refEncFrameLength, _refEncFrame);
554 
555     // Init then decode.
556     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
557     ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
558     frameLength = 0;
559     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
560     // first frame is a key frame.
561     encodedImage._frameType = kKeyFrame;
562     while (frameLength == 0)
563     {
564         _decoder->Decode(encodedImage, false, NULL);
565         frameLength = WaitForDecodedFrame();
566     }
567     unsigned int length = CalcBufferSize(kI420, width, height);
568     scoped_ptr<uint8_t[]> decoded_buffer(new uint8_t[length]);
569     ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame,
570                   decoded_buffer.get());
571     EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength, _refDecFrame,
572                                 _lengthSourceFrame) == true);
573 
574     // Reset then decode.
575     EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
576     frameLength = 0;
577     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
578     while (frameLength == 0)
579     {
580         _decoder->Decode(encodedImage, false, NULL);
581         frameLength = WaitForDecodedFrame();
582     }
583     ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame,
584                   decoded_buffer.get());
585     EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength,
586                                 _refDecFrame, _lengthSourceFrame) == true);
587 
588     // Decode with other size, reset, then decode with original size again
589     // to verify that decoder is reset to a "fresh" state upon Reset().
590     {
591         // Assert that input frame size is a factor of two, so that we can use
592         // quarter size below.
593         EXPECT_TRUE((_inst.width % 2 == 0) && (_inst.height % 2 == 0));
594 
595         VideoCodec tempInst;
596         memcpy(&tempInst, &_inst, sizeof(VideoCodec));
597         tempInst.width /= 2;
598         tempInst.height /= 2;
599         int tmpHalfWidth = (tempInst.width + 1) / 2;
600         int tmpHalfHeight = (tempInst.height + 1) / 2;
601 
602         int tmpSizeY = tempInst.width * tempInst.height;
603         int tmpSizeUv = tmpHalfWidth * tmpHalfHeight;
604 
605         // Encode reduced (quarter) frame size.
606         EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
607         EXPECT_TRUE(_encoder->InitEncode(&tempInst, 1, 1440) ==
608             WEBRTC_VIDEO_CODEC_OK);
609         webrtc::I420VideoFrame tempInput;
610         tempInput.CreateFrame(tmpSizeY, _inputVideoBuffer.buffer(kYPlane),
611                               tmpSizeUv, _inputVideoBuffer.buffer(kUPlane),
612                               tmpSizeUv, _inputVideoBuffer.buffer(kVPlane),
613                               tempInst.width, tempInst.height,
614                               tempInst.width, tmpHalfWidth, tmpHalfWidth);
615         _encoder->Encode(tempInput, NULL, NULL);
616         frameLength = WaitForEncodedFrame();
617         EXPECT_TRUE(frameLength > 0);
618         // Reset then decode.
619         EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
620         frameLength = 0;
621         VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
622         while (frameLength == 0)
623         {
624             _decoder->Decode(encodedImage, false, NULL);
625             frameLength = WaitForDecodedFrame();
626         }
627 
628         // Encode original frame again
629         EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
630         EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
631             WEBRTC_VIDEO_CODEC_OK);
632         _encoder->Encode(_inputVideoBuffer, NULL, NULL);
633         frameLength = WaitForEncodedFrame();
634         EXPECT_TRUE(frameLength > 0);
635 
636         // Reset then decode original frame again.
637         EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
638         frameLength = 0;
639         VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
640         while (frameLength == 0)
641         {
642             _decoder->Decode(encodedImage, false, NULL);
643             frameLength = WaitForDecodedFrame();
644         }
645 
646         // check that decoded frame matches with reference
647         unsigned int length = CalcBufferSize(kI420, width, height);
648         scoped_ptr<uint8_t[]> decoded_buffer(new uint8_t[length]);
649         ExtractBuffer(_decodedVideoBuffer, length, decoded_buffer.get());
650         EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), length,
651                                     _refDecFrame, _lengthSourceFrame) == true);
652     }
653 
654     // Release then decode.
655     EXPECT_TRUE(_decoder->Release() == WEBRTC_VIDEO_CODEC_OK);
656     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
657     ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
658     frameLength = 0;
659     VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
660     while (frameLength == 0)
661     {
662         _decoder->Decode(encodedImage, false, NULL);
663         frameLength = WaitForDecodedFrame();
664     }
665     ExtractBuffer(_decodedVideoBuffer, length, decoded_buffer.get());
666     EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength,
667                                 _refDecFrame, _lengthSourceFrame) == true);
668     _encodedVideoBuffer.SetLength(0);
669 
670     delete [] tmpBuf;
671 
672     //----- Function tests -----
673     int frames = 0;
674     // Do not specify maxBitRate (as in ViE).
675     _inst.maxBitrate = 0;
676 
677     //-- Timestamp propagation --
678     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
679     EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
680     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
681     ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
682 
683     frames = 0;
684     int frameDelay = 0;
685     int encTimeStamp;
686     _decodedVideoBuffer.set_timestamp(0);
687     while (fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile) ==
688         _lengthSourceFrame)
689     {
690       _inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
691                                     size_uv, _sourceBuffer + size_y,
692                                     size_uv, _sourceBuffer + size_y + size_uv,
693                                     width, height,
694                                     width, half_width, half_width);
695 
696         _inputVideoBuffer.set_timestamp(frames);
697         ASSERT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
698             WEBRTC_VIDEO_CODEC_OK);
699         frameLength = WaitForEncodedFrame();
700         //ASSERT_TRUE(frameLength);
701         EXPECT_TRUE(frameLength > 0);
702         encTimeStamp = _encodedVideoBuffer.TimeStamp();
703         EXPECT_TRUE(_inputVideoBuffer.timestamp() ==
704                 static_cast<unsigned>(encTimeStamp));
705         if (frames == 0) {
706             // First frame is always a key frame.
707             is_key_frame_ = true;
708         }
709 
710         frameLength = Decode();
711         if (frameLength == 0)
712         {
713             frameDelay++;
714         }
715 
716         encTimeStamp -= frameDelay;
717         if (encTimeStamp < 0)
718         {
719             encTimeStamp = 0;
720         }
721         EXPECT_TRUE(_decodedVideoBuffer.timestamp() ==
722                 static_cast<unsigned>(encTimeStamp));
723         frames++;
724     }
725     ASSERT_TRUE(feof(_sourceFile) != 0);
726     rewind(_sourceFile);
727 
728     RateControlTests();
729 
730     Teardown();
731 }
732 
733 void
RateControlTests()734 UnitTest::RateControlTests()
735 {
736     int frames = 0;
737     VideoFrame inputImage;
738     uint32_t frameLength;
739 
740     // Do not specify maxBitRate (as in ViE).
741     _inst.maxBitrate = 0;
742     // Verify rate control. For this test turn on codec frame dropper.
743     // At least one other test (BasicUnitTest) assumes frame dropper off, so
744     // for now we only set frame dropper on for this (rate control) test.
745     _inst.codecSpecific.VP8.frameDroppingOn = true;
746     EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
747     EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
748     EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
749     // add: should also be 0, and 1
750     const int bitRate[] = {100, 500};
751     const int nBitrates = sizeof(bitRate)/sizeof(*bitRate);
752 
753     printf("\nRate control test\n");
754     for (int i = 0; i < nBitrates; i++)
755     {
756         _bitRate = bitRate[i];
757         int totalBytes = 0;
758         _inst.startBitrate = _bitRate;
759         _encoder->InitEncode(&_inst, 4, 1440);
760         _decoder->Reset();
761         _decoder->InitDecode(&_inst, 1);
762         frames = 0;
763 
764         if (_bitRate > _inst.maxBitrate)
765         {
766             CodecSpecific_SetBitrate(_bitRate, _inst.maxFramerate);
767         }
768         else
769         {
770             CodecSpecific_SetBitrate(_bitRate, _inst.maxFramerate);
771         }
772         int width = _source->GetWidth();
773         int half_width = (width + 1) / 2;
774         int height = _source->GetHeight();
775         int half_height = (height + 1) / 2;
776         int size_y = width * height;
777         int size_uv = half_width * half_height;
778         while (fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile) ==
779             _lengthSourceFrame)
780         {
781             _inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
782                                            size_uv, _sourceBuffer + size_y,
783                                            size_uv, _sourceBuffer + size_y +
784                                            size_uv,
785                                            width, height,
786                                            width, half_width, half_width);
787             _inputVideoBuffer.set_timestamp(static_cast<uint32_t>(9e4 /
788                     static_cast<float>(_inst.maxFramerate)));
789             ASSERT_EQ(_encoder->Encode(_inputVideoBuffer, NULL, NULL),
790                       WEBRTC_VIDEO_CODEC_OK);
791             frameLength = WaitForEncodedFrame();
792             ASSERT_GE(frameLength, 0u);
793             totalBytes += frameLength;
794             frames++;
795 
796             _encodedVideoBuffer.SetLength(0);
797         }
798         uint32_t actualBitrate =
799             (totalBytes  / frames * _inst.maxFramerate * 8)/1000;
800         printf("Target bitrate: %d kbps, actual bitrate: %d kbps\n", _bitRate,
801             actualBitrate);
802         // Test for close match over reasonable range.
803           EXPECT_TRUE(abs(int32_t(actualBitrate - _bitRate)) <
804                       0.12 * _bitRate);
805         ASSERT_TRUE(feof(_sourceFile) != 0);
806         rewind(_sourceFile);
807     }
808 }
809 
810 bool
CheckIfBitExact(const void * ptrA,unsigned int aLengthBytes,const void * ptrB,unsigned int bLengthBytes)811 UnitTest::CheckIfBitExact(const void* ptrA, unsigned int aLengthBytes,
812                           const void* ptrB, unsigned int bLengthBytes)
813 {
814     if (aLengthBytes != bLengthBytes)
815     {
816         return false;
817     }
818 
819     return memcmp(ptrA, ptrB, aLengthBytes) == 0;
820 }
821