video coding test: Adding MT functionality

Review URL: http://webrtc-codereview.appspot.com/135008

git-svn-id: http://webrtc.googlecode.com/svn/trunk@570 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@webrtc.org 2011-09-09 14:38:59 +00:00
parent ecc43fd084
commit 6f54c20703
7 changed files with 302 additions and 106 deletions

View File

@ -31,6 +31,7 @@
'../test/generic_codec_test.h', '../test/generic_codec_test.h',
'../test/jitter_estimate_test.h', '../test/jitter_estimate_test.h',
'../test/media_opt_test.h', '../test/media_opt_test.h',
'../test/mt_test_common.h',
'../test/normal_test.h', '../test/normal_test.h',
'../test/quality_modes_test.h', '../test/quality_modes_test.h',
'../test/receiver_tests.h', '../test/receiver_tests.h',
@ -46,6 +47,7 @@
'../test/generic_codec_test.cc', '../test/generic_codec_test.cc',
'../test/jitter_buffer_test.cc', '../test/jitter_buffer_test.cc',
'../test/media_opt_test.cc', '../test/media_opt_test.cc',
'../test/mt_test_common.cc',
'../test/mt_rx_tx_test.cc', '../test/mt_rx_tx_test.cc',
'../test/normal_test.cc', '../test/normal_test.cc',
'../test/quality_modes_test.cc', '../test/quality_modes_test.cc',

View File

@ -14,16 +14,17 @@
* *
**************************************************/ **************************************************/
#include "receiver_tests.h" // shared RTP state and receive side threads #include <string.h>
#include "video_coding.h"
#include "rtp_rtcp.h"
#include "thread_wrapper.h"
#include "../source/event.h" #include "../source/event.h"
#include "media_opt_test.h"
#include "mt_test_common.h"
#include "receiver_tests.h" // shared RTP state and receive side threads
#include "rtp_rtcp.h"
#include "test_macros.h" #include "test_macros.h"
#include "test_util.h" // send side callback #include "test_util.h" // send side callback
#include "media_opt_test.h" #include "thread_wrapper.h"
#include "video_coding.h"
#include <string.h>
using namespace webrtc; using namespace webrtc;

View File

@ -0,0 +1,132 @@
/*
* 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 "mt_test_common.h"
#include <cmath>
#include "rtp_dump.h"
TransportCallback::TransportCallback(webrtc::RtpRtcp* rtp,
const char* filename):
RTPSendCompleteCallback(rtp, filename)
{
//
}
TransportCallback::~TransportCallback()
{
//
}
int
TransportCallback::SendPacket(int channel, const void *data, int len)
{
_sendCount++;
_totalSentLength += len;
if (_rtpDump != NULL)
{
if (_rtpDump->DumpPacket((const WebRtc_UWord8*)data, len) != 0)
{
return -1;
}
}
bool transmitPacket = true;
// Off-line tests, don't drop first Key frame (approx.)
if (_sendCount > 20)
{
transmitPacket = PacketLoss();
}
WebRtc_UWord64 now = VCMTickTime::MillisecondTimestamp();
// Insert outgoing packet into list
if (transmitPacket)
{
rtpPacket* newPacket = new rtpPacket();
memcpy(newPacket->data, data, len);
newPacket->length = len;
// Simulate receive time = network delay + packet jitter
// simulated as a Normal distribution random variable with
// mean = networkDelay and variance = jitterVar
WebRtc_Word32
simulatedDelay = (WebRtc_Word32)NormalDist(_networkDelayMs,
sqrt(_jitterVar));
newPacket->receiveTime = now + simulatedDelay;
_rtpPackets.PushBack(newPacket);
}
return 0;
}
int
TransportCallback::TransportPackets()
{
// Are we ready to send packets to the receiver?
rtpPacket* packet = NULL;
WebRtc_UWord64 now = VCMTickTime::MillisecondTimestamp();
while (!_rtpPackets.Empty())
{
// Take first packet in list
packet = static_cast<rtpPacket*>((_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 0; // OK
}
bool VCMProcessingThread(void* obj)
{
SharedRTPState* state = static_cast<SharedRTPState*>(obj);
if (state->_vcm.TimeUntilNextProcess() <= 0)
{
if (state->_vcm.Process() < 0)
{
return false;
}
}
return true;
}
bool VCMDecodeThread(void* obj)
{
SharedRTPState* state = static_cast<SharedRTPState*>(obj);
state->_vcm.Decode();
return true;
}
bool TransportThread(void *obj)
{
SharedTransportState* state = static_cast<SharedTransportState*>(obj);
state->_transport.TransportPackets();
return true;
}

View File

@ -0,0 +1,86 @@
/*
* 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.
*/
/*
* Common multi-thread functionality across video coding module tests
*/
#ifndef WEBRTC_MODULES_VIDEO_CODING_TEST_MT_TEST_COMMON_H_
#define WEBRTC_MODULES_VIDEO_CODING_TEST_MT_TEST_COMMON_H_
#include "rtp_rtcp.h"
#include "test_util.h"
#include "video_coding.h"
using namespace webrtc;
class SendSharedState
{
public:
SendSharedState(webrtc::VideoCodingModule& vcm, webrtc::RtpRtcp& rtp,
CmdArgs args) :
_vcm(vcm),
_rtp(rtp),
_args(args),
_sourceFile(NULL),
_frameCnt(0),
_timestamp(0) {}
webrtc::VideoCodingModule& _vcm;
webrtc::RtpRtcp& _rtp;
CmdArgs _args;
FILE* _sourceFile;
WebRtc_Word32 _frameCnt;
WebRtc_Word32 _timestamp;
};
// MT implementation of the RTPSendCompleteCallback (Transport)
class TransportCallback:public RTPSendCompleteCallback
{
public:
// constructor input: (receive side) rtp module to send encoded data to
TransportCallback(webrtc::RtpRtcp* rtp,
const char* filename = NULL);
virtual ~TransportCallback();
// Add packets to list
// Incorporate network conditions - delay and packet loss
// Actual transmission will occur on a separate thread
int SendPacket(int channel, const void *data, int len);
// Send to the receiver packets which are ready to be submitted
int TransportPackets();
};
class SharedRTPState
{
public:
SharedRTPState(webrtc::VideoCodingModule& vcm, webrtc::RtpRtcp& rtp) :
_vcm(vcm),
_rtp(rtp) {}
webrtc::VideoCodingModule& _vcm;
webrtc::RtpRtcp& _rtp;
};
class SharedTransportState
{
public:
SharedTransportState(webrtc::RtpRtcp& rtp, TransportCallback& transport):
_rtp(rtp),
_transport(transport) {}
webrtc::RtpRtcp& _rtp;
TransportCallback& _transport;
};
bool VCMProcessingThread(void* obj);
bool VCMDecodeThread(void* obj);
bool TransportThread(void *obj);
#endif // WEBRTC_MODULES_VIDEO_CODING_TEST_MT_TEST_COMMON_H_

