| /* |
| * 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 "test_util.h" |
| #include "rtp_dump.h" |
| #include <cmath> |
| |
| using namespace webrtc; |
| |
| /****************************** |
| * VCMEncodeCompleteCallback |
| *****************************/ |
| // Basic callback implementation |
| // passes the encoded frame directly to the encoder |
| // Packetization callback implmentation |
| VCMEncodeCompleteCallback::VCMEncodeCompleteCallback(FILE* encodedFile): |
| _seqNo(0), |
| _encodedFile(encodedFile), |
| _encodedBytes(0), |
| _VCMReceiver(NULL), |
| _encodeComplete(false), |
| _width(0), |
| _height(0), |
| _codecType(kRTPVideoNoVideo), |
| _layerPacketId(1) |
| { |
| // |
| } |
| VCMEncodeCompleteCallback::~VCMEncodeCompleteCallback() |
| { |
| } |
| |
| void |
| VCMEncodeCompleteCallback::RegisterTransportCallback(VCMPacketizationCallback* transport) |
| { |
| } |
| |
| WebRtc_Word32 |
| VCMEncodeCompleteCallback::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; // end of frame |
| rtpInfo.type.Video.isFirstPacket = true; |
| rtpInfo.type.Video.codec = _codecType; |
| switch (_codecType) |
| { |
| case webrtc::kRTPVideoH263: |
| rtpInfo.type.Video.codecHeader.H263.bits = false; |
| rtpInfo.type.Video.codecHeader.H263.independentlyDecodable = false; |
| rtpInfo.type.Video.height = (WebRtc_UWord16)_height; |
| rtpInfo.type.Video.width = (WebRtc_UWord16)_width; |
| 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; |
| // directly to receiver |
| _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo); |
| _encodeComplete = true; |
| |
| return 0; |
| } |
| |
| float |
| VCMEncodeCompleteCallback::EncodedBytes() |
| { |
| return _encodedBytes; |
| } |
| |
| bool |
| VCMEncodeCompleteCallback::EncodeComplete() |
| { |
| if (_encodeComplete) |
| { |
| _encodeComplete = false; |
| return true; |
| } |
| return false; |
| } |
| |
| void |
| VCMEncodeCompleteCallback::Initialize() |
| { |
| _encodeComplete = false; |
| _encodedBytes = 0; |
| _seqNo = 0; |
| return; |
| } |
| |
| void |
| VCMEncodeCompleteCallback::ResetByteCount() |
| { |
| _encodedBytes = 0; |
| } |
| |
| /**********************************/ |
| /* VCMRTPEncodeCompleteCallback / |
| /********************************/ |
| // Encode Complete callback implementation |
| // passes the encoded frame via the RTP module to the decoder |
| // Packetization callback implmentation |
| |
| WebRtc_Word32 |
| VCMRTPEncodeCompleteCallback::SendData(const FrameType frameType, |
| const WebRtc_UWord8 payloadType, |
| const WebRtc_UWord32 timeStamp, |
| const WebRtc_UWord8* payloadData, |
| const WebRtc_UWord32 payloadSize, |
| const RTPFragmentationHeader& fragmentationHeader) |
| { |
| _frameType = frameType; |
| _encodedBytes+= payloadSize; |
| _encodeComplete = true; |
| //printf("encoded = %d Bytes\n", payloadSize); |
| return _RTPModule->SendOutgoingData(frameType, payloadType, timeStamp, payloadData, payloadSize, &fragmentationHeader); |
| } |
| |
| float |
| VCMRTPEncodeCompleteCallback::EncodedBytes() |
| { |
| // only good for one call - after which will reset value; |
| float tmp = _encodedBytes; |
| _encodedBytes = 0; |
| return tmp; |
| } |
| |
| bool |
| VCMRTPEncodeCompleteCallback::EncodeComplete() |
| { |
| if (_encodeComplete) |
| { |
| _encodeComplete = false; |
| return true; |
| } |
| return false; |
| } |
| |
| // Decoded Frame Callback Implmentation |
| |
| WebRtc_Word32 |
| VCMDecodeCompleteCallback::FrameToRender(VideoFrame& videoFrame) |
| { |
| fwrite(videoFrame.Buffer(), 1, videoFrame.Length(), _decodedFile); |
| _decodedBytes+= videoFrame.Length(); |
| // keeping last decoded frame |
| _lastDecodedFrame.VerifyAndAllocate(videoFrame.Size()); |
| _lastDecodedFrame.CopyFrame(videoFrame.Size(), videoFrame.Buffer()); |
| _lastDecodedFrame.SetHeight(videoFrame.Height()); |
| _lastDecodedFrame.SetWidth(videoFrame.Width()); |
| _lastDecodedFrame.SetTimeStamp(videoFrame.TimeStamp()); |
| |
| return VCM_OK; |
| } |
| |
| int |
| VCMDecodeCompleteCallback::PSNRLastFrame(const VideoFrame& sourceFrame, double *YPSNRptr) |
| { |
| double mse = 0.0; |
| double mseLogSum = 0.0; |
| |
| WebRtc_Word32 frameBytes = sourceFrame.Height() * sourceFrame.Width(); // only Y |
| WebRtc_UWord8 *ref = sourceFrame.Buffer(); |
| if (_lastDecodedFrame.Height() == 0) |
| { |
| *YPSNRptr = 0; |
| return 0; // no new decoded frames |
| } |
| WebRtc_UWord8 *test = _lastDecodedFrame.Buffer(); |
| for( int k = 0; k < frameBytes; k++ ) |
| { |
| mse += (test[k] - ref[k]) * (test[k] - ref[k]); |
| } |
| |
| // divide by number of pixels |
| mse /= (double) (frameBytes); |
| |
| // accumulate for total average |
| mseLogSum += std::log10( mse ); |
| |
| *YPSNRptr = 20.0 * std::log10(255.0) - 10.0 * mseLogSum; // for only 1 frame |
| |
| _lastDecodedFrame.Free(); |
| _lastDecodedFrame.SetHeight(0); |
| return 0; |
| } |
| |
| WebRtc_Word32 |
| VCMDecodeCompleteCallback::DecodedBytes() |
| { |
| return _decodedBytes; |
| } |
| |
| RTPSendCompleteCallback::RTPSendCompleteCallback(RtpRtcp* rtp, const char* filename): |
| _rtp(rtp), |
| _sendCount(0), |
| _lossPct(0), |
| _rtpDump(NULL) |
| { |
| if (filename != NULL) |
| { |
| _rtpDump = RtpDump::CreateRtpDump(); |
| _rtpDump->Start(filename); |
| } |
| } |
| RTPSendCompleteCallback::~RTPSendCompleteCallback() |
| { |
| if (_rtpDump != NULL) |
| { |
| _rtpDump->Stop(); |
| RtpDump::DestroyRtpDump(_rtpDump); |
| } |
| } |
| int |
| RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) |
| { |
| _sendCount++; |
| // Packet Loss - randomly drop %loss packets |
| // don't drop I-frame packets |
| if(PacketLoss(_lossPct) && (_sendCount > 12)) |
| { |
| // drop |
| //printf("\tDrop packet, sendCount = %d\n", _sendCount); |
| return len; |
| } |
| if (_rtpDump != NULL) |
| { |
| if (_rtpDump->DumpPacket((const WebRtc_UWord8*)data, len) != 0) |
| { |
| return -1; |
| } |
| } |
| if(_rtp->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) |
| { |
| return len; |
| } |
| return -1; |
| } |
| |
| int |
| RTPSendCompleteCallback::SendRTCPPacket(int channel, const void *data, int len) |
| { |
| if(_rtp->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) |
| { |
| return len; |
| } |
| return -1; |
| } |
| |
| void |
| RTPSendCompleteCallback::SetLossPct(double lossPct) |
| { |
| _lossPct = lossPct; |
| return; |
| } |
| |
| bool |
| RTPSendCompleteCallback::PacketLoss(double lossPct) |
| { |
| double randVal = (std::rand() + 1.0)/(RAND_MAX + 1.0); |
| return randVal < lossPct/100; |
| } |
| |
| WebRtc_Word32 |
| PacketRequester::ResendPackets(const WebRtc_UWord16* sequenceNumbers, WebRtc_UWord16 length) |
| { |
| return _rtp.SendNACK(sequenceNumbers, length); |
| } |
| |
| WebRtc_Word32 |
| PSNRfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, WebRtc_Word32 width, WebRtc_Word32 height, double *YPSNRptr) |
| { |
| FILE *refFp = fopen(refFileName, "rb"); |
| if( refFp == NULL ) { |
| // cannot open reference file |
| fprintf(stderr, "Cannot open file %s\n", refFileName); |
| return -1; |
| } |
| |
| FILE *testFp = fopen(testFileName, "rb"); |
| if( testFp == NULL ) { |
| // cannot open test file |
| fprintf(stderr, "Cannot open file %s\n", testFileName); |
| return -2; |
| } |
| |
| double mse = 0.0; |
| double mseLogSum = 0.0; |
| WebRtc_Word32 frames = 0; |
| |
| WebRtc_Word32 frameBytes = 3*width*height/2; // bytes in one frame I420 |
| WebRtc_UWord8 *ref = new WebRtc_UWord8[frameBytes]; // space for one frame I420 |
| WebRtc_UWord8 *test = new WebRtc_UWord8[frameBytes]; // space for one frame I420 |
| |
| WebRtc_Word32 refBytes = (WebRtc_Word32) fread(ref, 1, frameBytes, refFp); |
| WebRtc_Word32 testBytes = (WebRtc_Word32) fread(test, 1, frameBytes, testFp); |
| |
| while( refBytes == frameBytes && testBytes == frameBytes ) |
| { |
| mse = 0.0; |
| |
| int sh = 8;//boundary offset |
| for( int k2 = sh; k2 < height-sh;k2++) |
| for( int k = sh; k < width-sh;k++) |
| { |
| int kk = k2*width + k; |
| mse += (test[kk] - ref[kk]) * (test[kk] - ref[kk]); |
| } |
| |
| // divide by number of pixels |
| mse /= (double) (width * height); |
| |
| // accumulate for total average |
| mseLogSum += std::log10( mse ); |
| frames++; |
| |
| refBytes = (int) fread(ref, 1, frameBytes, refFp); |
| testBytes = (int) fread(test, 1, frameBytes, testFp); |
| } |
| // for identical reproduction: |
| if (mse == 0) |
| { |
| *YPSNRptr = 48; |
| } |
| else |
| { |
| *YPSNRptr = 20.0 * std::log10(255.0) - 10.0 * mseLogSum / frames; |
| } |
| |
| |
| delete [] ref; |
| delete [] test; |
| |
| fclose(refFp); |
| fclose(testFp); |
| |
| return 0; |
| } |
| |
| WebRtc_Word32 |
| SSIMfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, WebRtc_Word32 width, WebRtc_Word32 height, double *SSIMptr) |
| { |
| FILE *refFp = fopen(refFileName, "rb"); |
| if( refFp == NULL ) { |
| // cannot open reference file |
| fprintf(stderr, "Cannot open file %s\n", refFileName); |
| return -1; |
| } |
| |
| FILE *testFp = fopen(testFileName, "rb"); |
| if( testFp == NULL ) { |
| // cannot open test file |
| fprintf(stderr, "Cannot open file %s\n", testFileName); |
| return -2; |
| } |
| |
| int frames = 0; |
| |
| int frameBytes = 3*width*height/2; // bytes in one frame I420 |
| unsigned char *ref = new unsigned char[frameBytes]; // space for one frame I420 |
| unsigned char *test = new unsigned char[frameBytes]; // space for one frame I420 |
| |
| int refBytes = (int) fread(ref, 1, frameBytes, refFp); |
| int testBytes = (int) fread(test, 1, frameBytes, testFp); |
| |
| float *righMostColumnAvgTest = new float[width]; |
| float *righMostColumnAvgRef = new float[width]; |
| float *righMostColumnContrastTest = new float[width]; |
| float *righMostColumnContrastRef = new float[width]; |
| float *righMostColumnCrossCorr = new float[width]; |
| |
| float term1,term2,term3,term4,term5; |
| |
| // |
| // SSIM: variable definition, window function, initialization |
| int window = 10; |
| // |
| int flag_window = 0; //0 and 1 for uniform window filter, 2 for gaussian window |
| // |
| float variance_window = 2.0; //variance for window function |
| float ssimFilter[121]; //2d window filter: typically 11x11 = (window+1)*(window+1) |
| //statistics per column of window (#columns = window+1), 0 element for avg over all columns |
| float avgTest[12]; |
| float avgRef[12]; |
| float contrastTest[12]; |
| float contrastRef[12]; |
| float crossCorr[12]; |
| // |
| //offsets for stability |
| float offset1 = 1.0f; //0.1 |
| float offset2 = 1.0f; //0.1 |
| //for Guassian window: settings from paper: |
| //float offset1 = 6.0f; // ~ (K1*L)^2 , K1 = 0.01 |
| //float offset2 = 58.0f; // ~ (K1*L)^2 , K2 = 0.03 |
| |
| |
| float offset3 = offset2/2; |
| // |
| //define window for SSIM: take uniform filter for now |
| float sumfil = 0.0; |
| int nn=-1; |
| for(int j=-window/2;j<=window/2;j++) |
| for(int i=-window/2;i<=window/2;i++) |
| { |
| nn+=1; |
| if (flag_window != 2) |
| ssimFilter[nn] = 1.0; |
| else |
| { |
| float dist = (float)(i*i) + (float)(j*j); |
| float tmp = 0.5f*dist/variance_window; |
| ssimFilter[nn] = exp(-tmp); |
| } |
| sumfil +=ssimFilter[nn]; |
| } |
| //normalize window |
| nn=-1; |
| for(int j=-window/2;j<=window/2;j++) |
| for(int i=-window/2;i<=window/2;i++) |
| { |
| nn+=1; |
| ssimFilter[nn] = ssimFilter[nn]/((float)sumfil); |
| } |
| // |
| float ssimScene = 0.0; //avgerage SSIM for sequence |
| // |
| //SSIM: done with variables and defintion |
| // |
| |
| int sh = 8; //boundary offset |
| |
| while( refBytes == frameBytes && testBytes == frameBytes ) |
| { |
| float ssimFrame = 0.0; |
| |
| int numPixels = 0; |
| |
| //skip over pixels vertically and horizontally |
| //for window cases 1 and 2 |
| int skipH = 2; |
| int skipV = 2; |
| |
| //uniform window case, with window computation updated for each pixel horiz and vert: can't skip pixels for this case |
| if (flag_window == 0) |
| { |
| skipH = 1; |
| skipV = 1; |
| } |
| for(int i=sh;i<height-sh;i+=skipV) |
| for(int j=sh;j<width-sh;j+=skipH) |
| { |
| avgTest[0] = 0.0; |
| avgRef[0] = 0.0; |
| contrastTest[0] = 0.0; |
| contrastRef[0] = 0.0; |
| crossCorr[0] = 0.0; |
| |
| numPixels +=1; |
| |
| if (flag_window > 0 ) |
| { |
| //initialize statistics |
| avgTest[0] = 0.0; |
| avgRef[0] = 0.0; |
| contrastTest[0] = 0.0; |
| contrastRef[0] = 0.0; |
| crossCorr[0] = 0.0; |
| |
| int nn=-1; |
| //compute contrast and correlation |
| //windows are symmetrics |
| for(int jj=-window/2;jj<=window/2;jj++) |
| for(int ii=-window/2;ii<=window/2;ii++) |
| { |
| nn+=1; |
| int i2 = i+ii; |
| int j2 = j+jj; |
| float tmp1 = (float)test[i2*width+j2]; |
| float tmp2 = (float)ref[i2*width+j2]; |
| |
| term1 = tmp1; |
| term2 = tmp2; |
| term3 = tmp1*tmp1; |
| term4 = tmp2*tmp2; |
| term5 = tmp1*tmp2; |
| |
| //local average of each signal |
| avgTest[0] += ssimFilter[nn]*term1; |
| avgRef[0] += ssimFilter[nn]*term2; |
| //local correlation/contrast of each signal |
| contrastTest[0] += ssimFilter[nn]*term3; |
| contrastRef[0] += ssimFilter[nn]*term4; |
| //local cross correlation |
| crossCorr[0] += ssimFilter[nn]*term5; |
| |
| } |
| |
| } |
| |
| else |
| { |
| //for uniform window case == 0: only need to loop over whole window for first row and column, and then shift/update |
| if (j == sh || i == sh) |
| { |
| //initialize statistics |
| for(int k=0;k<window+2;k++) |
| { |
| avgTest[k] = 0.0; |
| avgRef[k] = 0.0; |
| contrastTest[k] = 0.0; |
| contrastRef[k] = 0.0; |
| crossCorr[k] = 0.0; |
| } |
| |
| int nn=-1; |
| //compute contrast and correlation |
| //windows are symmetrics |
| for(int jj=-window/2;jj<=window/2;jj++) |
| for(int ii=-window/2;ii<=window/2;ii++) |
| { |
| nn+=1; |
| int i2 = i+ii; |
| int j2 = j+jj; |
| float tmp1 = (float)test[i2*width+j2]; |
| float tmp2 = (float)ref[i2*width+j2]; |
| |
| term1 = tmp1; |
| term2 = tmp2; |
| term3 = tmp1*tmp1; |
| term4 = tmp2*tmp2; |
| term5 = tmp1*tmp2; |
| |
| //local average of each signal |
| avgTest[jj+window/2+1] += term1; |
| avgRef[jj+window/2+1] += term2; |
| //local correlation/contrast of each signal |
| contrastTest[jj+window/2+1] += term3; |
| contrastRef[jj+window/2+1] += term4; |
| //local cross correlation |
| crossCorr[jj+window/2+1] += term5; |
| |
| } |
| |
| //normalize |
| for(int k=1;k<window+2;k++) |
| { |
| avgTest[k] = ssimFilter[0]*avgTest[k]; |
| avgRef[k] = ssimFilter[0]*avgRef[k]; |
| contrastTest[k] = ssimFilter[0]*contrastTest[k]; |
| contrastRef[k] = ssimFilter[0]*contrastRef[k]; |
| crossCorr[k] = ssimFilter[0]*crossCorr[k]; |
| } |
| |
| } |
| //for all other pixels, update window filter computation |
| else |
| { |
| //shift statistics horiz. |
| for(int k=1;k<window+1;k++) |
| { |
| avgTest[k]=avgTest[k+1]; |
| avgRef[k]=avgRef[k+1]; |
| contrastTest[k] = contrastTest[k+1]; |
| contrastRef[k] = contrastRef[k+1]; |
| crossCorr[k] = crossCorr[k+1]; |
| } |
| |
| //compute statistics for last column |
| //update right-most column, by updating with bottom pixel contribution |
| int j2 = j + window/2; //last column of window |
| int i2 = i + window/2; //last window pixel of column |
| int ix = i - window/2 - 1; //last window pixel of top neighboring pixel |
| float tmp1 = (float)test[i2*width+j2]; |
| float tmp2 = (float)ref[i2*width+j2]; |
| float tmp1x = (float)test[ix*width+j2]; |
| float tmp2x = (float)ref[ix*width+j2]; |
| |
| avgTest[window+1] = righMostColumnAvgTest[j] + ssimFilter[0]*(tmp1 - tmp1x); |
| avgRef[window+1] = righMostColumnAvgRef[j] + ssimFilter[0]*(tmp2 - tmp2x); |
| contrastTest[window+1] = righMostColumnContrastTest[j] + ssimFilter[0]*(tmp1*tmp1 - tmp1x*tmp1x); |
| contrastRef[window+1] = righMostColumnContrastRef[j] + ssimFilter[0]*(tmp2*tmp2 - tmp2x*tmp2x); |
| crossCorr[window+1] = righMostColumnCrossCorr[j] + ssimFilter[0]*(tmp1*tmp2 - tmp1x*tmp2x); |
| } |
| |
| //sum over all columns |
| for(int k=1;k<window+2;k++) |
| { |
| avgTest[0] += avgTest[k]; |
| avgRef[0] += avgRef[k]; |
| contrastTest[0] += contrastTest[k]; |
| contrastRef[0] += contrastRef[k]; |
| crossCorr[0] += crossCorr[k]; |
| } |
| |
| // |
| righMostColumnAvgTest[j] = avgTest[window+1]; |
| righMostColumnAvgRef[j] = avgRef[window+1]; |
| righMostColumnContrastTest[j] = contrastTest[window+1]; |
| righMostColumnContrastRef[j] = contrastRef[window+1]; |
| righMostColumnCrossCorr[j] = crossCorr[window+1]; |
| // |
| |
| } //end of window = 0 case |
| |
| float tmp1 = (contrastTest[0] - avgTest[0]*avgTest[0]); |
| if (tmp1 < 0.0) tmp1 = 0.0; |
| contrastTest[0] = sqrt(tmp1); |
| float tmp2 = (contrastRef[0] - avgRef[0]*avgRef[0]); |
| if (tmp2 < 0.0) tmp2 = 0.0; |
| contrastRef[0] = sqrt(tmp2); |
| crossCorr[0] = crossCorr[0] - avgTest[0]*avgRef[0]; |
| |
| float ssimCorrCoeff = (crossCorr[0]+offset3)/(contrastTest[0]*contrastRef[0] + offset3); |
| float ssimLuminance = (2*avgTest[0]*avgRef[0]+offset1)/(avgTest[0]*avgTest[0] + avgRef[0]*avgRef[0] + offset1); |
| float ssimContrast = (2*contrastTest[0]*contrastRef[0]+offset2)/(contrastTest[0]*contrastTest[0] + contrastRef[0]*contrastRef[0] + offset2); |
| |
| float ssimPixel = ssimCorrCoeff * ssimLuminance * ssimContrast; |
| ssimFrame += ssimPixel; |
| |
| } //done with ssim computation |
| |
| ssimFrame = ssimFrame / (numPixels); |
| //printf("***SSIM for frame ***%f \n",ssimFrame); |
| ssimScene += ssimFrame; |
| // |
| //SSIM: done with SSIM computation |
| // |
| |
| frames++; |
| |
| refBytes = (int) fread(ref, 1, frameBytes, refFp); |
| testBytes = (int) fread(test, 1, frameBytes, testFp); |
| |
| } |
| |
| //SSIM: normalize/average for sequence |
| ssimScene = ssimScene / frames; |
| *SSIMptr = ssimScene; |
| |
| |
| delete [] ref; |
| delete [] test; |
| |
| delete [] righMostColumnAvgTest; |
| delete [] righMostColumnAvgRef; |
| delete [] righMostColumnContrastTest; |
| delete [] righMostColumnContrastRef; |
| delete [] righMostColumnCrossCorr; |
| |
| |
| fclose(refFp); |
| fclose(testFp); |
| |
| return 0; |
| |
| } |
| |
| |
| RTPVideoCodecTypes |
| ConvertCodecType(const char* plname) |
| { |
| if (strncmp(plname,"VP8" , 3) == 0) |
| { |
| return kRTPVideoVP8; |
| }else if (strncmp(plname,"H263" , 5) == 0) |
| { |
| return kRTPVideoH263; |
| }else if (strncmp(plname, "H263-1998",10) == 0) |
| { |
| return kRTPVideoH263; |
| }else if (strncmp(plname,"I420" , 5) == 0) |
| { |
| return kRTPVideoI420; |
| }else |
| { |
| return kRTPVideoNoVideo; // defualt value |
| } |
| |
| } |
| |
| WebRtc_Word32 |
| SendStatsTest::SendStatistics(const WebRtc_UWord32 bitRate, const WebRtc_UWord32 frameRate) |
| { |
| TEST(frameRate <= _frameRate); |
| TEST(bitRate > 0 && bitRate < 100000); |
| printf("VCM 1 sec: Bit rate: %u\tFrame rate: %u\n", bitRate, frameRate); |
| return 0; |
| } |
| |
| WebRtc_Word32 |
| KeyFrameReqTest::FrameTypeRequest(const FrameType frameType) |
| { |
| TEST(frameType == kVideoFrameKey); |
| if (frameType == kVideoFrameKey) |
| { |
| printf("Key frame requested\n"); |
| } |
| else |
| { |
| printf("Non-key frame requested: %d\n", frameType); |
| } |
| return 0; |
| } |