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
22using namespace webrtc;
23
24UnitTest::UnitTest()
25:
26CodecTest("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),
35is_key_frame_(false),
36_encodeCompleteCallback(NULL),
37_decodeCompleteCallback(NULL)
38{
39}
40
41UnitTest::UnitTest(std::string name, std::string description)
42:
43CodecTest(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),
52is_key_frame_(false),
53_encodeCompleteCallback(NULL),
54_decodeCompleteCallback(NULL)
55{
56}
57
58UnitTest::~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
93int32_t
94UnitTestEncodeCompleteCallback::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
114int32_t UnitTestDecodeCompleteCallback::Decoded(I420VideoFrame& image)
115{
116    _decodedVideoBuffer->CopyFrame(image);
117    _decodeComplete = true;
118    return 0;
119}
120
121bool
122UnitTestEncodeCompleteCallback::EncodeComplete()
123{
124    if (_encodeComplete)
125    {
126        _encodeComplete = false;
127        return true;
128    }
129    return false;
130}
131
132VideoFrameType
133UnitTestEncodeCompleteCallback::EncodedFrameType() const
134{
135    return _encodedFrameType;
136}
137
138bool
139UnitTestDecodeCompleteCallback::DecodeComplete()
140{
141    if (_decodeComplete)
142    {
143        _decodeComplete = false;
144        return true;
145    }
146    return false;
147}
148
149uint32_t
150UnitTest::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
163uint32_t
164UnitTest::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
178uint32_t
179UnitTest::CodecSpecific_SetBitrate(uint32_t bitRate,
180                                   uint32_t /* frameRate */)
181{
182    return _encoder->SetRates(bitRate, _inst.maxFramerate);
183}
184
185void
186UnitTest::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
292void
293UnitTest::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
316void
317UnitTest::Print()
318{
319}
320
321int
322UnitTest::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
332int
333UnitTest::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.
356void
357UnitTest::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 = static_cast<unsigned int>(-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
733void
734UnitTest::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
810bool
811UnitTest::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