From d70b77d19fe59af072bf34f3532ebb0479eb47f5 Mon Sep 17 00:00:00 2001 From: "mikhal@webrtc.org" Date: Mon, 22 Aug 2011 21:08:15 +0000 Subject: [PATCH] video_coding: Updating offline tests 1. Adding parameters to the input arguments. 2. Introducing delay in the RTPSend callback 3. Clean-up Review URL: http://webrtc-codereview.appspot.com/116006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@414 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../video_coding/main/test/test_util.cc | 186 +++++++++++------- .../video_coding/main/test/test_util.h | 118 ++++++----- .../video_coding/main/test/tester_main.cc | 26 ++- 3 files changed, 207 insertions(+), 123 deletions(-) diff --git a/src/modules/video_coding/main/test/test_util.cc b/src/modules/video_coding/main/test/test_util.cc index 3b34d873a..469882a84 100644 --- a/src/modules/video_coding/main/test/test_util.cc +++ b/src/modules/video_coding/main/test/test_util.cc @@ -21,7 +21,7 @@ using namespace webrtc; *****************************/ // Basic callback implementation // passes the encoded frame directly to the encoder -// Packetization callback implmentation +// Packetization callback implementation VCMEncodeCompleteCallback::VCMEncodeCompleteCallback(FILE* encodedFile): _encodedFile(encodedFile), _encodedBytes(0), @@ -90,10 +90,10 @@ VCMEncodeCompleteCallback::SendData( // TODO(hlundin): Remove assert once we've piped PictureID into VCM // through the WebRtcRTPHeader. assert(rtpInfo.type.Video.codec != kRTPVideoVP8); - _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo); + int ret = _VCMReceiver->IncomingPacket(payloadData, payloadSize, rtpInfo); _encodeComplete = true; - return 0; + return ret; } float @@ -133,7 +133,7 @@ VCMEncodeCompleteCallback::ResetByteCount() /***********************************/ // Encode Complete callback implementation // passes the encoded frame via the RTP module to the decoder -// Packetization callback implmentation +// Packetization callback implementation WebRtc_Word32 VCMRTPEncodeCompleteCallback::SendData( @@ -148,7 +148,6 @@ VCMRTPEncodeCompleteCallback::SendData( _frameType = frameType; _encodedBytes+= payloadSize; _encodeComplete = true; - //printf("encoded = %d Bytes\n", payloadSize); return _RTPModule->SendOutgoingData(frameType, payloadType, timeStamp, @@ -178,7 +177,7 @@ VCMRTPEncodeCompleteCallback::EncodeComplete() return false; } -// Decoded Frame Callback Implmentation +// Decoded Frame Callback Implementation WebRtc_Word32 VCMDecodeCompleteCallback::FrameToRender(VideoFrame& videoFrame) @@ -196,12 +195,14 @@ VCMRTPEncodeCompleteCallback::EncodeComplete() } int -VCMDecodeCompleteCallback::PSNRLastFrame(const VideoFrame& sourceFrame, double *YPSNRptr) +VCMDecodeCompleteCallback::PSNRLastFrame(const VideoFrame& sourceFrame, + double *YPSNRptr) { double mse = 0.0; double mseLogSum = 0.0; - WebRtc_Word32 frameBytes = sourceFrame.Height() * sourceFrame.Width(); // only Y + // Y only + WebRtc_Word32 frameBytes = sourceFrame.Height() * sourceFrame.Width(); WebRtc_UWord8 *ref = sourceFrame.Buffer(); if (_lastDecodedFrame.Height() == 0) { @@ -233,12 +234,16 @@ VCMDecodeCompleteCallback::DecodedBytes() return _decodedBytes; } -RTPSendCompleteCallback::RTPSendCompleteCallback(RtpRtcp* rtp, const char* filename): +RTPSendCompleteCallback::RTPSendCompleteCallback(RtpRtcp* rtp, + const char* filename): _sendCount(0), _rtp(rtp), _lossPct(0), _burstLength(0), + _networkDelayMs(0), _prevLossState(0), + _totalSentLength(0), + _rtpPackets(), _rtpDump(NULL) { if (filename != NULL) @@ -254,11 +259,20 @@ RTPSendCompleteCallback::~RTPSendCompleteCallback() _rtpDump->Stop(); RtpDump::DestroyRtpDump(_rtpDump); } + // Delete remaining packets + while (!_rtpPackets.Empty()) + { + // Take first packet in list + delete static_cast((_rtpPackets.First())->GetItem()); + _rtpPackets.PopFront(); + } } int RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) { _sendCount++; + _totalSentLength += len; + bool transmitPacket = true; // Packet Loss @@ -268,8 +282,7 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) if (PacketLoss(_lossPct)) { // drop - //printf("\tDrop packet, sendCount = %d\n", _sendCount); - return len; + transmitPacket = false; } } else @@ -291,7 +304,7 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) // to the transition probabilities: double probTrans10 = 100 * (1.0 / _burstLength); double probTrans11 = (100.0 - probTrans10); - double probTrans01 = (probTrans10 * ( _lossPct / (100.0 - _lossPct) ) ); + double probTrans01 = (probTrans10 * ( _lossPct / (100.0 - _lossPct))); // Note: Random loss (Bernoulli) model is a special case where: // burstLength = 100.0 / (100.0 - _lossPct) (i.e., p10 + p01 = 100) @@ -299,25 +312,24 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) if (_prevLossState == 0 ) { // previous packet was received - if (PacketLoss(probTrans01) ) + if (PacketLoss(probTrans01)) { // drop, update previous state to loss _prevLossState = 1; - return len; + transmitPacket = false; } } else if (_prevLossState == 1) { + _prevLossState = 0; // previous packet was lost - if (PacketLoss(probTrans11) ) + if (PacketLoss(probTrans11)) { // drop, update previous state to loss _prevLossState = 1; - return len; + transmitPacket = false; } } - // no drop, update previous state to received - _prevLossState = 0; } if (_rtpDump != NULL) @@ -327,17 +339,53 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len) return -1; } } - if(_rtp->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) + + WebRtc_UWord64 now = VCMTickTime::MillisecondTimestamp(); + // Insert outgoing packet into list + if (transmitPacket) { - return len; + rtpPacket* newPacket = new rtpPacket(); + memcpy(newPacket->data, data, len); + newPacket->length = len; + // Simulate receive time + newPacket->receiveTime = now + _networkDelayMs; + _rtpPackets.PushBack(newPacket); } - return -1; + + // Are we ready to send packets to the receiver? + rtpPacket* packet = NULL; + + while (!_rtpPackets.Empty()) + { + // Take first packet in list + packet = static_cast((_rtpPackets.First())->GetItem()); + WebRtc_Word64 timeToReceive = packet->receiveTime - now; + if (timeToReceive > 0) + { + // No available packets to send + break; + } + + _rtpPackets.PopFront(); + // Send to receive side + if (_rtp->IncomingPacket((const WebRtc_UWord8*)packet->data, + packet->length) < 0) + { + delete packet; + packet = NULL; + // Will return an error after the first packet that goes wrong + return -1; + } + delete packet; + packet = NULL; } + return len; // OK +} int RTPSendCompleteCallback::SendRTCPPacket(int channel, const void *data, int len) { - if(_rtp->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) + if (_rtp->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) { return len; } @@ -366,13 +414,15 @@ RTPSendCompleteCallback::PacketLoss(double lossPct) } WebRtc_Word32 -PacketRequester::ResendPackets(const WebRtc_UWord16* sequenceNumbers, WebRtc_UWord16 length) +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) +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 ) { @@ -392,9 +442,10 @@ PSNRfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, 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 + // Allocating size for one I420 frame. + WebRtc_Word32 frameBytes = 3 * width * height >> 1; + WebRtc_UWord8 *ref = new WebRtc_UWord8[frameBytes]; + WebRtc_UWord8 *test = new WebRtc_UWord8[frameBytes]; WebRtc_Word32 refBytes = (WebRtc_Word32) fread(ref, 1, frameBytes, refFp); WebRtc_Word32 testBytes = (WebRtc_Word32) fread(test, 1, frameBytes, testFp); @@ -440,16 +491,9 @@ PSNRfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, return 0; } - static double -similarity -( - unsigned long sum_s, - unsigned long sum_r, - unsigned long sum_sq_s, - unsigned long sum_sq_r, - unsigned long sum_sxr, - int count +similarity(unsigned long sum_s, unsigned long sum_r, unsigned long sum_sq_s, + unsigned long sum_sq_r, unsigned long sum_sxr, int count ) { int64_t ssim_n, ssim_d; @@ -472,13 +516,7 @@ similarity } static double -ssim_8x8_c -( - unsigned char *s, - int sp, - unsigned char *r, - int rp -) +ssim_8x8_c(unsigned char *s, int sp, unsigned char *r, int rp) { unsigned long sum_s = 0; unsigned long sum_r = 0; @@ -487,9 +525,9 @@ ssim_8x8_c unsigned long sum_sxr = 0; int i,j; - for(i=0;i<8;i++,s+=sp,r+=rp) + for (i = 0;i < 8; i++, s += sp,r += rp) { - for(j=0;j<8;j++) + for (j = 0; j < 8; j++) { sum_s += s[j]; sum_r += r[j]; @@ -498,20 +536,13 @@ ssim_8x8_c sum_sxr += s[j] * r[j]; } } - return similarity(sum_s, sum_r, sum_sq_s, sum_sq_r, sum_sxr, 64); } #if defined(WEBRTC_USE_SSE2) #include static double -ssim_8x8_sse2 -( - unsigned char *s, - int sp, - unsigned char *r, - int rp -) +ssim_8x8_sse2(unsigned char *s, int sp, unsigned char *r, int rp) { int i; const __m128i z = _mm_setzero_si128(); @@ -521,7 +552,7 @@ ssim_8x8_sse2 __m128i sum_sq_r_32 = _mm_setzero_si128(); __m128i sum_sxr_32 = _mm_setzero_si128(); - for(i=0;i<8;i++,s+=sp,r+=rp) + for (i = 0;i < 8; i++,s += sp,r += rp) { const __m128i s_8 = _mm_loadl_epi64((__m128i*)(s)); const __m128i r_8 = _mm_loadl_epi64((__m128i*)(r)); @@ -577,14 +608,8 @@ ssim_8x8_sse2 #endif double -SSIM_frame -( - unsigned char *img1, - unsigned char *img2, - int stride_img1, - int stride_img2, - int width, - int height) +SSIM_frame(unsigned char *img1, unsigned char *img2, int stride_img1, + int stride_img2,int width, int height) { int i,j; unsigned int samples = 0; @@ -592,7 +617,7 @@ SSIM_frame double (*ssim_8x8)(unsigned char*, int, unsigned char*, int rp); ssim_8x8 = ssim_8x8_c; - if(WebRtc_GetCPUInfo(kSSE2)) + if (WebRtc_GetCPUInfo(kSSE2)) { #if defined(WEBRTC_USE_SSE2) ssim_8x8 = ssim_8x8_sse2; @@ -600,11 +625,12 @@ SSIM_frame } // sample point start with each 4x4 location - for(i=0; i < height-8; i+=4, img1 += stride_img1*4, img2 += stride_img2*4) + for (i = 0; i < height-8; i += 4, img1 += stride_img1 * 4, + img2 += stride_img2 * 4) { - for(j=0; j < width-8; j+=4 ) + for (j = 0; j < width - 8; j += 4 ) { - double v = ssim_8x8(img1+j, stride_img1, img2+j, stride_img2); + double v = ssim_8x8(img1 + j, stride_img1, img2 + j, stride_img2); ssim_total += v; samples++; } @@ -614,17 +640,20 @@ SSIM_frame } WebRtc_Word32 -SSIMfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, WebRtc_Word32 width, WebRtc_Word32 height, double *SSIMptr) +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 ) { + 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 ) { + if ( testFp == NULL ) + { // cannot open test file fprintf(stderr, "Cannot open file %s\n", testFileName); return -2; @@ -632,7 +661,7 @@ SSIMfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, int frames = 0; - const int frameBytes = 3*width*height/2; // bytes in one frame I420 + const int frameBytes = 3 * width *height / 2; // bytes in one frame I420 unsigned char *ref = new unsigned char[frameBytes]; unsigned char *test = new unsigned char[frameBytes]; @@ -674,24 +703,29 @@ ConvertCodecType(const char* plname) if (strncmp(plname,"VP8" , 3) == 0) { return kRTPVideoVP8; - }else if (strncmp(plname,"H263" , 5) == 0) + } + else if (strncmp(plname,"H263" , 5) == 0) { return kRTPVideoH263; - }else if (strncmp(plname, "H263-1998",10) == 0) + } + else if (strncmp(plname, "H263-1998",10) == 0) { return kRTPVideoH263; - }else if (strncmp(plname,"I420" , 5) == 0) + } + else if (strncmp(plname,"I420" , 5) == 0) { return kRTPVideoI420; - }else + } + else { - return kRTPVideoNoVideo; // defualt value + return kRTPVideoNoVideo; // Default value } } WebRtc_Word32 -SendStatsTest::SendStatistics(const WebRtc_UWord32 bitRate, const WebRtc_UWord32 frameRate) +SendStatsTest::SendStatistics(const WebRtc_UWord32 bitRate, + const WebRtc_UWord32 frameRate) { TEST(frameRate <= _frameRate); TEST(bitRate > 0 && bitRate < 100000); diff --git a/src/modules/video_coding/main/test/test_util.h b/src/modules/video_coding/main/test/test_util.h index 68a0e1486..9831cbd6e 100644 --- a/src/modules/video_coding/main/test/test_util.h +++ b/src/modules/video_coding/main/test/test_util.h @@ -17,6 +17,7 @@ #include "module_common_types.h" #include "tick_time.h" #include "test_util.h" +#include "list_wrapper.h" #include #include @@ -28,19 +29,24 @@ enum { kMaxWaitEncTimeMs = 100 }; class CmdArgs { public: - CmdArgs() : codecName(""), codecType(webrtc::kVideoCodecVP8), width(-1), - height(-1), bitRate(-1), frameRate(-1), - inputFile(""), outputFile(""), testNum(-1) - {} - std::string codecName; - webrtc::VideoCodecType codecType; - int width; - int height; - int bitRate; - int frameRate; - std::string inputFile; - std::string outputFile; - int testNum; + CmdArgs() : codecName(""), codecType(webrtc::kVideoCodecVP8), width(-1), + height(-1), bitRate(-1), frameRate(-1), packetLoss(0), rtt(0), + protectionMode(0), camaEnable(0), inputFile(""), outputFile(""), + testNum(-1) + {} + std::string codecName; + webrtc::VideoCodecType codecType; + int width; + int height; + int bitRate; + int frameRate; + int packetLoss; + int rtt; + int protectionMode; + int camaEnable; + std::string inputFile; + std::string outputFile; + int testNum; }; // forward declaration @@ -50,7 +56,8 @@ namespace webrtc class RtpDump; } -// definition of general test function to be used by VCM tester (mainly send side) +// Definition of general test function to be used by VCM tester +// (mainly send side) /* Includes the following: 1. General Callback definition for VCM test functions - no RTP. @@ -60,31 +67,34 @@ namespace webrtc 3. Caluclate PSNR from file function (for now: does not deal with frame drops) */ -//Send Side - Packetization callback - send an encoded frame directly to the VCMReceiver +// Send Side - Packetization callback - send an encoded frame to the VCMReceiver class VCMEncodeCompleteCallback: public webrtc::VCMPacketizationCallback { public: - // constructor input: file in which encoded data will be written, and test parameters + // constructor input: file in which encoded data will be written VCMEncodeCompleteCallback(FILE* encodedFile); virtual ~VCMEncodeCompleteCallback(); // Register transport callback void RegisterTransportCallback(webrtc::VCMPacketizationCallback* transport); - // process encoded data received from the encoder, pass stream to the VCMReceiver module + // Process encoded data received from the encoder, pass stream to the + // VCMReceiver module WebRtc_Word32 SendData(const webrtc::FrameType frameType, const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const webrtc::RTPFragmentationHeader& fragmentationHeader, const webrtc::RTPVideoTypeHeader* videoTypeHdr); - // Register exisitng VCM. Currently - encode and decode with the same vcm module. - void RegisterReceiverVCM(webrtc::VideoCodingModule *vcm) { _VCMReceiver = vcm; } + // Register exisitng VCM. Currently - encode and decode under same module. + void RegisterReceiverVCM(webrtc::VideoCodingModule *vcm) {_VCMReceiver = vcm;} // Return size of last encoded frame encoded data (all frames in the sequence) - // Good for only one call - after which will reset value (to allow detection of frame drop) + // Good for only one call - after which will reset value + // (to allow detection of frame drop) float EncodedBytes(); - // return encode complete (true/false) + // Return encode complete (true/false) bool EncodeComplete(); // Inform callback of codec used - void SetCodecType(webrtc::RTPVideoCodecTypes codecType) { _codecType = codecType; } - // inform callback of frame dimensions + void SetCodecType(webrtc::RTPVideoCodecTypes codecType) + {_codecType = codecType;} + // Inform callback of frame dimensions void SetFrameDimensions(WebRtc_Word32 width, WebRtc_Word32 height) { _width = width; @@ -94,8 +104,7 @@ public: void Initialize(); void ResetByteCount(); - // conversion function for payload type (needed for the callback function) - // RTPVideoVideoCodecTypes ConvertPayloadType(WebRtc_UWord8 payloadType); + // Conversion function for payload type (needed for the callback function) private: FILE* _encodedFile; @@ -111,7 +120,8 @@ private: }; // end of VCMEncodeCompleteCallback -//Send Side - Packetization callback - packetize an encoded frame via the RTP module +// Send Side - Packetization callback - packetize an encoded frame via the +// RTP module class VCMRTPEncodeCompleteCallback: public webrtc::VCMPacketizationCallback { public: @@ -122,7 +132,8 @@ public: _RTPModule(rtp) {} virtual ~VCMRTPEncodeCompleteCallback() {} - // process encoded data received from the encoder, pass stream to the RTP module + // Process encoded data received from the encoder, pass stream to the + // RTP module WebRtc_Word32 SendData(const webrtc::FrameType frameType, const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, @@ -134,9 +145,10 @@ public: // return encode complete (true/false) bool EncodeComplete(); // Inform callback of codec used - void SetCodecType(webrtc::RTPVideoCodecTypes codecType) { _codecType = codecType; } + void SetCodecType(webrtc::RTPVideoCodecTypes codecType) + {_codecType = codecType;} - // inform callback of frame dimensions + // Inform callback of frame dimensions void SetFrameDimensions(WebRtc_Word16 width, WebRtc_Word16 height) { _width = width; @@ -171,13 +183,21 @@ private: webrtc::VideoFrame _lastDecodedFrame; }; // end of VCMDecodeCompleCallback class -/// + +typedef struct +{ + WebRtc_Word8 data[1650]; // max packet size + WebRtc_Word32 length; + WebRtc_Word64 receiveTime; +} rtpPacket; + + class RTPSendCompleteCallback: public webrtc::Transport { public: - // constructor input: (reeive side) rtp module to send encoded data to - RTPSendCompleteCallback(webrtc::RtpRtcp* rtp, - const char* filename = NULL); + // constructor input: (receive side) rtp module to send encoded data to + RTPSendCompleteCallback(webrtc::RtpRtcp* rtp, + const char* filename = NULL); virtual ~RTPSendCompleteCallback(); // Send Packet to receive side RTP module virtual int SendPacket(int channel, const void *data, int len); @@ -187,21 +207,29 @@ public: void SetLossPct(double lossPct); // Set average size of burst loss void SetBurstLength(double burstLength); - // return send count - int SendCount() { return _sendCount; } + // Set network delay in the network + void SetNetworkDelay(WebRtc_UWord32 networkDelayMs) + {_networkDelayMs = networkDelayMs;}; + // Return send count + int SendCount() {return _sendCount; } + // Return accumulated length in bytes of transmitted packets + WebRtc_UWord32 TotalSentLength() {return _totalSentLength;} private: - // randomly decide weather to drop a packet or not, based on the channel model + // Randomly decide whether to drop packets, based on the channel model bool PacketLoss(double lossPct); - WebRtc_UWord32 _sendCount; - webrtc::RtpRtcp* _rtp; - double _lossPct; - double _burstLength; - bool _prevLossState; - webrtc::RtpDump* _rtpDump; + WebRtc_UWord32 _sendCount; + webrtc::RtpRtcp* _rtp; + double _lossPct; + double _burstLength; + WebRtc_UWord32 _networkDelayMs; + bool _prevLossState; + WebRtc_UWord32 _totalSentLength; + webrtc::ListWrapper _rtpPackets; + webrtc::RtpDump* _rtpDump; }; -// used in multi thread test +// Used in multi thread test class SendSharedState { public: @@ -245,7 +273,7 @@ SSIMfromFiles(const WebRtc_Word8 *refFileName, const WebRtc_Word8 *testFileName, WebRtc_Word32 width, WebRtc_Word32 height, double *SSIMptr); -// codec type conversion +// Codec type conversion webrtc::RTPVideoCodecTypes ConvertCodecType(const char* plname); @@ -255,7 +283,7 @@ public: SendStatsTest() : _frameRate(15) {} WebRtc_Word32 SendStatistics(const WebRtc_UWord32 bitRate, const WebRtc_UWord32 frameRate); - void SetTargetFrameRate(WebRtc_UWord32 frameRate) { _frameRate = frameRate; } + void SetTargetFrameRate(WebRtc_UWord32 frameRate) {_frameRate = frameRate;} private: WebRtc_UWord32 _frameRate; }; diff --git a/src/modules/video_coding/main/test/tester_main.cc b/src/modules/video_coding/main/test/tester_main.cc index eb32b38e4..a76e47041 100644 --- a/src/modules/video_coding/main/test/tester_main.cc +++ b/src/modules/video_coding/main/test/tester_main.cc @@ -121,6 +121,26 @@ int ParseArguments(int argc, char **argv, CmdArgs& args) args.testNum = n; break; } + case 'p': + { + args.packetLoss = atoi(argv[i+1]); + break; + } + case 'r': + { + args.rtt = atoi(argv[i+1]); + break; + } + case 'm': + { + args.protectionMode = atoi(argv[i+1]); + break; + } + case 'e': + { + args.camaEnable = atoi(argv[i+1]); + break; + } default: return -1; } @@ -136,10 +156,12 @@ int main(int argc, char **argv) if (ParseArguments(argc, argv, args) != 0) { printf("Unable to parse input arguments\n"); - printf("args: -n -w -h -f -b -c " - " -i -o \n"); + printf("args: -n -w -h -f -b " + "-c -i -o -p " + "-r -e -m \n"); return -1; } + int ret = 0; switch (args.testNum) {