/* * 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 "benchmark.h" #include "video_source.h" #include "vplib.h" #include #include #include #include #include #if defined(_WIN32) #include #endif #include "event_wrapper.h" #include "video_codec_interface.h" #define SSIM_CALC 0 // by default, don't compute SSIM using namespace webrtc; Benchmark::Benchmark() : _resultsFileName("../../../../testFiles/benchmark.txt"), _codecName("Default"), NormalAsyncTest("Benchmark", "Codec benchmark over a range of test cases", 6) { } Benchmark::Benchmark(std::string name, std::string description) : _resultsFileName("../../../../testFiles/benchmark.txt"), _codecName("Default"), NormalAsyncTest(name, description, 6) { } Benchmark::Benchmark(std::string name, std::string description, std::string resultsFileName, std::string codecName) : _resultsFileName(resultsFileName), _codecName(codecName), NormalAsyncTest(name, description, 6) { } void Benchmark::Perform() { std::vector sources; std::vector::iterator it; // Configuration -------------------------- sources.push_back(new const VideoSource("test/testFiles/foreman_cif.yuv", kCIF)); sources.push_back(new const VideoSource("test/testFiles/akiyo_cif.yuv", kCIF)); const VideoSize size[] = {kQCIF, kCIF}; const int frameRate[] = {10, 15, 30}; // Specifies the framerates for which to perform a speed test. const bool speedTestMask[] = {false, false, false}; const int bitRate[] = {50, 100, 200, 300, 400, 500, 600, 1000}; // Determines the number of iterations to perform to arrive at the speed result. enum { kSpeedTestIterations = 10 }; // ---------------------------------------- const int nFrameRates = sizeof(frameRate)/sizeof(*frameRate); assert(sizeof(speedTestMask)/sizeof(*speedTestMask) == nFrameRates); const int nBitrates = sizeof(bitRate)/sizeof(*bitRate); int testIterations = 10; double psnr[nBitrates]; double ssim[nBitrates]; double fps[nBitrates]; double totalEncodeTime[nBitrates]; double totalDecodeTime[nBitrates]; _results.open(_resultsFileName.c_str(), std::fstream::out); _results << GetMagicStr() << std::endl; _results << _codecName << std::endl; for (it = sources.begin() ; it < sources.end(); it++) { for (int i = 0; i < sizeof(size)/sizeof(*size); i++) { for (int j = 0; j < nFrameRates; j++) { std::stringstream ss; std::string strFrameRate; std::string outFileName; ss << frameRate[j]; ss >> strFrameRate; outFileName = (*it)->GetFilePath() + "/" + (*it)->GetName() + "_" + VideoSource::GetSizeString(size[i]) + "_" + strFrameRate + ".yuv"; _target = new const VideoSource(outFileName, size[i], frameRate[j]); (*it)->Convert(*_target); if (VideoSource::FileExists(outFileName.c_str())) { _inname = outFileName; } else { _inname = (*it)->GetFileName(); } std::cout << (*it)->GetName() << ", " << VideoSource::GetSizeString(size[i]) << ", " << frameRate[j] << " fps" << std::endl << "Bitrate [kbps]:"; _results << (*it)->GetName() << "," << VideoSource::GetSizeString(size[i]) << "," << frameRate[j] << " fps" << std::endl << "Bitrate [kbps]"; if (speedTestMask[j]) { testIterations = kSpeedTestIterations; } else { testIterations = 1; } for (int k = 0; k < nBitrates; k++) { _bitRate = (bitRate[k]); double avgFps = 0.0; totalEncodeTime[k] = 0; totalDecodeTime[k] = 0; for (int l = 0; l < testIterations; l++) { PerformNormalTest(); _appendNext = false; avgFps += _framecnt / (_totalEncodeTime + _totalDecodeTime); totalEncodeTime[k] += _totalEncodeTime; totalDecodeTime[k] += _totalDecodeTime; } avgFps /= testIterations; totalEncodeTime[k] /= testIterations; totalDecodeTime[k] /= testIterations; double actualBitRate = ActualBitRate(_framecnt) / 1000.0; std::cout << " " << actualBitRate; _results << "," << actualBitRate; PSNRfromFiles(_inname.c_str(), _outname.c_str(), _inst.width, _inst.height, &psnr[k]); if (SSIM_CALC) { SSIMfromFiles(_inname.c_str(), _outname.c_str(), _inst.width, _inst.height, &ssim[k]); } fps[k] = avgFps; } std::cout << std::endl << "Y-PSNR [dB]:"; _results << std::endl << "Y-PSNR [dB]"; for (int k = 0; k < nBitrates; k++) { std::cout << " " << psnr[k]; _results << "," << psnr[k]; } if (SSIM_CALC) { std::cout << std::endl << "SSIM: "; _results << std::endl << "SSIM "; for (int k = 0; k < nBitrates; k++) { std::cout << " " << ssim[k]; _results << "," << ssim[k]; } } std::cout << std::endl << "Encode Time[ms]:"; _results << std::endl << "Encode Time[ms]"; for (int k = 0; k < nBitrates; k++) { std::cout << " " << totalEncodeTime[k]; _results << "," << totalEncodeTime[k]; } std::cout << std::endl << "Decode Time[ms]:"; _results << std::endl << "Decode Time[ms]"; for (int k = 0; k < nBitrates; k++) { std::cout << " " << totalDecodeTime[k]; _results << "," << totalDecodeTime[k]; } if (speedTestMask[j]) { std::cout << std::endl << "Speed [fps]:"; _results << std::endl << "Speed [fps]"; for (int k = 0; k < nBitrates; k++) { std::cout << " " << static_cast(fps[k] + 0.5); _results << "," << static_cast(fps[k] + 0.5); } } std::cout << std::endl << std::endl; _results << std::endl << std::endl; delete _target; } } delete *it; } _results.close(); } void Benchmark::PerformNormalTest() { _encoder = GetNewEncoder(); _decoder = GetNewDecoder(); CodecSettings(_target->GetWidth(), _target->GetHeight(), _target->GetFrameRate(), _bitRate); Setup(); EventWrapper* waitEvent = EventWrapper::Create(); _inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame); _decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame); _encoder->InitEncode(&_inst, 4, 1440); CodecSpecific_InitBitrate(); _decoder->InitDecode(&_inst,1); FrameQueue frameQueue; VideoEncodeCompleteCallback encCallback(_encodedFile, &frameQueue, *this); VideoDecodeCompleteCallback decCallback(_decodedFile, *this); _encoder->RegisterEncodeCompleteCallback(&encCallback); _decoder->RegisterDecodeCompleteCallback(&decCallback); SetCodecSpecificParameters(); _totalEncodeTime = _totalDecodeTime = 0; _totalEncodePipeTime = _totalDecodePipeTime = 0; bool complete = false; _framecnt = 0; _encFrameCnt = 0; _sumEncBytes = 0; _lengthEncFrame = 0; while (!complete) { complete = Encode(); if (!frameQueue.Empty() || complete) { while (!frameQueue.Empty()) { _frameToDecode = static_cast(frameQueue.PopFrame()); DoPacketLoss(); int ret = Decode(); delete _frameToDecode; _frameToDecode = NULL; if (ret < 0) { fprintf(stderr,"\n\nError in decoder: %d\n\n", ret); exit(EXIT_FAILURE); } else if (ret == 0) { _framecnt++; } else { fprintf(stderr, "\n\nPositive return value from decode!\n\n"); } } } waitEvent->Wait(5); } _inputVideoBuffer.Free(); //_encodedVideoBuffer.Reset(); ? _encodedVideoBuffer.Free(); _decodedVideoBuffer.Free(); _encoder->Release(); _decoder->Release(); delete waitEvent; delete _encoder; delete _decoder; Teardown(); } void Benchmark::CodecSpecific_InitBitrate() { if (_bitRate == 0) { _encoder->SetRates(600, _inst.maxFramerate); } else { _encoder->SetRates(_bitRate, _inst.maxFramerate); } }