Fix dummy RTP playout in NetEqRTPplay

Make sure that playing dummy RTP files works, i.e., RTP dumps with only
headers, no actual payloads. It turs out that some RTP dumps did not
state how long the actual packet was (including the discarded payload),
which resulted in packets with zero length payload being inserted into
NetEQ. Now, the dummy packet will contain at least one byte of payload
(set to zero).

Also added capability to filter out a specific SSRC from the RTP
dump file.

Finally, added SSRC printout from RTPanalyze, and corresponding
change in RTPchange.

TEST=trybots

Review URL: https://webrtc-codereview.appspot.com/857007

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2876 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2012-10-05 08:34:37 +00:00
parent 3df18d72ba
commit 25fadd74d0
6 changed files with 68 additions and 19 deletions

View File

@ -14,6 +14,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <algorithm> // max
#ifdef WIN32 #ifdef WIN32
#include <winsock2.h> #include <winsock2.h>
#else #else
@ -56,17 +58,18 @@ int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
length = (WebRtc_UWord16) (length - _kRDHeaderLen); length = (WebRtc_UWord16) (length - _kRDHeaderLen);
// check buffer size // check buffer size
if (_datagram && _memSize < length) if (_datagram && _memSize < length + 1)
{ {
reset(); reset();
} }
if (!_datagram) if (!_datagram)
{ {
_datagram = new WebRtc_UWord8[length]; // Add one extra byte, to be able to fake a dummy payload of one byte.
_memSize = length; _datagram = new WebRtc_UWord8[length + 1];
_memSize = length + 1;
} }
memset(_datagram, 0, length); memset(_datagram, 0, length + 1);
if (length == 0) if (length == 0)
{ {
@ -75,7 +78,7 @@ int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
} }
// Read basic header // Read basic header
if (fread((unsigned short *) _datagram, 1, _kBasicHeaderLen, fp) if (fread(_datagram, 1, _kBasicHeaderLen, fp)
!= (size_t)_kBasicHeaderLen) != (size_t)_kBasicHeaderLen)
{ {
reset(); reset();
@ -83,6 +86,7 @@ int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
} }
_receiveTime = receiveTime; _receiveTime = receiveTime;
_datagramLen = _kBasicHeaderLen; _datagramLen = _kBasicHeaderLen;
int header_length = _kBasicHeaderLen;
// Parse the basic header // Parse the basic header
WebRtcNetEQ_RTPInfo tempRTPinfo; WebRtcNetEQ_RTPInfo tempRTPinfo;
@ -93,17 +97,18 @@ int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
if (X != 0 || CC != 0) if (X != 0 || CC != 0)
{ {
int newLen = _kBasicHeaderLen + CC * 4 + X * 4; int newLen = _kBasicHeaderLen + CC * 4 + X * 4;
assert(_memSize >= newLen); assert(_memSize >= newLen + 1);
// Read extension from file // Read extension from file
size_t readLen = newLen - _kBasicHeaderLen; size_t readLen = newLen - _kBasicHeaderLen;
if (fread((unsigned short *) _datagram + _kBasicHeaderLen, 1, readLen, if (fread(_datagram + _kBasicHeaderLen, 1, readLen,
fp) != readLen) fp) != readLen)
{ {
reset(); reset();
return -1; return -1;
} }
_datagramLen = newLen; _datagramLen = newLen;
header_length = newLen;
if (X != 0) if (X != 0)
{ {
@ -112,16 +117,19 @@ int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
// Read extension from file // Read extension from file
size_t readLen = totHdrLen - newLen; size_t readLen = totHdrLen - newLen;
if (fread((unsigned short *) _datagram + newLen, 1, readLen, fp) if (fread(_datagram + newLen, 1, readLen, fp)
!= readLen) != readLen)
{ {
reset(); reset();
return -1; return -1;
} }
_datagramLen = totHdrLen; _datagramLen = totHdrLen;
header_length = totHdrLen;
} }
} }
_datagramLen = length; // Make sure that we have at least one byte of dummy payload.
_datagramLen = std::max(static_cast<int>(length), header_length + 1);
assert(_datagramLen <= _memSize);
if (!_blockList.empty() && _blockList.count(payloadType()) > 0) if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
{ {
@ -129,6 +137,12 @@ int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
return readFromFile(fp); return readFromFile(fp);
} }
if (_filterSSRC && _selectSSRC != SSRC())
{
// Discard this payload.
return(readFromFile(fp));
}
return packetLen; return packetLen;
} }

