Rename neteq4 folder to neteq
Keep the old neteq4/audio_decoder_unittests.isolate while waiting for a hard-coded reference to change. This CL effectively reverts r6257 "Rename neteq4 folder to neteq". BUG=2996 TBR=tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/21629004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6367 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 "NETEQTEST_DummyRTPpacket.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <netinet/in.h> // for htons, htonl, etc
|
||||
#endif
|
||||
|
||||
int NETEQTEST_DummyRTPpacket::readFromFile(FILE *fp)
|
||||
{
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t length, plen;
|
||||
uint32_t offset;
|
||||
int packetLen;
|
||||
|
||||
bool readNextPacket = true;
|
||||
while (readNextPacket) {
|
||||
readNextPacket = false;
|
||||
if (fread(&length, 2, 1, fp) == 0)
|
||||
{
|
||||
reset();
|
||||
return -2;
|
||||
}
|
||||
length = ntohs(length);
|
||||
|
||||
if (fread(&plen, 2, 1, fp) == 0)
|
||||
{
|
||||
reset();
|
||||
return -1;
|
||||
}
|
||||
packetLen = ntohs(plen);
|
||||
|
||||
if (fread(&offset, 4, 1, fp) == 0)
|
||||
{
|
||||
reset();
|
||||
return -1;
|
||||
}
|
||||
// Store in local variable until we have passed the reset below.
|
||||
uint32_t receiveTime = ntohl(offset);
|
||||
|
||||
// Use length here because a plen of 0 specifies rtcp.
|
||||
length = (uint16_t) (length - _kRDHeaderLen);
|
||||
|
||||
// check buffer size
|
||||
if (_datagram && _memSize < length + 1)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
if (!_datagram)
|
||||
{
|
||||
// Add one extra byte, to be able to fake a dummy payload of 1 byte.
|
||||
_datagram = new uint8_t[length + 1];
|
||||
_memSize = length + 1;
|
||||
}
|
||||
memset(_datagram, 0, length + 1);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
_datagramLen = 0;
|
||||
_rtpParsed = false;
|
||||
return packetLen;
|
||||
}
|
||||
|
||||
// Read basic header
|
||||
if (fread((unsigned short *) _datagram, 1, _kBasicHeaderLen, fp)
|
||||
!= (size_t)_kBasicHeaderLen)
|
||||
{
|
||||
reset();
|
||||
return -1;
|
||||
}
|
||||
_receiveTime = receiveTime;
|
||||
_datagramLen = _kBasicHeaderLen;
|
||||
|
||||
// Parse the basic header
|
||||
webrtc::WebRtcRTPHeader tempRTPinfo;
|
||||
int P, X, CC;
|
||||
parseBasicHeader(&tempRTPinfo, &P, &X, &CC);
|
||||
|
||||
// Check if we have to extend the header
|
||||
if (X != 0 || CC != 0)
|
||||
{
|
||||
int newLen = _kBasicHeaderLen + CC * 4 + X * 4;
|
||||
assert(_memSize >= newLen);
|
||||
|
||||
// Read extension from file
|
||||
size_t readLen = newLen - _kBasicHeaderLen;
|
||||
if (fread(&_datagram[_kBasicHeaderLen], 1, readLen, fp) != readLen)
|
||||
{
|
||||
reset();
|
||||
return -1;
|
||||
}
|
||||
_datagramLen = newLen;
|
||||
|
||||
if (X != 0)
|
||||
{
|
||||
int totHdrLen = calcHeaderLength(X, CC);
|
||||
assert(_memSize >= totHdrLen);
|
||||
|
||||
// Read extension from file
|
||||
size_t readLen = totHdrLen - newLen;
|
||||
if (fread(&_datagram[newLen], 1, readLen, fp) != readLen)
|
||||
{
|
||||
reset();
|
||||
return -1;
|
||||
}
|
||||
_datagramLen = totHdrLen;
|
||||
}
|
||||
}
|
||||
_datagramLen = length;
|
||||
|
||||
if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
|
||||
{
|
||||
readNextPacket = true;
|
||||
}
|
||||
}
|
||||
|
||||
_rtpParsed = false;
|
||||
assert(_memSize > _datagramLen);
|
||||
_payloadLen = 1; // Set the length to 1 byte.
|
||||
return packetLen;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_DummyRTPpacket::writeToFile(FILE *fp)
|
||||
{
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t length, plen;
|
||||
uint32_t offset;
|
||||
|
||||
// length including RTPplay header
|
||||
length = htons(_datagramLen + _kRDHeaderLen);
|
||||
if (fwrite(&length, 2, 1, fp) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// payload length
|
||||
plen = htons(_datagramLen);
|
||||
if (fwrite(&plen, 2, 1, fp) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// offset (=receive time)
|
||||
offset = htonl(_receiveTime);
|
||||
if (fwrite(&offset, 4, 1, fp) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Figure out the length of the RTP header.
|
||||
int headerLen;
|
||||
if (_datagramLen == 0)
|
||||
{
|
||||
// No payload at all; we are done writing to file.
|
||||
headerLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
parseHeader();
|
||||
headerLen = _payloadPtr - _datagram;
|
||||
assert(headerLen >= 0);
|
||||
}
|
||||
|
||||
// write RTP header
|
||||
if (fwrite((unsigned short *) _datagram, 1, headerLen, fp) !=
|
||||
static_cast<size_t>(headerLen))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (headerLen + _kRDHeaderLen); // total number of bytes written
|
||||
|
||||
}
|
||||
|
||||
void NETEQTEST_DummyRTPpacket::parseHeader() {
|
||||
NETEQTEST_RTPpacket::parseHeader();
|
||||
// Change _payloadLen to 1 byte. The memory should always be big enough.
|
||||
assert(_memSize > _datagramLen);
|
||||
_payloadLen = 1;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef NETEQTEST_DUMMYRTPPACKET_H
|
||||
#define NETEQTEST_DUMMYRTPPACKET_H
|
||||
|
||||
#include "NETEQTEST_RTPpacket.h"
|
||||
|
||||
class NETEQTEST_DummyRTPpacket : public NETEQTEST_RTPpacket {
|
||||
public:
|
||||
virtual int readFromFile(FILE* fp) OVERRIDE;
|
||||
virtual int writeToFile(FILE* fp) OVERRIDE;
|
||||
virtual void parseHeader() OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // NETEQTEST_DUMMYRTPPACKET_H
|
||||
875
webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc
Normal file
875
webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc
Normal file
@ -0,0 +1,875 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 "NETEQTEST_RTPpacket.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h> // rand
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <netinet/in.h> // for htons, htonl, etc
|
||||
#endif
|
||||
|
||||
const int NETEQTEST_RTPpacket::_kRDHeaderLen = 8;
|
||||
const int NETEQTEST_RTPpacket::_kBasicHeaderLen = 12;
|
||||
|
||||
NETEQTEST_RTPpacket::NETEQTEST_RTPpacket()
|
||||
:
|
||||
_datagram(NULL),
|
||||
_payloadPtr(NULL),
|
||||
_memSize(0),
|
||||
_datagramLen(-1),
|
||||
_payloadLen(0),
|
||||
_rtpParsed(false),
|
||||
_receiveTime(0),
|
||||
_lost(false)
|
||||
{
|
||||
memset(&_rtpInfo, 0, sizeof(_rtpInfo));
|
||||
_blockList.clear();
|
||||
}
|
||||
|
||||
NETEQTEST_RTPpacket::~NETEQTEST_RTPpacket()
|
||||
{
|
||||
if(_datagram)
|
||||
{
|
||||
delete [] _datagram;
|
||||
}
|
||||
}
|
||||
|
||||
void NETEQTEST_RTPpacket::reset()
|
||||
{
|
||||
if(_datagram) {
|
||||
delete [] _datagram;
|
||||
}
|
||||
_datagram = NULL;
|
||||
_memSize = 0;
|
||||
_datagramLen = -1;
|
||||
_payloadLen = 0;
|
||||
_payloadPtr = NULL;
|
||||
_receiveTime = 0;
|
||||
memset(&_rtpInfo, 0, sizeof(_rtpInfo));
|
||||
_rtpParsed = false;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::skipFileHeader(FILE *fp)
|
||||
{
|
||||
if (!fp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int kFirstLineLength = 40;
|
||||
char firstline[kFirstLineLength];
|
||||
if (fgets(firstline, kFirstLineLength, fp) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(firstline, "#!rtpplay", 9) == 0) {
|
||||
if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
|
||||
if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
|
||||
if (fseek(fp, kRtpDumpHeaderSize, SEEK_CUR) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::readFromFile(FILE *fp)
|
||||
{
|
||||
if(!fp)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
uint16_t length, plen;
|
||||
uint32_t offset;
|
||||
int packetLen;
|
||||
|
||||
bool readNextPacket = true;
|
||||
while (readNextPacket) {
|
||||
readNextPacket = false;
|
||||
if (fread(&length,2,1,fp)==0)
|
||||
{
|
||||
reset();
|
||||
return(-2);
|
||||
}
|
||||
length = ntohs(length);
|
||||
|
||||
if (fread(&plen,2,1,fp)==0)
|
||||
{
|
||||
reset();
|
||||
return(-1);
|
||||
}
|
||||
packetLen = ntohs(plen);
|
||||
|
||||
if (fread(&offset,4,1,fp)==0)
|
||||
{
|
||||
reset();
|
||||
return(-1);
|
||||
}
|
||||
// store in local variable until we have passed the reset below
|
||||
uint32_t receiveTime = ntohl(offset);
|
||||
|
||||
// Use length here because a plen of 0 specifies rtcp
|
||||
length = (uint16_t) (length - _kRDHeaderLen);
|
||||
|
||||
// check buffer size
|
||||
if (_datagram && _memSize < length)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
if (!_datagram)
|
||||
{
|
||||
_datagram = new uint8_t[length];
|
||||
_memSize = length;
|
||||
}
|
||||
|
||||
if (fread((unsigned short *) _datagram,1,length,fp) != length)
|
||||
{
|
||||
reset();
|
||||
return(-1);
|
||||
}
|
||||
|
||||
_datagramLen = length;
|
||||
_receiveTime = receiveTime;
|
||||
|
||||
if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
|
||||
{
|
||||
readNextPacket = true;
|
||||
}
|
||||
}
|
||||
|
||||
_rtpParsed = false;
|
||||
return(packetLen);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int NETEQTEST_RTPpacket::readFixedFromFile(FILE *fp, size_t length)
|
||||
{
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check buffer size
|
||||
if (_datagram && _memSize < static_cast<int>(length))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
if (!_datagram)
|
||||
{
|
||||
_datagram = new uint8_t[length];
|
||||
_memSize = length;
|
||||
}
|
||||
|
||||
if (fread(_datagram, 1, length, fp) != length)
|
||||
{
|
||||
reset();
|
||||
return -1;
|
||||
}
|
||||
|
||||
_datagramLen = length;
|
||||
_receiveTime = 0;
|
||||
|
||||
if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
|
||||
{
|
||||
// discard this payload
|
||||
return readFromFile(fp);
|
||||
}
|
||||
|
||||
_rtpParsed = false;
|
||||
return length;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int NETEQTEST_RTPpacket::writeToFile(FILE *fp)
|
||||
{
|
||||
if (!fp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t length, plen;
|
||||
uint32_t offset;
|
||||
|
||||
// length including RTPplay header
|
||||
length = htons(_datagramLen + _kRDHeaderLen);
|
||||
if (fwrite(&length, 2, 1, fp) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// payload length
|
||||
plen = htons(_datagramLen);
|
||||
if (fwrite(&plen, 2, 1, fp) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// offset (=receive time)
|
||||
offset = htonl(_receiveTime);
|
||||
if (fwrite(&offset, 4, 1, fp) != 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// write packet data
|
||||
if (fwrite(_datagram, 1, _datagramLen, fp) !=
|
||||
static_cast<size_t>(_datagramLen))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _datagramLen + _kRDHeaderLen; // total number of bytes written
|
||||
|
||||
}
|
||||
|
||||
|
||||
void NETEQTEST_RTPpacket::blockPT(uint8_t pt)
|
||||
{
|
||||
_blockList[pt] = true;
|
||||
}
|
||||
|
||||
|
||||
void NETEQTEST_RTPpacket::parseHeader()
|
||||
{
|
||||
if (_rtpParsed)
|
||||
{
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if (_datagramLen < _kBasicHeaderLen)
|
||||
{
|
||||
// corrupt packet?
|
||||
return;
|
||||
}
|
||||
|
||||
_payloadLen = parseRTPheader(&_payloadPtr);
|
||||
|
||||
_rtpParsed = true;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void NETEQTEST_RTPpacket::parseHeader(webrtc::WebRtcRTPHeader* rtp_header) {
|
||||
if (!_rtpParsed) {
|
||||
parseHeader();
|
||||
}
|
||||
if (rtp_header) {
|
||||
rtp_header->header.markerBit = _rtpInfo.header.markerBit;
|
||||
rtp_header->header.payloadType = _rtpInfo.header.payloadType;
|
||||
rtp_header->header.sequenceNumber = _rtpInfo.header.sequenceNumber;
|
||||
rtp_header->header.timestamp = _rtpInfo.header.timestamp;
|
||||
rtp_header->header.ssrc = _rtpInfo.header.ssrc;
|
||||
}
|
||||
}
|
||||
|
||||
const webrtc::WebRtcRTPHeader* NETEQTEST_RTPpacket::RTPinfo() const
|
||||
{
|
||||
if (_rtpParsed)
|
||||
{
|
||||
return &_rtpInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * NETEQTEST_RTPpacket::datagram() const
|
||||
{
|
||||
if (_datagramLen > 0)
|
||||
{
|
||||
return _datagram;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * NETEQTEST_RTPpacket::payload() const
|
||||
{
|
||||
if (_payloadLen > 0)
|
||||
{
|
||||
return _payloadPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t NETEQTEST_RTPpacket::payloadLen()
|
||||
{
|
||||
parseHeader();
|
||||
return _payloadLen;
|
||||
}
|
||||
|
||||
int16_t NETEQTEST_RTPpacket::dataLen() const
|
||||
{
|
||||
return _datagramLen;
|
||||
}
|
||||
|
||||
bool NETEQTEST_RTPpacket::isParsed() const
|
||||
{
|
||||
return _rtpParsed;
|
||||
}
|
||||
|
||||
bool NETEQTEST_RTPpacket::isLost() const
|
||||
{
|
||||
return _lost;
|
||||
}
|
||||
|
||||
uint8_t NETEQTEST_RTPpacket::payloadType() const
|
||||
{
|
||||
webrtc::WebRtcRTPHeader tempRTPinfo;
|
||||
|
||||
if(_datagram && _datagramLen >= _kBasicHeaderLen)
|
||||
{
|
||||
parseRTPheader(&tempRTPinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tempRTPinfo.header.payloadType;
|
||||
}
|
||||
|
||||
uint16_t NETEQTEST_RTPpacket::sequenceNumber() const
|
||||
{
|
||||
webrtc::WebRtcRTPHeader tempRTPinfo;
|
||||
|
||||
if(_datagram && _datagramLen >= _kBasicHeaderLen)
|
||||
{
|
||||
parseRTPheader(&tempRTPinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tempRTPinfo.header.sequenceNumber;
|
||||
}
|
||||
|
||||
uint32_t NETEQTEST_RTPpacket::timeStamp() const
|
||||
{
|
||||
webrtc::WebRtcRTPHeader tempRTPinfo;
|
||||
|
||||
if(_datagram && _datagramLen >= _kBasicHeaderLen)
|
||||
{
|
||||
parseRTPheader(&tempRTPinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tempRTPinfo.header.timestamp;
|
||||
}
|
||||
|
||||
uint32_t NETEQTEST_RTPpacket::SSRC() const
|
||||
{
|
||||
webrtc::WebRtcRTPHeader tempRTPinfo;
|
||||
|
||||
if(_datagram && _datagramLen >= _kBasicHeaderLen)
|
||||
{
|
||||
parseRTPheader(&tempRTPinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tempRTPinfo.header.ssrc;
|
||||
}
|
||||
|
||||
uint8_t NETEQTEST_RTPpacket::markerBit() const
|
||||
{
|
||||
webrtc::WebRtcRTPHeader tempRTPinfo;
|
||||
|
||||
if(_datagram && _datagramLen >= _kBasicHeaderLen)
|
||||
{
|
||||
parseRTPheader(&tempRTPinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tempRTPinfo.header.markerBit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int NETEQTEST_RTPpacket::setPayloadType(uint8_t pt)
|
||||
{
|
||||
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_rtpParsed)
|
||||
{
|
||||
_rtpInfo.header.payloadType = pt;
|
||||
}
|
||||
|
||||
_datagram[1]=(unsigned char)(pt & 0xFF);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::setSequenceNumber(uint16_t sn)
|
||||
{
|
||||
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_rtpParsed)
|
||||
{
|
||||
_rtpInfo.header.sequenceNumber = sn;
|
||||
}
|
||||
|
||||
_datagram[2]=(unsigned char)((sn>>8)&0xFF);
|
||||
_datagram[3]=(unsigned char)((sn)&0xFF);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::setTimeStamp(uint32_t ts)
|
||||
{
|
||||
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_rtpParsed)
|
||||
{
|
||||
_rtpInfo.header.timestamp = ts;
|
||||
}
|
||||
|
||||
_datagram[4]=(unsigned char)((ts>>24)&0xFF);
|
||||
_datagram[5]=(unsigned char)((ts>>16)&0xFF);
|
||||
_datagram[6]=(unsigned char)((ts>>8)&0xFF);
|
||||
_datagram[7]=(unsigned char)(ts & 0xFF);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::setSSRC(uint32_t ssrc)
|
||||
{
|
||||
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_rtpParsed)
|
||||
{
|
||||
_rtpInfo.header.ssrc = ssrc;
|
||||
}
|
||||
|
||||
_datagram[8]=(unsigned char)((ssrc>>24)&0xFF);
|
||||
_datagram[9]=(unsigned char)((ssrc>>16)&0xFF);
|
||||
_datagram[10]=(unsigned char)((ssrc>>8)&0xFF);
|
||||
_datagram[11]=(unsigned char)(ssrc & 0xFF);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::setMarkerBit(uint8_t mb)
|
||||
{
|
||||
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_rtpParsed)
|
||||
{
|
||||
_rtpInfo.header.markerBit = mb;
|
||||
}
|
||||
|
||||
if (mb)
|
||||
{
|
||||
_datagram[0] |= 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
_datagram[0] &= 0xFE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::setRTPheader(const webrtc::WebRtcRTPHeader* RTPinfo)
|
||||
{
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
// this packet is not ok
|
||||
return -1;
|
||||
}
|
||||
|
||||
makeRTPheader(_datagram,
|
||||
RTPinfo->header.payloadType,
|
||||
RTPinfo->header.sequenceNumber,
|
||||
RTPinfo->header.timestamp,
|
||||
RTPinfo->header.ssrc,
|
||||
RTPinfo->header.markerBit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int NETEQTEST_RTPpacket::splitStereo(NETEQTEST_RTPpacket* slaveRtp,
|
||||
enum stereoModes mode)
|
||||
{
|
||||
// if mono, do nothing
|
||||
if (mode == stereoModeMono)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check that the RTP header info is parsed
|
||||
parseHeader();
|
||||
|
||||
// start by copying the main rtp packet
|
||||
*slaveRtp = *this;
|
||||
|
||||
if(_payloadLen == 0)
|
||||
{
|
||||
// do no more
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(_payloadLen%2 != 0)
|
||||
{
|
||||
// length must be a factor of 2
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case stereoModeSample1:
|
||||
{
|
||||
// sample based codec with 1-byte samples
|
||||
splitStereoSample(slaveRtp, 1 /* 1 byte/sample */);
|
||||
break;
|
||||
}
|
||||
case stereoModeSample2:
|
||||
{
|
||||
// sample based codec with 2-byte samples
|
||||
splitStereoSample(slaveRtp, 2 /* 2 bytes/sample */);
|
||||
break;
|
||||
}
|
||||
case stereoModeFrame:
|
||||
{
|
||||
// frame based codec
|
||||
splitStereoFrame(slaveRtp);
|
||||
break;
|
||||
}
|
||||
case stereoModeDuplicate:
|
||||
{
|
||||
// frame based codec, send the whole packet to both master and slave
|
||||
splitStereoDouble(slaveRtp);
|
||||
break;
|
||||
}
|
||||
case stereoModeMono:
|
||||
{
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void NETEQTEST_RTPpacket::makeRTPheader(unsigned char* rtp_data, uint8_t payloadType, uint16_t seqNo, uint32_t timestamp, uint32_t ssrc, uint8_t markerBit) const
|
||||
{
|
||||
rtp_data[0]=(unsigned char)0x80;
|
||||
if (markerBit)
|
||||
{
|
||||
rtp_data[0] |= 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtp_data[0] &= 0xFE;
|
||||
}
|
||||
rtp_data[1]=(unsigned char)(payloadType & 0xFF);
|
||||
rtp_data[2]=(unsigned char)((seqNo>>8)&0xFF);
|
||||
rtp_data[3]=(unsigned char)((seqNo)&0xFF);
|
||||
rtp_data[4]=(unsigned char)((timestamp>>24)&0xFF);
|
||||
rtp_data[5]=(unsigned char)((timestamp>>16)&0xFF);
|
||||
|
||||
rtp_data[6]=(unsigned char)((timestamp>>8)&0xFF);
|
||||
rtp_data[7]=(unsigned char)(timestamp & 0xFF);
|
||||
|
||||
rtp_data[8]=(unsigned char)((ssrc>>24)&0xFF);
|
||||
rtp_data[9]=(unsigned char)((ssrc>>16)&0xFF);
|
||||
|
||||
rtp_data[10]=(unsigned char)((ssrc>>8)&0xFF);
|
||||
rtp_data[11]=(unsigned char)(ssrc & 0xFF);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
NETEQTEST_RTPpacket::parseRTPheader(webrtc::WebRtcRTPHeader* RTPinfo,
|
||||
uint8_t **payloadPtr) const
|
||||
{
|
||||
int16_t *rtp_data = (int16_t *) _datagram;
|
||||
int i_P, i_X, i_CC;
|
||||
|
||||
assert(_datagramLen >= 12);
|
||||
parseBasicHeader(RTPinfo, &i_P, &i_X, &i_CC);
|
||||
|
||||
int i_startPosition = calcHeaderLength(i_X, i_CC);
|
||||
|
||||
int i_padlength = calcPadLength(i_P);
|
||||
|
||||
if (payloadPtr)
|
||||
{
|
||||
*payloadPtr = (uint8_t*) &rtp_data[i_startPosition >> 1];
|
||||
}
|
||||
|
||||
return (uint16_t) (_datagramLen - i_startPosition - i_padlength);
|
||||
}
|
||||
|
||||
|
||||
void NETEQTEST_RTPpacket::parseBasicHeader(webrtc::WebRtcRTPHeader* RTPinfo,
|
||||
int *i_P, int *i_X, int *i_CC) const
|
||||
{
|
||||
int16_t *rtp_data = (int16_t *) _datagram;
|
||||
if (_datagramLen < 12)
|
||||
{
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
*i_P=(((uint16_t)(rtp_data[0] & 0x20))>>5); /* Extract the P bit */
|
||||
*i_X=(((uint16_t)(rtp_data[0] & 0x10))>>4); /* Extract the X bit */
|
||||
*i_CC=(uint16_t)(rtp_data[0] & 0xF); /* Get the CC number */
|
||||
/* Get the marker bit */
|
||||
RTPinfo->header.markerBit = (uint8_t) ((rtp_data[0] >> 15) & 0x01);
|
||||
/* Get the coder type */
|
||||
RTPinfo->header.payloadType = (uint8_t) ((rtp_data[0] >> 8) & 0x7F);
|
||||
/* Get the packet number */
|
||||
RTPinfo->header.sequenceNumber =
|
||||
((( ((uint16_t)rtp_data[1]) >> 8) & 0xFF) |
|
||||
( ((uint16_t)(rtp_data[1] & 0xFF)) << 8));
|
||||
/* Get timestamp */
|
||||
RTPinfo->header.timestamp = ((((uint16_t)rtp_data[2]) & 0xFF) << 24) |
|
||||
((((uint16_t)rtp_data[2]) & 0xFF00) << 8) |
|
||||
((((uint16_t)rtp_data[3]) >> 8) & 0xFF) |
|
||||
((((uint16_t)rtp_data[3]) & 0xFF) << 8);
|
||||
/* Get the SSRC */
|
||||
RTPinfo->header.ssrc = ((((uint16_t)rtp_data[4]) & 0xFF) << 24) |
|
||||
((((uint16_t)rtp_data[4]) & 0xFF00) << 8) |
|
||||
((((uint16_t)rtp_data[5]) >> 8) & 0xFF) |
|
||||
((((uint16_t)rtp_data[5]) & 0xFF) << 8);
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::calcHeaderLength(int i_X, int i_CC) const
|
||||
{
|
||||
int i_extlength = 0;
|
||||
int16_t *rtp_data = (int16_t *) _datagram;
|
||||
|
||||
if (i_X == 1)
|
||||
{
|
||||
// Extension header exists.
|
||||
// Find out how many int32_t it consists of.
|
||||
assert(_datagramLen > 2 * (7 + 2 * i_CC));
|
||||
if (_datagramLen > 2 * (7 + 2 * i_CC))
|
||||
{
|
||||
i_extlength = (((((uint16_t) rtp_data[7 + 2 * i_CC]) >> 8)
|
||||
& 0xFF) | (((uint16_t) (rtp_data[7 + 2 * i_CC] & 0xFF))
|
||||
<< 8)) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 12 + 4 * i_extlength + 4 * i_CC;
|
||||
}
|
||||
|
||||
int NETEQTEST_RTPpacket::calcPadLength(int i_P) const
|
||||
{
|
||||
int16_t *rtp_data = (int16_t *) _datagram;
|
||||
if (i_P == 1)
|
||||
{
|
||||
/* Padding exists. Find out how many bytes the padding consists of. */
|
||||
if (_datagramLen & 0x1)
|
||||
{
|
||||
/* odd number of bytes => last byte in higher byte */
|
||||
return rtp_data[_datagramLen >> 1] & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* even number of bytes => last byte in lower byte */
|
||||
return ((uint16_t) rtp_data[(_datagramLen >> 1) - 1]) >> 8;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NETEQTEST_RTPpacket::splitStereoSample(NETEQTEST_RTPpacket* slaveRtp,
|
||||
int stride)
|
||||
{
|
||||
if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
|
||||
|| _payloadLen <= 0 || slaveRtp->_memSize < _memSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *readDataPtr = _payloadPtr;
|
||||
uint8_t *writeDataPtr = _payloadPtr;
|
||||
uint8_t *slaveData = slaveRtp->_payloadPtr;
|
||||
|
||||
while (readDataPtr - _payloadPtr < _payloadLen)
|
||||
{
|
||||
// master data
|
||||
for (int ix = 0; ix < stride; ix++) {
|
||||
*writeDataPtr = *readDataPtr;
|
||||
writeDataPtr++;
|
||||
readDataPtr++;
|
||||
}
|
||||
|
||||
// slave data
|
||||
for (int ix = 0; ix < stride; ix++) {
|
||||
*slaveData = *readDataPtr;
|
||||
slaveData++;
|
||||
readDataPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
_payloadLen /= 2;
|
||||
slaveRtp->_payloadLen = _payloadLen;
|
||||
}
|
||||
|
||||
|
||||
void NETEQTEST_RTPpacket::splitStereoFrame(NETEQTEST_RTPpacket* slaveRtp)
|
||||
{
|
||||
if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
|
||||
|| _payloadLen <= 0 || slaveRtp->_memSize < _memSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(slaveRtp->_payloadPtr, _payloadPtr + _payloadLen/2, _payloadLen/2);
|
||||
|
||||
_payloadLen /= 2;
|
||||
slaveRtp->_payloadLen = _payloadLen;
|
||||
}
|
||||
void NETEQTEST_RTPpacket::splitStereoDouble(NETEQTEST_RTPpacket* slaveRtp)
|
||||
{
|
||||
if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
|
||||
|| _payloadLen <= 0 || slaveRtp->_memSize < _memSize)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(slaveRtp->_payloadPtr, _payloadPtr, _payloadLen);
|
||||
slaveRtp->_payloadLen = _payloadLen;
|
||||
}
|
||||
|
||||
// Get the RTP header for the RED payload indicated by argument index.
|
||||
// The first RED payload is index = 0.
|
||||
int NETEQTEST_RTPpacket::extractRED(int index, webrtc::WebRtcRTPHeader& red)
|
||||
{
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |1| block PT | timestamp offset | block length |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |1| ... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |0| block PT |
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
//
|
||||
|
||||
parseHeader();
|
||||
|
||||
uint8_t* ptr = payload();
|
||||
uint8_t* payloadEndPtr = ptr + payloadLen();
|
||||
int num_encodings = 0;
|
||||
int total_len = 0;
|
||||
|
||||
while ((ptr < payloadEndPtr) && (*ptr & 0x80))
|
||||
{
|
||||
int len = ((ptr[2] & 0x03) << 8) + ptr[3];
|
||||
if (num_encodings == index)
|
||||
{
|
||||
// Header found.
|
||||
red.header.payloadType = ptr[0] & 0x7F;
|
||||
uint32_t offset = (ptr[1] << 6) + ((ptr[2] & 0xFC) >> 2);
|
||||
red.header.sequenceNumber = sequenceNumber();
|
||||
red.header.timestamp = timeStamp() - offset;
|
||||
red.header.markerBit = markerBit();
|
||||
red.header.ssrc = SSRC();
|
||||
return len;
|
||||
}
|
||||
++num_encodings;
|
||||
total_len += len;
|
||||
ptr += 4;
|
||||
}
|
||||
if ((ptr < payloadEndPtr) && (num_encodings == index))
|
||||
{
|
||||
// Last header.
|
||||
red.header.payloadType = ptr[0] & 0x7F;
|
||||
red.header.sequenceNumber = sequenceNumber();
|
||||
red.header.timestamp = timeStamp();
|
||||
red.header.markerBit = markerBit();
|
||||
red.header.ssrc = SSRC();
|
||||
++ptr;
|
||||
return payloadLen() - (ptr - payload()) - total_len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Randomize the payload, not the RTP header.
|
||||
void NETEQTEST_RTPpacket::scramblePayload(void)
|
||||
{
|
||||
parseHeader();
|
||||
|
||||
for (int i = 0; i < _payloadLen; ++i)
|
||||
{
|
||||
_payloadPtr[i] = static_cast<uint8_t>(rand());
|
||||
}
|
||||
}
|
||||
105
webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h
Normal file
105
webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef NETEQTEST_RTPPACKET_H
|
||||
#define NETEQTEST_RTPPACKET_H
|
||||
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
|
||||
enum stereoModes {
|
||||
stereoModeMono,
|
||||
stereoModeSample1,
|
||||
stereoModeSample2,
|
||||
stereoModeFrame,
|
||||
stereoModeDuplicate
|
||||
};
|
||||
|
||||
class NETEQTEST_RTPpacket
|
||||
{
|
||||
public:
|
||||
NETEQTEST_RTPpacket();
|
||||
bool operator !() const { return (dataLen() < 0); };
|
||||
virtual ~NETEQTEST_RTPpacket();
|
||||
void reset();
|
||||
static int skipFileHeader(FILE *fp);
|
||||
virtual int readFromFile(FILE *fp);
|
||||
int readFixedFromFile(FILE *fp, size_t len);
|
||||
virtual int writeToFile(FILE *fp);
|
||||
void blockPT(uint8_t pt);
|
||||
//int16_t payloadType();
|
||||
virtual void parseHeader();
|
||||
void parseHeader(webrtc::WebRtcRTPHeader* rtp_header);
|
||||
const webrtc::WebRtcRTPHeader* RTPinfo() const;
|
||||
uint8_t * datagram() const;
|
||||
uint8_t * payload() const;
|
||||
int16_t payloadLen();
|
||||
int16_t dataLen() const;
|
||||
bool isParsed() const;
|
||||
bool isLost() const;
|
||||
uint32_t time() const { return _receiveTime; };
|
||||
|
||||
uint8_t payloadType() const;
|
||||
uint16_t sequenceNumber() const;
|
||||
uint32_t timeStamp() const;
|
||||
uint32_t SSRC() const;
|
||||
uint8_t markerBit() const;
|
||||
|
||||
int setPayloadType(uint8_t pt);
|
||||
int setSequenceNumber(uint16_t sn);
|
||||
int setTimeStamp(uint32_t ts);
|
||||
int setSSRC(uint32_t ssrc);
|
||||
int setMarkerBit(uint8_t mb);
|
||||
void setTime(uint32_t receiveTime) { _receiveTime = receiveTime; };
|
||||
|
||||
int setRTPheader(const webrtc::WebRtcRTPHeader* RTPinfo);
|
||||
|
||||
int splitStereo(NETEQTEST_RTPpacket* slaveRtp, enum stereoModes mode);
|
||||
|
||||
int extractRED(int index, webrtc::WebRtcRTPHeader& red);
|
||||
|
||||
void scramblePayload(void);
|
||||
|
||||
uint8_t * _datagram;
|
||||
uint8_t * _payloadPtr;
|
||||
int _memSize;
|
||||
int16_t _datagramLen;
|
||||
int16_t _payloadLen;
|
||||
webrtc::WebRtcRTPHeader _rtpInfo;
|
||||
bool _rtpParsed;
|
||||
uint32_t _receiveTime;
|
||||
bool _lost;
|
||||
std::map<uint8_t, bool> _blockList;
|
||||
|
||||
protected:
|
||||
static const int _kRDHeaderLen;
|
||||
static const int _kBasicHeaderLen;
|
||||
|
||||
void parseBasicHeader(webrtc::WebRtcRTPHeader* RTPinfo, int *i_P, int *i_X,
|
||||
int *i_CC) const;
|
||||
int calcHeaderLength(int i_X, int i_CC) const;
|
||||
|
||||
private:
|
||||
void makeRTPheader(unsigned char* rtp_data, uint8_t payloadType,
|
||||
uint16_t seqNo, uint32_t timestamp,
|
||||
uint32_t ssrc, uint8_t markerBit) const;
|
||||
uint16_t parseRTPheader(webrtc::WebRtcRTPHeader* RTPinfo,
|
||||
uint8_t **payloadPtr = NULL) const;
|
||||
uint16_t parseRTPheader(uint8_t **payloadPtr = NULL)
|
||||
{ return parseRTPheader(&_rtpInfo, payloadPtr);};
|
||||
int calcPadLength(int i_P) const;
|
||||
void splitStereoSample(NETEQTEST_RTPpacket* slaveRtp, int stride);
|
||||
void splitStereoFrame(NETEQTEST_RTPpacket* slaveRtp);
|
||||
void splitStereoDouble(NETEQTEST_RTPpacket* slaveRtp);
|
||||
};
|
||||
|
||||
#endif //NETEQTEST_RTPPACKET_H
|
||||
77
webrtc/modules/audio_coding/neteq/test/PayloadTypes.h
Normal file
77
webrtc/modules/audio_coding/neteq/test/PayloadTypes.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
/* PayloadTypes.h */
|
||||
/* Used by NetEqRTPplay application */
|
||||
|
||||
/* RTP defined codepoints */
|
||||
#define NETEQ_CODEC_PCMU_PT 0
|
||||
#define NETEQ_CODEC_GSMFR_PT 3
|
||||
#define NETEQ_CODEC_G723_PT 4
|
||||
#define NETEQ_CODEC_DVI4_PT 125 // 8 kHz version
|
||||
//#define NETEQ_CODEC_DVI4_16_PT 6 // 16 kHz version
|
||||
#define NETEQ_CODEC_PCMA_PT 8
|
||||
#define NETEQ_CODEC_G722_PT 9
|
||||
#define NETEQ_CODEC_CN_PT 13
|
||||
//#define NETEQ_CODEC_G728_PT 15
|
||||
//#define NETEQ_CODEC_DVI4_11_PT 16 // 11.025 kHz version
|
||||
//#define NETEQ_CODEC_DVI4_22_PT 17 // 22.050 kHz version
|
||||
#define NETEQ_CODEC_G729_PT 18
|
||||
|
||||
/* Dynamic RTP codepoints as defined in VoiceEngine (file VEAPI.cpp) */
|
||||
#define NETEQ_CODEC_IPCMWB_PT 97
|
||||
#define NETEQ_CODEC_SPEEX8_PT 98
|
||||
#define NETEQ_CODEC_SPEEX16_PT 99
|
||||
#define NETEQ_CODEC_EG711U_PT 100
|
||||
#define NETEQ_CODEC_EG711A_PT 101
|
||||
#define NETEQ_CODEC_ILBC_PT 102
|
||||
#define NETEQ_CODEC_ISAC_PT 103
|
||||
#define NETEQ_CODEC_ISACLC_PT 119
|
||||
#define NETEQ_CODEC_ISACSWB_PT 104
|
||||
#define NETEQ_CODEC_AVT_PT 106
|
||||
#define NETEQ_CODEC_G722_1_16_PT 108
|
||||
#define NETEQ_CODEC_G722_1_24_PT 109
|
||||
#define NETEQ_CODEC_G722_1_32_PT 110
|
||||
#define NETEQ_CODEC_SC3_PT 111
|
||||
#define NETEQ_CODEC_AMR_PT 112
|
||||
#define NETEQ_CODEC_GSMEFR_PT 113
|
||||
//#define NETEQ_CODEC_ILBCRCU_PT 114
|
||||
#define NETEQ_CODEC_G726_16_PT 115
|
||||
#define NETEQ_CODEC_G726_24_PT 116
|
||||
#define NETEQ_CODEC_G726_32_PT 121
|
||||
#define NETEQ_CODEC_RED_PT 117
|
||||
#define NETEQ_CODEC_G726_40_PT 118
|
||||
//#define NETEQ_CODEC_ENERGY_PT 120
|
||||
#define NETEQ_CODEC_CN_WB_PT 105
|
||||
#define NETEQ_CODEC_CN_SWB_PT 126
|
||||
#define NETEQ_CODEC_G729_1_PT 107
|
||||
#define NETEQ_CODEC_G729D_PT 123
|
||||
#define NETEQ_CODEC_MELPE_PT 124
|
||||
#define NETEQ_CODEC_CELT32_PT 114
|
||||
|
||||
/* Extra dynamic codepoints */
|
||||
#define NETEQ_CODEC_AMRWB_PT 120
|
||||
#define NETEQ_CODEC_PCM16B_PT 93
|
||||
#define NETEQ_CODEC_PCM16B_WB_PT 94
|
||||
#define NETEQ_CODEC_PCM16B_SWB32KHZ_PT 95
|
||||
#define NETEQ_CODEC_PCM16B_SWB48KHZ_PT 96
|
||||
#define NETEQ_CODEC_MPEG4AAC_PT 122
|
||||
|
||||
|
||||
/* Not default in VoiceEngine */
|
||||
#define NETEQ_CODEC_G722_1C_24_PT 84
|
||||
#define NETEQ_CODEC_G722_1C_32_PT 85
|
||||
#define NETEQ_CODEC_G722_1C_48_PT 86
|
||||
|
||||
#define NETEQ_CODEC_SILK_8_PT 80
|
||||
#define NETEQ_CODEC_SILK_12_PT 81
|
||||
#define NETEQ_CODEC_SILK_16_PT 82
|
||||
#define NETEQ_CODEC_SILK_24_PT 83
|
||||
|
||||
75
webrtc/modules/audio_coding/neteq/test/RTPcat.cc
Normal file
75
webrtc/modules/audio_coding/neteq/test/RTPcat.cc
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h"
|
||||
|
||||
#define FIRSTLINELEN 40
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: RTPcat in1.rtp int2.rtp [...] out.rtp\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
FILE* in_file = fopen(argv[1], "rb");
|
||||
if (!in_file) {
|
||||
printf("Cannot open input file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* out_file = fopen(argv[argc - 1], "wb"); // Last parameter is out file.
|
||||
if (!out_file) {
|
||||
printf("Cannot open output file %s\n", argv[argc - 1]);
|
||||
return -1;
|
||||
}
|
||||
printf("Output RTP file: %s\n\n", argv[argc - 1]);
|
||||
|
||||
// Read file header and write directly to output file.
|
||||
char firstline[FIRSTLINELEN];
|
||||
const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
|
||||
EXPECT_TRUE(fgets(firstline, FIRSTLINELEN, in_file) != NULL);
|
||||
EXPECT_GT(fputs(firstline, out_file), 0);
|
||||
EXPECT_EQ(kRtpDumpHeaderSize, fread(firstline, 1, kRtpDumpHeaderSize,
|
||||
in_file));
|
||||
EXPECT_EQ(kRtpDumpHeaderSize, fwrite(firstline, 1, kRtpDumpHeaderSize,
|
||||
out_file));
|
||||
|
||||
// Close input file and re-open it later (easier to write the loop below).
|
||||
fclose(in_file);
|
||||
|
||||
for (int i = 1; i < argc - 1; i++) {
|
||||
in_file = fopen(argv[i], "rb");
|
||||
if (!in_file) {
|
||||
printf("Cannot open input file %s\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
printf("Input RTP file: %s\n", argv[i]);
|
||||
|
||||
NETEQTEST_RTPpacket::skipFileHeader(in_file);
|
||||
NETEQTEST_RTPpacket packet;
|
||||
int pack_len = packet.readFromFile(in_file);
|
||||
if (pack_len < 0) {
|
||||
exit(1);
|
||||
}
|
||||
while (pack_len >= 0) {
|
||||
packet.writeToFile(out_file);
|
||||
pack_len = packet.readFromFile(in_file);
|
||||
}
|
||||
fclose(in_file);
|
||||
}
|
||||
fclose(out_file);
|
||||
return 0;
|
||||
}
|
||||
133
webrtc/modules/audio_coding/neteq/test/RTPchange.cc
Normal file
133
webrtc/modules/audio_coding/neteq/test/RTPchange.cc
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_DummyRTPpacket.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h"
|
||||
|
||||
#define FIRSTLINELEN 40
|
||||
//#define WEBRTC_DUMMY_RTP
|
||||
|
||||
static bool pktCmp(NETEQTEST_RTPpacket *a, NETEQTEST_RTPpacket *b) {
|
||||
return (a->time() < b->time());
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
FILE* in_file = fopen(argv[1], "rb");
|
||||
if (!in_file) {
|
||||
printf("Cannot open input file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
printf("Input RTP file: %s\n", argv[1]);
|
||||
|
||||
FILE* stat_file = fopen(argv[2], "rt");
|
||||
if (!stat_file) {
|
||||
printf("Cannot open timing file %s\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
printf("Timing file: %s\n", argv[2]);
|
||||
|
||||
FILE* out_file = fopen(argv[3], "wb");
|
||||
if (!out_file) {
|
||||
printf("Cannot open output file %s\n", argv[3]);
|
||||
return -1;
|
||||
}
|
||||
printf("Output RTP file: %s\n\n", argv[3]);
|
||||
|
||||
// Read all statistics and insert into map.
|
||||
// Read first line.
|
||||
char temp_str[100];
|
||||
if (fgets(temp_str, 100, stat_file) == NULL) {
|
||||
printf("Failed to read timing file %s\n", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
// Define map.
|
||||
std::map<std::pair<uint16_t, uint32_t>, uint32_t> packet_stats;
|
||||
uint16_t seq_no;
|
||||
uint32_t ts;
|
||||
uint32_t send_time;
|
||||
|
||||
while (fscanf(stat_file,
|
||||
"%hu %u %u %*i %*i\n", &seq_no, &ts, &send_time) == 3) {
|
||||
std::pair<uint16_t, uint32_t>
|
||||
temp_pair = std::pair<uint16_t, uint32_t>(seq_no, ts);
|
||||
|
||||
packet_stats[temp_pair] = send_time;
|
||||
}
|
||||
|
||||
fclose(stat_file);
|
||||
|
||||
// Read file header and write directly to output file.
|
||||
char first_line[FIRSTLINELEN];
|
||||
if (fgets(first_line, FIRSTLINELEN, in_file) == NULL) {
|
||||
printf("Failed to read first line of input file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
fputs(first_line, out_file);
|
||||
// start_sec + start_usec + source + port + padding
|
||||
const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
|
||||
if (fread(first_line, 1, kRtpDumpHeaderSize, in_file)
|
||||
!= kRtpDumpHeaderSize) {
|
||||
printf("Failed to read RTP dump header from input file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (fwrite(first_line, 1, kRtpDumpHeaderSize, out_file)
|
||||
!= kRtpDumpHeaderSize) {
|
||||
printf("Failed to write RTP dump header to output file %s\n", argv[3]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<NETEQTEST_RTPpacket *> packet_vec;
|
||||
|
||||
while (1) {
|
||||
// Insert in vector.
|
||||
#ifdef WEBRTC_DUMMY_RTP
|
||||
NETEQTEST_RTPpacket *new_packet = new NETEQTEST_DummyRTPpacket();
|
||||
#else
|
||||
NETEQTEST_RTPpacket *new_packet = new NETEQTEST_RTPpacket();
|
||||
#endif
|
||||
if (new_packet->readFromFile(in_file) < 0) {
|
||||
// End of file.
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for new send time in statistics vector.
|
||||
std::pair<uint16_t, uint32_t> temp_pair =
|
||||
std::pair<uint16_t, uint32_t>(new_packet->sequenceNumber(),
|
||||
new_packet->timeStamp());
|
||||
|
||||
uint32_t new_send_time = packet_stats[temp_pair];
|
||||
new_packet->setTime(new_send_time); // Set new send time.
|
||||
packet_vec.push_back(new_packet); // Insert in vector.
|
||||
}
|
||||
|
||||
// Sort the vector according to send times.
|
||||
std::sort(packet_vec.begin(), packet_vec.end(), pktCmp);
|
||||
|
||||
std::vector<NETEQTEST_RTPpacket *>::iterator it;
|
||||
for (it = packet_vec.begin(); it != packet_vec.end(); it++) {
|
||||
// Write to out file.
|
||||
if ((*it)->writeToFile(out_file) < 0) {
|
||||
printf("Error writing to file\n");
|
||||
return -1;
|
||||
}
|
||||
// Delete packet.
|
||||
delete *it;
|
||||
}
|
||||
|
||||
fclose(in_file);
|
||||
fclose(out_file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
1826
webrtc/modules/audio_coding/neteq/test/RTPencode.cc
Normal file
1826
webrtc/modules/audio_coding/neteq/test/RTPencode.cc
Normal file
File diff suppressed because it is too large
Load Diff
217
webrtc/modules/audio_coding/neteq/test/RTPjitter.cc
Normal file
217
webrtc/modules/audio_coding/neteq/test/RTPjitter.cc
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
//TODO(hlundin): Reformat file to meet style guide.
|
||||
|
||||
/* header includes */
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifdef WEBRTC_LINUX
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
/*********************/
|
||||
/* Misc. definitions */
|
||||
/*********************/
|
||||
|
||||
#define FIRSTLINELEN 40
|
||||
#define CHECK_NOT_NULL(a) if((a)==NULL){fprintf(stderr,"\n %s \n line: %d \nerror at %s\n",__FILE__,__LINE__,#a );return(-1);}
|
||||
|
||||
struct arr_time {
|
||||
float time;
|
||||
uint32_t ix;
|
||||
};
|
||||
|
||||
int filelen(FILE *fid)
|
||||
{
|
||||
fpos_t cur_pos;
|
||||
int len;
|
||||
|
||||
if (!fid || fgetpos(fid, &cur_pos)) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
fseek(fid, 0, SEEK_END);
|
||||
len = ftell(fid);
|
||||
|
||||
fsetpos(fid, &cur_pos);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
||||
int compare_arr_time(const void *x, const void *y);
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
unsigned int dat_len, rtp_len, Npack, k;
|
||||
arr_time *time_vec;
|
||||
char firstline[FIRSTLINELEN];
|
||||
unsigned char* rtp_vec = NULL;
|
||||
unsigned char** packet_ptr = NULL;
|
||||
unsigned char* temp_packet = NULL;
|
||||
const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
|
||||
uint16_t len;
|
||||
uint32_t *offset;
|
||||
|
||||
/* check number of parameters */
|
||||
if (argc != 4) {
|
||||
/* print help text and exit */
|
||||
printf("Apply jitter on RTP stream.\n");
|
||||
printf("The program reads an RTP stream and packet timing from two files.\n");
|
||||
printf("The RTP stream is modified to have the same jitter as described in the timing files.\n");
|
||||
printf("The format of the RTP stream file should be the same as for rtpplay,\n");
|
||||
printf("and can be obtained e.g., from Ethereal by using\n");
|
||||
printf("Statistics -> RTP -> Show All Streams -> [select a stream] -> Save As\n\n");
|
||||
printf("Usage:\n\n");
|
||||
printf("%s RTP_infile dat_file RTP_outfile\n", argv[0]);
|
||||
printf("where:\n");
|
||||
|
||||
printf("RTP_infile : RTP stream input file\n\n");
|
||||
|
||||
printf("dat_file : file with packet arrival times in ms\n\n");
|
||||
|
||||
printf("RTP_outfile : RTP stream output file\n\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
FILE* in_file=fopen(argv[1],"rb");
|
||||
CHECK_NOT_NULL(in_file);
|
||||
printf("Input file: %s\n",argv[1]);
|
||||
FILE* dat_file=fopen(argv[2],"rb");
|
||||
CHECK_NOT_NULL(dat_file);
|
||||
printf("Dat-file: %s\n",argv[2]);
|
||||
FILE* out_file=fopen(argv[3],"wb");
|
||||
CHECK_NOT_NULL(out_file);
|
||||
printf("Output file: %s\n\n",argv[3]);
|
||||
|
||||
time_vec = (arr_time *) malloc(sizeof(arr_time)*(filelen(dat_file)/sizeof(float)) + 1000); // add 1000 bytes to avoid (rare) strange error
|
||||
if (time_vec==NULL) {
|
||||
fprintf(stderr, "Error: could not allocate memory for reading dat file\n");
|
||||
goto closing;
|
||||
}
|
||||
|
||||
dat_len=0;
|
||||
while(fread(&(time_vec[dat_len].time),sizeof(float),1,dat_file)>0) {
|
||||
time_vec[dat_len].ix=dat_len;
|
||||
dat_len++;
|
||||
}
|
||||
|
||||
if (dat_len == 0) {
|
||||
fprintf(stderr, "Error: dat_file is empty, no arrival time is given.\n");
|
||||
goto closing;
|
||||
}
|
||||
|
||||
qsort(time_vec,dat_len,sizeof(arr_time),compare_arr_time);
|
||||
|
||||
|
||||
rtp_vec = (unsigned char *) malloc(sizeof(unsigned char)*filelen(in_file));
|
||||
if (rtp_vec==NULL) {
|
||||
fprintf(stderr,"Error: could not allocate memory for reading rtp file\n");
|
||||
goto closing;
|
||||
}
|
||||
|
||||
// read file header and write directly to output file
|
||||
EXPECT_TRUE(fgets(firstline, FIRSTLINELEN, in_file) != NULL);
|
||||
EXPECT_GT(fputs(firstline, out_file), 0);
|
||||
EXPECT_EQ(kRtpDumpHeaderSize, fread(firstline, 1, kRtpDumpHeaderSize,
|
||||
in_file));
|
||||
EXPECT_EQ(kRtpDumpHeaderSize, fwrite(firstline, 1, kRtpDumpHeaderSize,
|
||||
out_file));
|
||||
|
||||
// read all RTP packets into vector
|
||||
rtp_len=0;
|
||||
Npack=0;
|
||||
len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); // read length of first packet
|
||||
while(len==2) {
|
||||
len = ntohs(*((uint16_t *)(rtp_vec + rtp_len)));
|
||||
rtp_len += 2;
|
||||
if(fread(&rtp_vec[rtp_len], sizeof(unsigned char), len-2, in_file)!=(unsigned) (len-2)) {
|
||||
fprintf(stderr,"Error: currupt packet length\n");
|
||||
goto closing;
|
||||
}
|
||||
rtp_len += len-2;
|
||||
Npack++;
|
||||
len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); // read length of next packet
|
||||
}
|
||||
|
||||
if (Npack == 0) {
|
||||
fprintf(stderr, "Error: No RTP packet found.\n");
|
||||
goto closing;
|
||||
}
|
||||
|
||||
packet_ptr = (unsigned char **) malloc(Npack*sizeof(unsigned char*));
|
||||
|
||||
packet_ptr[0]=rtp_vec;
|
||||
k=1;
|
||||
while(k<Npack) {
|
||||
len = ntohs(*((uint16_t *) packet_ptr[k-1]));
|
||||
packet_ptr[k]=packet_ptr[k-1]+len;
|
||||
k++;
|
||||
}
|
||||
|
||||
for(k=0; k<dat_len && k<Npack; k++) {
|
||||
if(time_vec[k].time < FLT_MAX && time_vec[k].ix < Npack){
|
||||
temp_packet = packet_ptr[time_vec[k].ix];
|
||||
offset = (uint32_t *) (temp_packet+4);
|
||||
if ( time_vec[k].time >= 0 ) {
|
||||
*offset = htonl((uint32_t) time_vec[k].time);
|
||||
}
|
||||
else {
|
||||
*offset = htonl((uint32_t) 0);
|
||||
fprintf(stderr, "Warning: negative receive time in dat file transformed to 0.\n");
|
||||
}
|
||||
|
||||
// write packet to file
|
||||
if (fwrite(temp_packet, sizeof(unsigned char),
|
||||
ntohs(*((uint16_t*) temp_packet)),
|
||||
out_file) !=
|
||||
ntohs(*((uint16_t*) temp_packet))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
closing:
|
||||
free(time_vec);
|
||||
free(rtp_vec);
|
||||
if (packet_ptr != NULL) {
|
||||
free(packet_ptr);
|
||||
}
|
||||
fclose(in_file);
|
||||
fclose(dat_file);
|
||||
fclose(out_file);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int compare_arr_time(const void *xp, const void *yp) {
|
||||
|
||||
if(((arr_time *)xp)->time == ((arr_time *)yp)->time)
|
||||
return(0);
|
||||
else if(((arr_time *)xp)->time > ((arr_time *)yp)->time)
|
||||
return(1);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
99
webrtc/modules/audio_coding/neteq/test/RTPtimeshift.cc
Normal file
99
webrtc/modules/audio_coding/neteq/test/RTPtimeshift.cc
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#include "NETEQTEST_RTPpacket.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
/*********************/
|
||||
/* Misc. definitions */
|
||||
/*********************/
|
||||
|
||||
#define FIRSTLINELEN 40
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if(argc < 4 || argc > 6)
|
||||
{
|
||||
printf("Usage: RTPtimeshift in.rtp out.rtp newStartTS [newStartSN [newStartArrTime]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
FILE *inFile=fopen(argv[1],"rb");
|
||||
if (!inFile)
|
||||
{
|
||||
printf("Cannot open input file %s\n", argv[1]);
|
||||
return(-1);
|
||||
}
|
||||
printf("Input RTP file: %s\n",argv[1]);
|
||||
|
||||
FILE *outFile=fopen(argv[2],"wb");
|
||||
if (!outFile)
|
||||
{
|
||||
printf("Cannot open output file %s\n", argv[2]);
|
||||
return(-1);
|
||||
}
|
||||
printf("Output RTP file: %s\n\n",argv[2]);
|
||||
|
||||
// read file header and write directly to output file
|
||||
const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
|
||||
char firstline[FIRSTLINELEN];
|
||||
EXPECT_TRUE(fgets(firstline, FIRSTLINELEN, inFile) != NULL);
|
||||
EXPECT_GT(fputs(firstline, outFile), 0);
|
||||
EXPECT_EQ(kRtpDumpHeaderSize,
|
||||
fread(firstline, 1, kRtpDumpHeaderSize, inFile));
|
||||
EXPECT_EQ(kRtpDumpHeaderSize,
|
||||
fwrite(firstline, 1, kRtpDumpHeaderSize, outFile));
|
||||
NETEQTEST_RTPpacket packet;
|
||||
int packLen = packet.readFromFile(inFile);
|
||||
if (packLen < 0)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// get new start TS and start SeqNo from arguments
|
||||
uint32_t TSdiff = atoi(argv[3]) - packet.timeStamp();
|
||||
uint16_t SNdiff = 0;
|
||||
uint32_t ATdiff = 0;
|
||||
if (argc > 4)
|
||||
{
|
||||
int startSN = atoi(argv[4]);
|
||||
if (startSN >= 0)
|
||||
SNdiff = startSN - packet.sequenceNumber();
|
||||
if (argc > 5)
|
||||
{
|
||||
int startTS = atoi(argv[5]);
|
||||
if (startTS >= 0)
|
||||
ATdiff = startTS - packet.time();
|
||||
}
|
||||
}
|
||||
|
||||
while (packLen >= 0)
|
||||
{
|
||||
|
||||
packet.setTimeStamp(packet.timeStamp() + TSdiff);
|
||||
packet.setSequenceNumber(packet.sequenceNumber() + SNdiff);
|
||||
packet.setTime(packet.time() + ATdiff);
|
||||
|
||||
packet.writeToFile(outFile);
|
||||
|
||||
packLen = packet.readFromFile(inFile);
|
||||
|
||||
}
|
||||
|
||||
fclose(inFile);
|
||||
fclose(outFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
105
webrtc/modules/audio_coding/neteq/test/audio_classifier_test.cc
Normal file
105
webrtc/modules/audio_coding/neteq/test/audio_classifier_test.cc
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 "webrtc/modules/audio_coding/neteq/audio_classifier.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 5) {
|
||||
std::cout << "Usage: " << argv[0] <<
|
||||
" channels output_type <input file name> <output file name> "
|
||||
<< std::endl << std::endl;
|
||||
std::cout << "Where channels can be 1 (mono) or 2 (interleaved stereo),";
|
||||
std::cout << " outputs can be 1 (classification (boolean)) or 2";
|
||||
std::cout << " (classification and music probability (float)),"
|
||||
<< std::endl;
|
||||
std::cout << "and the sampling frequency is assumed to be 48 kHz."
|
||||
<< std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int kFrameSizeSamples = 960;
|
||||
int channels = atoi(argv[1]);
|
||||
if (channels < 1 || channels > 2) {
|
||||
std::cout << "Disallowed number of channels " << channels << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int outputs = atoi(argv[2]);
|
||||
if (outputs < 1 || outputs > 2) {
|
||||
std::cout << "Disallowed number of outputs " << outputs << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int data_size = channels * kFrameSizeSamples;
|
||||
webrtc::scoped_ptr<int16_t[]> in(new int16_t[data_size]);
|
||||
|
||||
std::string input_filename = argv[3];
|
||||
std::string output_filename = argv[4];
|
||||
|
||||
std::cout << "Input file: " << input_filename << std::endl;
|
||||
std::cout << "Output file: " << output_filename << std::endl;
|
||||
|
||||
FILE* in_file = fopen(input_filename.c_str(), "rb");
|
||||
if (!in_file) {
|
||||
std::cout << "Cannot open input file " << input_filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* out_file = fopen(output_filename.c_str(), "wb");
|
||||
if (!out_file) {
|
||||
std::cout << "Cannot open output file " << output_filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
webrtc::AudioClassifier classifier;
|
||||
int frame_counter = 0;
|
||||
int music_counter = 0;
|
||||
while (fread(in.get(), sizeof(*in.get()),
|
||||
data_size, in_file) == (size_t) data_size) {
|
||||
bool is_music = classifier.Analysis(in.get(), data_size, channels);
|
||||
if (!fwrite(&is_music, sizeof(is_music), 1, out_file)) {
|
||||
std::cout << "Error writing." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if (is_music) {
|
||||
music_counter++;
|
||||
}
|
||||
std::cout << "frame " << frame_counter << " decision " << is_music;
|
||||
if (outputs == 2) {
|
||||
float music_prob = classifier.music_probability();
|
||||
if (!fwrite(&music_prob, sizeof(music_prob), 1, out_file)) {
|
||||
std::cout << "Error writing." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
std::cout << " music prob " << music_prob;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
frame_counter++;
|
||||
}
|
||||
std::cout << frame_counter << " frames processed." << std::endl;
|
||||
if (frame_counter > 0) {
|
||||
float music_percentage = music_counter / static_cast<float>(frame_counter);
|
||||
std::cout << music_percentage << " percent music." << std::endl;
|
||||
}
|
||||
|
||||
fclose(in_file);
|
||||
fclose(out_file);
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,191 @@
|
||||
function outStruct = parse_delay_file(file)
|
||||
|
||||
fid = fopen(file, 'rb');
|
||||
if fid == -1
|
||||
error('Cannot open file %s', file);
|
||||
end
|
||||
|
||||
textline = fgetl(fid);
|
||||
if ~strncmp(textline, '#!NetEQ_Delay_Logging', 21)
|
||||
error('Wrong file format');
|
||||
end
|
||||
|
||||
ver = sscanf(textline, '#!NetEQ_Delay_Logging%d.%d');
|
||||
if ~all(ver == [2; 0])
|
||||
error('Wrong version of delay logging function')
|
||||
end
|
||||
|
||||
|
||||
start_pos = ftell(fid);
|
||||
fseek(fid, -12, 'eof');
|
||||
textline = fgetl(fid);
|
||||
if ~strncmp(textline, 'End of file', 21)
|
||||
error('File ending is not correct. Seems like the simulation ended abnormally.');
|
||||
end
|
||||
|
||||
fseek(fid,-12-4, 'eof');
|
||||
Npackets = fread(fid, 1, 'int32');
|
||||
fseek(fid, start_pos, 'bof');
|
||||
|
||||
rtpts = zeros(Npackets, 1);
|
||||
seqno = zeros(Npackets, 1);
|
||||
pt = zeros(Npackets, 1);
|
||||
plen = zeros(Npackets, 1);
|
||||
recin_t = nan*ones(Npackets, 1);
|
||||
decode_t = nan*ones(Npackets, 1);
|
||||
playout_delay = zeros(Npackets, 1);
|
||||
optbuf = zeros(Npackets, 1);
|
||||
|
||||
fs_ix = 1;
|
||||
clock = 0;
|
||||
ts_ix = 1;
|
||||
ended = 0;
|
||||
late_packets = 0;
|
||||
fs_now = 8000;
|
||||
last_decode_k = 0;
|
||||
tot_expand = 0;
|
||||
tot_accelerate = 0;
|
||||
tot_preemptive = 0;
|
||||
|
||||
while not(ended)
|
||||
signal = fread(fid, 1, '*int32');
|
||||
|
||||
switch signal
|
||||
case 3 % NETEQ_DELAY_LOGGING_SIGNAL_CLOCK
|
||||
clock = fread(fid, 1, '*float32');
|
||||
|
||||
% keep on reading batches of M until the signal is no longer "3"
|
||||
% read int32 + float32 in one go
|
||||
% this is to save execution time
|
||||
temp = [3; 0];
|
||||
M = 120;
|
||||
while all(temp(1,:) == 3)
|
||||
fp = ftell(fid);
|
||||
temp = fread(fid, [2 M], '*int32');
|
||||
end
|
||||
|
||||
% back up to last clock event
|
||||
fseek(fid, fp - ftell(fid) + ...
|
||||
(find(temp(1,:) ~= 3, 1 ) - 2) * 2 * 4 + 4, 'cof');
|
||||
% read the last clock value
|
||||
clock = fread(fid, 1, '*float32');
|
||||
|
||||
case 1 % NETEQ_DELAY_LOGGING_SIGNAL_RECIN
|
||||
temp_ts = fread(fid, 1, 'uint32');
|
||||
|
||||
if late_packets > 0
|
||||
temp_ix = ts_ix - 1;
|
||||
while (temp_ix >= 1) && (rtpts(temp_ix) ~= temp_ts)
|
||||
% TODO(hlundin): use matlab vector search instead?
|
||||
temp_ix = temp_ix - 1;
|
||||
end
|
||||
|
||||
if temp_ix >= 1
|
||||
% the ts was found in the vector
|
||||
late_packets = late_packets - 1;
|
||||
else
|
||||
temp_ix = ts_ix;
|
||||
ts_ix = ts_ix + 1;
|
||||
end
|
||||
else
|
||||
temp_ix = ts_ix;
|
||||
ts_ix = ts_ix + 1;
|
||||
end
|
||||
|
||||
rtpts(temp_ix) = temp_ts;
|
||||
seqno(temp_ix) = fread(fid, 1, 'uint16');
|
||||
pt(temp_ix) = fread(fid, 1, 'int32');
|
||||
plen(temp_ix) = fread(fid, 1, 'int16');
|
||||
recin_t(temp_ix) = clock;
|
||||
|
||||
case 2 % NETEQ_DELAY_LOGGING_SIGNAL_FLUSH
|
||||
% do nothing
|
||||
|
||||
case 4 % NETEQ_DELAY_LOGGING_SIGNAL_EOF
|
||||
ended = 1;
|
||||
|
||||
case 5 % NETEQ_DELAY_LOGGING_SIGNAL_DECODE
|
||||
last_decode_ts = fread(fid, 1, 'uint32');
|
||||
temp_delay = fread(fid, 1, 'uint16');
|
||||
|
||||
k = find(rtpts(1:(ts_ix - 1))==last_decode_ts,1,'last');
|
||||
if ~isempty(k)
|
||||
decode_t(k) = clock;
|
||||
playout_delay(k) = temp_delay + ...
|
||||
5 * fs_now / 8000; % add overlap length
|
||||
last_decode_k = k;
|
||||
end
|
||||
|
||||
case 6 % NETEQ_DELAY_LOGGING_SIGNAL_CHANGE_FS
|
||||
fsvec(fs_ix) = fread(fid, 1, 'uint16');
|
||||
fschange_ts(fs_ix) = last_decode_ts;
|
||||
fs_now = fsvec(fs_ix);
|
||||
fs_ix = fs_ix + 1;
|
||||
|
||||
case 7 % NETEQ_DELAY_LOGGING_SIGNAL_MERGE_INFO
|
||||
playout_delay(last_decode_k) = playout_delay(last_decode_k) ...
|
||||
+ fread(fid, 1, 'int32');
|
||||
|
||||
case 8 % NETEQ_DELAY_LOGGING_SIGNAL_EXPAND_INFO
|
||||
temp = fread(fid, 1, 'int32');
|
||||
if last_decode_k ~= 0
|
||||
tot_expand = tot_expand + temp / (fs_now / 1000);
|
||||
end
|
||||
|
||||
case 9 % NETEQ_DELAY_LOGGING_SIGNAL_ACCELERATE_INFO
|
||||
temp = fread(fid, 1, 'int32');
|
||||
if last_decode_k ~= 0
|
||||
tot_accelerate = tot_accelerate + temp / (fs_now / 1000);
|
||||
end
|
||||
|
||||
case 10 % NETEQ_DELAY_LOGGING_SIGNAL_PREEMPTIVE_INFO
|
||||
temp = fread(fid, 1, 'int32');
|
||||
if last_decode_k ~= 0
|
||||
tot_preemptive = tot_preemptive + temp / (fs_now / 1000);
|
||||
end
|
||||
|
||||
case 11 % NETEQ_DELAY_LOGGING_SIGNAL_OPTBUF
|
||||
optbuf(last_decode_k) = fread(fid, 1, 'int32');
|
||||
|
||||
case 12 % NETEQ_DELAY_LOGGING_SIGNAL_DECODE_ONE_DESC
|
||||
last_decode_ts = fread(fid, 1, 'uint32');
|
||||
k = ts_ix - 1;
|
||||
|
||||
while (k >= 1) && (rtpts(k) ~= last_decode_ts)
|
||||
% TODO(hlundin): use matlab vector search instead?
|
||||
k = k - 1;
|
||||
end
|
||||
|
||||
if k < 1
|
||||
% packet not received yet
|
||||
k = ts_ix;
|
||||
rtpts(ts_ix) = last_decode_ts;
|
||||
late_packets = late_packets + 1;
|
||||
end
|
||||
|
||||
decode_t(k) = clock;
|
||||
playout_delay(k) = fread(fid, 1, 'uint16') + ...
|
||||
5 * fs_now / 8000; % add overlap length
|
||||
last_decode_k = k;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
fclose(fid);
|
||||
|
||||
outStruct = struct(...
|
||||
'ts', rtpts, ...
|
||||
'sn', seqno, ...
|
||||
'pt', pt,...
|
||||
'plen', plen,...
|
||||
'arrival', recin_t,...
|
||||
'decode', decode_t,...
|
||||
'fs', fsvec(:),...
|
||||
'fschange_ts', fschange_ts(:),...
|
||||
'playout_delay', playout_delay,...
|
||||
'tot_expand', tot_expand,...
|
||||
'tot_accelerate', tot_accelerate,...
|
||||
'tot_preemptive', tot_preemptive,...
|
||||
'optbuf', optbuf);
|
||||
@ -0,0 +1,187 @@
|
||||
function [delay_struct, delayvalues] = plot_neteq_delay(delayfile, varargin)
|
||||
|
||||
% InfoStruct = plot_neteq_delay(delayfile)
|
||||
% InfoStruct = plot_neteq_delay(delayfile, 'skipdelay', skip_seconds)
|
||||
%
|
||||
% Henrik Lundin, 2006-11-17
|
||||
% Henrik Lundin, 2011-05-17
|
||||
%
|
||||
|
||||
try
|
||||
s = parse_delay_file(delayfile);
|
||||
catch
|
||||
error(lasterr);
|
||||
end
|
||||
|
||||
delayskip=0;
|
||||
noplot=0;
|
||||
arg_ptr=1;
|
||||
delaypoints=[];
|
||||
|
||||
s.sn=unwrap_seqno(s.sn);
|
||||
|
||||
while arg_ptr+1 <= nargin
|
||||
switch lower(varargin{arg_ptr})
|
||||
case {'skipdelay', 'delayskip'}
|
||||
% skip a number of seconds in the beginning when calculating delays
|
||||
delayskip = varargin{arg_ptr+1};
|
||||
arg_ptr = arg_ptr + 2;
|
||||
case 'noplot'
|
||||
noplot=1;
|
||||
arg_ptr = arg_ptr + 1;
|
||||
case {'get_delay', 'getdelay'}
|
||||
% return a vector of delay values for the points in the given vector
|
||||
delaypoints = varargin{arg_ptr+1};
|
||||
arg_ptr = arg_ptr + 2;
|
||||
otherwise
|
||||
warning('Unknown switch %s\n', varargin{arg_ptr});
|
||||
arg_ptr = arg_ptr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
% find lost frames that were covered by one-descriptor decoding
|
||||
one_desc_ix=find(isnan(s.arrival));
|
||||
for k=1:length(one_desc_ix)
|
||||
ix=find(s.ts==max(s.ts(s.ts(one_desc_ix(k))>s.ts)));
|
||||
s.sn(one_desc_ix(k))=s.sn(ix)+1;
|
||||
s.pt(one_desc_ix(k))=s.pt(ix);
|
||||
s.arrival(one_desc_ix(k))=s.arrival(ix)+s.decode(one_desc_ix(k))-s.decode(ix);
|
||||
end
|
||||
|
||||
% remove duplicate received frames that were never decoded (RED codec)
|
||||
if length(unique(s.ts(isfinite(s.ts)))) < length(s.ts(isfinite(s.ts)))
|
||||
ix=find(isfinite(s.decode));
|
||||
s.sn=s.sn(ix);
|
||||
s.ts=s.ts(ix);
|
||||
s.arrival=s.arrival(ix);
|
||||
s.playout_delay=s.playout_delay(ix);
|
||||
s.pt=s.pt(ix);
|
||||
s.optbuf=s.optbuf(ix);
|
||||
plen=plen(ix);
|
||||
s.decode=s.decode(ix);
|
||||
end
|
||||
|
||||
% find non-unique sequence numbers
|
||||
[~,un_ix]=unique(s.sn);
|
||||
nonun_ix=setdiff(1:length(s.sn),un_ix);
|
||||
if ~isempty(nonun_ix)
|
||||
warning('RTP sequence numbers are in error');
|
||||
end
|
||||
|
||||
% sort vectors
|
||||
[s.sn,sort_ix]=sort(s.sn);
|
||||
s.ts=s.ts(sort_ix);
|
||||
s.arrival=s.arrival(sort_ix);
|
||||
s.decode=s.decode(sort_ix);
|
||||
s.playout_delay=s.playout_delay(sort_ix);
|
||||
s.pt=s.pt(sort_ix);
|
||||
|
||||
send_t=s.ts-s.ts(1);
|
||||
if length(s.fs)<1
|
||||
warning('No info about sample rate found in file. Using default 8000.');
|
||||
s.fs(1)=8000;
|
||||
s.fschange_ts(1)=min(s.ts);
|
||||
elseif s.fschange_ts(1)>min(s.ts)
|
||||
s.fschange_ts(1)=min(s.ts);
|
||||
end
|
||||
|
||||
end_ix=length(send_t);
|
||||
for k=length(s.fs):-1:1
|
||||
start_ix=find(s.ts==s.fschange_ts(k));
|
||||
send_t(start_ix:end_ix)=send_t(start_ix:end_ix)/s.fs(k)*1000;
|
||||
s.playout_delay(start_ix:end_ix)=s.playout_delay(start_ix:end_ix)/s.fs(k)*1000;
|
||||
s.optbuf(start_ix:end_ix)=s.optbuf(start_ix:end_ix)/s.fs(k)*1000;
|
||||
end_ix=start_ix-1;
|
||||
end
|
||||
|
||||
tot_time=max(send_t)-min(send_t);
|
||||
|
||||
seq_ix=s.sn-min(s.sn)+1;
|
||||
send_t=send_t+max(min(s.arrival-send_t),0);
|
||||
|
||||
plot_send_t=nan*ones(max(seq_ix),1);
|
||||
plot_send_t(seq_ix)=send_t;
|
||||
plot_nw_delay=nan*ones(max(seq_ix),1);
|
||||
plot_nw_delay(seq_ix)=s.arrival-send_t;
|
||||
|
||||
cng_ix=find(s.pt~=13); % find those packets that are not CNG/SID
|
||||
|
||||
if noplot==0
|
||||
h=plot(plot_send_t/1000,plot_nw_delay);
|
||||
set(h,'color',0.75*[1 1 1]);
|
||||
hold on
|
||||
if any(s.optbuf~=0)
|
||||
peak_ix=find(s.optbuf(cng_ix)<0); % peak mode is labeled with negative values
|
||||
no_peak_ix=find(s.optbuf(cng_ix)>0); %setdiff(1:length(cng_ix),peak_ix);
|
||||
h1=plot(send_t(cng_ix(peak_ix))/1000,...
|
||||
s.arrival(cng_ix(peak_ix))+abs(s.optbuf(cng_ix(peak_ix)))-send_t(cng_ix(peak_ix)),...
|
||||
'r.');
|
||||
h2=plot(send_t(cng_ix(no_peak_ix))/1000,...
|
||||
s.arrival(cng_ix(no_peak_ix))+abs(s.optbuf(cng_ix(no_peak_ix)))-send_t(cng_ix(no_peak_ix)),...
|
||||
'g.');
|
||||
set([h1, h2],'markersize',1)
|
||||
end
|
||||
%h=plot(send_t(seq_ix)/1000,s.decode+s.playout_delay-send_t(seq_ix));
|
||||
h=plot(send_t(cng_ix)/1000,s.decode(cng_ix)+s.playout_delay(cng_ix)-send_t(cng_ix));
|
||||
set(h,'linew',1.5);
|
||||
hold off
|
||||
ax1=axis;
|
||||
axis tight
|
||||
ax2=axis;
|
||||
axis([ax2(1:3) ax1(4)])
|
||||
end
|
||||
|
||||
|
||||
% calculate delays and other parameters
|
||||
|
||||
delayskip_ix = find(send_t-send_t(1)>=delayskip*1000, 1 );
|
||||
|
||||
use_ix = intersect(cng_ix,... % use those that are not CNG/SID frames...
|
||||
intersect(find(isfinite(s.decode)),... % ... that did arrive ...
|
||||
(delayskip_ix:length(s.decode))')); % ... and are sent after delayskip seconds
|
||||
|
||||
mean_delay = mean(s.decode(use_ix)+s.playout_delay(use_ix)-send_t(use_ix));
|
||||
neteq_delay = mean(s.decode(use_ix)+s.playout_delay(use_ix)-s.arrival(use_ix));
|
||||
|
||||
Npack=max(s.sn(delayskip_ix:end))-min(s.sn(delayskip_ix:end))+1;
|
||||
nw_lossrate=(Npack-length(s.sn(delayskip_ix:end)))/Npack;
|
||||
neteq_lossrate=(length(s.sn(delayskip_ix:end))-length(use_ix))/Npack;
|
||||
|
||||
delay_struct=struct('mean_delay',mean_delay,'neteq_delay',neteq_delay,...
|
||||
'nw_lossrate',nw_lossrate,'neteq_lossrate',neteq_lossrate,...
|
||||
'tot_expand',round(s.tot_expand),'tot_accelerate',round(s.tot_accelerate),...
|
||||
'tot_preemptive',round(s.tot_preemptive),'tot_time',tot_time,...
|
||||
'filename',delayfile,'units','ms','fs',unique(s.fs));
|
||||
|
||||
if not(isempty(delaypoints))
|
||||
delayvalues=interp1(send_t(cng_ix),...
|
||||
s.decode(cng_ix)+s.playout_delay(cng_ix)-send_t(cng_ix),...
|
||||
delaypoints,'nearest',NaN);
|
||||
else
|
||||
delayvalues=[];
|
||||
end
|
||||
|
||||
|
||||
|
||||
% SUBFUNCTIONS %
|
||||
|
||||
function y=unwrap_seqno(x)
|
||||
|
||||
jumps=find(abs((diff(x)-1))>65000);
|
||||
|
||||
while ~isempty(jumps)
|
||||
n=jumps(1);
|
||||
if x(n+1)-x(n) < 0
|
||||
% negative jump
|
||||
x(n+1:end)=x(n+1:end)+65536;
|
||||
else
|
||||
% positive jump
|
||||
x(n+1:end)=x(n+1:end)-65536;
|
||||
end
|
||||
|
||||
jumps=find(abs((diff(x(n+1:end))-1))>65000);
|
||||
end
|
||||
|
||||
y=x;
|
||||
|
||||
return;
|
||||
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 <gflags/gflags.h>
|
||||
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
using google::RegisterFlagValidator;
|
||||
using google::ParseCommandLineFlags;
|
||||
using std::string;
|
||||
using testing::InitGoogleTest;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
static const int kOpusBlockDurationMs = 20;
|
||||
static const int kOpusInputSamplingKhz = 48;
|
||||
static const int kOpusOutputSamplingKhz = 32;
|
||||
|
||||
static bool ValidateInFilename(const char* flagname, const string& value) {
|
||||
FILE* fid = fopen(value.c_str(), "rb");
|
||||
if (fid != NULL) {
|
||||
fclose(fid);
|
||||
return true;
|
||||
}
|
||||
printf("Invalid input filename.");
|
||||
return false;
|
||||
}
|
||||
DEFINE_string(in_filename,
|
||||
ResourcePath("audio_coding/speech_mono_32_48kHz", "pcm"),
|
||||
"Filename for input audio (should be 48 kHz sampled raw data).");
|
||||
static const bool in_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_in_filename, &ValidateInFilename);
|
||||
|
||||
static bool ValidateOutFilename(const char* flagname, const string& value) {
|
||||
FILE* fid = fopen(value.c_str(), "wb");
|
||||
if (fid != NULL) {
|
||||
fclose(fid);
|
||||
return true;
|
||||
}
|
||||
printf("Invalid output filename.");
|
||||
return false;
|
||||
}
|
||||
DEFINE_string(out_filename, OutputPath() + "neteq4_opus_fec_quality_test.pcm",
|
||||
"Name of output audio file.");
|
||||
static const bool out_filename_dummy =
|
||||
RegisterFlagValidator(&FLAGS_out_filename, &ValidateOutFilename);
|
||||
|
||||
static bool ValidateChannels(const char* flagname, int32_t value) {
|
||||
if (value == 1 || value == 2)
|
||||
return true;
|
||||
printf("Invalid number of channels, should be either 1 or 2.");
|
||||
return false;
|
||||
}
|
||||
DEFINE_int32(channels, 1, "Number of channels in input audio.");
|
||||
static const bool channels_dummy =
|
||||
RegisterFlagValidator(&FLAGS_channels, &ValidateChannels);
|
||||
|
||||
static bool ValidateBitRate(const char* flagname, int32_t value) {
|
||||
if (value >= 6 && value <= 510)
|
||||
return true;
|
||||
printf("Invalid bit rate, should be between 6 and 510 kbps.");
|
||||
return false;
|
||||
}
|
||||
DEFINE_int32(bit_rate_kbps, 32, "Target bit rate (kbps).");
|
||||
static const bool bit_rate_dummy =
|
||||
RegisterFlagValidator(&FLAGS_bit_rate_kbps, &ValidateBitRate);
|
||||
|
||||
static bool ValidatePacketLossRate(const char* flagname, int32_t value) {
|
||||
if (value >= 0 && value <= 100)
|
||||
return true;
|
||||
printf("Invalid packet loss percentile, should be between 0 and 100.");
|
||||
return false;
|
||||
}
|
||||
DEFINE_int32(reported_loss_rate, 10, "Reported percentile of packet loss.");
|
||||
static const bool reported_loss_rate_dummy =
|
||||
RegisterFlagValidator(&FLAGS_reported_loss_rate, &ValidatePacketLossRate);
|
||||
DEFINE_int32(actual_loss_rate, 0, "Actual percentile of packet loss.");
|
||||
static const bool actual_loss_rate_dummy =
|
||||
RegisterFlagValidator(&FLAGS_actual_loss_rate, &ValidatePacketLossRate);
|
||||
|
||||
static bool ValidateRuntime(const char* flagname, int32_t value) {
|
||||
if (value > 0)
|
||||
return true;
|
||||
printf("Invalid runtime, should be greater than 0.");
|
||||
return false;
|
||||
}
|
||||
DEFINE_int32(runtime_ms, 10000, "Simulated runtime (milliseconds).");
|
||||
static const bool runtime_dummy =
|
||||
RegisterFlagValidator(&FLAGS_runtime_ms, &ValidateRuntime);
|
||||
|
||||
DEFINE_bool(fec, true, "Whether to enable FEC for encoding.");
|
||||
|
||||
class NetEqOpusFecQualityTest : public NetEqQualityTest {
|
||||
protected:
|
||||
NetEqOpusFecQualityTest();
|
||||
virtual void SetUp() OVERRIDE;
|
||||
virtual void TearDown() OVERRIDE;
|
||||
virtual int EncodeBlock(int16_t* in_data, int block_size_samples,
|
||||
uint8_t* payload, int max_bytes);
|
||||
virtual bool PacketLost(int packet_input_time_ms);
|
||||
private:
|
||||
WebRtcOpusEncInst* opus_encoder_;
|
||||
int channels_;
|
||||
int bit_rate_kbps_;
|
||||
bool fec_;
|
||||
int target_loss_rate_;
|
||||
int actual_loss_rate_;
|
||||
};
|
||||
|
||||
NetEqOpusFecQualityTest::NetEqOpusFecQualityTest()
|
||||
: NetEqQualityTest(kOpusBlockDurationMs, kOpusInputSamplingKhz,
|
||||
kOpusOutputSamplingKhz,
|
||||
(FLAGS_channels == 1) ? kDecoderOpus : kDecoderOpus_2ch,
|
||||
FLAGS_channels, 0.0f, FLAGS_in_filename,
|
||||
FLAGS_out_filename),
|
||||
opus_encoder_(NULL),
|
||||
channels_(FLAGS_channels),
|
||||
bit_rate_kbps_(FLAGS_bit_rate_kbps),
|
||||
fec_(FLAGS_fec),
|
||||
target_loss_rate_(FLAGS_reported_loss_rate),
|
||||
actual_loss_rate_(FLAGS_actual_loss_rate) {
|
||||
}
|
||||
|
||||
void NetEqOpusFecQualityTest::SetUp() {
|
||||
// Create encoder memory.
|
||||
WebRtcOpus_EncoderCreate(&opus_encoder_, channels_);
|
||||
ASSERT_TRUE(opus_encoder_ != NULL);
|
||||
// Set bitrate.
|
||||
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_kbps_ * 1000));
|
||||
if (fec_) {
|
||||
EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
|
||||
EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_,
|
||||
target_loss_rate_));
|
||||
}
|
||||
NetEqQualityTest::SetUp();
|
||||
}
|
||||
|
||||
void NetEqOpusFecQualityTest::TearDown() {
|
||||
// Free memory.
|
||||
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
|
||||
NetEqQualityTest::TearDown();
|
||||
}
|
||||
|
||||
int NetEqOpusFecQualityTest::EncodeBlock(int16_t* in_data,
|
||||
int block_size_samples,
|
||||
uint8_t* payload, int max_bytes) {
|
||||
int value = WebRtcOpus_Encode(opus_encoder_, in_data,
|
||||
block_size_samples, max_bytes,
|
||||
payload);
|
||||
EXPECT_GT(value, 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool NetEqOpusFecQualityTest::PacketLost(int packet_input_time_ms) {
|
||||
static int packets = 0, lost_packets = 0;
|
||||
packets++;
|
||||
if (lost_packets * 100 < actual_loss_rate_ * packets) {
|
||||
lost_packets++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TEST_F(NetEqOpusFecQualityTest, Test) {
|
||||
Simulate(FLAGS_runtime_ms);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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 "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.h"
|
||||
#include "webrtc/test/testsupport/perf_test.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// Runs a test with 10% packet losses and 10% clock drift, to exercise
|
||||
// both loss concealment and time-stretching code.
|
||||
TEST(NetEqPerformanceTest, Run) {
|
||||
const int kSimulationTimeMs = 10000000;
|
||||
const int kLossPeriod = 10; // Drop every 10th packet.
|
||||
const double kDriftFactor = 0.1;
|
||||
int64_t runtime = webrtc::test::NetEqPerformanceTest::Run(
|
||||
kSimulationTimeMs, kLossPeriod, kDriftFactor);
|
||||
ASSERT_GT(runtime, 0);
|
||||
webrtc::test::PrintResult(
|
||||
"neteq_performance", "", "10_pl_10_drift", runtime, "ms", true);
|
||||
}
|
||||
|
||||
// Runs a test with neither packet losses nor clock drift, to put
|
||||
// emphasis on the "good-weather" code path, which is presumably much
|
||||
// more lightweight.
|
||||
TEST(NetEqPerformanceTest, RunClean) {
|
||||
const int kSimulationTimeMs = 10000000;
|
||||
const int kLossPeriod = 0; // No losses.
|
||||
const double kDriftFactor = 0.0; // No clock drift.
|
||||
int64_t runtime = webrtc::test::NetEqPerformanceTest::Run(
|
||||
kSimulationTimeMs, kLossPeriod, kDriftFactor);
|
||||
ASSERT_GT(runtime, 0);
|
||||
webrtc::test::PrintResult(
|
||||
"neteq_performance", "", "0_pl_0_drift", runtime, "ms", true);
|
||||
}
|
||||
80
webrtc/modules/audio_coding/neteq/test/neteq_speed_test.cc
Normal file
80
webrtc/modules/audio_coding/neteq/test/neteq_speed_test.cc
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2013 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 <stdio.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gflags/gflags.h"
|
||||
#include "webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// Flag validators.
|
||||
static bool ValidateRuntime(const char* flagname, int value) {
|
||||
if (value > 0) // Value is ok.
|
||||
return true;
|
||||
printf("Invalid value for --%s: %d\n", flagname, static_cast<int>(value));
|
||||
return false;
|
||||
}
|
||||
static bool ValidateLossrate(const char* flagname, int value) {
|
||||
if (value >= 0) // Value is ok.
|
||||
return true;
|
||||
printf("Invalid value for --%s: %d\n", flagname, static_cast<int>(value));
|
||||
return false;
|
||||
}
|
||||
static bool ValidateDriftfactor(const char* flagname, double value) {
|
||||
if (value >= 0.0 && value < 1.0) // Value is ok.
|
||||
return true;
|
||||
printf("Invalid value for --%s: %f\n", flagname, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Define command line flags.
|
||||
DEFINE_int32(runtime_ms, 10000, "Simulated runtime in ms.");
|
||||
static const bool runtime_ms_dummy =
|
||||
google::RegisterFlagValidator(&FLAGS_runtime_ms, &ValidateRuntime);
|
||||
DEFINE_int32(lossrate, 10,
|
||||
"Packet lossrate; drop every N packets.");
|
||||
static const bool lossrate_dummy =
|
||||
google::RegisterFlagValidator(&FLAGS_lossrate, &ValidateLossrate);
|
||||
DEFINE_double(drift, 0.1,
|
||||
"Clockdrift factor.");
|
||||
static const bool drift_dummy =
|
||||
google::RegisterFlagValidator(&FLAGS_drift, &ValidateDriftfactor);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string program_name = argv[0];
|
||||
std::string usage = "Tool for measuring the speed of NetEq.\n"
|
||||
"Usage: " + program_name + " [options]\n\n"
|
||||
" --runtime_ms=N runtime in ms; default is 10000 ms\n"
|
||||
" --lossrate=N drop every N packets; default is 10\n"
|
||||
" --drift=F clockdrift factor between 0.0 and 1.0; "
|
||||
"default is 0.1\n";
|
||||
google::SetUsageMessage(usage);
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
if (argc != 1) {
|
||||
// Print usage information.
|
||||
std::cout << google::ProgramUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t result =
|
||||
webrtc::test::NetEqPerformanceTest::Run(FLAGS_runtime_ms, FLAGS_lossrate,
|
||||
FLAGS_drift);
|
||||
if (result <= 0) {
|
||||
std::cout << "There was an error" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Simulation done" << std::endl;
|
||||
std::cout << "Runtime = " << result << " ms" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
124
webrtc/modules/audio_coding/neteq/test/rtp_to_text.cc
Normal file
124
webrtc/modules/audio_coding/neteq/test/rtp_to_text.cc
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parses an rtpdump file and outputs a text table parsable by parseLog.m.
|
||||
* The output file will have .txt appended to the specified base name.
|
||||
* $ rtp_to_text [-d] <input_rtp_file> <output_base_name>
|
||||
*
|
||||
* -d RTP headers only
|
||||
*
|
||||
*/
|
||||
|
||||
#include "data_log.h"
|
||||
#include "NETEQTEST_DummyRTPpacket.h"
|
||||
#include "NETEQTEST_RTPpacket.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/*********************/
|
||||
/* Misc. definitions */
|
||||
/*********************/
|
||||
|
||||
#define FIRSTLINELEN 40
|
||||
|
||||
using ::webrtc::DataLog;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int arg_count = 1;
|
||||
NETEQTEST_RTPpacket* packet;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
printf("Usage: %s [-d] <input_rtp_file> <output_base_name>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Parse dummy option
|
||||
if (argc >= 3 && strcmp(argv[arg_count], "-d") == 0)
|
||||
{
|
||||
packet = new NETEQTEST_DummyRTPpacket;
|
||||
++arg_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet = new NETEQTEST_RTPpacket;
|
||||
}
|
||||
|
||||
std::string input_filename = argv[arg_count++];
|
||||
std::string table_name = argv[arg_count];
|
||||
|
||||
std::cout << "Input file: " << input_filename << std::endl;
|
||||
std::cout << "Output file: " << table_name << ".txt" << std::endl;
|
||||
|
||||
FILE *inFile=fopen(input_filename.c_str(),"rb");
|
||||
if (!inFile)
|
||||
{
|
||||
std::cout << "Cannot open input file " << input_filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up the DataLog and define the table
|
||||
DataLog::CreateLog();
|
||||
if (DataLog::AddTable(table_name) < 0)
|
||||
{
|
||||
std::cout << "Error adding table " << table_name << ".txt" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DataLog::AddColumn(table_name, "seq", 1);
|
||||
DataLog::AddColumn(table_name, "ssrc", 1);
|
||||
DataLog::AddColumn(table_name, "payload type", 1);
|
||||
DataLog::AddColumn(table_name, "length", 1);
|
||||
DataLog::AddColumn(table_name, "timestamp", 1);
|
||||
DataLog::AddColumn(table_name, "marker bit", 1);
|
||||
DataLog::AddColumn(table_name, "arrival", 1);
|
||||
|
||||
// read file header
|
||||
char firstline[FIRSTLINELEN];
|
||||
if (fgets(firstline, FIRSTLINELEN, inFile) == NULL)
|
||||
{
|
||||
std::cout << "Error reading file " << input_filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// start_sec + start_usec + source + port + padding
|
||||
if (fread(firstline, 4+4+4+2+2, 1, inFile) != 1)
|
||||
{
|
||||
std::cout << "Error reading file " << input_filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (packet->readFromFile(inFile) >= 0)
|
||||
{
|
||||
// write packet headers to
|
||||
DataLog::InsertCell(table_name, "seq", packet->sequenceNumber());
|
||||
DataLog::InsertCell(table_name, "ssrc", packet->SSRC());
|
||||
DataLog::InsertCell(table_name, "payload type", packet->payloadType());
|
||||
DataLog::InsertCell(table_name, "length", packet->dataLen());
|
||||
DataLog::InsertCell(table_name, "timestamp", packet->timeStamp());
|
||||
DataLog::InsertCell(table_name, "marker bit", packet->markerBit());
|
||||
DataLog::InsertCell(table_name, "arrival", packet->time());
|
||||
DataLog::NextRow(table_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DataLog::ReturnLog();
|
||||
|
||||
fclose(inFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user