Home | History | Annotate | Download | only in tools
      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