git-svn-id: http://webrtc.googlecode.com/svn/trunk@4 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
		
							
								
								
									
										373
									
								
								modules/video_coding/main/test/normal_test.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								modules/video_coding/main/test/normal_test.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,373 @@ | ||||
| /* | ||||
|  *  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 "../source/event.h" | ||||
| #include "tick_time.h" | ||||
| #include "common_types.h" | ||||
| #include "trace.h" | ||||
| #include "test_util.h" | ||||
| #include <assert.h> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <time.h> | ||||
|  | ||||
| using namespace webrtc; | ||||
|  | ||||
| int NormalTest::RunTest(CmdArgs& args) | ||||
| { | ||||
|     // Don't run this test with debug time | ||||
| #if defined(TICK_TIME_DEBUG) || defined(EVENT_DEBUG) | ||||
|     printf("SIMULATION TIME\n"); | ||||
| #else | ||||
|     printf("REAL-TIME\n"); | ||||
| #endif | ||||
|     Trace::CreateTrace(); | ||||
|     Trace::SetTraceFile("VCMNormalTestTrace.txt"); | ||||
|     Trace::SetLevelFilter(webrtc::kTraceAll); | ||||
|     VideoCodingModule* vcm = VideoCodingModule::Create(1); | ||||
|     NormalTest VCMNTest(vcm); | ||||
|     VCMNTest.Perform(args); | ||||
|     VideoCodingModule::Destroy(vcm); | ||||
|     Trace::ReturnTrace(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| //////////////// | ||||
| // Callback Implementation | ||||
| ////////////// | ||||
|  | ||||
| VCMNTEncodeCompleteCallback::VCMNTEncodeCompleteCallback(FILE* encodedFile, NormalTest& test): | ||||
| _seqNo(0), | ||||
| _layerPacketId(1), | ||||
| _encodedFile(encodedFile), | ||||
| _encodedBytes(0), | ||||
| _skipCnt(0), | ||||
| _VCMReceiver(NULL), | ||||
| _test(test) | ||||
| { | ||||
|     // | ||||
| } | ||||
| VCMNTEncodeCompleteCallback::~VCMNTEncodeCompleteCallback() | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| VCMNTEncodeCompleteCallback::RegisterTransportCallback(VCMPacketizationCallback* transport) | ||||
| { | ||||
| } | ||||
|  | ||||
| WebRtc_Word32 | ||||
| VCMNTEncodeCompleteCallback::SendData(const FrameType frameType, | ||||
|                                  const WebRtc_UWord8  payloadType, | ||||
|                                  const WebRtc_UWord32 timeStamp, | ||||
|                                  const WebRtc_UWord8* payloadData, | ||||
|                                  const WebRtc_UWord32 payloadSize, | ||||
|                                  const RTPFragmentationHeader& fragmentationHeader) | ||||
|  | ||||
| { | ||||
|     // will call the VCMReceiver input packet | ||||
|     _frameType = frameType; | ||||
|     // writing encodedData into file | ||||
|     fwrite(payloadData, 1, payloadSize, _encodedFile); | ||||
|     WebRtcRTPHeader rtpInfo; | ||||
|     rtpInfo.header.markerBit = true; | ||||
|     rtpInfo.type.Video.width = 0; | ||||
|     rtpInfo.type.Video.height = 0; | ||||
|     switch (_test.VideoType()) | ||||
|     { | ||||
|     case kVideoCodecH263: | ||||
|         rtpInfo.type.Video.codec = kRTPVideoH263; | ||||
|         rtpInfo.type.Video.codecHeader.H263.bits = false; | ||||
|         rtpInfo.type.Video.codecHeader.H263.independentlyDecodable = false; | ||||
|         rtpInfo.type.Video.height = (WebRtc_UWord16)_test.Height(); | ||||
|         rtpInfo.type.Video.width = (WebRtc_UWord16)_test.Width(); | ||||
|         break; | ||||
|     case kVideoCodecVP8: | ||||
|         rtpInfo.type.Video.codec = kRTPVideoVP8; | ||||
|         break; | ||||
|     case kVideoCodecI420: | ||||
|         rtpInfo.type.Video.codec = kRTPVideoI420; | ||||
|         break; | ||||
|     } | ||||
|     rtpInfo.header.payloadType = payloadType; | ||||
|     rtpInfo.header.sequenceNumber = _seqNo++; | ||||
|     rtpInfo.header.ssrc = 0; | ||||
|     rtpInfo.header.timestamp = timeStamp; | ||||
|     rtpInfo.frameType = frameType; | ||||
|     // Size should also be received from that table, since the payload type | ||||
|     // defines the size. | ||||
|  | ||||
|     _encodedBytes += payloadSize; | ||||
|     if (payloadSize < 20) | ||||
|     { | ||||
|         _skipCnt++; | ||||
|     } | ||||
|     _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo); | ||||
|     return 0; | ||||
| } | ||||
| void | ||||
| VCMNTEncodeCompleteCallback::RegisterReceiverVCM(VideoCodingModule *vcm) | ||||
| { | ||||
|     _VCMReceiver = vcm; | ||||
|     return; | ||||
| } | ||||
|  WebRtc_Word32 | ||||
| VCMNTEncodeCompleteCallback::EncodedBytes() | ||||
| { | ||||
|     return _encodedBytes; | ||||
| } | ||||
|  | ||||
| WebRtc_UWord32 | ||||
| VCMNTEncodeCompleteCallback::SkipCnt() | ||||
| { | ||||
|     return _skipCnt; | ||||
| } | ||||
|  | ||||
| // Decoded Frame Callback Implmentation | ||||
| VCMNTDecodeCompleCallback::~VCMNTDecodeCompleCallback() | ||||
| { | ||||
|     // | ||||
| } | ||||
|  WebRtc_Word32 | ||||
| VCMNTDecodeCompleCallback::FrameToRender(webrtc::VideoFrame& videoFrame) | ||||
| { | ||||
|     if (videoFrame.Width() != _currentWidth || | ||||
|         videoFrame.Height() != _currentHeight) | ||||
|     { | ||||
|         _currentWidth = videoFrame.Width(); | ||||
|         _currentHeight = videoFrame.Height(); | ||||
|         if (_decodedFile != NULL) | ||||
|         { | ||||
|             fclose(_decodedFile); | ||||
|             _decodedFile = NULL; | ||||
|         } | ||||
|         _decodedFile = fopen(_outname.c_str(), "wb"); | ||||
|     } | ||||
|     fwrite(videoFrame.Buffer(), 1, videoFrame.Length(), _decodedFile); | ||||
|     _decodedBytes+= videoFrame.Length(); | ||||
|     return VCM_OK; | ||||
| } | ||||
|  | ||||
|  WebRtc_Word32 | ||||
| VCMNTDecodeCompleCallback::DecodedBytes() | ||||
| { | ||||
|     return _decodedBytes; | ||||
| } | ||||
|  | ||||
|  //VCM Normal Test Class implementation | ||||
|  | ||||
| NormalTest::NormalTest(VideoCodingModule* vcm) | ||||
| : | ||||
| _vcm(vcm), | ||||
| _totalEncodeTime(0), | ||||
| _totalDecodeTime(0), | ||||
| _decodeCompleteTime(0), | ||||
| _encodeCompleteTime(0), | ||||
| _totalEncodePipeTime(0), | ||||
| _totalDecodePipeTime(0), | ||||
| _frameCnt(0), | ||||
| _timeStamp(0), | ||||
| _encFrameCnt(0), | ||||
| _decFrameCnt(0), | ||||
| _sumEncBytes(0) | ||||
|  | ||||
| { | ||||
|     // | ||||
| } | ||||
|  | ||||
| NormalTest::~NormalTest() | ||||
| { | ||||
|     // | ||||
| } | ||||
| void | ||||
| NormalTest::Setup(CmdArgs& args) | ||||
| { | ||||
|     _inname = args.inputFile; | ||||
|     _encodedName = "encoded_normaltest.yuv"; | ||||
|     _width = args.width; | ||||
|     _height = args.height; | ||||
|     _frameRate = args.frameRate; | ||||
|     _bitRate = args.bitRate; | ||||
|     if (args.outputFile == "") | ||||
|     { | ||||
|         std::ostringstream filename; | ||||
|         filename << "../NormalTest_" << _width << "x" << _height << "_" << _frameRate << "Hz_P420.yuv"; | ||||
|         _outname = filename.str(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         _outname = args.outputFile; | ||||
|     } | ||||
|     _lengthSourceFrame  = 3*_width*_height/2; | ||||
|     _videoType = args.codecType; | ||||
|  | ||||
|     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); | ||||
|     } | ||||
|  | ||||
|     _log.open("../TestLog.txt", std::fstream::out | std::fstream::app); | ||||
|     return; | ||||
| } | ||||
|  | ||||
| WebRtc_Word32 | ||||
| NormalTest::Perform(CmdArgs& args) | ||||
| { | ||||
|     Setup(args); | ||||
|     EventWrapper* waitEvent = EventWrapper::Create(); | ||||
|     VideoCodec _sendCodec;//, _receiveCodec; // tmp - sendCodecd used as receive codec | ||||
|     _vcm->InitializeReceiver(); | ||||
|     _vcm->InitializeSender(); | ||||
|     TEST(VideoCodingModule::Codec(_videoType, &_sendCodec) == VCM_OK); | ||||
|     _sendCodec.startBitrate = (int)_bitRate; // should be later on changed via the API | ||||
|     _sendCodec.width = static_cast<WebRtc_UWord16>(_width); | ||||
|     _sendCodec.height = static_cast<WebRtc_UWord16>(_height); | ||||
|     _sendCodec.maxFramerate = _frameRate; | ||||
|     TEST(_vcm->RegisterSendCodec(&_sendCodec, 4, 1400) == VCM_OK);// will also set and init the desired codec | ||||
|     // register a decoder (same codec for decoder and encoder ) | ||||
|     TEST(_vcm->RegisterReceiveCodec(&_sendCodec, 1) == VCM_OK); | ||||
|     /* Callback Settings */ | ||||
|     VCMNTDecodeCompleCallback _decodeCallback(_outname); | ||||
|     _vcm->RegisterReceiveCallback(&_decodeCallback); | ||||
|     VCMNTEncodeCompleteCallback _encodeCompleteCallback(_encodedFile, *this); | ||||
|     _vcm->RegisterTransportCallback(&_encodeCompleteCallback); | ||||
|     // encode and decode with the same vcm | ||||
|     _encodeCompleteCallback.RegisterReceiverVCM(_vcm); | ||||
|     /////////////////////// | ||||
|     /// Start Test | ||||
|     /////////////////////// | ||||
|     VideoFrame sourceFrame; | ||||
|     sourceFrame.VerifyAndAllocate(_lengthSourceFrame); | ||||
|     WebRtc_UWord8* tmpBuffer = new WebRtc_UWord8[_lengthSourceFrame]; | ||||
|     double startTime = clock()/(double)CLOCKS_PER_SEC; | ||||
|     _vcm->SetChannelParameters((WebRtc_UWord32)_bitRate, 0, 0); | ||||
|  | ||||
|     SendStatsTest sendStats; | ||||
|     sendStats.SetTargetFrameRate(static_cast<WebRtc_UWord32>(_frameRate)); | ||||
|     _vcm->RegisterSendStatisticsCallback(&sendStats); | ||||
|  | ||||
|     while (feof(_sourceFile)== 0) | ||||
|     { | ||||
|         WebRtc_Word64 processStartTime = VCMTickTime::MillisecondTimestamp(); | ||||
|         fread(tmpBuffer, 1, _lengthSourceFrame, _sourceFile); | ||||
|         _frameCnt++; | ||||
|         sourceFrame.CopyFrame(_lengthSourceFrame, tmpBuffer); | ||||
|         sourceFrame.SetHeight(_height); | ||||
|         sourceFrame.SetWidth(_width); | ||||
|         _timeStamp += (WebRtc_UWord32)(9e4 / static_cast<float>(_sendCodec.maxFramerate)); | ||||
|         sourceFrame.SetTimeStamp(_timeStamp); | ||||
|         _encodeTimes[int(sourceFrame.TimeStamp())] = clock()/(double)CLOCKS_PER_SEC; | ||||
|         WebRtc_Word32 ret = _vcm->AddVideoFrame(sourceFrame); | ||||
|         double encodeTime = clock()/(double)CLOCKS_PER_SEC - _encodeTimes[int(sourceFrame.TimeStamp())]; | ||||
|         _totalEncodeTime += encodeTime; | ||||
|         if (ret < 0) | ||||
|         { | ||||
|             printf("Error in AddFrame: %d\n", ret); | ||||
|             //exit(1); | ||||
|         } | ||||
|         _decodeTimes[int(sourceFrame.TimeStamp())] = clock()/(double)CLOCKS_PER_SEC; // same timestamp value for encode and decode | ||||
|         ret = _vcm->Decode(); | ||||
|         _totalDecodeTime += clock()/(double)CLOCKS_PER_SEC - _decodeTimes[int(sourceFrame.TimeStamp())]; | ||||
|         if (ret < 0) | ||||
|         { | ||||
|             printf("Error in Decode: %d\n", ret); | ||||
|             //exit(1); | ||||
|         } | ||||
|         if (_vcm->TimeUntilNextProcess() <= 0) | ||||
|         { | ||||
|             _vcm->Process(); | ||||
|         } | ||||
|         WebRtc_UWord32 framePeriod = static_cast<WebRtc_UWord32>(1000.0f/static_cast<float>(_sendCodec.maxFramerate) + 0.5f); | ||||
| #if defined(TICK_TIME_DEBUG) || defined(EVENT_DEBUG) | ||||
|         for (int i=0; i < framePeriod; i++) | ||||
|         { | ||||
|             VCMTickTime::IncrementDebugClock(); | ||||
|         } | ||||
| #else | ||||
|         WebRtc_Word64 timeSpent = VCMTickTime::MillisecondTimestamp() - processStartTime; | ||||
|         if (timeSpent < framePeriod) | ||||
|         { | ||||
|             waitEvent->Wait(framePeriod - timeSpent); | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|     double endTime = clock()/(double)CLOCKS_PER_SEC; | ||||
|     _testTotalTime = endTime - startTime; | ||||
|     _sumEncBytes = _encodeCompleteCallback.EncodedBytes(); | ||||
|  | ||||
|     delete tmpBuffer; | ||||
|     delete waitEvent; | ||||
|     Teardown(); | ||||
|     Print(); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void | ||||
| NormalTest::FrameEncoded(WebRtc_UWord32 timeStamp) | ||||
| { | ||||
|     _encodeCompleteTime = clock()/(double)CLOCKS_PER_SEC; | ||||
|     _encFrameCnt++; | ||||
|     _totalEncodePipeTime += _encodeCompleteTime - _encodeTimes[int(timeStamp)]; | ||||
|  | ||||
| } | ||||
|  | ||||
| void | ||||
| NormalTest::FrameDecoded(WebRtc_UWord32 timeStamp) | ||||
| { | ||||
|     _decodeCompleteTime = clock()/(double)CLOCKS_PER_SEC; | ||||
|     _decFrameCnt++; | ||||
|     _totalDecodePipeTime += _decodeCompleteTime - _decodeTimes[timeStamp]; | ||||
| } | ||||
|  | ||||
| void | ||||
| NormalTest::Print() | ||||
| { | ||||
|     std::cout << "Normal Test Completed!" << std::endl; | ||||
|     (_log) << "Normal Test Completed!" << std::endl; | ||||
|     (_log) << "Input file: " << _inname << std::endl; | ||||
|     (_log) << "Output file: " << _outname << std::endl; | ||||
|     (_log) << "Total run time: " << _testTotalTime << std::endl; | ||||
|     printf("Total run time: %f s \n", _testTotalTime); | ||||
|     double ActualBitRate =  8.0 *( _sumEncBytes / (_frameCnt / _frameRate)); | ||||
|     double actualBitRate = ActualBitRate / 1000.0; | ||||
|     double avgEncTime = _totalEncodeTime / _frameCnt; | ||||
|     double avgDecTime = _totalDecodeTime / _frameCnt; | ||||
|     double psnr; | ||||
|     PSNRfromFiles(_inname.c_str(), _outname.c_str(), _width, _height, &psnr); | ||||
|     printf("Actual bitrate: %f kbps\n", actualBitRate); | ||||
|     printf("Target bitrate: %f kbps\n", _bitRate); | ||||
|     ( _log) << "Actual bitrate: " << actualBitRate<< " kbps\tTarget: " << _bitRate << " kbps" << std::endl; | ||||
|     printf("Average encode time: %f s\n", avgEncTime); | ||||
|     ( _log) << "Average encode time: " << avgEncTime << " s" << std::endl; | ||||
|     printf("Average decode time: %f s\n", avgDecTime); | ||||
|     ( _log) << "Average decode time: " << avgDecTime << " s" << std::endl; | ||||
|     printf("PSNR: %f \n", psnr); | ||||
|     ( _log) << "PSNR: " << psnr << std::endl; | ||||
|     (_log) << std::endl; | ||||
| } | ||||
| void | ||||
| NormalTest::Teardown() | ||||
| { | ||||
|     //_log.close(); | ||||
|     fclose(_sourceFile); | ||||
|     fclose(_encodedFile); | ||||
|     return; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 niklase@google.com
					niklase@google.com