Let RtpFileSource use RtpFileReader

RtpFileSource used to implement it's own RTP dump file reader, but
with this change it simply uses RtpFileReader. One benefit is that
pcap files are now also supported.

All NetEq test tools that use RtpFileSource are updated.

BUG=2692
R=kwiberg@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7367 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2014-10-02 08:19:38 +00:00
parent 348eac641e
commit 4b133da5fd
6 changed files with 45 additions and 99 deletions

View File

@ -170,6 +170,7 @@
'type': 'static_library',
'dependencies': [
'rtp_rtcp',
'<(webrtc_root)/test/webrtc_test_common.gyp:webrtc_test_common',
],
'direct_dependent_settings': {
'include_dirs': [

View File

@ -172,12 +172,12 @@ int main(int argc, char* argv[]) {
RegisterPayloadTypes(neteq);
// Read first packet.
if (file_source->EndOfFile()) {
webrtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket());
if (!packet) {
printf("Warning: RTP file is empty");
webrtc::Trace::ReturnTrace();
return 0;
}
webrtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket());
bool packet_available = true;
// Set up variables for audio replacement if needed.
@ -195,8 +195,8 @@ int main(int argc, char* argv[]) {
replacement_audio.reset(new int16_t[input_frame_size_timestamps]);
payload_mem_size_bytes = 2 * input_frame_size_timestamps;
payload.reset(new uint8_t[payload_mem_size_bytes]);
assert(!file_source->EndOfFile());
next_packet.reset(file_source->NextPacket());
assert(next_packet);
next_packet_available = true;
}
@ -241,8 +241,9 @@ int main(int argc, char* argv[]) {
}
// Get next packet from file.
if (!file_source->EndOfFile()) {
packet.reset(file_source->NextPacket());
webrtc::test::Packet* temp_packet = file_source->NextPacket();
if (temp_packet) {
packet.reset(temp_packet);
} else {
packet_available = false;
}

View File

@ -24,7 +24,7 @@ class Packet;
// Interface class for an object delivering RTP packets to test applications.
class PacketSource {
public:
PacketSource() {}
PacketSource() : use_ssrc_filter_(false), ssrc_(0) {}
virtual ~PacketSource() {}
// Returns a pointer to the next packet. Returns NULL if the source is
@ -35,8 +35,16 @@ class PacketSource {
filter_.set(payload_type, true);
}
virtual void SelectSsrc(uint32_t ssrc) {
use_ssrc_filter_ = true;
ssrc_ = ssrc;
}
protected:
std::bitset<128> filter_; // Payload type is 7 bits in the RFC.
// If SSRC filtering discards all packet that do not match the SSRC.
bool use_ssrc_filter_; // True when SSRC filtering is active.
uint32_t ssrc_; // The selected SSRC. All other SSRCs will be discarded.
private:
DISALLOW_COPY_AND_ASSIGN(PacketSource);

View File

@ -91,13 +91,12 @@ int main(int argc, char* argv[]) {
fprintf(out_file, "\n");
webrtc::scoped_ptr<webrtc::test::Packet> packet;
while (!file_source->EndOfFile()) {
while (true) {
packet.reset(file_source->NextPacket());
if (!packet.get()) {
// This is probably an RTCP packet. Move on to the next one.
continue;
// End of file reached.
break;
}
assert(packet.get());
// Write packet data to file.
fprintf(out_file,
"%5u %10u %10u %5i %5i %2i %#08X",

View File

@ -18,26 +18,21 @@
#include <netinet/in.h>
#endif
#include "webrtc/base/checks.h"
#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
#include "webrtc/test/rtp_file_reader.h"
namespace webrtc {
namespace test {
RtpFileSource* RtpFileSource::Create(const std::string& file_name) {
RtpFileSource* source = new RtpFileSource;
assert(source);
if (!source->OpenFile(file_name) || !source->SkipFileHeader()) {
assert(false);
delete source;
return NULL;
}
RtpFileSource* source = new RtpFileSource();
CHECK(source->OpenFile(file_name));
return source;
}
RtpFileSource::~RtpFileSource() {
if (in_file_)
fclose(in_file_);
}
bool RtpFileSource::RegisterRtpHeaderExtension(RTPExtensionType type,
@ -47,102 +42,48 @@ bool RtpFileSource::RegisterRtpHeaderExtension(RTPExtensionType type,
}
Packet* RtpFileSource::NextPacket() {
while (!EndOfFile()) {
uint16_t length;
if (fread(&length, sizeof(length), 1, in_file_) == 0) {
assert(false);
while (true) {
RtpFileReader::Packet temp_packet;
if (!rtp_reader_->NextPacket(&temp_packet)) {
return NULL;
}
length = ntohs(length);
uint16_t plen;
if (fread(&plen, sizeof(plen), 1, in_file_) == 0) {
assert(false);
return NULL;
}
plen = ntohs(plen);
uint32_t offset;
if (fread(&offset, sizeof(offset), 1, in_file_) == 0) {
assert(false);
return NULL;
}
offset = ntohl(offset);
// Use length here because a plen of 0 specifies RTCP.
assert(length >= kPacketHeaderSize);
size_t packet_size_bytes = length - kPacketHeaderSize;
if (packet_size_bytes == 0) {
if (temp_packet.length == 0) {
// May be an RTCP packet.
// Read the next one.
continue;
}
scoped_ptr<uint8_t> packet_memory(new uint8_t[packet_size_bytes]);
if (fread(packet_memory.get(), 1, packet_size_bytes, in_file_) !=
packet_size_bytes) {
assert(false);
return NULL;
}
scoped_ptr<uint8_t[]> packet_memory(new uint8_t[temp_packet.length]);
memcpy(packet_memory.get(), temp_packet.data, temp_packet.length);
scoped_ptr<Packet> packet(new Packet(packet_memory.release(),
packet_size_bytes,
plen,
offset,
temp_packet.length,
temp_packet.original_length,
temp_packet.time_ms,
*parser_.get()));
if (!packet->valid_header()) {
assert(false);
return NULL;
}
if (filter_.test(packet->header().payloadType)) {
if (filter_.test(packet->header().payloadType) ||
(use_ssrc_filter_ && packet->header().ssrc != ssrc_)) {
// This payload type should be filtered out. Continue to the next packet.
continue;
}
return packet.release();
}
return NULL;
}
bool RtpFileSource::EndOfFile() const {
assert(in_file_);
return ftell(in_file_) >= file_end_;
}
RtpFileSource::RtpFileSource()
: PacketSource(),
in_file_(NULL),
file_end_(-1),
parser_(RtpHeaderParser::Create()) {}
bool RtpFileSource::OpenFile(const std::string& file_name) {
in_file_ = fopen(file_name.c_str(), "rb");
assert(in_file_);
if (in_file_ == NULL) {
return false;
}
// Find out how long the file is.
fseek(in_file_, 0, SEEK_END);
file_end_ = ftell(in_file_);
rewind(in_file_);
return true;
}
bool RtpFileSource::SkipFileHeader() {
char firstline[kFirstLineLength];
assert(in_file_);
if (fgets(firstline, kFirstLineLength, in_file_) == NULL) {
assert(false);
return false;
}
// Check that the first line is ok.
if ((strncmp(firstline, "#!rtpplay1.0", 12) != 0) &&
(strncmp(firstline, "#!RTPencode1.0", 14) != 0)) {
assert(false);
return false;
}
// Skip the file header.
if (fseek(in_file_, kRtpFileHeaderSize, SEEK_CUR) != 0) {
assert(false);
return false;
rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kRtpDump, file_name));
if (rtp_reader_)
return true;
rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kPcap, file_name));
if (!rtp_reader_) {
FATAL() << "Couldn't open input file as either a rtpdump or .pcap. Note "
"that .pcapng is not supported.";
}
return true;
}

View File

@ -26,6 +26,8 @@ class RtpHeaderParser;
namespace test {
class RtpFileReader;
class RtpFileSource : public PacketSource {
public:
// Creates an RtpFileSource reading from |file_name|. If the file cannot be
@ -39,10 +41,7 @@ class RtpFileSource : public PacketSource {
// Returns a pointer to the next packet. Returns NULL if end of file was
// reached, or if a the data was corrupt.
virtual Packet* NextPacket();
// Returns true if the end of file has been reached.
virtual bool EndOfFile() const;
virtual Packet* NextPacket() OVERRIDE;
private:
static const int kFirstLineLength = 40;
@ -53,10 +52,7 @@ class RtpFileSource : public PacketSource {
bool OpenFile(const std::string& file_name);
bool SkipFileHeader();
FILE* in_file_;
int64_t file_end_;
scoped_ptr<RtpFileReader> rtp_reader_;
scoped_ptr<RtpHeaderParser> parser_;
DISALLOW_COPY_AND_ASSIGN(RtpFileSource);