View File

@ -63,15 +63,6 @@ public:
RTPPlayer& _rtpPlayer; RTPPlayer& _rtpPlayer;
}; };
class SharedRTPState
{
public:
SharedRTPState(webrtc::VideoCodingModule& vcm, webrtc::RtpRtcp& rtp) :
_vcm(vcm),
_rtp(rtp) {}
webrtc::VideoCodingModule& _vcm;
webrtc::RtpRtcp& _rtp;
};
int RtpPlay(CmdArgs& args); int RtpPlay(CmdArgs& args);
int RtpPlayMT(CmdArgs& args, int RtpPlayMT(CmdArgs& args,

View File

@ -249,65 +249,6 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
{ {
_sendCount++; _sendCount++;
_totalSentLength += len; _totalSentLength += len;
bool transmitPacket = true;
// Packet Loss
if (_burstLength <= 1.0)
{
// Random loss: if _burstLength parameter is not set, or <=1
if (PacketLoss(_lossPct))
{
// drop
transmitPacket = false;
}
}
else
{
// Simulate bursty channel (Gilbert model)
// (1st order) Markov chain model with memory of the previous/last
// packet state (loss or received)
// 0 = received state
// 1 = loss state
// probTrans10: if previous packet is lost, prob. to -> received state
// probTrans11: if previous packet is lost, prob. to -> loss state
// probTrans01: if previous packet is received, prob. to -> loss state
// probTrans00: if previous packet is received, prob. to -> received
// Map the two channel parameters (average loss rate and burst length)
// to the transition probabilities:
double probTrans10 = 100 * (1.0 / _burstLength);
double probTrans11 = (100.0 - probTrans10);
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)
if (_prevLossState == 0 )
{
// previous packet was received
if (PacketLoss(probTrans01))
{
// drop, update previous state to loss
_prevLossState = 1;
transmitPacket = false;
}
}
else if (_prevLossState == 1)
{
_prevLossState = 0;
// previous packet was lost
if (PacketLoss(probTrans11))
{
// drop, update previous state to loss
_prevLossState = 1;
transmitPacket = false;
}
}
}
if (_rtpDump != NULL) if (_rtpDump != NULL)
{ {
@ -317,6 +258,8 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
} }
} }
bool transmitPacket = PacketLoss();
WebRtc_UWord64 now = VCMTickTime::MillisecondTimestamp(); WebRtc_UWord64 now = VCMTickTime::MillisecondTimestamp();
// Insert outgoing packet into list // Insert outgoing packet into list
if (transmitPacket) if (transmitPacket)
@ -367,11 +310,8 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
int int
RTPSendCompleteCallback::SendRTCPPacket(int channel, const void *data, int len) RTPSendCompleteCallback::SendRTCPPacket(int channel, const void *data, int len)
{ {
if (_rtp->IncomingPacket((const WebRtc_UWord8*)data, len) == 0) // Incorporate network conditions
{ return SendPacket(channel, data, len);
return len;
}
return -1;
} }
void void
@ -389,7 +329,70 @@ RTPSendCompleteCallback::SetBurstLength(double burstLength)
} }
bool bool
RTPSendCompleteCallback::PacketLoss(double lossPct) RTPSendCompleteCallback::PacketLoss()
{
bool transmitPacket = true;
if (_burstLength <= 1.0)
{
// Random loss: if _burstLength parameter is not set, or <=1
if (UnifomLoss(_lossPct))
{
// drop
transmitPacket = false;
}
}
else
{
// Simulate bursty channel (Gilbert model)
// (1st order) Markov chain model with memory of the previous/last
// packet state (loss or received)
// 0 = received state
// 1 = loss state
// probTrans10: if previous packet is lost, prob. to -> received state
// probTrans11: if previous packet is lost, prob. to -> loss state
// probTrans01: if previous packet is received, prob. to -> loss state
// probTrans00: if previous packet is received, prob. to -> received
// Map the two channel parameters (average loss rate and burst length)
// to the transition probabilities:
double probTrans10 = 100 * (1.0 / _burstLength);
double probTrans11 = (100.0 - probTrans10);
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)
if (_prevLossState == 0 )
{
// previous packet was received
if (UnifomLoss(probTrans01))
{
// drop, update previous state to loss
_prevLossState = 1;
transmitPacket = false;
}
}
else if (_prevLossState == 1)
{
_prevLossState = 0;
// previous packet was lost
if (UnifomLoss(probTrans11))
{
// drop, update previous state to loss
_prevLossState = 1;
transmitPacket = false;
}
}
}
return transmitPacket;
}
bool
RTPSendCompleteCallback::UnifomLoss(double lossPct)
{ {
double randVal = (std::rand() + 1.0)/(RAND_MAX + 1.0); double randVal = (std::rand() + 1.0)/(RAND_MAX + 1.0);
return randVal < lossPct/100; return randVal < lossPct/100;
@ -402,7 +405,6 @@ PacketRequester::ResendPackets(const WebRtc_UWord16* sequenceNumbers,
return _rtp.SendNACK(sequenceNumbers, length); return _rtp.SendNACK(sequenceNumbers, length);
} }
RTPVideoCodecTypes RTPVideoCodecTypes
ConvertCodecType(const char* plname) ConvertCodecType(const char* plname)
{ {

View File

@ -51,6 +51,7 @@ public:
// forward declaration // forward declaration
int MTRxTxTest(CmdArgs& args); int MTRxTxTest(CmdArgs& args);
double NormalDist(double mean, double stdDev);
namespace webrtc namespace webrtc
{ {
class RtpDump; class RtpDump;
@ -64,7 +65,7 @@ namespace webrtc
2. EncodeComplete callback: 2. EncodeComplete callback:
2a. Transfer encoded data directly to the decoder 2a. Transfer encoded data directly to the decoder
2b. Pass encoded data via the RTP module 2b. Pass encoded data via the RTP module
3. Caluclate PSNR from file function (for now: does not deal with frame drops) 3. Calculate PSNR from file function (for now: does not deal with frame drops)
*/ */
// Send Side - Packetization callback - send an encoded frame to the VCMReceiver // Send Side - Packetization callback - send an encoded frame to the VCMReceiver
@ -215,9 +216,11 @@ public:
int SendCount() {return _sendCount; } int SendCount() {return _sendCount; }
// Return accumulated length in bytes of transmitted packets // Return accumulated length in bytes of transmitted packets
WebRtc_UWord32 TotalSentLength() {return _totalSentLength;} WebRtc_UWord32 TotalSentLength() {return _totalSentLength;}
private: protected:
// Randomly decide whether to drop packets, based on the channel model // Randomly decide whether to drop packets, based on the channel model
bool PacketLoss(double lossPct); bool PacketLoss();
// Random uniform loss model
bool UnifomLoss(double lossPct);
WebRtc_UWord32 _sendCount; WebRtc_UWord32 _sendCount;
webrtc::RtpRtcp* _rtp; webrtc::RtpRtcp* _rtp;
@ -231,27 +234,6 @@ private:
webrtc::RtpDump* _rtpDump; webrtc::RtpDump* _rtpDump;
}; };
// Used in multi thread test
class SendSharedState
{
public:
SendSharedState(webrtc::VideoCodingModule& vcm, webrtc::RtpRtcp& rtp,
CmdArgs args) :
_vcm(vcm),
_rtp(rtp),
_args(args),
_sourceFile(NULL),
_frameCnt(0),
_timestamp(0) {}
webrtc::VideoCodingModule& _vcm;
webrtc::RtpRtcp& _rtp;
CmdArgs _args;
FILE* _sourceFile;
WebRtc_Word32 _frameCnt;
WebRtc_Word32 _timestamp;
};
class PacketRequester: public webrtc::VCMPacketRequestCallback class PacketRequester: public webrtc::VCMPacketRequestCallback
{ {
public: public: