Files
platform-external-webrtc/webrtc/modules/audio_coding/main/test/RTPFile.cc
henrik.lundin@webrtc.org 741711a861 Revert r7049/r7123, which added unnecessary "u"s to "return 0"s.
r7049 added some unnecessary casts ("return 0" -> "return static_cast<uint16_t>(0)").  r7123 converted these to "return 0u".  The original impetus for this was to eliminate type conversion warnings.  However, the 'u's are unnecessary; Visual Studio can return "0" from a function returning an unsigned value without producing a warning.  The real reason for the original warnings was that the code was returning -1 from a function returning an unsigned value, which does need a cast; the -1s were eliminated before the above two revisions landed.

Also reverse the order of some conditionals to prevent possible underflow.
While the underflow wouldn't have changed the behavior of the code, it's easier
to reason about the code when such underflow can't happen, and possibly safer
against future modifications as well.

BUG=3663
TEST=none
R=tina.legrand@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7296 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-09-25 07:38:14 +00:00

249 lines
7.6 KiB
C++

/*
* 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>
#ifdef WIN32
# include <Winsock2.h>
#else
# include <arpa/inet.h>
#endif
#include "audio_coding_module.h"
#include "engine_configurations.h"
#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] = (unsigned char) 0x80;
rtpHeader[1] = (unsigned char) (payloadType & 0xFF);
rtpHeader[2] = (unsigned char) ((seqNo >> 8) & 0xFF);
rtpHeader[3] = (unsigned char) ((seqNo) & 0xFF);
rtpHeader[4] = (unsigned char) ((timeStamp >> 24) & 0xFF);
rtpHeader[5] = (unsigned char) ((timeStamp >> 16) & 0xFF);
rtpHeader[6] = (unsigned char) ((timeStamp >> 8) & 0xFF);
rtpHeader[7] = (unsigned char) (timeStamp & 0xFF);
rtpHeader[8] = (unsigned char) ((ssrc >> 24) & 0xFF);
rtpHeader[9] = (unsigned char) ((ssrc >> 16) & 0xFF);
rtpHeader[10] = (unsigned char) ((ssrc >> 8) & 0xFF);
rtpHeader[11] = (unsigned char) (ssrc & 0xFF);
}
RTPPacket::RTPPacket(uint8_t payloadType, uint32_t timeStamp, int16_t seqNo,
const uint8_t* payloadData, uint16_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 uint16_t payloadSize, uint32_t frequency) {
RTPPacket *packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData,
payloadSize, frequency);
_queueRWLock->AcquireLockExclusive();
_rtpQueue.push(packet);
_queueRWLock->ReleaseLockExclusive();
}
uint16_t RTPBuffer::Read(WebRtcRTPHeader* rtpInfo, uint8_t* payloadData,
uint16_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
if (fwrite(&dummy_variable, 4, 1, _rtpFile) != 1) {
return;
}
if (fwrite(&dummy_variable, 4, 1, _rtpFile) != 1) {
return;
}
if (fwrite(&dummy_variable, 4, 1, _rtpFile) != 1) {
return;
}
if (fwrite(&dummy_variable, 2, 1, _rtpFile) != 1) {
return;
}
if (fwrite(&dummy_variable, 2, 1, _rtpFile) != 1) {
return;
}
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 uint16_t payloadSize, uint32_t frequency) {
/* write RTP packet to file */
uint8_t rtpHeader[12];
MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0);
uint16_t lengthBytes = htons(12 + payloadSize + 8);
uint16_t plen = htons(12 + payloadSize);
uint32_t offsetMs;
offsetMs = (timeStamp / (frequency / 1000));
offsetMs = htonl(offsetMs);
if (fwrite(&lengthBytes, 2, 1, _rtpFile) != 1) {
return;
}
if (fwrite(&plen, 2, 1, _rtpFile) != 1) {
return;
}
if (fwrite(&offsetMs, 4, 1, _rtpFile) != 1) {
return;
}
if (fwrite(rtpHeader, 12, 1, _rtpFile) != 1) {
return;
}
if (fwrite(payloadData, 1, payloadSize, _rtpFile) != payloadSize) {
return;
}
}
uint16_t RTPFile::Read(WebRtcRTPHeader* rtpInfo, uint8_t* payloadData,
uint16_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 < (lengthBytes - 20)) {
return 0;
}
lengthBytes -= 20;
EXPECT_EQ(lengthBytes, fread(payloadData, 1, lengthBytes, _rtpFile));
return lengthBytes;
}
} // namespace webrtc