1/* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" 12 13#include <assert.h> 14#include <string.h> 15#ifdef WIN32 16#include <winsock2.h> 17#else 18#include <netinet/in.h> 19#endif 20 21#include "webrtc/modules/audio_coding/neteq/tools/packet.h" 22#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 23 24namespace webrtc { 25namespace test { 26 27RtpFileSource* RtpFileSource::Create(const std::string& file_name) { 28 RtpFileSource* source = new RtpFileSource; 29 assert(source); 30 if (!source->OpenFile(file_name) || !source->SkipFileHeader()) { 31 assert(false); 32 delete source; 33 return NULL; 34 } 35 return source; 36} 37 38RtpFileSource::~RtpFileSource() { 39 if (in_file_) 40 fclose(in_file_); 41} 42 43bool RtpFileSource::RegisterRtpHeaderExtension(RTPExtensionType type, 44 uint8_t id) { 45 assert(parser_.get()); 46 return parser_->RegisterRtpHeaderExtension(type, id); 47} 48 49Packet* RtpFileSource::NextPacket() { 50 while (!EndOfFile()) { 51 uint16_t length; 52 if (fread(&length, sizeof(length), 1, in_file_) == 0) { 53 assert(false); 54 return NULL; 55 } 56 length = ntohs(length); 57 58 uint16_t plen; 59 if (fread(&plen, sizeof(plen), 1, in_file_) == 0) { 60 assert(false); 61 return NULL; 62 } 63 plen = ntohs(plen); 64 65 uint32_t offset; 66 if (fread(&offset, sizeof(offset), 1, in_file_) == 0) { 67 assert(false); 68 return NULL; 69 } 70 offset = ntohl(offset); 71 72 // Use length here because a plen of 0 specifies RTCP. 73 assert(length >= kPacketHeaderSize); 74 size_t packet_size_bytes = length - kPacketHeaderSize; 75 if (packet_size_bytes == 0) { 76 // May be an RTCP packet. 77 // Read the next one. 78 continue; 79 } 80 scoped_ptr<uint8_t> packet_memory(new uint8_t[packet_size_bytes]); 81 if (fread(packet_memory.get(), 1, packet_size_bytes, in_file_) != 82 packet_size_bytes) { 83 assert(false); 84 return NULL; 85 } 86 scoped_ptr<Packet> packet(new Packet(packet_memory.release(), 87 packet_size_bytes, 88 plen, 89 offset, 90 *parser_.get())); 91 if (!packet->valid_header()) { 92 assert(false); 93 return NULL; 94 } 95 if (filter_.test(packet->header().payloadType)) { 96 // This payload type should be filtered out. Continue to the next packet. 97 continue; 98 } 99 return packet.release(); 100 } 101 return NULL; 102} 103 104bool RtpFileSource::EndOfFile() const { 105 assert(in_file_); 106 return ftell(in_file_) >= file_end_; 107} 108 109RtpFileSource::RtpFileSource() 110 : PacketSource(), 111 in_file_(NULL), 112 file_end_(-1), 113 parser_(RtpHeaderParser::Create()) {} 114 115bool RtpFileSource::OpenFile(const std::string& file_name) { 116 in_file_ = fopen(file_name.c_str(), "rb"); 117 assert(in_file_); 118 if (in_file_ == NULL) { 119 return false; 120 } 121 122 // Find out how long the file is. 123 fseek(in_file_, 0, SEEK_END); 124 file_end_ = ftell(in_file_); 125 rewind(in_file_); 126 return true; 127} 128 129bool RtpFileSource::SkipFileHeader() { 130 char firstline[kFirstLineLength]; 131 assert(in_file_); 132 if (fgets(firstline, kFirstLineLength, in_file_) == NULL) { 133 assert(false); 134 return false; 135 } 136 // Check that the first line is ok. 137 if ((strncmp(firstline, "#!rtpplay1.0", 12) != 0) && 138 (strncmp(firstline, "#!RTPencode1.0", 14) != 0)) { 139 assert(false); 140 return false; 141 } 142 // Skip the file header. 143 if (fseek(in_file_, kRtpFileHeaderSize, SEEK_CUR) != 0) { 144 assert(false); 145 return false; 146 } 147 return true; 148} 149 150} // namespace test 151} // namespace webrtc 152