14d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org/*
2ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
34d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *
44d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *  Use of this source code is governed by a BSD-style license
54d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *  that can be found in the LICENSE file in the root of the source
64d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *  tree. An additional intellectual property rights grant can be found
74d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *  in the file PATENTS.  All contributing project authors may
84d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
94d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org */
104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
11ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#include "webrtc/test/rtp_file_reader.h"
124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <stdio.h>
143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org
154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <map>
164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <string>
174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <vector>
184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h"
214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgnamespace webrtc {
23ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgnamespace test {
24ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
25ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgstatic const size_t kFirstLineLength = 40;
26ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgstatic uint16_t kPacketHeaderSize = 8;
27ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
28ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#if 1
29ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG(text)
30ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG1(text, arg)
31ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#else
32ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG(text) (printf(text "\n"))
33ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG1(text, arg) (printf(text "\n", arg))
34ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#endif
35ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
36ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#define TRY(expr)                                      \
37ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  do {                                                 \
38ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (!(expr)) {                                     \
39ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \
40ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;                                    \
41ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }                                                  \
42ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  } while (0)
43ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
44ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgclass RtpFileReaderImpl : public RtpFileReader {
45ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org public:
46ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  virtual bool Init(const std::string& filename) = 0;
47ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org};
48ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
49ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org// Read RTP packets from file in rtpdump format, as documented at:
50ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org// http://www.cs.columbia.edu/irt/software/rtptools/
51ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgclass RtpDumpReader : public RtpFileReaderImpl {
52ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org public:
53ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  RtpDumpReader() : file_(NULL) {}
54ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  virtual ~RtpDumpReader() {
55ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (file_ != NULL) {
56ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      fclose(file_);
57ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      file_ = NULL;
58ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
59ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
60ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
61ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  bool Init(const std::string& filename) {
62ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    file_ = fopen(filename.c_str(), "rb");
63ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (file_ == NULL) {
64ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      printf("ERROR: Can't open file: %s\n", filename.c_str());
65ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;
66ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
67ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
68ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    char firstline[kFirstLineLength + 1] = {0};
69ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (fgets(firstline, kFirstLineLength, file_) == NULL) {
70ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      DEBUG_LOG("ERROR: Can't read from file\n");
71ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;
72ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
73ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (strncmp(firstline, "#!rtpplay", 9) == 0) {
74ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
75ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        DEBUG_LOG("ERROR: wrong rtpplay version, must be 1.0\n");
76ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        return false;
77ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      }
78ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    } else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
79ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
80ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        DEBUG_LOG("ERROR: wrong RTPencode version, must be 1.0\n");
81ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        return false;
82ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      }
83ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    } else {
84ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      DEBUG_LOG("ERROR: wrong file format of input file\n");
85ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;
86ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
87ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
88ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint32_t start_sec;
89ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint32_t start_usec;
90ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint32_t source;
91ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint16_t port;
92ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint16_t padding;
93ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&start_sec));
94ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&start_usec));
95ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&source));
96ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&port));
97ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&padding));
98ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
99ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    return true;
100ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
101ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
102ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  virtual bool NextPacket(Packet* packet) OVERRIDE {
103ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint8_t* rtp_data = packet->data;
104ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    packet->length = Packet::kMaxPacketBufferSize;
105ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
106ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint16_t len;
107ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint16_t plen;
108ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint32_t offset;
109ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&len));
110ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&plen));
111ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY(Read(&offset));
112ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
113ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    // Use 'len' here because a 'plen' of 0 specifies rtcp.
114ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    len -= kPacketHeaderSize;
115ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (packet->length < len) {
116ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;
117ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
118ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (fread(rtp_data, 1, len, file_) != len) {
119ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;
120ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
121ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
122ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    packet->length = len;
123ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    packet->time_ms = offset;
124ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    return true;
125ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
126ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
127ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org private:
128ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  bool Read(uint32_t* out) {
129ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    *out = 0;
130ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    for (size_t i = 0; i < 4; ++i) {
131ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      *out <<= 8;
132ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      uint8_t tmp;
133ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t))
134ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        return false;
135ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      *out |= tmp;
136ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
137ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    return true;
138ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
139ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
140ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  bool Read(uint16_t* out) {
141ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    *out = 0;
142ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    for (size_t i = 0; i < 2; ++i) {
143ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      *out <<= 8;
144ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      uint8_t tmp;
145ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t))
146ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        return false;
147ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      *out |= tmp;
148ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }
149ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    return true;
150ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
151ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
152ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  FILE* file_;
153ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
154ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  DISALLOW_COPY_AND_ASSIGN(RtpDumpReader);
155ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org};
1564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgenum {
1584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kResultFail = -1,
1594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kResultSuccess = 0,
1604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kResultSkip = 1,
1614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kPcapVersionMajor = 2,
1634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kPcapVersionMinor = 4,
1644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kLinktypeNull = 0,
1654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kLinktypeEthernet = 1,
1664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kBsdNullLoopback1 = 0x00000002,
1674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kBsdNullLoopback2 = 0x02000000,
1684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kEthernetIIHeaderMacSkip = 12,
1694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kEthertypeIp = 0x0800,
1704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kIpVersion4 = 4,
1714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kMinIpHeaderLength = 20,
1724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kFragmentOffsetClear = 0x0000,
1734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kFragmentOffsetDoNotFragment = 0x4000,
1744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kProtocolTcp = 0x06,
1754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kProtocolUdp = 0x11,
1764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kUdpHeaderLength = 8,
1774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kMaxReadBufferSize = 4096
1784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
1794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgconst uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL;
1814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgconst uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL;
1824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
183ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#define TRY_PCAP(expr)                                 \
184ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  do {                                                 \
185ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    int r = (expr);                                    \
186ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (r == kResultFail) {                            \
187ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \
188ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return kResultFail;                              \
189ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    } else if (r == kResultSkip) {                     \
190ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return kResultSkip;                              \
191ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    }                                                  \
1924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  } while (0)
1934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org// Read RTP packets from file in tcpdump/libpcap format, as documented at:
1954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org// http://wiki.wireshark.org/Development/LibpcapFileFormat
196ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgclass PcapReader : public RtpFileReaderImpl {
1974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org public:
198ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  PcapReader()
1994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    : file_(NULL),
2004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      swap_pcap_byte_order_(false),
201ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#ifdef WEBRTC_ARCH_BIG_ENDIAN
2024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      swap_network_byte_order_(false),
203ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#else
204ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      swap_network_byte_order_(true),
205ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#endif
2064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      read_buffer_(),
2074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      packets_by_ssrc_(),
2084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      packets_(),
2094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      next_packet_it_() {
2104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
2114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
212ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  virtual ~PcapReader() {
2134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (file_ != NULL) {
2144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      fclose(file_);
2154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      file_ = NULL;
2164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
2184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
219ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  bool Init(const std::string& filename) OVERRIDE {
220ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    return Initialize(filename) == kResultSuccess;
221ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
222ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
2234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int Initialize(const std::string& filename) {
2244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    file_ = fopen(filename.c_str(), "rb");
2254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (file_ == NULL) {
2264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      printf("ERROR: Can't open file: %s\n", filename.c_str());
2274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
2284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (ReadGlobalHeader() < 0) {
2314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
2324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int total_packet_count = 0;
2354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t stream_start_ms = 0;
2364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int32_t next_packet_pos = ftell(file_);
2374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (;;) {
238ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET));
2394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      int result = ReadPacket(&next_packet_pos, stream_start_ms,
2400be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org                              ++total_packet_count);
2414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (result == kResultFail) {
2424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        break;
2434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      } else if (result == kResultSuccess && packets_.size() == 1) {
2444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        assert(stream_start_ms == 0);
2454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        PacketIterator it = packets_.begin();
2464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        stream_start_ms = it->time_offset_ms;
2474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        it->time_offset_ms = 0;
2484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
2494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (feof(file_) == 0) {
2524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      printf("Failed reading file!\n");
2534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
2544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Total packets in file: %d\n", total_packet_count);
2574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Total RTP/RTCP packets: %d\n", static_cast<int>(packets_.size()));
2584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (SsrcMapIterator mit = packets_by_ssrc_.begin();
2604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        mit != packets_by_ssrc_.end(); ++mit) {
2614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      uint32_t ssrc = mit->first;
2624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      const std::vector<uint32_t>& packet_numbers = mit->second;
2630be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org      uint8_t pt = packets_[packet_numbers[0]].rtp_header.payloadType;
2640be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org      printf("SSRC: %08x, %d packets, pt=%d\n", ssrc,
2650be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org             static_cast<int>(packet_numbers.size()), pt);
2664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // TODO(solenberg): Better validation of identified SSRC streams.
2694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    //
2704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Since we're dealing with raw network data here, we will wrongly identify
2714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // some packets as RTP. When these packets are consumed by RtpPlayer, they
2724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // are unlikely to cause issues as they will ultimately be filtered out by
2734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // the RtpRtcp module. However, we should really do better filtering here,
2744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // which we can accomplish in a number of ways, e.g.:
2754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    //
2764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // - Verify that the time stamps and sequence numbers for RTP packets are
2774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    //   both increasing/decreasing. If they move in different directions, the
2784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    //   SSRC is likely bogus and can be dropped. (Normally they should be inc-
2794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    //   reasing but we must allow packet reordering).
2804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // - If RTP sequence number is not changing, drop the stream.
2814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // - Can also use srcip:port->dstip:port pairs, assuming few SSRC collisions
2824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    //   for up/down streams.
2834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    next_packet_it_ = packets_.begin();
2854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
2864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
2874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
288ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  virtual bool NextPacket(Packet* packet) OVERRIDE {
289ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    uint32_t length = Packet::kMaxPacketBufferSize;
290ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    if (NextPcap(packet->data, &length, &packet->time_ms) != kResultSuccess)
291ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      return false;
292ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    packet->length = static_cast<size_t>(length);
293ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    return true;
294ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
295ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
296ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  virtual int NextPcap(uint8_t* data, uint32_t* length, uint32_t* time_ms) {
2974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(data);
2984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(length);
2994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(time_ms);
3004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (next_packet_it_ == packets_.end()) {
3024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return -1;
3034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
3044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (*length < next_packet_it_->payload_length) {
3054d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return -1;
3064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
307ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(fseek(file_, next_packet_it_->pos_in_file, SEEK_SET));
308ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(data, next_packet_it_->payload_length));
3094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    *length = next_packet_it_->payload_length;
3104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    *time_ms = next_packet_it_->time_offset_ms;
3114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    next_packet_it_++;
3124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return 0;
3144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
3154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org private:
3174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  // A marker of an RTP packet within the file.
3184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  struct RtpPacketMarker {
3190be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org    uint32_t packet_number;   // One-based index (like in WireShark)
3204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t time_offset_ms;
3214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t source_ip;
3224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t dest_ip;
3234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t source_port;
3244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t dest_port;
3256696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    RTPHeader rtp_header;
3260be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org    int32_t pos_in_file;      // Byte offset of payload from start of file.
3274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t payload_length;
3284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  };
3294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef std::vector<RtpPacketMarker>::iterator PacketIterator;
3314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef std::map<uint32_t, std::vector<uint32_t> > SsrcMap;
3324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef std::map<uint32_t, std::vector<uint32_t> >::iterator SsrcMapIterator;
3334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int ReadGlobalHeader() {
3354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t magic;
336ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&magic, false));
3374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (magic == kPcapBOMSwapOrder) {
3384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      swap_pcap_byte_order_ = true;
3394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    } else if (magic == kPcapBOMNoSwapOrder) {
3404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      swap_pcap_byte_order_ = false;
3414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    } else {
3424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
3434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
3444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t version_major;
3464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t version_minor;
347ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&version_major, false));
348ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&version_minor, false));
3494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (version_major != kPcapVersionMajor ||
3504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        version_minor != kPcapVersionMinor) {
3514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
3524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
3534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int32_t this_zone;  // GMT to local correction.
3554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t sigfigs;   // Accuracy of timestamps.
3564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t snaplen;   // Max length of captured packets, in octets.
3574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t network;   // Data link type.
358ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&this_zone, false));
359ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&sigfigs, false));
360ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&snaplen, false));
361ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&network, false));
3624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET.
3644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // See: http://www.tcpdump.org/linktypes.html
3654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (network != kLinktypeNull && network != kLinktypeEthernet) {
3664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
3674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
3684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
3704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
3714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int ReadPacket(int32_t* next_packet_pos, uint32_t stream_start_ms,
3734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org                 uint32_t number) {
3744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(next_packet_pos);
3754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t ts_sec;    // Timestamp seconds.
3774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t ts_usec;   // Timestamp microseconds.
3784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t incl_len;  // Number of octets of packet saved in file.
3794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t orig_len;  // Actual length of packet.
380ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&ts_sec, false));
381ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&ts_usec, false));
382ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&incl_len, false));
383ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&orig_len, false));
3844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    *next_packet_pos = ftell(file_) + incl_len;
3864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    RtpPacketMarker marker = {0};
3884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    marker.packet_number = number;
3894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    marker.time_offset_ms = CalcTimeDelta(ts_sec, ts_usec, stream_start_ms);
390ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(ReadPacketHeader(&marker));
3914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    marker.pos_in_file = ftell(file_);
3924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (marker.payload_length > sizeof(read_buffer_)) {
3944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      printf("Packet too large!\n");
3954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
3964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
397ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(read_buffer_, marker.payload_length));
3984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3996aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org    RtpUtility::RtpHeaderParser rtp_parser(read_buffer_, marker.payload_length);
4004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (rtp_parser.RTCP()) {
4010be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org      rtp_parser.ParseRtcp(&marker.rtp_header);
4024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      packets_.push_back(marker);
4034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    } else {
4044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (!rtp_parser.Parse(marker.rtp_header, NULL)) {
4054d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        DEBUG_LOG("Not recognized as RTP/RTCP");
4064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return kResultSkip;
4074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
4084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4096696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org      uint32_t ssrc = marker.rtp_header.ssrc;
4104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      packets_by_ssrc_[ssrc].push_back(marker.packet_number);
4114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      packets_.push_back(marker);
4124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
4134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
4154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
4164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int ReadPacketHeader(RtpPacketMarker* marker) {
4184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int32_t file_pos = ftell(file_);
4194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Check for BSD null/loopback frame header. The header is just 4 bytes in
4214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // native byte order, so we check for both versions as we don't care about
4224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // the header as such and will likely fail reading the IP header if this is
4234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // something else than null/loopback.
4244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t protocol;
425ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&protocol, true));
4264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) {
4274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      int result = ReadXxpIpHeader(marker);
4284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      DEBUG_LOG("Recognized loopback frame");
4294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (result != kResultSkip) {
4304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return result;
4314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
4324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
4334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
434ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(fseek(file_, file_pos, SEEK_SET));
4354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Check for Ethernet II, IP frame header.
4374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t type;
438ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Skip(kEthernetIIHeaderMacSkip));  // Source+destination MAC.
439ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&type, true));
4404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (type == kEthertypeIp) {
4414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      int result = ReadXxpIpHeader(marker);
4424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      DEBUG_LOG("Recognized ethernet 2 frame");
4434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (result != kResultSkip) {
4444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return result;
4454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
4464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
4474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSkip;
4494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
4504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t CalcTimeDelta(uint32_t ts_sec, uint32_t ts_usec, uint32_t start_ms) {
4524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Round to nearest ms.
4534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint64_t t2_ms = ((static_cast<uint64_t>(ts_sec) * 1000000) + ts_usec +
4544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        500) / 1000;
4554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint64_t t1_ms = static_cast<uint64_t>(start_ms);
4564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (t2_ms < t1_ms) {
4574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return 0;
4584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    } else {
4594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return t2_ms - t1_ms;
4604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
4614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
4624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int ReadXxpIpHeader(RtpPacketMarker* marker) {
4644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(marker);
4654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t version;
4674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t length;
4684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t id;
4694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t fragment;
4704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t protocol;
4714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t checksum;
472ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&version, true));
473ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&length, true));
474ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&id, true));
475ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&fragment, true));
476ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&protocol, true));
477ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&checksum, true));
478ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&marker->source_ip, true));
479ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Read(&marker->dest_ip, true));
4804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (((version >> 12) & 0x000f) != kIpVersion4) {
4824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      DEBUG_LOG("IP header is not IPv4");
4834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultSkip;
4844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
4854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (fragment != kFragmentOffsetClear &&
4874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        fragment != kFragmentOffsetDoNotFragment) {
4884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      DEBUG_LOG("IP fragments cannot be handled");
4894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultSkip;
4904d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
4914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Skip remaining fields of IP header.
4934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t header_length = (version & 0x0f00) >> (8 - 2);
4944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(header_length >= kMinIpHeaderLength);
495ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    TRY_PCAP(Skip(header_length - kMinIpHeaderLength));
4964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    protocol = protocol & 0x00ff;
4984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (protocol == kProtocolTcp) {
4994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      DEBUG_LOG("TCP packets are not handled");
5004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultSkip;
5014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    } else if (protocol == kProtocolUdp) {
5024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      uint16_t length;
5034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      uint16_t checksum;
504ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      TRY_PCAP(Read(&marker->source_port, true));
505ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      TRY_PCAP(Read(&marker->dest_port, true));
506ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      TRY_PCAP(Read(&length, true));
507ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      TRY_PCAP(Read(&checksum, true));
5084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      marker->payload_length = length - kUdpHeaderLength;
5094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    } else {
5104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      DEBUG_LOG("Unknown transport (expected UDP or TCP)");
5114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultSkip;
5124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
5154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
5164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int Read(uint32_t* out, bool expect_network_order) {
5184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t tmp = 0;
5194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
5204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
5214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if ((!expect_network_order && swap_pcap_byte_order_) ||
5234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        (expect_network_order && swap_network_byte_order_)) {
5244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) |
5254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000);
5264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    *out = tmp;
5284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
5294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
5304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int Read(uint16_t* out, bool expect_network_order) {
5324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint16_t tmp = 0;
5334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (fread(&tmp, 1, sizeof(uint16_t), file_) != sizeof(uint16_t)) {
5344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
5354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if ((!expect_network_order && swap_pcap_byte_order_) ||
5374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        (expect_network_order && swap_network_byte_order_)) {
5384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      tmp = ((tmp >> 8) & 0x00ff) | (tmp << 8);
5394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    *out = tmp;
5414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
5424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
5434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int Read(uint8_t* out, uint32_t count) {
5454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (fread(out, 1, count, file_) != count) {
5464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
5474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
5494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
5504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int Read(int32_t* out, bool expect_network_order) {
5524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int32_t tmp = 0;
5534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
5544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
5554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if ((!expect_network_order && swap_pcap_byte_order_) ||
5574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        (expect_network_order && swap_network_byte_order_)) {
5584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) |
5594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000);
5604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    *out = tmp;
5624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
5634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
5644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int Skip(uint32_t length) {
5664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (fseek(file_, length, SEEK_CUR) != 0) {
5674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return kResultFail;
5684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
5694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return kResultSuccess;
5704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
5714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  FILE* file_;
5734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  bool swap_pcap_byte_order_;
574ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  const bool swap_network_byte_order_;
5754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint8_t read_buffer_[kMaxReadBufferSize];
5764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
5774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  SsrcMap packets_by_ssrc_;
5784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  std::vector<RtpPacketMarker> packets_;
5794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  PacketIterator next_packet_it_;
5804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
581ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  DISALLOW_COPY_AND_ASSIGN(PcapReader);
5824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
5834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
584ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgRtpFileReader* RtpFileReader::Create(FileFormat format,
585ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org                                     const std::string& filename) {
586ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  RtpFileReaderImpl* reader = NULL;
587ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  switch (format) {
588ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    case kPcap:
589ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      reader = new PcapReader();
590ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      break;
591ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    case kRtpDump:
592ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      reader = new RtpDumpReader();
593ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      break;
594ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  }
595ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  if (!reader->Init(filename)) {
596ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    delete reader;
5974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return NULL;
5984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
599ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  return reader;
6004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org}
601ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org
602ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org}  // namespace test
6034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org}  // namespace webrtc
604