diff options
Diffstat (limited to 'webrtc/modules/audio_coding/test/RTPFile.cc')
-rw-r--r-- | webrtc/modules/audio_coding/test/RTPFile.cc | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/webrtc/modules/audio_coding/test/RTPFile.cc b/webrtc/modules/audio_coding/test/RTPFile.cc new file mode 100644 index 0000000000..60777178c6 --- /dev/null +++ b/webrtc/modules/audio_coding/test/RTPFile.cc @@ -0,0 +1,227 @@ +/* + * 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 "RTPFile.h" + +#include <stdlib.h> +#include <limits> + +#ifdef WIN32 +# include <Winsock2.h> +#else +# include <arpa/inet.h> +#endif + +#include "audio_coding_module.h" +#include "engine_configurations.h" +#include "webrtc/system_wrappers/include/rw_lock_wrapper.h" +// TODO(tlegrand): Consider removing usage of gtest. +#include "testing/gtest/include/gtest/gtest.h" + +namespace webrtc { + +void RTPStream::ParseRTPHeader(WebRtcRTPHeader* rtpInfo, + const uint8_t* rtpHeader) { + rtpInfo->header.payloadType = rtpHeader[1]; + rtpInfo->header.sequenceNumber = (static_cast<uint16_t>(rtpHeader[2]) << 8) | + rtpHeader[3]; + rtpInfo->header.timestamp = (static_cast<uint32_t>(rtpHeader[4]) << 24) | + (static_cast<uint32_t>(rtpHeader[5]) << 16) | + (static_cast<uint32_t>(rtpHeader[6]) << 8) | rtpHeader[7]; + rtpInfo->header.ssrc = (static_cast<uint32_t>(rtpHeader[8]) << 24) | + (static_cast<uint32_t>(rtpHeader[9]) << 16) | + (static_cast<uint32_t>(rtpHeader[10]) << 8) | rtpHeader[11]; +} + +void RTPStream::MakeRTPheader(uint8_t* rtpHeader, uint8_t payloadType, + int16_t seqNo, uint32_t timeStamp, + uint32_t ssrc) { + rtpHeader[0] = 0x80; + rtpHeader[1] = payloadType; + rtpHeader[2] = (seqNo >> 8) & 0xFF; + rtpHeader[3] = seqNo & 0xFF; + rtpHeader[4] = timeStamp >> 24; + rtpHeader[5] = (timeStamp >> 16) & 0xFF; + rtpHeader[6] = (timeStamp >> 8) & 0xFF; + rtpHeader[7] = timeStamp & 0xFF; + rtpHeader[8] = ssrc >> 24; + rtpHeader[9] = (ssrc >> 16) & 0xFF; + rtpHeader[10] = (ssrc >> 8) & 0xFF; + rtpHeader[11] = ssrc & 0xFF; +} + +RTPPacket::RTPPacket(uint8_t payloadType, uint32_t timeStamp, int16_t seqNo, + const uint8_t* payloadData, size_t payloadSize, + uint32_t frequency) + : payloadType(payloadType), + timeStamp(timeStamp), + seqNo(seqNo), + payloadSize(payloadSize), + frequency(frequency) { + if (payloadSize > 0) { + this->payloadData = new uint8_t[payloadSize]; + memcpy(this->payloadData, payloadData, payloadSize); + } +} + +RTPPacket::~RTPPacket() { + delete[] payloadData; +} + +RTPBuffer::RTPBuffer() { + _queueRWLock = RWLockWrapper::CreateRWLock(); +} + +RTPBuffer::~RTPBuffer() { + delete _queueRWLock; +} + +void RTPBuffer::Write(const uint8_t payloadType, const uint32_t timeStamp, + const int16_t seqNo, const uint8_t* payloadData, + const size_t payloadSize, uint32_t frequency) { + RTPPacket *packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData, + payloadSize, frequency); + _queueRWLock->AcquireLockExclusive(); + _rtpQueue.push(packet); + _queueRWLock->ReleaseLockExclusive(); +} + +size_t RTPBuffer::Read(WebRtcRTPHeader* rtpInfo, uint8_t* payloadData, + size_t payloadSize, uint32_t* offset) { + _queueRWLock->AcquireLockShared(); + RTPPacket *packet = _rtpQueue.front(); + _rtpQueue.pop(); + _queueRWLock->ReleaseLockShared(); + rtpInfo->header.markerBit = 1; + rtpInfo->header.payloadType = packet->payloadType; + rtpInfo->header.sequenceNumber = packet->seqNo; + rtpInfo->header.ssrc = 0; + rtpInfo->header.timestamp = packet->timeStamp; + if (packet->payloadSize > 0 && payloadSize >= packet->payloadSize) { + memcpy(payloadData, packet->payloadData, packet->payloadSize); + } else { + return 0; + } + *offset = (packet->timeStamp / (packet->frequency / 1000)); + + return packet->payloadSize; +} + +bool RTPBuffer::EndOfFile() const { + _queueRWLock->AcquireLockShared(); + bool eof = _rtpQueue.empty(); + _queueRWLock->ReleaseLockShared(); + return eof; +} + +void RTPFile::Open(const char *filename, const char *mode) { + if ((_rtpFile = fopen(filename, mode)) == NULL) { + printf("Cannot write file %s.\n", filename); + ADD_FAILURE() << "Unable to write file"; + exit(1); + } +} + +void RTPFile::Close() { + if (_rtpFile != NULL) { + fclose(_rtpFile); + _rtpFile = NULL; + } +} + +void RTPFile::WriteHeader() { + // Write data in a format that NetEQ and RTP Play can parse + fprintf(_rtpFile, "#!RTPencode%s\n", "1.0"); + uint32_t dummy_variable = 0; + // should be converted to network endian format, but does not matter when 0 + EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile)); + fflush(_rtpFile); +} + +void RTPFile::ReadHeader() { + uint32_t start_sec, start_usec, source; + uint16_t port, padding; + char fileHeader[40]; + EXPECT_TRUE(fgets(fileHeader, 40, _rtpFile) != 0); + EXPECT_EQ(1u, fread(&start_sec, 4, 1, _rtpFile)); + start_sec = ntohl(start_sec); + EXPECT_EQ(1u, fread(&start_usec, 4, 1, _rtpFile)); + start_usec = ntohl(start_usec); + EXPECT_EQ(1u, fread(&source, 4, 1, _rtpFile)); + source = ntohl(source); + EXPECT_EQ(1u, fread(&port, 2, 1, _rtpFile)); + port = ntohs(port); + EXPECT_EQ(1u, fread(&padding, 2, 1, _rtpFile)); + padding = ntohs(padding); +} + +void RTPFile::Write(const uint8_t payloadType, const uint32_t timeStamp, + const int16_t seqNo, const uint8_t* payloadData, + const size_t payloadSize, uint32_t frequency) { + /* write RTP packet to file */ + uint8_t rtpHeader[12]; + MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0); + ASSERT_LE(12 + payloadSize + 8, std::numeric_limits<u_short>::max()); + uint16_t lengthBytes = htons(static_cast<u_short>(12 + payloadSize + 8)); + uint16_t plen = htons(static_cast<u_short>(12 + payloadSize)); + uint32_t offsetMs; + + offsetMs = (timeStamp / (frequency / 1000)); + offsetMs = htonl(offsetMs); + EXPECT_EQ(1u, fwrite(&lengthBytes, 2, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&plen, 2, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&offsetMs, 4, 1, _rtpFile)); + EXPECT_EQ(1u, fwrite(&rtpHeader, 12, 1, _rtpFile)); + EXPECT_EQ(payloadSize, fwrite(payloadData, 1, payloadSize, _rtpFile)); +} + +size_t RTPFile::Read(WebRtcRTPHeader* rtpInfo, uint8_t* payloadData, + size_t payloadSize, uint32_t* offset) { + uint16_t lengthBytes; + uint16_t plen; + uint8_t rtpHeader[12]; + size_t read_len = fread(&lengthBytes, 2, 1, _rtpFile); + /* Check if we have reached end of file. */ + if ((read_len == 0) && feof(_rtpFile)) { + _rtpEOF = true; + return 0; + } + EXPECT_EQ(1u, fread(&plen, 2, 1, _rtpFile)); + EXPECT_EQ(1u, fread(offset, 4, 1, _rtpFile)); + lengthBytes = ntohs(lengthBytes); + plen = ntohs(plen); + *offset = ntohl(*offset); + EXPECT_GT(plen, 11); + + EXPECT_EQ(1u, fread(rtpHeader, 12, 1, _rtpFile)); + ParseRTPHeader(rtpInfo, rtpHeader); + rtpInfo->type.Audio.isCNG = false; + rtpInfo->type.Audio.channel = 1; + EXPECT_EQ(lengthBytes, plen + 8); + + if (plen == 0) { + return 0; + } + if (lengthBytes < 20) { + return 0; + } + if (payloadSize < static_cast<size_t>((lengthBytes - 20))) { + return 0; + } + lengthBytes -= 20; + EXPECT_EQ(lengthBytes, fread(payloadData, 1, lengthBytes, _rtpFile)); + return lengthBytes; +} + +} // namespace webrtc |