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_async_test.h"
     12 
     13 #include <assert.h>
     14 #include <queue>
     15 #include <sstream>
     16 #include <string.h>
     17 #include <vector>
     18 
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
     21 #include "webrtc/system_wrappers/interface/tick_util.h"
     22 #include "webrtc/test/testsupport/fileutils.h"
     23 #include "webrtc/typedefs.h"
     24 
     25 using namespace webrtc;
     26 
     27 NormalAsyncTest::NormalAsyncTest()
     28 :
     29 NormalTest("Async Normal Test 1", "A test of normal execution of the codec", 1),
     30 _decodeCompleteTime(0),
     31 _encodeCompleteTime(0),
     32 _encFrameCnt(0),
     33 _decFrameCnt(0),
     34 _requestKeyFrame(false),
     35 _appendNext(false),
     36 _missingFrames(false),
     37 _rttFrames(0),
     38 _hasReceivedSLI(false),
     39 _hasReceivedRPSI(false),
     40 _hasReceivedPLI(false),
     41 _waitForKey(false)
     42 {
     43 }
     44 
     45 NormalAsyncTest::NormalAsyncTest(uint32_t bitRate)
     46 :
     47 NormalTest("Async Normal Test 1", "A test of normal execution of the codec",
     48            bitRate,
     49            1),
     50 _decodeCompleteTime(0),
     51 _encodeCompleteTime(0),
     52 _encFrameCnt(0),
     53 _decFrameCnt(0),
     54 _requestKeyFrame(false),
     55 _appendNext(false),
     56 _missingFrames(false),
     57 _rttFrames(0),
     58 _hasReceivedSLI(false),
     59 _hasReceivedRPSI(false),
     60 _hasReceivedPLI(false),
     61 _waitForKey(false)
     62 {
     63 }
     64 
     65 NormalAsyncTest::NormalAsyncTest(std::string name, std::string description,
     66                                  unsigned int testNo)
     67 :
     68 NormalTest(name, description, testNo),
     69 _decodeCompleteTime(0),
     70 _encodeCompleteTime(0),
     71 _encFrameCnt(0),
     72 _decFrameCnt(0),
     73 _requestKeyFrame(false),
     74 _lengthEncFrame(0),
     75 _appendNext(false),
     76 _missingFrames(false),
     77 _rttFrames(0),
     78 _hasReceivedSLI(false),
     79 _hasReceivedRPSI(false),
     80 _hasReceivedPLI(false),
     81 _waitForKey(false)
     82 {
     83 }
     84 
     85 NormalAsyncTest::NormalAsyncTest(std::string name, std::string description,
     86                                  uint32_t bitRate, unsigned int testNo)
     87 :
     88 NormalTest(name, description, bitRate, testNo),
     89 _decodeCompleteTime(0),
     90 _encodeCompleteTime(0),
     91 _encFrameCnt(0),
     92 _decFrameCnt(0),
     93 _requestKeyFrame(false),
     94 _lengthEncFrame(0),
     95 _appendNext(false),
     96 _missingFrames(false),
     97 _rttFrames(0),
     98 _hasReceivedSLI(false),
     99 _hasReceivedRPSI(false),
    100 _hasReceivedPLI(false),
    101 _waitForKey(false)
    102 {
    103 }
    104 
    105 NormalAsyncTest::NormalAsyncTest(std::string name, std::string description,
    106                                  uint32_t bitRate, unsigned int testNo,
    107                                  unsigned int rttFrames)
    108 :
    109 NormalTest(name, description, bitRate, testNo),
    110 _decodeCompleteTime(0),
    111 _encodeCompleteTime(0),
    112 _encFrameCnt(0),
    113 _decFrameCnt(0),
    114 _requestKeyFrame(false),
    115 _lengthEncFrame(0),
    116 _appendNext(false),
    117 _missingFrames(false),
    118 _rttFrames(rttFrames),
    119 _hasReceivedSLI(false),
    120 _hasReceivedRPSI(false),
    121 _hasReceivedPLI(false),
    122 _waitForKey(false)
    123 {
    124 }
    125 
    126 void
    127 NormalAsyncTest::Setup()
    128 {
    129     CodecTest::Setup();
    130     std::stringstream ss;
    131     std::string strTestNo;
    132     ss << _testNo;
    133     ss >> strTestNo;
    134 
    135     // Check if settings exist. Otherwise use defaults.
    136     if (_outname == "")
    137     {
    138         _outname = webrtc::test::OutputPath() + "out_normaltest" + strTestNo +
    139             ".yuv";
    140     }
    141 
    142     if (_encodedName == "")
    143     {
    144         _encodedName = webrtc::test::OutputPath() + "encoded_normaltest" +
    145             strTestNo + ".yuv";
    146     }
    147 
    148     if ((_sourceFile = fopen(_inname.c_str(), "rb")) == NULL)
    149     {
    150         printf("Cannot read file %s.\n", _inname.c_str());
    151         exit(1);
    152     }
    153 
    154     if ((_encodedFile = fopen(_encodedName.c_str(), "wb")) == NULL)
    155     {
    156         printf("Cannot write encoded file.\n");
    157         exit(1);
    158     }
    159 
    160     char mode[3] = "wb";
    161     if (_appendNext)
    162     {
    163         strncpy(mode, "ab", 3);
    164     }
    165 
    166     if ((_decodedFile = fopen(_outname.c_str(), mode)) == NULL)
    167     {
    168         printf("Cannot write file %s.\n", _outname.c_str());
    169         exit(1);
    170     }
    171 
    172     _appendNext = true;
    173 }
    174 
    175 void
    176 NormalAsyncTest::Teardown()
    177 {
    178     CodecTest::Teardown();
    179     fclose(_sourceFile);
    180     fclose(_encodedFile);
    181     fclose(_decodedFile);
    182 }
    183 
    184 FrameQueueTuple::~FrameQueueTuple()
    185 {
    186     if (_codecSpecificInfo != NULL)
    187     {
    188         delete _codecSpecificInfo;
    189     }
    190     if (_frame != NULL)
    191     {
    192         delete _frame;
    193     }
    194 }
    195 
    196 void FrameQueue::PushFrame(VideoFrame *frame,
    197                            webrtc::CodecSpecificInfo* codecSpecificInfo)
    198 {
    199     WriteLockScoped cs(_queueRWLock);
    200     _frameBufferQueue.push(new FrameQueueTuple(frame, codecSpecificInfo));
    201 }
    202 
    203 FrameQueueTuple* FrameQueue::PopFrame()
    204 {
    205     WriteLockScoped cs(_queueRWLock);
    206     if (_frameBufferQueue.empty())
    207     {
    208         return NULL;
    209     }
    210     FrameQueueTuple* tuple = _frameBufferQueue.front();
    211     _frameBufferQueue.pop();
    212     return tuple;
    213 }
    214 
    215 bool FrameQueue::Empty()
    216 {
    217     ReadLockScoped cs(_queueRWLock);
    218     return _frameBufferQueue.empty();
    219 }
    220 
    221 uint32_t VideoEncodeCompleteCallback::EncodedBytes()
    222 {
    223     return _encodedBytes;
    224 }
    225 
    226 int32_t
    227 VideoEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
    228                                      const webrtc::CodecSpecificInfo* codecSpecificInfo,
    229                                      const webrtc::RTPFragmentationHeader*
    230                                      fragmentation)
    231 {
    232     _test.Encoded(encodedImage);
    233     VideoFrame *newBuffer = new VideoFrame();
    234     newBuffer->VerifyAndAllocate(encodedImage._size);
    235     _encodedBytes += encodedImage._length;
    236     // If _frameQueue would have been a fixed sized buffer we could have asked
    237     // it for an empty frame and then just do:
    238     // emptyFrame->SwapBuffers(encodedBuffer);
    239     // This is how it should be done in Video Engine to save in on memcpys
    240     webrtc::CodecSpecificInfo* codecSpecificInfoCopy =
    241         _test.CopyCodecSpecificInfo(codecSpecificInfo);
    242     _test.CopyEncodedImage(*newBuffer, encodedImage, codecSpecificInfoCopy);
    243     if (_encodedFile != NULL)
    244     {
    245       if (fwrite(newBuffer->Buffer(), 1, newBuffer->Length(),
    246                  _encodedFile) !=  newBuffer->Length()) {
    247         return -1;
    248       }
    249     }
    250     _frameQueue->PushFrame(newBuffer, codecSpecificInfoCopy);
    251     return 0;
    252 }
    253 
    254 uint32_t VideoDecodeCompleteCallback::DecodedBytes()
    255 {
    256     return _decodedBytes;
    257 }
    258 
    259 int32_t
    260 VideoDecodeCompleteCallback::Decoded(I420VideoFrame& image)
    261 {
    262     _test.Decoded(image);
    263     _decodedBytes += CalcBufferSize(kI420, image.width(), image.height());
    264     if (_decodedFile != NULL)
    265     {
    266        return PrintI420VideoFrame(image, _decodedFile);
    267     }
    268     return 0;
    269 }
    270 
    271 int32_t
    272 VideoDecodeCompleteCallback::ReceivedDecodedReferenceFrame(
    273     const uint64_t pictureId)
    274 {
    275     return _test.ReceivedDecodedReferenceFrame(pictureId);
    276 }
    277 
    278 int32_t
    279 VideoDecodeCompleteCallback::ReceivedDecodedFrame(
    280     const uint64_t pictureId)
    281 {
    282     return _test.ReceivedDecodedFrame(pictureId);
    283 }
    284 
    285 void
    286 NormalAsyncTest::Encoded(const EncodedImage& encodedImage)
    287 {
    288     _encodeCompleteTime = tGetTime();
    289     _encFrameCnt++;
    290     _totalEncodePipeTime += _encodeCompleteTime -
    291         _encodeTimes[encodedImage._timeStamp];
    292 }
    293 
    294 void
    295 NormalAsyncTest::Decoded(const I420VideoFrame& decodedImage)
    296 {
    297     _decodeCompleteTime = tGetTime();
    298     _decFrameCnt++;
    299     _totalDecodePipeTime += _decodeCompleteTime -
    300         _decodeTimes[decodedImage.timestamp()];
    301     _decodedWidth = decodedImage.width();
    302     _decodedHeight = decodedImage.height();
    303 }
    304 
    305 void
    306 NormalAsyncTest::Perform()
    307 {
    308     _inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv";
    309     CodecSettings(352, 288, 30, _bitRate);
    310     Setup();
    311     if(_encoder->InitEncode(&_inst, 1, 1440) < 0)
    312     {
    313         exit(EXIT_FAILURE);
    314     }
    315     _decoder->InitDecode(&_inst, 1);
    316     FrameQueue frameQueue;
    317     VideoEncodeCompleteCallback encCallback(_encodedFile, &frameQueue, *this);
    318     VideoDecodeCompleteCallback decCallback(_decodedFile, *this);
    319     _encoder->RegisterEncodeCompleteCallback(&encCallback);
    320     _decoder->RegisterDecodeCompleteCallback(&decCallback);
    321     if (SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK)
    322     {
    323         exit(EXIT_FAILURE);
    324     }
    325     _totalEncodeTime = _totalDecodeTime = 0;
    326     _totalEncodePipeTime = _totalDecodePipeTime = 0;
    327     bool complete = false;
    328     _framecnt = 0;
    329     _encFrameCnt = 0;
    330     _decFrameCnt = 0;
    331     _sumEncBytes = 0;
    332     _lengthEncFrame = 0;
    333     double starttime = tGetTime();
    334     while (!complete)
    335     {
    336         CodecSpecific_InitBitrate();
    337         complete = Encode();
    338         if (!frameQueue.Empty() || complete)
    339         {
    340             while (!frameQueue.Empty())
    341             {
    342                 _frameToDecode =
    343                     static_cast<FrameQueueTuple *>(frameQueue.PopFrame());
    344                 int lost = DoPacketLoss();
    345                 if (lost == 2)
    346                 {
    347                     // Lost the whole frame, continue
    348                     _missingFrames = true;
    349                     delete _frameToDecode;
    350                     _frameToDecode = NULL;
    351                     continue;
    352                 }
    353                 int ret = Decode(lost);
    354                 delete _frameToDecode;
    355                 _frameToDecode = NULL;
    356                 if (ret < 0)
    357                 {
    358                     fprintf(stderr,"\n\nError in decoder: %d\n\n", ret);
    359                     exit(EXIT_FAILURE);
    360                 }
    361                 else if (ret == 0)
    362                 {
    363                     _framecnt++;
    364                 }
    365                 else
    366                 {
    367                     fprintf(stderr,
    368                         "\n\nPositive return value from decode!\n\n");
    369                 }
    370             }
    371         }
    372     }
    373     double endtime = tGetTime();
    374     double totalExecutionTime = endtime - starttime;
    375     printf("Total execution time: %.1f s\n", totalExecutionTime);
    376     _sumEncBytes = encCallback.EncodedBytes();
    377     double actualBitRate = ActualBitRate(_encFrameCnt) / 1000.0;
    378     double avgEncTime = _totalEncodeTime / _encFrameCnt;
    379     double avgDecTime = _totalDecodeTime / _decFrameCnt;
    380     printf("Actual bitrate: %f kbps\n", actualBitRate);
    381     printf("Average encode time: %.1f ms\n", 1000 * avgEncTime);
    382     printf("Average decode time: %.1f ms\n", 1000 * avgDecTime);
    383     printf("Average encode pipeline time: %.1f ms\n",
    384            1000 * _totalEncodePipeTime / _encFrameCnt);
    385     printf("Average decode pipeline  time: %.1f ms\n",
    386            1000 * _totalDecodePipeTime / _decFrameCnt);
    387     printf("Number of encoded frames: %u\n", _encFrameCnt);
    388     printf("Number of decoded frames: %u\n", _decFrameCnt);
    389     (*_log) << "Actual bitrate: " << actualBitRate << " kbps\tTarget: " <<
    390         _bitRate << " kbps" << std::endl;
    391     (*_log) << "Average encode time: " << avgEncTime << " s" << std::endl;
    392     (*_log) << "Average decode time: " << avgDecTime << " s" << std::endl;
    393     _encoder->Release();
    394     _decoder->Release();
    395     Teardown();
    396 }
    397 
    398 bool
    399 NormalAsyncTest::Encode()
    400 {
    401     _lengthEncFrame = 0;
    402     if (feof(_sourceFile) != 0)
    403     {
    404         return true;
    405     }
    406     EXPECT_GT(fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile), 0u);
    407     EXPECT_EQ(0, _inputVideoBuffer.CreateFrame(_sizeY, _sourceBuffer,
    408                                   _sizeUv, _sourceBuffer + _sizeY,
    409                                   _sizeUv, _sourceBuffer + _sizeY + _sizeUv,
    410                                   _width, _height,
    411                                   _width, _halfWidth, _halfWidth));
    412     _inputVideoBuffer.set_timestamp((unsigned int)
    413         (_encFrameCnt * 9e4 / _inst.maxFramerate));
    414     _encodeCompleteTime = 0;
    415     _encodeTimes[_inputVideoBuffer.timestamp()] = tGetTime();
    416     std::vector<VideoFrameType> frame_types(1, kDeltaFrame);
    417 
    418     // check SLI queue
    419     _hasReceivedSLI = false;
    420     while (!_signalSLI.empty() && _signalSLI.front().delay == 0)
    421     {
    422         // SLI message has arrived at sender side
    423         _hasReceivedSLI = true;
    424         _pictureIdSLI = _signalSLI.front().id;
    425         _signalSLI.pop_front();
    426     }
    427     // decrement SLI queue times
    428     for (std::list<fbSignal>::iterator it = _signalSLI.begin();
    429         it !=_signalSLI.end(); it++)
    430     {
    431         (*it).delay--;
    432     }
    433 
    434     // check PLI queue
    435     _hasReceivedPLI = false;
    436     while (!_signalPLI.empty() && _signalPLI.front().delay == 0)
    437     {
    438         // PLI message has arrived at sender side
    439         _hasReceivedPLI = true;
    440         _signalPLI.pop_front();
    441     }
    442     // decrement PLI queue times
    443     for (std::list<fbSignal>::iterator it = _signalPLI.begin();
    444         it != _signalPLI.end(); it++)
    445     {
    446         (*it).delay--;
    447     }
    448 
    449     if (_hasReceivedPLI)
    450     {
    451         // respond to PLI by encoding a key frame
    452         frame_types[0] = kKeyFrame;
    453         _hasReceivedPLI = false;
    454         _hasReceivedSLI = false; // don't trigger both at once
    455     }
    456 
    457     webrtc::CodecSpecificInfo* codecSpecificInfo = CreateEncoderSpecificInfo();
    458     int ret = _encoder->Encode(_inputVideoBuffer,
    459                                codecSpecificInfo, &frame_types);
    460     EXPECT_EQ(ret, WEBRTC_VIDEO_CODEC_OK);
    461     if (codecSpecificInfo != NULL)
    462     {
    463         delete codecSpecificInfo;
    464         codecSpecificInfo = NULL;
    465     }
    466     if (_encodeCompleteTime > 0)
    467     {
    468         _totalEncodeTime += _encodeCompleteTime -
    469             _encodeTimes[_inputVideoBuffer.timestamp()];
    470     }
    471     else
    472     {
    473         _totalEncodeTime += tGetTime() -
    474             _encodeTimes[_inputVideoBuffer.timestamp()];
    475     }
    476     assert(ret >= 0);
    477     return false;
    478 }
    479 
    480 int
    481 NormalAsyncTest::Decode(int lossValue)
    482 {
    483     _sumEncBytes += _frameToDecode->_frame->Length();
    484     EncodedImage encodedImage;
    485     VideoEncodedBufferToEncodedImage(*(_frameToDecode->_frame), encodedImage);
    486     encodedImage._completeFrame = !lossValue;
    487     _decodeCompleteTime = 0;
    488     _decodeTimes[encodedImage._timeStamp] = tGetTime();
    489     int ret = WEBRTC_VIDEO_CODEC_OK;
    490     // TODO(mikhal):  Update frame type.
    491     //if (!_waitForKey || encodedImage._frameType == kKeyFrame)
    492     {
    493         _waitForKey = false;
    494         ret = _decoder->Decode(encodedImage, _missingFrames, NULL,
    495                                _frameToDecode->_codecSpecificInfo);
    496 
    497         if (ret >= 0)
    498         {
    499             _missingFrames = false;
    500         }
    501     }
    502 
    503     // check for SLI
    504     if (ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI)
    505     {
    506         // add an SLI feedback to the feedback "queue"
    507         // to be delivered to encoder with _rttFrames delay
    508         _signalSLI.push_back(fbSignal(_rttFrames,
    509             static_cast<uint8_t>((_lastDecPictureId) & 0x3f))); // 6 lsb
    510 
    511         ret = WEBRTC_VIDEO_CODEC_OK;
    512     }
    513     else if (ret == WEBRTC_VIDEO_CODEC_ERR_REQUEST_SLI)
    514     {
    515         // add an SLI feedback to the feedback "queue"
    516         // to be delivered to encoder with _rttFrames delay
    517         _signalSLI.push_back(fbSignal(_rttFrames,
    518             static_cast<uint8_t>((_lastDecPictureId + 1) & 0x3f)));//6 lsb
    519 
    520         ret = WEBRTC_VIDEO_CODEC_OK;
    521     }
    522     else if (ret == WEBRTC_VIDEO_CODEC_ERROR)
    523     {
    524         // wait for new key frame
    525         // add an PLI feedback to the feedback "queue"
    526         // to be delivered to encoder with _rttFrames delay
    527         _signalPLI.push_back(fbSignal(_rttFrames, 0 /* picId not used*/));
    528         _waitForKey = true;
    529 
    530         ret = WEBRTC_VIDEO_CODEC_OK;
    531     }
    532 
    533     if (_decodeCompleteTime > 0)
    534     {
    535         _totalDecodeTime += _decodeCompleteTime -
    536             _decodeTimes[encodedImage._timeStamp];
    537     }
    538     else
    539     {
    540         _totalDecodeTime += tGetTime() - _decodeTimes[encodedImage._timeStamp];
    541     }
    542     return ret;
    543 }
    544 
    545 webrtc::CodecSpecificInfo*
    546 NormalAsyncTest::CopyCodecSpecificInfo(
    547         const webrtc::CodecSpecificInfo* codecSpecificInfo) const
    548 {
    549     webrtc::CodecSpecificInfo* info = new webrtc::CodecSpecificInfo;
    550     *info = *codecSpecificInfo;
    551     return info;
    552 }
    553 
    554 void NormalAsyncTest::CodecSpecific_InitBitrate()
    555 {
    556     if (_bitRate == 0)
    557     {
    558         _encoder->SetRates(600, _inst.maxFramerate);
    559     }
    560     else
    561     {
    562         _encoder->SetRates(_bitRate, _inst.maxFramerate);
    563     }
    564 }
    565 
    566 void NormalAsyncTest::CopyEncodedImage(VideoFrame& dest,
    567                                        EncodedImage& src,
    568                                        void* /*codecSpecificInfo*/) const
    569 {
    570     dest.CopyFrame(src._length, src._buffer);
    571     //dest.SetFrameType(src._frameType);
    572     dest.SetWidth((uint16_t)src._encodedWidth);
    573     dest.SetHeight((uint16_t)src._encodedHeight);
    574     dest.SetTimeStamp(src._timeStamp);
    575 }
    576 
    577 int32_t NormalAsyncTest::ReceivedDecodedReferenceFrame(
    578     const uint64_t pictureId) {
    579   _lastDecRefPictureId = pictureId;
    580   return 0;
    581 }
    582 
    583 int32_t NormalAsyncTest::ReceivedDecodedFrame(
    584     const uint64_t pictureId) {
    585   _lastDecPictureId = pictureId;
    586   return 0;
    587 }
    588 
    589 double
    590 NormalAsyncTest::tGetTime()
    591 {// return time in sec
    592     return ((double) (TickTime::MillisecondTimestamp())/1000);
    593  }
    594