89714f2880
git-svn-id: http://webrtc.googlecode.com/svn/trunk@88 4adac7df-926f-26a2-2b94-8c16560cd09d
1240 lines
46 KiB
C++
1240 lines
46 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
// testAPI.cpp : Defines the entry point for the console application.
|
|
//
|
|
#define _CRTDBG_MAP_ALLOC
|
|
#include <stdlib.h>
|
|
#include <crtdbg.h>
|
|
|
|
#include <cassert>
|
|
#include <windows.h>
|
|
#include <iostream>
|
|
#include <tchar.h>
|
|
|
|
#include "rtp_rtcp.h"
|
|
#include "common_types.h"
|
|
#include "process_thread.h"
|
|
#include "trace.h"
|
|
|
|
#include "../source/ModuleRtpRtcpImpl.h"
|
|
|
|
#define TEST_AUDIO
|
|
#define TEST_VIDEO
|
|
|
|
WebRtc_UWord8 _payloadDataFile[65000];
|
|
WebRtc_UWord16 _payloadDataFileLength;
|
|
#define VIDEO_NACK_LIST_SIZE 30
|
|
|
|
class LoopBackTransport : public webrtc::Transport
|
|
{
|
|
public:
|
|
LoopBackTransport(RtpRtcp* rtpRtcpModule) :
|
|
_rtpRtcpModule(rtpRtcpModule)
|
|
{
|
|
_sendCount = 0;
|
|
}
|
|
virtual int SendPacket(int channel, const void *data, int len)
|
|
{
|
|
_sendCount++;
|
|
if(_sendCount > 500 && _sendCount <= 510)
|
|
{
|
|
// drop 10 packets
|
|
printf("\tDrop packet\n");
|
|
return len;
|
|
}
|
|
if(_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, len) == 0)
|
|
{
|
|
return len;
|
|
}
|
|
return -1;
|
|
}
|
|
virtual int SendRTCPPacket(int channel, const void *data, int len)
|
|
{
|
|
if(_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, len) == 0)
|
|
{
|
|
return len;
|
|
}
|
|
return -1;
|
|
}
|
|
WebRtc_UWord32 _sendCount;
|
|
RtpRtcp* _rtpRtcpModule;
|
|
};
|
|
|
|
class DataRelayReceiverVideo : public RtpData
|
|
{
|
|
public:
|
|
DataRelayReceiverVideo(RtpRtcp* rtpRtcpModule) : _rtpRtcpModule(rtpRtcpModule)
|
|
{}
|
|
virtual WebRtc_Word32 OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
|
|
const WebRtc_UWord16 payloadSize,
|
|
const webrtc::WebRtcRTPHeader* rtpHeader,
|
|
const WebRtc_UWord8* rtpPacket,
|
|
const WebRtc_UWord16 rtpPacketSize)
|
|
{
|
|
if(rtpPacketSize == 0)
|
|
{
|
|
// we relay only one packet once, but this function in called for each NALU
|
|
return 0;
|
|
}
|
|
if(_rtpRtcpModule->SendRTPPacket(rtpHeader, rtpPacket, rtpPacketSize) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
RtpRtcp* _rtpRtcpModule;
|
|
};
|
|
|
|
// Dummy comment, shall be removed
|
|
class LoopBackTransportVideo : public webrtc::Transport
|
|
{
|
|
public:
|
|
LoopBackTransportVideo(RtpRtcp* rtpRtcpModule) :
|
|
_count(0),
|
|
_packetLoss(0),
|
|
_rtpRtcpModule(rtpRtcpModule)
|
|
{
|
|
}
|
|
virtual int SendPacket(int channel, const void *data, int len)
|
|
{
|
|
if(static_cast<const WebRtc_UWord8*>(data)[0] == 0)
|
|
{
|
|
// printf("\t\tReceived pad data length:%d\n", len);
|
|
return len;
|
|
}
|
|
_count++;
|
|
if(_packetLoss > 0)
|
|
{
|
|
if(_count%_packetLoss == 0)
|
|
{
|
|
// printf("Drop video packet: %u\n", static_cast<const unsigned char*>(data)[3]);
|
|
return len;
|
|
}
|
|
// printf("video packet: %u\n", static_cast<const unsigned char*>(data)[3]);
|
|
} else
|
|
{
|
|
// printf("video packet: %u\n", static_cast<const unsigned char*>(data)[3]);
|
|
}
|
|
if(_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, len) == 0)
|
|
{
|
|
return len;
|
|
}
|
|
return -1;
|
|
}
|
|
virtual int SendRTCPPacket(int channel, const void *data, int len)
|
|
{
|
|
if(_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, len) == 0)
|
|
{
|
|
return len;
|
|
}
|
|
return -1;
|
|
}
|
|
WebRtc_UWord32 _packetLoss;
|
|
WebRtc_UWord32 _count;
|
|
WebRtc_UWord32 _time;
|
|
RtpRtcp* _rtpRtcpModule;
|
|
};
|
|
|
|
|
|
class DataReceiver : public RtpData
|
|
{
|
|
public:
|
|
DataReceiver(RtpRtcp* rtpRtcpModule) :
|
|
_rtpRtcpModule(rtpRtcpModule)
|
|
{
|
|
}
|
|
|
|
virtual WebRtc_Word32 OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
|
|
const WebRtc_UWord16 payloadSize,
|
|
const webrtc::WebRtcRTPHeader* rtpHeader,
|
|
const WebRtc_UWord8* rtpPacket,
|
|
const WebRtc_UWord16 rtpPacketSize)
|
|
{
|
|
// printf("\tReceived packet:%d payload type:%d length:%d\n", rtpHeader->header.sequenceNumber, rtpHeader->header.payloadType, payloadSize);
|
|
|
|
if(rtpHeader->header.payloadType == 98 ||
|
|
rtpHeader->header.payloadType == 99)
|
|
{
|
|
if(strncmp("test", (const char*)payloadData, 4) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
if(rtpHeader->header.payloadType == 100 ||
|
|
rtpHeader->header.payloadType == 101 ||
|
|
rtpHeader->header.payloadType == 102)
|
|
{
|
|
if(rtpHeader->type.Audio.channel == 1)
|
|
{
|
|
if(payloadData[0] == 0xff)
|
|
{
|
|
return 0;
|
|
}
|
|
}else if(rtpHeader->type.Audio.channel == 2)
|
|
{
|
|
if(payloadData[0] == 0x0)
|
|
{
|
|
return 0;
|
|
}
|
|
}else if(rtpHeader->type.Audio.channel == 3)
|
|
{
|
|
if(payloadData[0] == 0xaa)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
if(payloadSize == 10)
|
|
{
|
|
if(strncmp("testEnergy", (const char*)payloadData, 10) == 0)
|
|
{
|
|
if(rtpHeader->type.Audio.numEnergy == 2)
|
|
{
|
|
if( rtpHeader->type.Audio.arrOfEnergy[0] == 7 &&
|
|
rtpHeader->type.Audio.arrOfEnergy[1] == 9)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
RtpRtcp* _rtpRtcpModule;
|
|
};
|
|
|
|
class DataReceiverVideo : public RtpData
|
|
{
|
|
public:
|
|
DataReceiverVideo() :
|
|
_packetLoss(false),
|
|
_curLength(0)
|
|
{
|
|
}
|
|
void CheckRecivedFrame(bool nack)
|
|
{
|
|
printf("\t\tCheckRecivedFrame\n");
|
|
{
|
|
assert(_curLength == _payloadDataFileLength);
|
|
_curLength = 0;
|
|
if(!nack)
|
|
{
|
|
for (int i = 0; i < _payloadDataFileLength; i++)
|
|
{
|
|
assert(_receiveBuffer[i] == _payloadDataFile[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual WebRtc_Word32 OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
|
|
const WebRtc_UWord16 payloadSize,
|
|
const webrtc::WebRtcRTPHeader* rtpHeader,
|
|
const WebRtc_UWord8* rtpPacket,
|
|
const WebRtc_UWord16 rtpPacketSize)
|
|
{
|
|
if(rtpHeader->frameType == webrtc::kFrameEmpty && payloadSize == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
// store received payload data
|
|
int sByte = 0;
|
|
if (rtpHeader->type.Video.codec == VideoH263 && rtpHeader->type.Video.codecHeader.H263.bits)
|
|
{
|
|
// "or" the first bits
|
|
assert(_curLength > 0);
|
|
_receiveBuffer[_curLength - 1] |= payloadData[0];
|
|
sByte = 1;
|
|
}
|
|
memcpy(&_receiveBuffer[_curLength], &payloadData[sByte], payloadSize - sByte);
|
|
_curLength += payloadSize - sByte;
|
|
|
|
if(!_packetLoss)
|
|
{
|
|
if (rtpHeader->header.markerBit && payloadSize)
|
|
{
|
|
// last packet, compare send and received data stream
|
|
CheckRecivedFrame(false);
|
|
}
|
|
} else
|
|
{
|
|
for(int i = 0; i < VIDEO_NACK_LIST_SIZE; i++)
|
|
{
|
|
if(_nackList[i] == rtpHeader->header.sequenceNumber)
|
|
{
|
|
_nackList[i] = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool _packetLoss;
|
|
WebRtc_Word32 _nackList[VIDEO_NACK_LIST_SIZE];
|
|
WebRtc_UWord8 _receiveBuffer[100000];
|
|
WebRtc_UWord32 _curLength;
|
|
};
|
|
|
|
class VideoFeedback : public RtpVideoFeedback
|
|
{
|
|
virtual void OnReceivedIntraFrameRequest(const WebRtc_Word32 id,
|
|
const WebRtc_UWord8 message)
|
|
{
|
|
printf("\tReceived video IntraFrameRequest message:%d \n", message);
|
|
};
|
|
|
|
virtual void OnNetworkChanged(const WebRtc_Word32 id,
|
|
const WebRtc_UWord32 bitrateTarget,
|
|
const WebRtc_UWord8 fractionLost,
|
|
const WebRtc_UWord16 roundTripTimeMs,
|
|
const WebRtc_UWord32 jitterMS,
|
|
const WebRtc_UWord16 bwEstimateKbitMin,
|
|
const WebRtc_UWord16 bwEstimateKbitMax)
|
|
{
|
|
static int count = 0;
|
|
count++;
|
|
const WebRtc_UWord32 bitrateTargetKbit = bitrateTarget/1000;
|
|
|
|
// todo jitter is not valid due to send rate
|
|
if(count == 1)
|
|
{
|
|
assert(3667 >= bwEstimateKbitMax);
|
|
assert(fractionLost >= 80 && fractionLost < 150);
|
|
assert(300 == bitrateTargetKbit); // no inc due to no fraction loss
|
|
|
|
} else if(count == 2)
|
|
{
|
|
assert(1517 == bwEstimateKbitMax);
|
|
assert(0 == fractionLost);
|
|
assert(300 == bitrateTargetKbit); // no inc due to no actual bitrate
|
|
} else if(count == 3)
|
|
{
|
|
assert(1517 == bwEstimateKbitMax);
|
|
assert(0 == fractionLost);
|
|
assert(220 == bitrateTargetKbit);
|
|
} else if(count == 4)
|
|
{
|
|
assert(0 == fractionLost);
|
|
assert(243 == bitrateTargetKbit);
|
|
} else
|
|
{
|
|
assert(10 == jitterMS);
|
|
assert(4 == fractionLost);
|
|
}
|
|
|
|
printf("\tReceived video OnNetworkChanged bitrateTargetKbit:%d RTT:%d Loss:%d\n", bitrateTargetKbit, roundTripTimeMs, fractionLost);
|
|
};
|
|
};
|
|
|
|
class AudioFeedback : public RtpAudioFeedback
|
|
{
|
|
virtual void OnReceivedTelephoneEvent(const WebRtc_Word32 id,
|
|
const WebRtc_UWord8 event,
|
|
const bool end)
|
|
{
|
|
static WebRtc_UWord8 expectedEvent = 0;
|
|
|
|
if(end)
|
|
{
|
|
WebRtc_UWord8 oldEvent = expectedEvent-1;
|
|
if(expectedEvent == 32)
|
|
{
|
|
oldEvent = 15;
|
|
}
|
|
#if 0 // test of multiple events
|
|
else if(expectedEvent == 34)
|
|
{
|
|
oldEvent = 32;
|
|
expectedEvent = 33;
|
|
}else if(expectedEvent == 33)
|
|
{
|
|
oldEvent = 33;
|
|
expectedEvent = 34;
|
|
}
|
|
#endif
|
|
assert(oldEvent == event);
|
|
}else
|
|
{
|
|
assert(expectedEvent == event);
|
|
expectedEvent++;
|
|
}
|
|
if(expectedEvent == 16)
|
|
{
|
|
expectedEvent = 32;
|
|
}
|
|
|
|
if(end)
|
|
{
|
|
printf("\tReceived End of DTMF event:%d with id:%d\n", event, id);
|
|
}else
|
|
{
|
|
printf("\tReceived Start of DTMF event:%d with id:%d\n", event, id);
|
|
}
|
|
}
|
|
virtual void OnPlayTelephoneEvent(const WebRtc_Word32 id,
|
|
const WebRtc_UWord8 event,
|
|
const WebRtc_UWord16 lengthMs,
|
|
const WebRtc_UWord8 volume)
|
|
{
|
|
printf("\tPlayout DTMF event:%d time:%d ms volume:%d with id:%d\n", event, lengthMs,volume, id);
|
|
};
|
|
};
|
|
|
|
class RtcpFeedback : public RtcpFeedback
|
|
{
|
|
public:
|
|
RtcpFeedback()
|
|
{
|
|
_rtpRtcpModule = NULL;
|
|
_rtpRtcpModuleRelay = NULL;
|
|
};
|
|
virtual void OnRTCPPacketTimeout(const WebRtc_Word32 id)
|
|
{
|
|
printf("\tReceived OnPacketTimeout for RTCP id:%d\n", id);
|
|
}
|
|
|
|
// if audioVideoOffset > 0 video is behind audio
|
|
virtual void OnLipSyncUpdate(const WebRtc_Word32 id,
|
|
const WebRtc_Word32 audioVideoOffset)
|
|
{
|
|
// printf("\tReceived OnLipSyncUpdate:%d with id:%d\n", audioVideoOffset, id);
|
|
};
|
|
virtual void OnTMMBRReceived(const WebRtc_Word32 id,
|
|
const WebRtc_UWord16 bwEstimateKbit)
|
|
{
|
|
printf("\tReceived OnTMMBRReceived:%d with id:%d\n", bwEstimateKbit, id);
|
|
};
|
|
|
|
virtual void OnXRVoIPMetricReceived(const WebRtc_Word32 id,
|
|
const RTCPVoIPMetric* metric,
|
|
const WebRtc_Word8 VoIPmetricBuffer[28])
|
|
{
|
|
printf("\tOnXRVoIPMetricReceived:%d with id:%d\n", metric->burstDensity, id);
|
|
};
|
|
virtual void OnSLIReceived(const WebRtc_Word32 id,
|
|
const WebRtc_UWord8 pictureId)
|
|
{
|
|
printf("\tReceived OnSLIReceived:%d with id:%d\n", pictureId, id);
|
|
assert(pictureId == 28);
|
|
};
|
|
|
|
virtual void OnRPSIReceived(const WebRtc_Word32 id,
|
|
const WebRtc_UWord64 pictureId)
|
|
{
|
|
printf("\tReceived OnRPSIReceived:%d with id:%d\n", pictureId, id);
|
|
assert(pictureId == 12345678);
|
|
};
|
|
|
|
virtual void OnApplicationDataReceived(const WebRtc_Word32 id,
|
|
const WebRtc_UWord8 subType,
|
|
const WebRtc_UWord32 name,
|
|
const WebRtc_UWord16 length,
|
|
const WebRtc_UWord8* data)
|
|
{
|
|
WebRtc_Word8 printName[5];
|
|
printName[0] = (WebRtc_Word8)(name >> 24);
|
|
printName[1] = (WebRtc_Word8)(name >> 16);
|
|
printName[2] = (WebRtc_Word8)(name >> 8);
|
|
printName[3] = (WebRtc_Word8)name;
|
|
printName[4] = 0;
|
|
|
|
WebRtc_Word8* printData = new WebRtc_Word8[length+1];
|
|
memcpy(printData, data, length);
|
|
printData[length] = 0;
|
|
|
|
printf("\tOnApplicationDataReceived subtype:%d name:%s data:%s with id:%d\n", subType, printName, printData, id);
|
|
|
|
assert(strncmp("test",printName, 5) == 0);
|
|
delete [] printData;
|
|
};
|
|
|
|
virtual void OnSendReportReceived(const WebRtc_Word32 id,
|
|
const WebRtc_UWord32 senderSSRC,
|
|
const WebRtc_UWord8* incomingPacket,
|
|
const WebRtc_UWord16 packetLength)
|
|
{
|
|
printf("\tOnSendReportReceived RTCP id:%d\n", id);
|
|
|
|
if(_rtpRtcpModule)
|
|
{
|
|
RTCPSenderInfo senderInfo;
|
|
assert(_rtpRtcpModule->RemoteRTCPStat(&senderInfo) == 0);
|
|
senderInfo.sendOctetCount;
|
|
senderInfo.sendPacketCount;
|
|
}
|
|
if(_rtpRtcpModuleRelay)
|
|
{
|
|
// relay packet
|
|
_rtpRtcpModuleRelay->SendRTCPPacket(incomingPacket, packetLength);
|
|
}
|
|
};
|
|
|
|
// for relay conferencing
|
|
virtual void OnReceiveReportReceived(const WebRtc_Word32 id,
|
|
const WebRtc_UWord32 senderSSRC,
|
|
const WebRtc_UWord8* incomingPacket,
|
|
const WebRtc_UWord16 packetLength)
|
|
{
|
|
WebRtc_UWord16 RTT = 0;
|
|
WebRtc_UWord32 remoteSSRC;
|
|
switch(id)
|
|
{
|
|
case 123:
|
|
remoteSSRC = 124;
|
|
break;
|
|
case 124:
|
|
remoteSSRC = 123;
|
|
break;
|
|
case 125:
|
|
remoteSSRC = 126;
|
|
break;
|
|
case 126:
|
|
remoteSSRC = 125;
|
|
break;
|
|
default:
|
|
assert(false);
|
|
}
|
|
|
|
_rtpRtcpModule->RTT(remoteSSRC, &RTT,NULL,NULL,NULL);
|
|
|
|
printf("\tOnReceiveReportReceived RTT:%d RTCP id:%d\n", RTT, id);
|
|
if(_rtpRtcpModuleRelay)
|
|
{
|
|
// relay packet
|
|
_rtpRtcpModuleRelay->SendRTCPPacket(incomingPacket, packetLength);
|
|
}
|
|
};
|
|
RtpRtcp* _rtpRtcpModule;
|
|
RtpRtcp* _rtpRtcpModuleRelay;
|
|
};
|
|
|
|
class RTPCallback : public RtpFeedback
|
|
{
|
|
public:
|
|
virtual WebRtc_Word32 OnInitializeDecoder(const WebRtc_Word32 id,
|
|
const WebRtc_Word8 payloadType,
|
|
const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE],
|
|
const WebRtc_UWord32 frequency,
|
|
const WebRtc_UWord8 channels,
|
|
const WebRtc_UWord32 rate)
|
|
{
|
|
if(payloadType == 96)
|
|
{
|
|
assert(rate == 64000);
|
|
}
|
|
printf("\tReceived OnInitializeDecoder \n\t\tpayloadName:%s \n\t\tpayloadType:%d \n\t\tfrequency:%d \n\t\tchannels:%d \n\t\trate:%d \n\t\twith id:%d\n", payloadName,payloadType,frequency, channels, rate, id);
|
|
return 0;
|
|
}
|
|
|
|
virtual void OnPacketTimeout(const WebRtc_Word32 id)
|
|
{
|
|
printf("\tReceived OnPacketTimeout\n");
|
|
}
|
|
|
|
virtual void OnReceivedPacket(const WebRtc_Word32 id,
|
|
const RtpRtcpPacketType packetType)
|
|
{
|
|
printf("\tReceived OnReceivedPacket\n");
|
|
}
|
|
|
|
virtual void OnPeriodicDeadOrAlive(const WebRtc_Word32 id,
|
|
const RTPAliveType alive)
|
|
{
|
|
printf("\tReceived OnPeriodicDeadOrAlive\n");
|
|
}
|
|
|
|
virtual void OnIncomingSSRCChanged( const WebRtc_Word32 id,
|
|
const WebRtc_UWord32 SSRC)
|
|
{
|
|
printf("\tReceived OnIncomingSSRCChanged\n");
|
|
}
|
|
|
|
virtual void OnIncomingCSRCChanged( const WebRtc_Word32 id,
|
|
const WebRtc_UWord32 CSRC,
|
|
const bool added)
|
|
{
|
|
printf("\tReceived OnIncomingCSRCChanged\n");
|
|
}
|
|
};
|
|
|
|
// todo look at VE 3.0 test app
|
|
int _tmain(int argc, _TCHAR* argv[])
|
|
{
|
|
// _crtBreakAlloc = 17967;
|
|
|
|
WebRtc_Word8 fileName[1024] = "testTrace.txt";
|
|
Trace::CreateTrace();
|
|
Trace::SetTraceFile(fileName);
|
|
memcpy(fileName, "testTraceDebug.txt", 19);
|
|
Trace::SetEncryptedTraceFile(fileName);
|
|
Trace::SetLevelFilter(webrtc::kTraceAll);
|
|
|
|
int myId = 123;
|
|
ProcessThread* processThread = ProcessThread::CreateProcessThread();
|
|
processThread->Start();
|
|
|
|
#ifdef TEST_AUDIO
|
|
// test all APIs in RTP/RTCP module
|
|
RtpRtcp* rtpRtcpModule1 = RtpRtcp::CreateRtpRtcp(myId,
|
|
true); // audio
|
|
|
|
RtpRtcp* rtpRtcpModule2 = RtpRtcp::CreateRtpRtcp(myId+1,
|
|
true); // audio
|
|
|
|
processThread->RegisterModule(rtpRtcpModule1);
|
|
processThread->RegisterModule(rtpRtcpModule2);
|
|
|
|
printf("Welcome to API test of RTP/RTCP module\n");
|
|
|
|
WebRtc_Word8 version[256];
|
|
WebRtc_UWord32 remainingBufferInBytes = 256;
|
|
WebRtc_UWord32 position = 0;
|
|
assert( 0 == rtpRtcpModule1->Version(version, remainingBufferInBytes, position));
|
|
assert(-1 == rtpRtcpModule1->Version(NULL, remainingBufferInBytes, position));
|
|
printf("\nVersion\n\t%s\n\n", version);
|
|
|
|
assert( 0 == rtpRtcpModule1->InitReceiver());
|
|
assert( 0 == rtpRtcpModule1->InitSender());
|
|
|
|
assert( 0 == rtpRtcpModule2->InitReceiver());
|
|
assert( 0 == rtpRtcpModule2->InitSender());
|
|
|
|
printf("\tInitialization done\n");
|
|
|
|
assert(-1 == rtpRtcpModule1->SetMaxTransferUnit(10));
|
|
assert(-1 == rtpRtcpModule1->SetMaxTransferUnit(IP_PACKET_SIZE + 1));
|
|
assert( 0 == rtpRtcpModule1->SetMaxTransferUnit(1234));
|
|
assert(1234-20-8 == rtpRtcpModule1->MaxPayloadLength());
|
|
|
|
assert( 0 == rtpRtcpModule1->SetTransportOverhead(true, true, 12));
|
|
assert(1234 - 20- 20 -20 - 12 == rtpRtcpModule1->MaxPayloadLength());
|
|
|
|
assert( 0 == rtpRtcpModule1->SetTransportOverhead(false, false, 0));
|
|
assert(1234 - 20 - 8== rtpRtcpModule1->MaxPayloadLength());
|
|
|
|
assert( 0 == rtpRtcpModule1->SetSequenceNumber(2345));
|
|
assert(2345 == rtpRtcpModule1->SequenceNumber());
|
|
|
|
assert( 0 == rtpRtcpModule1->SetSSRC(3456));
|
|
assert(3456 == rtpRtcpModule1->SSRC());
|
|
|
|
assert( 0 == rtpRtcpModule1->SetStartTimestamp(4567));
|
|
assert(4567 == rtpRtcpModule1->StartTimestamp());
|
|
|
|
assert(0 == rtpRtcpModule1->SetAudioEnergy(NULL,0));
|
|
|
|
WebRtc_UWord32 arrOfCSRC[webrtc::kRtpCsrcSize] = {1234,2345};
|
|
WebRtc_UWord32 testOfCSRC[webrtc::kRtpCsrcSize] = {0,0,0};
|
|
assert( 0 == rtpRtcpModule1->SetCSRCs(arrOfCSRC,2));
|
|
assert( 2 == rtpRtcpModule1->CSRCs(testOfCSRC));
|
|
assert(arrOfCSRC[0] == testOfCSRC[0]);
|
|
assert(arrOfCSRC[1] == testOfCSRC[1]);
|
|
|
|
assert( kRtcpOff == rtpRtcpModule1->RTCP());
|
|
assert(0 == rtpRtcpModule1->SetRTCPStatus(kRtcpCompound));
|
|
assert( kRtcpCompound == rtpRtcpModule1->RTCP());
|
|
|
|
assert( kRtcpOff == rtpRtcpModule2->RTCP());
|
|
assert(0 == rtpRtcpModule2->SetRTCPStatus(kRtcpCompound));
|
|
assert( kRtcpCompound == rtpRtcpModule2->RTCP());
|
|
|
|
assert( 0 == rtpRtcpModule1->SetCNAME("john.doe@test.test"));
|
|
assert( 0 == rtpRtcpModule2->SetCNAME("jane.doe@test.test"));
|
|
assert(-1 == rtpRtcpModule1->SetCNAME(NULL));
|
|
WebRtc_Word8 cName[RTCP_CNAME_SIZE];
|
|
assert(0 == rtpRtcpModule1->CNAME(cName));
|
|
assert(0 == strncmp(cName, "john.doe@test.test", RTCP_CNAME_SIZE));
|
|
assert(-1 == rtpRtcpModule1->CNAME(NULL));
|
|
|
|
assert( false == rtpRtcpModule1->TMMBR());
|
|
assert(0 == rtpRtcpModule1->SetTMMBRStatus(true));
|
|
assert( true == rtpRtcpModule1->TMMBR());
|
|
assert(0 == rtpRtcpModule1->SetTMMBRStatus(false));
|
|
assert( false == rtpRtcpModule1->TMMBR());
|
|
|
|
assert( kNackOff == rtpRtcpModule1->NACK());
|
|
assert(0 == rtpRtcpModule1->SetNACKStatus(kNackRtcp));
|
|
assert( kNackRtcp == rtpRtcpModule1->NACK());
|
|
|
|
assert( false == rtpRtcpModule1->Sending());
|
|
assert(0 == rtpRtcpModule1->SetSendingStatus(true));
|
|
assert( true == rtpRtcpModule1->Sending());
|
|
assert(0 == rtpRtcpModule2->SetSendingStatus(true));
|
|
|
|
// audio specific
|
|
assert( false == rtpRtcpModule1->TelephoneEvent());
|
|
assert(0 == rtpRtcpModule2->SetTelephoneEventStatus(true, true, true)); // to test detection at the end of a DTMF tone
|
|
assert( true == rtpRtcpModule2->TelephoneEvent());
|
|
|
|
printf("Basic set/get test done\n");
|
|
|
|
// test setup
|
|
DataReceiver* myDataReceiver1 = new DataReceiver(rtpRtcpModule1);
|
|
assert(0 == rtpRtcpModule1->RegisterIncomingDataCallback(myDataReceiver1));
|
|
|
|
DataReceiver* myDataReceiver2 = new DataReceiver(rtpRtcpModule2);
|
|
assert(0 == rtpRtcpModule2->RegisterIncomingDataCallback(myDataReceiver2));
|
|
|
|
LoopBackTransport* myLoopBackTransport1 = new LoopBackTransport(rtpRtcpModule2);
|
|
assert(0 == rtpRtcpModule1->RegisterSendTransport(myLoopBackTransport1));
|
|
|
|
LoopBackTransport* myLoopBackTransport2 = new LoopBackTransport(rtpRtcpModule1);
|
|
assert(0 == rtpRtcpModule2->RegisterSendTransport(myLoopBackTransport2));
|
|
|
|
RTPCallback* myRTPCallback = new RTPCallback();
|
|
assert(0 == rtpRtcpModule2->RegisterIncomingRTPCallback(myRTPCallback));
|
|
|
|
RtcpFeedback* myRTCPFeedback1 = new RtcpFeedback();
|
|
RtcpFeedback* myRTCPFeedback2 = new RtcpFeedback();
|
|
myRTCPFeedback1->_rtpRtcpModule = rtpRtcpModule1;
|
|
myRTCPFeedback2->_rtpRtcpModule = rtpRtcpModule2;
|
|
assert(0 == rtpRtcpModule1->RegisterIncomingRTCPCallback(myRTCPFeedback1));
|
|
assert(0 == rtpRtcpModule2->RegisterIncomingRTCPCallback(myRTCPFeedback2));
|
|
|
|
assert(0 == rtpRtcpModule1->SetSendingStatus(true));
|
|
|
|
// start basic RTP test
|
|
// send an empty RTP packet, should fail since we have not registerd the payload type
|
|
assert(-1 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96, 0, NULL, 0));
|
|
|
|
WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE] = "PCMU";
|
|
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 96, 8000));
|
|
assert(0 == rtpRtcpModule1->RegisterReceivePayload(payloadName, 96, 8000));
|
|
assert(0 == rtpRtcpModule2->RegisterSendPayload( payloadName, 96, 8000));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 96, 8000, 1, 64000));
|
|
|
|
WebRtc_Word8 testPayloadName[RTP_PAYLOAD_NAME_SIZE];
|
|
WebRtc_UWord32 testFrequency = 0;
|
|
WebRtc_Word8 testPayloadType= 0;
|
|
WebRtc_UWord8 testChannels= 0;
|
|
|
|
assert(0 == rtpRtcpModule1->ReceivePayload( 96,testPayloadName, &testFrequency, &testChannels));
|
|
assert(0 == strncmp(testPayloadName, payloadName, 4));
|
|
assert(1 == testChannels);
|
|
|
|
assert(0 == rtpRtcpModule1->ReceivePayloadType( payloadName,8000,1,&testPayloadType));
|
|
assert(testPayloadType == 96);
|
|
|
|
// energy test
|
|
const WebRtc_UWord8 energy[3] = {7,9,3};
|
|
assert(-1 == rtpRtcpModule1->SetAudioEnergy(energy,3)); //should fails since we only have 2 CSRCs
|
|
assert(0 == rtpRtcpModule1->SetAudioEnergy(energy,2));
|
|
|
|
// send RTP packet with the data "testtest"
|
|
const WebRtc_UWord8 test[9] = "testtest";
|
|
const WebRtc_UWord8 testEnergy[11] = "testEnergy";
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,96, 0, testEnergy, 10));
|
|
assert(0 == rtpRtcpModule2->SendOutgoingData(webrtc::kAudioFrameSpeech,96, 0, test, 8));
|
|
// assert(-1 == rtpRtcpModule->SendOutgoingData(96, 0, NULL, 4));
|
|
|
|
assert(3456 == rtpRtcpModule2->RemoteSSRC());
|
|
assert(4567 == rtpRtcpModule2->RemoteTimestamp());
|
|
|
|
assert(0 == rtpRtcpModule1->SetStorePacketsStatus(true, 100));
|
|
|
|
assert(-1 == rtpRtcpModule1->SetTFRCStatus(true));
|
|
assert(0 == rtpRtcpModule1->SetAudioEnergy(NULL,0));
|
|
assert(0 == rtpRtcpModule1->SetTFRCStatus(true));
|
|
|
|
memcpy(payloadName, "RED",4);
|
|
// Test RED
|
|
assert(0 == rtpRtcpModule1->SetSendREDPayloadType(127));
|
|
WebRtc_Word8 red = 0;
|
|
assert(0 == rtpRtcpModule1->SendREDPayloadType(red));
|
|
assert(127 == red);
|
|
assert(0 == rtpRtcpModule1->RegisterReceivePayload( payloadName, 127));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 127));
|
|
|
|
{
|
|
RTPFragmentationHeader fragmentation;
|
|
fragmentation.fragmentationVectorSize = 2;
|
|
fragmentation.fragmentationLength = new WebRtc_UWord32[2];
|
|
fragmentation.fragmentationLength[0] = 4;
|
|
fragmentation.fragmentationLength[1] = 4;
|
|
fragmentation.fragmentationOffset = new WebRtc_UWord32[2];
|
|
fragmentation.fragmentationOffset[0] = 0;
|
|
fragmentation.fragmentationOffset[1] = 4;
|
|
fragmentation.fragmentationTimeDiff = new WebRtc_UWord16[2];
|
|
fragmentation.fragmentationTimeDiff[0] = 0;
|
|
fragmentation.fragmentationTimeDiff[1] = 0;
|
|
fragmentation.fragmentationPlType = new WebRtc_UWord8[2];
|
|
fragmentation.fragmentationPlType[0] = 96;
|
|
fragmentation.fragmentationPlType[1] = 96;
|
|
|
|
// send a RTP packet
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,96, 160, test,8, &fragmentation));
|
|
}
|
|
assert(0 == rtpRtcpModule1->SetSendREDPayloadType(-1));
|
|
assert(-1 == rtpRtcpModule1->SendREDPayloadType(red));
|
|
|
|
assert(0 == rtpRtcpModule1->SetStorePacketsStatus(false));
|
|
|
|
assert(0 == rtpRtcpModule1->SetTFRCStatus(false));
|
|
|
|
printf("Basic RTP test done\n");
|
|
|
|
// todo CNG
|
|
|
|
AudioFeedback* audioFeedback = new AudioFeedback();
|
|
assert(0 == rtpRtcpModule2->RegisterAudioCallback(audioFeedback));
|
|
|
|
// prepare for DTMF
|
|
memcpy(payloadName, "telephone-event",16);
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 97, 8000));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 97));
|
|
|
|
// prepare for 3 channel audio 8 bits per sample
|
|
memcpy(payloadName, "PCMA",5);
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 98, 8000, 3));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 98,8000, 3));
|
|
|
|
// prepare for 3 channel audio 16 bits per sample
|
|
memcpy(payloadName, "L16",4);
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 99, 8000, 3));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 99, 8000, 3));
|
|
|
|
// prepare for 3 channel audio 5 bits per sample
|
|
memcpy(payloadName, "G726-40",8);
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 100, 8000, 3));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 100, 8000, 3));
|
|
|
|
// prepare for 3 channel audio 3 bits per sample
|
|
memcpy(payloadName, "G726-24",8);
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 101, 8000, 3));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 101, 8000, 3));
|
|
|
|
// prepare for 3 channel audio 2 bits per sample
|
|
memcpy(payloadName, "G726-16",8);
|
|
assert(0 == rtpRtcpModule1->RegisterSendPayload( payloadName, 102, 8000, 3));
|
|
assert(0 == rtpRtcpModule2->RegisterReceivePayload( payloadName, 102, 8000, 3));
|
|
|
|
// Start DTMF test
|
|
|
|
// Send a DTMF tone using RFC 2833 (4733)
|
|
for(int i = 0; i < 16; i++)
|
|
{
|
|
printf("\tSending tone: %d\n", i);
|
|
assert(0 == rtpRtcpModule1->SendTelephoneEventOutband(i, 160, 10));
|
|
}
|
|
|
|
// send RTP packets for 16 tones a 160 ms + 100ms pause between = 2560ms + 1600ms = 4160ms
|
|
int j = 2;
|
|
for(;j <= 250;j++)
|
|
{
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,96, 160*j, test,8));
|
|
Sleep(20);
|
|
}
|
|
printf("Basic DTMF test done\n");
|
|
|
|
assert(0 == rtpRtcpModule1->SendTelephoneEventOutband(32, 9000, 10));
|
|
|
|
for(;j <= 740;j++)
|
|
{
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,96, 160*j, test,8));
|
|
Sleep(20);
|
|
}
|
|
|
|
printf("Start Stereo test\n");
|
|
// test sample based multi channel codec, 3 channels 8 bits
|
|
WebRtc_UWord8 test3channels[15] = "ttteeesssttt";
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,98, 160*j, test3channels,12));
|
|
Sleep(20);
|
|
j++;
|
|
|
|
// test sample based multi channel codec, 3 channels 16 bits
|
|
const WebRtc_UWord8 test3channels16[13] = "teteteststst";
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,99, 160*j, test3channels16,12));
|
|
Sleep(20);
|
|
j++;
|
|
|
|
// test sample based multi channel codec, 3 channels 5 bits
|
|
test3channels[0] = 0xf8; // 5 ones 3 zeros
|
|
test3channels[1] = 0x2b; // 2 zeros 5 10 1 one
|
|
test3channels[2] = 0xf0; // 4 ones 4 zeros
|
|
test3channels[3] = 0x2b; // 1 zero 5 01 2 ones
|
|
test3channels[4] = 0xe0; // 3 ones 5 zeros
|
|
test3channels[5] = 0x0;
|
|
test3channels[6] = 0x0;
|
|
test3channels[7] = 0x0;
|
|
test3channels[8] = 0x0;
|
|
test3channels[9] = 0x0;
|
|
test3channels[10] = 0x0;
|
|
test3channels[11] = 0x0;
|
|
test3channels[12] = 0x0;
|
|
test3channels[13] = 0x0;
|
|
test3channels[14] = 0x0;
|
|
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,100, 160*j, test3channels,15));
|
|
Sleep(20);
|
|
j++;
|
|
|
|
// test sample based multi channel codec, 3 channels 3 bits
|
|
test3channels[0] = 0xe2; // 3 ones 3 zeros 2 10
|
|
test3channels[1] = 0xf0; // 1 1 3 ones 3 zeros 1 0
|
|
test3channels[2] = 0xb8; // 2 10 3 ones 3 zeros
|
|
test3channels[3] = 0xa0; // 3 101 5 zeros
|
|
test3channels[4] = 0x0;
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,101, 160*j, test3channels,15));
|
|
Sleep(20);
|
|
j++;
|
|
|
|
// test sample based multi channel codec, 3 channels 2 bits
|
|
test3channels[0] = 0xcb; // 2 ones 2 zeros 2 10 2 ones
|
|
test3channels[1] = 0x2c; // 2 zeros 2 10 2 ones 2 zeros
|
|
test3channels[2] = 0xb2; // 2 10 2 ones 2 zeros 2 10
|
|
test3channels[3] = 0xcb; // 2 ones 2 zeros 2 10 2 ones
|
|
test3channels[4] = 0x2c; // 2 zeros 2 10 2 ones 2 zeros
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,102, 160*j, test3channels,15));
|
|
Sleep(20);
|
|
j++;
|
|
|
|
for(;j <= 750;j++)
|
|
{
|
|
assert(0 == rtpRtcpModule1->SendOutgoingData(webrtc::kAudioFrameSpeech,96, 160*j, test,8));
|
|
Sleep(20);
|
|
}
|
|
|
|
printf("Long tone DTMF test done\n");
|
|
|
|
// start basic RTCP test
|
|
assert(0 == rtpRtcpModule1->SendRTCPReferencePictureSelection(12345678));
|
|
|
|
assert(0 == rtpRtcpModule1->SendRTCPSliceLossIndication(156));
|
|
|
|
testOfCSRC[0] = 0;
|
|
testOfCSRC[1] = 0;
|
|
assert( 2 == rtpRtcpModule2->RemoteCSRCs(testOfCSRC));
|
|
assert(arrOfCSRC[0] == testOfCSRC[0]);
|
|
assert(arrOfCSRC[1] == testOfCSRC[1]);
|
|
|
|
// set cname of mixed
|
|
assert( 0 == rtpRtcpModule1->AddMixedCNAME(arrOfCSRC[0], "john@192.168.0.1"));
|
|
assert( 0 == rtpRtcpModule1->AddMixedCNAME(arrOfCSRC[1], "jane@192.168.0.2"));
|
|
assert(-1 == rtpRtcpModule1->AddMixedCNAME(arrOfCSRC[0], NULL));
|
|
|
|
assert(-1 == rtpRtcpModule1->RemoveMixedCNAME(arrOfCSRC[0] + 1)); // not added
|
|
assert( 0 == rtpRtcpModule1->RemoveMixedCNAME(arrOfCSRC[1]));
|
|
assert( 0 == rtpRtcpModule1->AddMixedCNAME(arrOfCSRC[1], "jane@192.168.0.2"));
|
|
|
|
RTCPReportBlock reportBlock;
|
|
reportBlock.cumulativeLost = 1;
|
|
reportBlock.delaySinceLastSR = 2;
|
|
reportBlock.extendedHighSeqNum= 3;
|
|
reportBlock.fractionLost= 4;
|
|
reportBlock.jitter= 5;
|
|
reportBlock.lastSR= 6;
|
|
|
|
// set report blocks
|
|
assert(-1 == rtpRtcpModule1->AddRTCPReportBlock(arrOfCSRC[0], NULL));
|
|
assert( 0 == rtpRtcpModule1->AddRTCPReportBlock(arrOfCSRC[0], &reportBlock));
|
|
|
|
reportBlock.lastSR= 7;
|
|
assert(0 == rtpRtcpModule1->AddRTCPReportBlock(arrOfCSRC[1], &reportBlock));
|
|
|
|
WebRtc_UWord32 name = 't'<<24;
|
|
name += 'e'<<16;
|
|
name += 's'<<8;
|
|
name += 't';
|
|
assert(0 == rtpRtcpModule1->SetRTCPApplicationSpecificData(3,name,(const WebRtc_UWord8 *)"test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test ",300));
|
|
|
|
// send RTCP packet, triggered by timer
|
|
Sleep(8000);
|
|
|
|
WebRtc_UWord32 receivedNTPsecs = 0;
|
|
WebRtc_UWord32 receivedNTPfrac = 0;
|
|
WebRtc_UWord32 RTCPArrivalTimeSecs = 0;
|
|
WebRtc_UWord32 RTCPArrivalTimeFrac = 0;
|
|
|
|
assert(0 == rtpRtcpModule2->RemoteNTP(&receivedNTPsecs,
|
|
&receivedNTPfrac,
|
|
&RTCPArrivalTimeSecs,
|
|
&RTCPArrivalTimeFrac));
|
|
|
|
assert(-1 == rtpRtcpModule2->RemoteCNAME(rtpRtcpModule2->RemoteSSRC() + 1, cName)); // not received
|
|
assert(-1 == rtpRtcpModule2->RemoteCNAME(rtpRtcpModule2->RemoteSSRC(), NULL));
|
|
|
|
// check multiple CNAME
|
|
assert(0 == rtpRtcpModule2->RemoteCNAME(rtpRtcpModule2->RemoteSSRC(), cName));
|
|
assert(0 == strncmp(cName, "john.doe@test.test", RTCP_CNAME_SIZE));
|
|
|
|
assert(0 == rtpRtcpModule2->RemoteCNAME(arrOfCSRC[0], cName));
|
|
assert(0 == strncmp(cName, "john@192.168.0.1", RTCP_CNAME_SIZE));
|
|
|
|
assert(0 == rtpRtcpModule2->RemoteCNAME(arrOfCSRC[1], cName));
|
|
assert(0 == strncmp(cName, "jane@192.168.0.2", RTCP_CNAME_SIZE));
|
|
|
|
// get all report blocks
|
|
RTCPReportBlock reportBlockReceived;
|
|
|
|
assert(-1 == rtpRtcpModule1->RemoteRTCPStat(rtpRtcpModule1->RemoteSSRC() + 1, &reportBlockReceived)); // not received
|
|
assert(-1 == rtpRtcpModule1->RemoteRTCPStat(rtpRtcpModule1->RemoteSSRC(), NULL));
|
|
assert(0 == rtpRtcpModule1->RemoteRTCPStat(rtpRtcpModule1->RemoteSSRC(), &reportBlockReceived));
|
|
float secSinceLastReport = (float)reportBlockReceived.delaySinceLastSR/65536.0f;
|
|
assert( secSinceLastReport > 0.0f && secSinceLastReport < 7.5f); // audio RTCP max 7.5 sec
|
|
// startSeqNum + number of sent + number of extra due to DTMF
|
|
assert(2345+750+2+16 == reportBlockReceived.extendedHighSeqNum);
|
|
assert(0 == reportBlockReceived.fractionLost);
|
|
// we have dropped 10 packets but since we change codec it's reset
|
|
assert(0 == reportBlockReceived.cumulativeLost);
|
|
|
|
WebRtc_UWord8 fraction_lost = 0; // scale 0 to 255
|
|
WebRtc_UWord32 cum_lost = 0; // number of lost packets
|
|
WebRtc_UWord32 ext_max = 0; // highest sequence number received
|
|
WebRtc_UWord32 jitter = 0;
|
|
WebRtc_UWord32 max_jitter = 0;
|
|
assert(0 == rtpRtcpModule2->StatisticsRTP(&fraction_lost, &cum_lost, &ext_max, &jitter, &max_jitter));
|
|
assert(0 == fraction_lost);
|
|
assert(0 == cum_lost);
|
|
assert(2345+750+16+2 == ext_max);
|
|
assert(reportBlockReceived.jitter == jitter);
|
|
|
|
WebRtc_UWord16 RTT;
|
|
WebRtc_UWord16 avgRTT;
|
|
WebRtc_UWord16 minRTT;
|
|
WebRtc_UWord16 maxRTT;
|
|
|
|
// Get RoundTripTime
|
|
assert(0 == rtpRtcpModule1->RTT(rtpRtcpModule1->RemoteSSRC(),&RTT, &avgRTT, &minRTT, &maxRTT));
|
|
assert(RTT < 10);
|
|
assert(avgRTT < 10);
|
|
assert(minRTT < 10);
|
|
assert(minRTT > 0);
|
|
assert(maxRTT < 10);
|
|
|
|
/* since we filter out this in the receiver we can't get it
|
|
|
|
assert(0 == rtpRtcpModule2->RemoteRTCPStat(arrOfCSRC[0], &reportBlockReceived));
|
|
assert(reportBlock.cumulativeLost == reportBlockReceived.cumulativeLost);
|
|
assert(reportBlock.delaySinceLastSR == reportBlockReceived.delaySinceLastSR);
|
|
assert(reportBlock.extendedHighSeqNum == reportBlockReceived.extendedHighSeqNum);
|
|
assert(reportBlock.fractionLost == reportBlockReceived.fractionLost);
|
|
assert(reportBlock.jitter == reportBlockReceived.jitter);
|
|
assert(6 == reportBlockReceived.lastSR);
|
|
|
|
assert(0 == rtpRtcpModule2->RemoteRTCPStat(arrOfCSRC[1], &reportBlockReceived));
|
|
assert(reportBlock.cumulativeLost == reportBlockReceived.cumulativeLost);
|
|
assert(reportBlock.delaySinceLastSR == reportBlockReceived.delaySinceLastSR);
|
|
assert(reportBlock.extendedHighSeqNum == reportBlockReceived.extendedHighSeqNum);
|
|
assert(reportBlock.fractionLost == reportBlockReceived.fractionLost);
|
|
assert(reportBlock.jitter == reportBlockReceived.jitter);
|
|
assert(reportBlock.lastSR == reportBlockReceived.lastSR);
|
|
*/
|
|
// set report blocks
|
|
assert(0 == rtpRtcpModule1->AddRTCPReportBlock(arrOfCSRC[0], &reportBlock));
|
|
|
|
// test receive report
|
|
assert(0 == rtpRtcpModule1->SetSendingStatus(false));
|
|
|
|
// test that BYE clears the CNAME
|
|
assert(-1 == rtpRtcpModule2->RemoteCNAME(rtpRtcpModule2->RemoteSSRC(), cName));
|
|
|
|
// send RTCP packet, triggered by timer
|
|
Sleep(5000);
|
|
printf("\tBasic RTCP test done\n");
|
|
|
|
processThread->DeRegisterModule(rtpRtcpModule1);
|
|
processThread->DeRegisterModule(rtpRtcpModule2);
|
|
|
|
RtpRtcp::DestroyRtpRtcp(rtpRtcpModule1);
|
|
RtpRtcp::DestroyRtpRtcp(rtpRtcpModule2);
|
|
|
|
#endif // TEST_AUDIO
|
|
|
|
#ifdef TEST_VIDEO
|
|
|
|
// Test video
|
|
RtpRtcp* rtpRtcpModuleVideo = RtpRtcp::CreateRtpRtcp(myId,
|
|
false); // video
|
|
|
|
assert( 0 == rtpRtcpModuleVideo->InitReceiver());
|
|
assert( 0 == rtpRtcpModuleVideo->InitSender());
|
|
|
|
LoopBackTransportVideo* myLoopBackTransportVideo = new LoopBackTransportVideo(rtpRtcpModuleVideo);
|
|
assert(0 == rtpRtcpModuleVideo->RegisterSendTransport(myLoopBackTransportVideo));
|
|
|
|
DataReceiverVideo* myDataReceiverVideo = new DataReceiverVideo();
|
|
assert(0 == rtpRtcpModuleVideo->RegisterIncomingDataCallback(myDataReceiverVideo));
|
|
|
|
VideoFeedback* myVideoFeedback = new VideoFeedback();
|
|
assert(0 == rtpRtcpModuleVideo->RegisterIncomingVideoCallback(myVideoFeedback));
|
|
|
|
printf("Start video test\n");
|
|
WebRtc_UWord32 timestamp = 3000;
|
|
WebRtc_Word8 payloadNameVideo[RTP_PAYLOAD_NAME_SIZE] = "I420";
|
|
|
|
assert(0 == rtpRtcpModuleVideo->RegisterSendPayload(payloadNameVideo, 123));
|
|
assert(0 == rtpRtcpModuleVideo->RegisterReceivePayload(payloadNameVideo, 123));
|
|
|
|
_payloadDataFileLength = (WebRtc_UWord16)sizeof(_payloadDataFile);
|
|
|
|
for(int n = 0; n< _payloadDataFileLength; n++)
|
|
{
|
|
_payloadDataFile[n] = n%10;
|
|
}
|
|
|
|
printf("\tSending I420 frame. Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,123, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
|
|
memcpy(payloadNameVideo, "MP4V-ES", 8);
|
|
assert(0 == rtpRtcpModuleVideo->RegisterSendPayload(payloadNameVideo, 122));
|
|
assert(0 == rtpRtcpModuleVideo->RegisterReceivePayload(payloadNameVideo, 122));
|
|
|
|
// fake a MPEG-4 coded stream
|
|
for (int m = 500; m< _payloadDataFileLength; m+= 500)
|
|
{
|
|
// start codes
|
|
_payloadDataFile[m] = 0;
|
|
_payloadDataFile[m+1] = 0;
|
|
}
|
|
printf("\tSending MPEG-4 frame. Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,122, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
|
|
memcpy(payloadNameVideo, "H263-1998", 10);
|
|
assert(0 == rtpRtcpModuleVideo->RegisterSendPayload(payloadNameVideo, 124));
|
|
assert(0 == rtpRtcpModuleVideo->RegisterReceivePayload(payloadNameVideo, 124));
|
|
|
|
// Test send H.263 frame
|
|
FILE* openFile = fopen("H263_CIF_IFRAME.bin", "rb");
|
|
assert(openFile != NULL);
|
|
fseek(openFile, 0, SEEK_END);
|
|
_payloadDataFileLength = (WebRtc_Word16)(ftell(openFile));
|
|
rewind(openFile);
|
|
assert(_payloadDataFileLength > 0);
|
|
fread(_payloadDataFile, 1, _payloadDataFileLength, openFile);
|
|
fclose(openFile);
|
|
|
|
// send frame (1998/2000)
|
|
printf("\tSending H263(1998) frame. Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,124, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
|
|
memcpy(payloadNameVideo, "H263",5);
|
|
assert(0 == rtpRtcpModuleVideo->RegisterSendPayload(payloadNameVideo, 34));
|
|
assert(0 == rtpRtcpModuleVideo->RegisterReceivePayload(payloadNameVideo, 34));
|
|
|
|
timestamp += 3000;
|
|
|
|
// send frame
|
|
printf("\tSending H263 frame. Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,34, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
timestamp += 3000;
|
|
|
|
// lower MTU -> mode B
|
|
printf("\tSending H263 frame (MTU 300). Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SetMaxTransferUnit(300));
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,34, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
|
|
timestamp += 3000;
|
|
// get frame w/ non-byte aligned GOB headers
|
|
openFile = fopen("H263_QCIF_IFRAME.bin", "rb");
|
|
assert(openFile != NULL);
|
|
fseek(openFile, 0, SEEK_END);
|
|
_payloadDataFileLength = (WebRtc_Word16)(ftell(openFile));
|
|
rewind(openFile);
|
|
assert(_payloadDataFileLength > 0);
|
|
fread(_payloadDataFile, 1, _payloadDataFileLength, openFile);
|
|
fclose(openFile);
|
|
|
|
// send frame
|
|
printf("\tSending H263 frame (MTU 1500). Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SetMaxTransferUnit(1500));
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameKey,34, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
timestamp += 3000;
|
|
|
|
// lower MTU -> mode B
|
|
printf("\tSending H263 frame (MTU 300). Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SetMaxTransferUnit(300));
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameKey,34, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
timestamp += 3000;
|
|
|
|
openFile = fopen("H263_CIF_PFRAME.bin", "rb");
|
|
assert(openFile != NULL);
|
|
fseek(openFile, 0, SEEK_END);
|
|
_payloadDataFileLength = (WebRtc_Word16)(ftell(openFile));
|
|
rewind(openFile);
|
|
assert(_payloadDataFileLength > 0);
|
|
fread(_payloadDataFile, 1, _payloadDataFileLength, openFile);
|
|
fclose(openFile);
|
|
|
|
// test H.263 without all GOBs
|
|
assert(0 == rtpRtcpModuleVideo->SetMaxTransferUnit(1500));
|
|
printf("\tSending H263 frame without all GOBs (MTU 1500). Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,34, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
timestamp += 3000;
|
|
|
|
// test H.263 without all GOBs small MTU
|
|
assert(0 == rtpRtcpModuleVideo->SetMaxTransferUnit(500));
|
|
printf("\tSending H263 frame without all GOBs (MTU 500). Length: %d\n", _payloadDataFileLength);
|
|
assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameDelta,34, timestamp, _payloadDataFile, _payloadDataFileLength));
|
|
|
|
// test PLI with relay
|
|
assert(0 == rtpRtcpModuleVideo->RegisterIncomingVideoCallback(myVideoFeedback));
|
|
assert(0 == rtpRtcpModuleVideoReceiver->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp));
|
|
assert(0 == rtpRtcpModuleVideoReceiver->RequestKeyFrame());
|
|
|
|
|
|
processThread->DeRegisterModule(rtpRtcpModuleVideo);
|
|
processThread->DeRegisterModule(rtpRtcpModuleVideoReceiver);
|
|
processThread->Stop();
|
|
ProcessThread::DestroyProcessThread(processThread);
|
|
|
|
RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideoReceiver);
|
|
RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideoRelay);
|
|
RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideoRelay2);
|
|
RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideo);
|
|
#endif // TEST_VIDEO
|
|
|
|
printf("\nAPI test of RTP/RTCP module done\n");
|
|
|
|
#ifdef TEST_AUDIO
|
|
delete myLoopBackTransport1;
|
|
delete myLoopBackTransport2;
|
|
delete myDataReceiver1;
|
|
delete myDataReceiver2;
|
|
delete myRTCPFeedback1;
|
|
delete myRTCPFeedback2;
|
|
delete audioFeedback;
|
|
delete myRTPCallback;
|
|
#endif
|
|
#ifdef TEST_VIDEO
|
|
delete myLoopBackTransportVideo;
|
|
delete myVideoFeedback;
|
|
delete myDataReceiverVideo;
|
|
delete myRelayDataReceiver;
|
|
delete myRelaySender;
|
|
delete myRelayReceiver;
|
|
|
|
delete myRelaySender2;
|
|
delete myRelayReceiver2;
|
|
delete myRelayDataReceiver2;
|
|
delete myDataReceive2;
|
|
|
|
delete myRTCPFeedbackVideo;
|
|
delete myRTCPFeedbackRealy;
|
|
delete myRTCPFeedbackReceiver;
|
|
delete myRTCPFeedbackRealy2;
|
|
|
|
#endif // TEST_VIDEO
|
|
|
|
::Sleep(5000);
|
|
Trace::ReturnTrace();
|
|
return 0;
|
|
}
|
|
|