| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "normal_test.h" |
| |
| #include <time.h> |
| #include <sstream> |
| #include <string.h> |
| |
| #include "gtest/gtest.h" |
| #include "testsupport/fileutils.h" |
| |
| NormalTest::NormalTest() |
| : |
| Test("Normal Test 1", "A test of normal execution of the codec"), |
| _testNo(1), |
| _lengthEncFrame(0), |
| _appendNext(false) |
| { |
| } |
| |
| NormalTest::NormalTest(std::string name, std::string description, |
| unsigned int testNo) |
| : |
| Test(name, description), |
| _requestKeyFrame(false), |
| _testNo(testNo), |
| _lengthEncFrame(0), |
| _appendNext(false) |
| { |
| } |
| |
| NormalTest::NormalTest(std::string name, std::string description, |
| WebRtc_UWord32 bitRate, unsigned int testNo) |
| : |
| Test(name, description, bitRate), |
| _requestKeyFrame(false), |
| _testNo(testNo), |
| _lengthEncFrame(0), |
| _appendNext(false) |
| { |
| } |
| |
| void |
| NormalTest::Setup() |
| { |
| Test::Setup(); |
| std::stringstream ss; |
| std::string strTestNo; |
| ss << _testNo; |
| ss >> strTestNo; |
| |
| // Check if settings exist. Otherwise use defaults. |
| if (_outname == "") |
| { |
| _outname = webrtc::test::OutputPath() + "out_normaltest" + strTestNo + |
| ".yuv"; |
| } |
| |
| if (_encodedName == "") |
| { |
| _encodedName = webrtc::test::OutputPath() + "encoded_normaltest" + |
| strTestNo + ".yuv"; |
| } |
| |
| if ((_sourceFile = fopen(_inname.c_str(), "rb")) == NULL) |
| { |
| printf("Cannot read file %s.\n", _inname.c_str()); |
| exit(1); |
| } |
| |
| if ((_encodedFile = fopen(_encodedName.c_str(), "wb")) == NULL) |
| { |
| printf("Cannot write encoded file.\n"); |
| exit(1); |
| } |
| |
| char mode[3] = "wb"; |
| if (_appendNext) |
| { |
| strncpy(mode, "ab", 3); |
| } |
| |
| if ((_decodedFile = fopen(_outname.c_str(), mode)) == NULL) |
| { |
| printf("Cannot write file %s.\n", _outname.c_str()); |
| exit(1); |
| } |
| |
| _appendNext = true; |
| } |
| |
| void |
| NormalTest::Teardown() |
| { |
| Test::Teardown(); |
| fclose(_sourceFile); |
| fclose(_decodedFile); |
| } |
| |
| void |
| NormalTest::Perform() |
| { |
| _inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv"; |
| CodecSettings(352, 288, 30, _bitRate); |
| Setup(); |
| |
| _inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame); |
| _decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame); |
| _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame); |
| |
| _encoder->InitEncode(&_inst, 1, 1460); |
| CodecSpecific_InitBitrate(); |
| _decoder->InitDecode(&_inst,1); |
| |
| _totalEncodeTime = _totalDecodeTime = 0; |
| _framecnt = 0; |
| _sumEncBytes = 0; |
| _lengthEncFrame = 0; |
| int decodeLength = 0; |
| while (!Encode()) |
| { |
| DoPacketLoss(); |
| _encodedVideoBuffer.UpdateLength(_encodedVideoBuffer.GetLength()); |
| fwrite(_encodedVideoBuffer.GetBuffer(), 1, _encodedVideoBuffer.GetLength(), _encodedFile); |
| decodeLength = Decode(); |
| if (decodeLength < 0) |
| { |
| fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength); |
| exit(EXIT_FAILURE); |
| } |
| fwrite(_decodedVideoBuffer.GetBuffer(), 1, decodeLength, _decodedFile); |
| CodecSpecific_InitBitrate(); |
| _framecnt++; |
| } |
| |
| // Ensure we empty the decoding queue. |
| while (decodeLength > 0) |
| { |
| decodeLength = Decode(); |
| if (decodeLength < 0) |
| { |
| fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength); |
| exit(EXIT_FAILURE); |
| } |
| fwrite(_decodedVideoBuffer.GetBuffer(), 1, decodeLength, _decodedFile); |
| } |
| |
| double actualBitRate = ActualBitRate(_framecnt) / 1000.0; |
| double avgEncTime = _totalEncodeTime / _framecnt; |
| double avgDecTime = _totalDecodeTime / _framecnt; |
| printf("Actual bitrate: %f kbps\n", actualBitRate); |
| printf("Average encode time: %f s\n", avgEncTime); |
| printf("Average decode time: %f s\n", avgDecTime); |
| (*_log) << "Actual bitrate: " << actualBitRate << " kbps\tTarget: " << _bitRate << " kbps" << std::endl; |
| (*_log) << "Average encode time: " << avgEncTime << " s" << std::endl; |
| (*_log) << "Average decode time: " << avgDecTime << " s" << std::endl; |
| |
| _inputVideoBuffer.Free(); |
| _encodedVideoBuffer.Reset(); |
| _decodedVideoBuffer.Free(); |
| |
| _encoder->Release(); |
| _decoder->Release(); |
| |
| Teardown(); |
| } |
| |
| bool |
| NormalTest::Encode() |
| { |
| _lengthEncFrame = 0; |
| EXPECT_GT(fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile), 0u); |
| if (feof(_sourceFile) != 0) |
| { |
| return true; |
| } |
| _inputVideoBuffer.CopyBuffer(_lengthSourceFrame, _sourceBuffer); |
| _inputVideoBuffer.SetTimeStamp(_framecnt); |
| |
| // This multiple attempt ridiculousness is to accomodate VP7: |
| // 1. The wrapper can unilaterally reduce the framerate for low bitrates. |
| // 2. The codec inexplicably likes to reject some frames. Perhaps there |
| // is a good reason for this... |
| int encodingAttempts = 0; |
| double starttime = 0; |
| double endtime = 0; |
| while (_lengthEncFrame == 0) |
| { |
| starttime = clock()/(double)CLOCKS_PER_SEC; |
| |
| _inputVideoBuffer.SetWidth(_inst.width); |
| _inputVideoBuffer.SetHeight(_inst.height); |
| //_lengthEncFrame = _encoder->Encode(_inputVideoBuffer, _encodedVideoBuffer, _frameInfo, |
| // _inst.frameRate, _requestKeyFrame && !(_framecnt%50)); |
| |
| endtime = clock()/(double)CLOCKS_PER_SEC; |
| |
| _encodedVideoBuffer.SetCaptureHeight(_inst.height); |
| _encodedVideoBuffer.SetCaptureWidth(_inst.width); |
| if (_lengthEncFrame < 0) |
| { |
| (*_log) << "Error in encoder: " << _lengthEncFrame << std::endl; |
| fprintf(stderr,"\n\nError in encoder: %d\n\n", _lengthEncFrame); |
| exit(EXIT_FAILURE); |
| } |
| _sumEncBytes += _lengthEncFrame; |
| |
| encodingAttempts++; |
| if (encodingAttempts > 50) |
| { |
| (*_log) << "Unable to encode frame: " << _framecnt << std::endl; |
| fprintf(stderr,"\n\nUnable to encode frame: %d\n\n", _framecnt); |
| exit(EXIT_FAILURE); |
| } |
| } |
| _totalEncodeTime += endtime - starttime; |
| |
| if (encodingAttempts > 1) |
| { |
| (*_log) << encodingAttempts << " attempts required to encode frame: " << |
| _framecnt + 1 << std::endl; |
| fprintf(stderr,"\n%d attempts required to encode frame: %d\n", encodingAttempts, |
| _framecnt + 1); |
| } |
| |
| return false; |
| } |
| |
| int |
| NormalTest::Decode(int lossValue) |
| { |
| _encodedVideoBuffer.SetWidth(_inst.width); |
| _encodedVideoBuffer.SetHeight(_inst.height); |
| int lengthDecFrame = 0; |
| //int lengthDecFrame = _decoder->Decode(_encodedVideoBuffer, _decodedVideoBuffer); |
| //_totalDecodeTime += (double)((clock()/(double)CLOCKS_PER_SEC) - starttime); |
| if (lengthDecFrame < 0) |
| { |
| return lengthDecFrame; |
| } |
| _encodedVideoBuffer.Reset(); |
| _encodedVideoBuffer.UpdateLength(0); |
| return lengthDecFrame; |
| } |
| |