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 24 namespace webrtc { 25 namespace test { 26 27 RtpFileSource* 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 38 RtpFileSource::~RtpFileSource() { 39 if (in_file_) 40 fclose(in_file_); 41 } 42 43 bool RtpFileSource::RegisterRtpHeaderExtension(RTPExtensionType type, 44 uint8_t id) { 45 assert(parser_.get()); 46 return parser_->RegisterRtpHeaderExtension(type, id); 47 } 48 49 Packet* 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 return packet.release(); 96 } 97 return NULL; 98 } 99 100 bool RtpFileSource::EndOfFile() const { 101 assert(in_file_); 102 return ftell(in_file_) >= file_end_; 103 } 104 105 RtpFileSource::RtpFileSource() 106 : PacketSource(), 107 in_file_(NULL), 108 file_end_(-1), 109 parser_(RtpHeaderParser::Create()) {} 110 111 bool RtpFileSource::OpenFile(const std::string& file_name) { 112 in_file_ = fopen(file_name.c_str(), "rb"); 113 assert(in_file_); 114 if (in_file_ == NULL) { 115 return false; 116 } 117 118 // Find out how long the file is. 119 fseek(in_file_, 0, SEEK_END); 120 file_end_ = ftell(in_file_); 121 rewind(in_file_); 122 return true; 123 } 124 125 bool RtpFileSource::SkipFileHeader() { 126 char firstline[kFirstLineLength]; 127 assert(in_file_); 128 if (fgets(firstline, kFirstLineLength, in_file_) == NULL) { 129 assert(false); 130 return false; 131 } 132 // Check that the first line is ok. 133 if ((strncmp(firstline, "#!rtpplay1.0", 12) != 0) && 134 (strncmp(firstline, "#!RTPencode1.0", 14) != 0)) { 135 assert(false); 136 return false; 137 } 138 // Skip the file header. 139 if (fseek(in_file_, kRtpFileHeaderSize, SEEK_CUR) != 0) { 140 assert(false); 141 return false; 142 } 143 return true; 144 } 145 146 } // namespace test 147 } // namespace webrtc 148