Home | History | Annotate | Download | only in test_framework
      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 "webrtc/modules/video_coding/codecs/test_framework/normal_test.h"
     12 
     13 #include <sstream>
     14 #include <string.h>
     15 #include <time.h>
     16 
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
     19 #include "webrtc/test/testsupport/fileutils.h"
     20 
     21 NormalTest::NormalTest()
     22 :
     23 CodecTest("Normal Test 1", "A test of normal execution of the codec"),
     24 _testNo(1),
     25 _lengthEncFrame(0),
     26 _appendNext(false)
     27 {
     28 }
     29 
     30 NormalTest::NormalTest(std::string name, std::string description,
     31                        unsigned int testNo)
     32 :
     33 CodecTest(name, description),
     34 _requestKeyFrame(false),
     35 _testNo(testNo),
     36 _lengthEncFrame(0),
     37 _appendNext(false)
     38 {
     39 }
     40 
     41 NormalTest::NormalTest(std::string name, std::string description,
     42                        uint32_t bitRate, unsigned int testNo)
     43 :
     44 CodecTest(name, description, bitRate),
     45 _requestKeyFrame(false),
     46 _testNo(testNo),
     47 _lengthEncFrame(0),
     48 _appendNext(false)
     49 {
     50 }
     51 
     52 void
     53 NormalTest::Setup()
     54 {
     55     CodecTest::Setup();
     56     std::stringstream ss;
     57     std::string strTestNo;
     58     ss << _testNo;
     59     ss >> strTestNo;
     60 
     61     // Check if settings exist. Otherwise use defaults.
     62     if (_outname == "")
     63     {
     64         _outname = webrtc::test::OutputPath() + "out_normaltest" + strTestNo +
     65             ".yuv";
     66     }
     67 
     68     if (_encodedName == "")
     69     {
     70         _encodedName = webrtc::test::OutputPath() + "encoded_normaltest" +
     71             strTestNo + ".yuv";
     72     }
     73 
     74     if ((_sourceFile = fopen(_inname.c_str(), "rb")) == NULL)
     75     {
     76         printf("Cannot read file %s.\n", _inname.c_str());
     77         exit(1);
     78     }
     79 
     80     if ((_encodedFile = fopen(_encodedName.c_str(), "wb")) == NULL)
     81     {
     82         printf("Cannot write encoded file.\n");
     83         exit(1);
     84     }
     85 
     86     char mode[3] = "wb";
     87     if (_appendNext)
     88     {
     89         strncpy(mode, "ab", 3);
     90     }
     91 
     92     if ((_decodedFile = fopen(_outname.c_str(), mode)) == NULL)
     93     {
     94         printf("Cannot write file %s.\n", _outname.c_str());
     95         exit(1);
     96     }
     97 
     98     _appendNext = true;
     99 }
    100 
    101 void
    102 NormalTest::Teardown()
    103 {
    104     CodecTest::Teardown();
    105     fclose(_sourceFile);
    106     fclose(_decodedFile);
    107 }
    108 
    109 void
    110 NormalTest::Perform()
    111 {
    112     _width = 352;
    113     _halfWidth = (_width + 1) / 2;
    114     _height = 288;
    115     _halfHeight = (_height + 1) / 2;
    116     _sizeY = _width * _height;
    117     _sizeUv = _halfWidth * _halfHeight;
    118     _inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv";
    119     CodecSettings(_width, _height, 30, _bitRate);
    120     Setup();
    121 
    122     _inputVideoBuffer.CreateEmptyFrame(_width, _height,
    123                                        _width, _halfWidth, _halfWidth);
    124     _decodedVideoBuffer.CreateEmptyFrame(_width, _height,
    125                                          _width, _halfWidth, _halfWidth);
    126     _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
    127 
    128     _encoder->InitEncode(&_inst, 1, 1460);
    129     CodecSpecific_InitBitrate();
    130     _decoder->InitDecode(&_inst,1);
    131 
    132     _totalEncodeTime = _totalDecodeTime = 0;
    133     _framecnt = 0;
    134     _sumEncBytes = 0;
    135     _lengthEncFrame = 0;
    136     int decodeLength = 0;
    137     while (!Encode())
    138     {
    139         DoPacketLoss();
    140         _encodedVideoBuffer.SetLength(_encodedVideoBuffer.Length());
    141         if (fwrite(_encodedVideoBuffer.Buffer(), 1,
    142                    _encodedVideoBuffer.Length(),
    143                    _encodedFile) !=  _encodedVideoBuffer.Length()) {
    144           return;
    145         }
    146         decodeLength = Decode();
    147         if (decodeLength < 0)
    148         {
    149             fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength);
    150             exit(EXIT_FAILURE);
    151         }
    152         if (PrintI420VideoFrame(_decodedVideoBuffer, _decodedFile) < 0) {
    153           return;
    154         }
    155         CodecSpecific_InitBitrate();
    156         _framecnt++;
    157     }
    158 
    159     // Ensure we empty the decoding queue.
    160     while (decodeLength > 0)
    161     {
    162         decodeLength = Decode();
    163         if (decodeLength < 0)
    164         {
    165             fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength);
    166             exit(EXIT_FAILURE);
    167         }
    168         if (PrintI420VideoFrame(_decodedVideoBuffer, _decodedFile) < 0) {
    169           return;
    170         }
    171     }
    172 
    173     double actualBitRate = ActualBitRate(_framecnt) / 1000.0;
    174     double avgEncTime = _totalEncodeTime / _framecnt;
    175     double avgDecTime = _totalDecodeTime / _framecnt;
    176     printf("Actual bitrate: %f kbps\n", actualBitRate);
    177     printf("Average encode time: %f s\n", avgEncTime);
    178     printf("Average decode time: %f s\n", avgDecTime);
    179     (*_log) << "Actual bitrate: " << actualBitRate << " kbps\tTarget: " << _bitRate << " kbps" << std::endl;
    180     (*_log) << "Average encode time: " << avgEncTime << " s" << std::endl;
    181     (*_log) << "Average decode time: " << avgDecTime << " s" << std::endl;
    182 
    183     _encoder->Release();
    184     _decoder->Release();
    185 
    186     Teardown();
    187 }
    188 
    189 bool
    190 NormalTest::Encode()
    191 {
    192     _lengthEncFrame = 0;
    193     EXPECT_GT(fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile), 0u);
    194     if (feof(_sourceFile) != 0)
    195     {
    196         return true;
    197     }
    198         _inputVideoBuffer.CreateFrame(_sizeY, _sourceBuffer,
    199                                       _sizeUv, _sourceBuffer + _sizeY,
    200                                       _sizeUv, _sourceBuffer + _sizeY +
    201                                       _sizeUv,
    202                                       _width, _height,
    203                                       _width, _halfWidth, _halfWidth);
    204     _inputVideoBuffer.set_timestamp(_framecnt);
    205 
    206     // This multiple attempt ridiculousness is to accomodate VP7:
    207     // 1. The wrapper can unilaterally reduce the framerate for low bitrates.
    208     // 2. The codec inexplicably likes to reject some frames. Perhaps there
    209     //    is a good reason for this...
    210     int encodingAttempts = 0;
    211     double starttime = 0;
    212     double endtime = 0;
    213     while (_lengthEncFrame == 0)
    214     {
    215         starttime = clock()/(double)CLOCKS_PER_SEC;
    216 
    217         _inputVideoBuffer.set_width(_inst.width);
    218         _inputVideoBuffer.set_height(_inst.height);
    219         endtime = clock()/(double)CLOCKS_PER_SEC;
    220 
    221         _encodedVideoBuffer.SetHeight(_inst.height);
    222         _encodedVideoBuffer.SetWidth(_inst.width);
    223         if (_lengthEncFrame < 0)
    224         {
    225             (*_log) << "Error in encoder: " << _lengthEncFrame << std::endl;
    226             fprintf(stderr,"\n\nError in encoder: %d\n\n", _lengthEncFrame);
    227             exit(EXIT_FAILURE);
    228         }
    229         _sumEncBytes += _lengthEncFrame;
    230 
    231         encodingAttempts++;
    232         if (encodingAttempts > 50)
    233         {
    234             (*_log) << "Unable to encode frame: " << _framecnt << std::endl;
    235             fprintf(stderr,"\n\nUnable to encode frame: %d\n\n", _framecnt);
    236             exit(EXIT_FAILURE);
    237         }
    238     }
    239     _totalEncodeTime += endtime - starttime;
    240 
    241     if (encodingAttempts > 1)
    242     {
    243         (*_log) << encodingAttempts << " attempts required to encode frame: " <<
    244             _framecnt + 1 << std::endl;
    245         fprintf(stderr,"\n%d attempts required to encode frame: %d\n", encodingAttempts,
    246             _framecnt + 1);
    247     }
    248 
    249     return false;
    250 }
    251 
    252 int
    253 NormalTest::Decode(int lossValue)
    254 {
    255     _encodedVideoBuffer.SetWidth(_inst.width);
    256     _encodedVideoBuffer.SetHeight(_inst.height);
    257     int lengthDecFrame = 0;
    258     if (lengthDecFrame < 0)
    259     {
    260         return lengthDecFrame;
    261     }
    262     _encodedVideoBuffer.SetLength(0);
    263     return lengthDecFrame;
    264 }
    265