View File

@ -32,7 +32,9 @@ _datagramLen(-1),
_payloadLen(0), _payloadLen(0),
_rtpParsed(false), _rtpParsed(false),
_receiveTime(0), _receiveTime(0),
_lost(false) _lost(false),
_selectSSRC(0),
_filterSSRC(false)
{ {
memset(&_rtpInfo, 0, sizeof(_rtpInfo)); memset(&_rtpInfo, 0, sizeof(_rtpInfo));
_blockList.clear(); _blockList.clear();
@ -157,6 +159,12 @@ int NETEQTEST_RTPpacket::readFromFile(FILE *fp)
return(readFromFile(fp)); return(readFromFile(fp));
} }
if (_filterSSRC && _selectSSRC != SSRC())
{
// Discard this payload.
return(readFromFile(fp));
}
return(packetLen); return(packetLen);
} }
@ -250,6 +258,11 @@ void NETEQTEST_RTPpacket::blockPT(WebRtc_UWord8 pt)
_blockList[pt] = true; _blockList[pt] = true;
} }
void NETEQTEST_RTPpacket::selectSSRC(uint32_t ssrc)
{
_selectSSRC = ssrc;
_filterSSRC = true;
}
void NETEQTEST_RTPpacket::parseHeader() void NETEQTEST_RTPpacket::parseHeader()
{ {

View File

@ -36,6 +36,7 @@ public:
int readFixedFromFile(FILE *fp, size_t len); int readFixedFromFile(FILE *fp, size_t len);
virtual int writeToFile(FILE *fp); virtual int writeToFile(FILE *fp);
void blockPT(WebRtc_UWord8 pt); void blockPT(WebRtc_UWord8 pt);
void selectSSRC(uint32_t ssrc);
//WebRtc_Word16 payloadType(); //WebRtc_Word16 payloadType();
void parseHeader(); void parseHeader();
void parseHeader(WebRtcNetEQ_RTPInfo & rtpInfo); void parseHeader(WebRtcNetEQ_RTPInfo & rtpInfo);
@ -79,6 +80,8 @@ public:
WebRtc_UWord32 _receiveTime; WebRtc_UWord32 _receiveTime;
bool _lost; bool _lost;
std::map<WebRtc_UWord8, bool> _blockList; std::map<WebRtc_UWord8, bool> _blockList;
uint32_t _selectSSRC;
bool _filterSSRC;
protected: protected:
static const int _kRDHeaderLen; static const int _kRDHeaderLen;

View File

@ -185,6 +185,8 @@ int main(int argc, char* argv[])
std::map<WebRtc_UWord8, decoderStruct> decoders; std::map<WebRtc_UWord8, decoderStruct> decoders;
bool dummyRtp = false; bool dummyRtp = false;
bool noDecode = false; bool noDecode = false;
bool filterSSRC = false;
uint32_t ssrc;
#ifdef DEF_BUILD_DATE #ifdef DEF_BUILD_DATE
printf("Build time: %s\n", __BUILD_DATE); printf("Build time: %s\n", __BUILD_DATE);
@ -224,6 +226,7 @@ int main(int argc, char* argv[])
printf("\t-rtponly packLenBytes : input file consists of constant size RTP packets without RTPplay headers\n"); printf("\t-rtponly packLenBytes : input file consists of constant size RTP packets without RTPplay headers\n");
printf("\t-dummyrtp : input file contains only RTP headers\n"); printf("\t-dummyrtp : input file contains only RTP headers\n");
printf("\t-nodecode : no decoding will be done\n"); printf("\t-nodecode : no decoding will be done\n");
printf("\t-ssrc 0xNNNNNNNN : discard all other SSRCs\n");
//printf("\t-switchms : switch from mono to stereo (copy channel) after 10 seconds\n"); //printf("\t-switchms : switch from mono to stereo (copy channel) after 10 seconds\n");
//printf("\t-duplicate : use two instances with identical input (2-channel mono)\n"); //printf("\t-duplicate : use two instances with identical input (2-channel mono)\n");
@ -321,6 +324,17 @@ int main(int argc, char* argv[])
argIx++; argIx++;
noDecode = true; noDecode = true;
} }
else if (strcmp(argv[argIx], "-ssrc") == 0)
{
argIx++;
filterSSRC = true;
if (sscanf(argv[argIx], "%X", &ssrc) != 1)
{
printf("Could not read SSRC argument.\n");
exit(1);
}
argIx++;
}
//else if( strcmp(argv[argIx], "-switchms") == 0 ) { //else if( strcmp(argv[argIx], "-switchms") == 0 ) {
// argIx++; // argIx++;
// switchMS = true; // switchMS = true;
@ -407,6 +421,15 @@ int main(int argc, char* argv[])
slaveRtp = new NETEQTEST_DummyRTPpacket(); slaveRtp = new NETEQTEST_DummyRTPpacket();
} }
/* Uncomment and edit the line(s) below to block some payload types. */
//rtp->blockPT(72);
//rtp->blockPT(23);
/* Select a specific SSRC. */
if (filterSSRC) {
rtp->selectSSRC(ssrc);
}
if (!rtpOnly) if (!rtpOnly)
{ {
while (rtp->readFromFile(in_file) >= 0) while (rtp->readFromFile(in_file) >= 0)
@ -440,11 +463,6 @@ int main(int argc, char* argv[])
fseek(in_file, tempFilePos, SEEK_SET /* from beginning */); fseek(in_file, tempFilePos, SEEK_SET /* from beginning */);
/* block some payload types */
//rtp->blockPT(72);
//rtp->blockPT(23);
/* read first packet */ /* read first packet */
if (!rtpOnly) if (!rtpOnly)
{ {

View File

@ -37,7 +37,7 @@ int main(int argc, char* argv[]) {
printf("Output file: %s\n\n", argv[2]); printf("Output file: %s\n\n", argv[2]);
// Print file header. // Print file header.
fprintf(out_file, "SeqNo TimeStamp SendTime Size PT M\n"); fprintf(out_file, "SeqNo TimeStamp SendTime Size PT M SSRC\n");
// Read file header. // Read file header.
NETEQTEST_RTPpacket::skipFileHeader(in_file); NETEQTEST_RTPpacket::skipFileHeader(in_file);
@ -49,9 +49,10 @@ int main(int argc, char* argv[]) {
while (packet.readFromFile(in_file) >= 0) { while (packet.readFromFile(in_file) >= 0) {
// Write packet data to file. // Write packet data to file.
fprintf(out_file, "%5u %10u %10u %5i %5i %2i\n", fprintf(out_file, "%5u %10u %10u %5i %5i %2i %#08X\n",
packet.sequenceNumber(), packet.timeStamp(), packet.time(), packet.sequenceNumber(), packet.timeStamp(), packet.time(),
packet.dataLen(), packet.payloadType(), packet.markerBit()); packet.dataLen(), packet.payloadType(), packet.markerBit(),
packet.SSRC());
if (packet.payloadType() == kRedPayloadType) { if (packet.payloadType() == kRedPayloadType) {
WebRtcNetEQ_RTPInfo red_header; WebRtcNetEQ_RTPInfo red_header;
int len; int len;

View File

@ -59,7 +59,7 @@ int main(int argc, char* argv[]) {
uint32_t send_time; uint32_t send_time;
while (fscanf(stat_file, while (fscanf(stat_file,
"%hu %u %u %*i %*i\n", &seq_no, &ts, &send_time) == 3) { "%hu %u %u %*i %*i %*i %*x\n", &seq_no, &ts, &send_time) == 3) {
std::pair<uint16_t, uint32_t> std::pair<uint16_t, uint32_t>
temp_pair = std::pair<uint16_t, uint32_t>(seq_no, ts); temp_pair = std::pair<uint16_t, uint32_t>(seq_no, ts);