1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "test/rtp_file_reader.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <map>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_util.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/arch.h"
24*d9f75844SAndroid Build Coastguard Worker
25*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
26*d9f75844SAndroid Build Coastguard Worker namespace test {
27*d9f75844SAndroid Build Coastguard Worker
28*d9f75844SAndroid Build Coastguard Worker static const size_t kFirstLineLength = 80;
29*d9f75844SAndroid Build Coastguard Worker static uint16_t kPacketHeaderSize = 8;
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker #define TRY(expr) \
32*d9f75844SAndroid Build Coastguard Worker do { \
33*d9f75844SAndroid Build Coastguard Worker if (!(expr)) { \
34*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Failed to read"; \
35*d9f75844SAndroid Build Coastguard Worker return false; \
36*d9f75844SAndroid Build Coastguard Worker } \
37*d9f75844SAndroid Build Coastguard Worker } while (0)
38*d9f75844SAndroid Build Coastguard Worker
ReadUint32(uint32_t * out,FILE * file)39*d9f75844SAndroid Build Coastguard Worker bool ReadUint32(uint32_t* out, FILE* file) {
40*d9f75844SAndroid Build Coastguard Worker *out = 0;
41*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < 4; ++i) {
42*d9f75844SAndroid Build Coastguard Worker *out <<= 8;
43*d9f75844SAndroid Build Coastguard Worker uint8_t tmp;
44*d9f75844SAndroid Build Coastguard Worker if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t))
45*d9f75844SAndroid Build Coastguard Worker return false;
46*d9f75844SAndroid Build Coastguard Worker *out |= tmp;
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker return true;
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker
ReadUint16(uint16_t * out,FILE * file)51*d9f75844SAndroid Build Coastguard Worker bool ReadUint16(uint16_t* out, FILE* file) {
52*d9f75844SAndroid Build Coastguard Worker *out = 0;
53*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < 2; ++i) {
54*d9f75844SAndroid Build Coastguard Worker *out <<= 8;
55*d9f75844SAndroid Build Coastguard Worker uint8_t tmp;
56*d9f75844SAndroid Build Coastguard Worker if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t))
57*d9f75844SAndroid Build Coastguard Worker return false;
58*d9f75844SAndroid Build Coastguard Worker *out |= tmp;
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker return true;
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker
63*d9f75844SAndroid Build Coastguard Worker class RtpFileReaderImpl : public RtpFileReader {
64*d9f75844SAndroid Build Coastguard Worker public:
65*d9f75844SAndroid Build Coastguard Worker virtual bool Init(FILE* file, const std::set<uint32_t>& ssrc_filter) = 0;
66*d9f75844SAndroid Build Coastguard Worker };
67*d9f75844SAndroid Build Coastguard Worker
68*d9f75844SAndroid Build Coastguard Worker class InterleavedRtpFileReader : public RtpFileReaderImpl {
69*d9f75844SAndroid Build Coastguard Worker public:
~InterleavedRtpFileReader()70*d9f75844SAndroid Build Coastguard Worker ~InterleavedRtpFileReader() override {
71*d9f75844SAndroid Build Coastguard Worker if (file_ != nullptr) {
72*d9f75844SAndroid Build Coastguard Worker fclose(file_);
73*d9f75844SAndroid Build Coastguard Worker file_ = nullptr;
74*d9f75844SAndroid Build Coastguard Worker }
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker
Init(FILE * file,const std::set<uint32_t> & ssrc_filter)77*d9f75844SAndroid Build Coastguard Worker bool Init(FILE* file, const std::set<uint32_t>& ssrc_filter) override {
78*d9f75844SAndroid Build Coastguard Worker file_ = file;
79*d9f75844SAndroid Build Coastguard Worker return true;
80*d9f75844SAndroid Build Coastguard Worker }
81*d9f75844SAndroid Build Coastguard Worker
NextPacket(RtpPacket * packet)82*d9f75844SAndroid Build Coastguard Worker bool NextPacket(RtpPacket* packet) override {
83*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(file_);
84*d9f75844SAndroid Build Coastguard Worker packet->length = RtpPacket::kMaxPacketBufferSize;
85*d9f75844SAndroid Build Coastguard Worker uint32_t len = 0;
86*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint32(&len, file_));
87*d9f75844SAndroid Build Coastguard Worker if (packet->length < len) {
88*d9f75844SAndroid Build Coastguard Worker RTC_FATAL() << "Packet is too large to fit: " << len << " bytes vs "
89*d9f75844SAndroid Build Coastguard Worker << packet->length
90*d9f75844SAndroid Build Coastguard Worker << " bytes allocated. Consider increasing the buffer "
91*d9f75844SAndroid Build Coastguard Worker << "size";
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker if (fread(packet->data, 1, len, file_) != len)
94*d9f75844SAndroid Build Coastguard Worker return false;
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker packet->length = len;
97*d9f75844SAndroid Build Coastguard Worker packet->original_length = len;
98*d9f75844SAndroid Build Coastguard Worker packet->time_ms = time_ms_;
99*d9f75844SAndroid Build Coastguard Worker time_ms_ += 5;
100*d9f75844SAndroid Build Coastguard Worker return true;
101*d9f75844SAndroid Build Coastguard Worker }
102*d9f75844SAndroid Build Coastguard Worker
103*d9f75844SAndroid Build Coastguard Worker private:
104*d9f75844SAndroid Build Coastguard Worker FILE* file_ = nullptr;
105*d9f75844SAndroid Build Coastguard Worker int64_t time_ms_ = 0;
106*d9f75844SAndroid Build Coastguard Worker };
107*d9f75844SAndroid Build Coastguard Worker
108*d9f75844SAndroid Build Coastguard Worker // Read RTP packets from file in rtpdump format, as documented at:
109*d9f75844SAndroid Build Coastguard Worker // http://www.cs.columbia.edu/irt/software/rtptools/
110*d9f75844SAndroid Build Coastguard Worker class RtpDumpReader : public RtpFileReaderImpl {
111*d9f75844SAndroid Build Coastguard Worker public:
RtpDumpReader()112*d9f75844SAndroid Build Coastguard Worker RtpDumpReader() : file_(nullptr) {}
~RtpDumpReader()113*d9f75844SAndroid Build Coastguard Worker ~RtpDumpReader() override {
114*d9f75844SAndroid Build Coastguard Worker if (file_ != nullptr) {
115*d9f75844SAndroid Build Coastguard Worker fclose(file_);
116*d9f75844SAndroid Build Coastguard Worker file_ = nullptr;
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker RtpDumpReader(const RtpDumpReader&) = delete;
121*d9f75844SAndroid Build Coastguard Worker RtpDumpReader& operator=(const RtpDumpReader&) = delete;
122*d9f75844SAndroid Build Coastguard Worker
Init(FILE * file,const std::set<uint32_t> & ssrc_filter)123*d9f75844SAndroid Build Coastguard Worker bool Init(FILE* file, const std::set<uint32_t>& ssrc_filter) override {
124*d9f75844SAndroid Build Coastguard Worker file_ = file;
125*d9f75844SAndroid Build Coastguard Worker
126*d9f75844SAndroid Build Coastguard Worker char firstline[kFirstLineLength + 1] = {0};
127*d9f75844SAndroid Build Coastguard Worker if (fgets(firstline, kFirstLineLength, file_) == nullptr) {
128*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Can't read from file";
129*d9f75844SAndroid Build Coastguard Worker return false;
130*d9f75844SAndroid Build Coastguard Worker }
131*d9f75844SAndroid Build Coastguard Worker if (strncmp(firstline, "#!rtpplay", 9) == 0) {
132*d9f75844SAndroid Build Coastguard Worker if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
133*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Wrong rtpplay version, must be 1.0";
134*d9f75844SAndroid Build Coastguard Worker return false;
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker } else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
137*d9f75844SAndroid Build Coastguard Worker if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
138*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Wrong RTPencode version, must be 1.0";
139*d9f75844SAndroid Build Coastguard Worker return false;
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker } else {
142*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Wrong file format of input file";
143*d9f75844SAndroid Build Coastguard Worker return false;
144*d9f75844SAndroid Build Coastguard Worker }
145*d9f75844SAndroid Build Coastguard Worker
146*d9f75844SAndroid Build Coastguard Worker uint32_t start_sec;
147*d9f75844SAndroid Build Coastguard Worker uint32_t start_usec;
148*d9f75844SAndroid Build Coastguard Worker uint32_t source;
149*d9f75844SAndroid Build Coastguard Worker uint16_t port;
150*d9f75844SAndroid Build Coastguard Worker uint16_t padding;
151*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint32(&start_sec, file_));
152*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint32(&start_usec, file_));
153*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint32(&source, file_));
154*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint16(&port, file_));
155*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint16(&padding, file_));
156*d9f75844SAndroid Build Coastguard Worker
157*d9f75844SAndroid Build Coastguard Worker return true;
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker
NextPacket(RtpPacket * packet)160*d9f75844SAndroid Build Coastguard Worker bool NextPacket(RtpPacket* packet) override {
161*d9f75844SAndroid Build Coastguard Worker uint8_t* rtp_data = packet->data;
162*d9f75844SAndroid Build Coastguard Worker packet->length = RtpPacket::kMaxPacketBufferSize;
163*d9f75844SAndroid Build Coastguard Worker
164*d9f75844SAndroid Build Coastguard Worker uint16_t len;
165*d9f75844SAndroid Build Coastguard Worker uint16_t plen;
166*d9f75844SAndroid Build Coastguard Worker uint32_t offset;
167*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint16(&len, file_));
168*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint16(&plen, file_));
169*d9f75844SAndroid Build Coastguard Worker TRY(ReadUint32(&offset, file_));
170*d9f75844SAndroid Build Coastguard Worker
171*d9f75844SAndroid Build Coastguard Worker // Use 'len' here because a 'plen' of 0 specifies rtcp.
172*d9f75844SAndroid Build Coastguard Worker len -= kPacketHeaderSize;
173*d9f75844SAndroid Build Coastguard Worker if (packet->length < len) {
174*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Packet is too large to fit: " << len << " bytes vs "
175*d9f75844SAndroid Build Coastguard Worker << packet->length
176*d9f75844SAndroid Build Coastguard Worker << " bytes allocated. Consider increasing the buffer "
177*d9f75844SAndroid Build Coastguard Worker "size";
178*d9f75844SAndroid Build Coastguard Worker return false;
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker if (fread(rtp_data, 1, len, file_) != len) {
181*d9f75844SAndroid Build Coastguard Worker return false;
182*d9f75844SAndroid Build Coastguard Worker }
183*d9f75844SAndroid Build Coastguard Worker
184*d9f75844SAndroid Build Coastguard Worker packet->length = len;
185*d9f75844SAndroid Build Coastguard Worker packet->original_length = plen;
186*d9f75844SAndroid Build Coastguard Worker packet->time_ms = offset;
187*d9f75844SAndroid Build Coastguard Worker return true;
188*d9f75844SAndroid Build Coastguard Worker }
189*d9f75844SAndroid Build Coastguard Worker
190*d9f75844SAndroid Build Coastguard Worker private:
191*d9f75844SAndroid Build Coastguard Worker FILE* file_;
192*d9f75844SAndroid Build Coastguard Worker };
193*d9f75844SAndroid Build Coastguard Worker
194*d9f75844SAndroid Build Coastguard Worker enum {
195*d9f75844SAndroid Build Coastguard Worker kResultFail = -1,
196*d9f75844SAndroid Build Coastguard Worker kResultSuccess = 0,
197*d9f75844SAndroid Build Coastguard Worker kResultSkip = 1,
198*d9f75844SAndroid Build Coastguard Worker
199*d9f75844SAndroid Build Coastguard Worker kPcapVersionMajor = 2,
200*d9f75844SAndroid Build Coastguard Worker kPcapVersionMinor = 4,
201*d9f75844SAndroid Build Coastguard Worker kLinktypeNull = 0,
202*d9f75844SAndroid Build Coastguard Worker kLinktypeEthernet = 1,
203*d9f75844SAndroid Build Coastguard Worker kBsdNullLoopback1 = 0x00000002,
204*d9f75844SAndroid Build Coastguard Worker kBsdNullLoopback2 = 0x02000000,
205*d9f75844SAndroid Build Coastguard Worker kEthernetIIHeaderMacSkip = 12,
206*d9f75844SAndroid Build Coastguard Worker kEthertypeIp = 0x0800,
207*d9f75844SAndroid Build Coastguard Worker kIpVersion4 = 4,
208*d9f75844SAndroid Build Coastguard Worker kMinIpHeaderLength = 20,
209*d9f75844SAndroid Build Coastguard Worker kFragmentOffsetClear = 0x0000,
210*d9f75844SAndroid Build Coastguard Worker kFragmentOffsetDoNotFragment = 0x4000,
211*d9f75844SAndroid Build Coastguard Worker kProtocolTcp = 0x06,
212*d9f75844SAndroid Build Coastguard Worker kProtocolUdp = 0x11,
213*d9f75844SAndroid Build Coastguard Worker kUdpHeaderLength = 8,
214*d9f75844SAndroid Build Coastguard Worker kMaxReadBufferSize = 4096
215*d9f75844SAndroid Build Coastguard Worker };
216*d9f75844SAndroid Build Coastguard Worker
217*d9f75844SAndroid Build Coastguard Worker const uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL;
218*d9f75844SAndroid Build Coastguard Worker const uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL;
219*d9f75844SAndroid Build Coastguard Worker
220*d9f75844SAndroid Build Coastguard Worker #define TRY_PCAP(expr) \
221*d9f75844SAndroid Build Coastguard Worker do { \
222*d9f75844SAndroid Build Coastguard Worker int r = (expr); \
223*d9f75844SAndroid Build Coastguard Worker if (r == kResultFail) { \
224*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "FAIL at " << __FILE__ << ":" << __LINE__; \
225*d9f75844SAndroid Build Coastguard Worker return kResultFail; \
226*d9f75844SAndroid Build Coastguard Worker } else if (r == kResultSkip) { \
227*d9f75844SAndroid Build Coastguard Worker return kResultSkip; \
228*d9f75844SAndroid Build Coastguard Worker } \
229*d9f75844SAndroid Build Coastguard Worker } while (0)
230*d9f75844SAndroid Build Coastguard Worker
231*d9f75844SAndroid Build Coastguard Worker // Read RTP packets from file in tcpdump/libpcap format, as documented at:
232*d9f75844SAndroid Build Coastguard Worker // http://wiki.wireshark.org/Development/LibpcapFileFormat
233*d9f75844SAndroid Build Coastguard Worker class PcapReader : public RtpFileReaderImpl {
234*d9f75844SAndroid Build Coastguard Worker public:
PcapReader()235*d9f75844SAndroid Build Coastguard Worker PcapReader()
236*d9f75844SAndroid Build Coastguard Worker : file_(nullptr),
237*d9f75844SAndroid Build Coastguard Worker swap_pcap_byte_order_(false),
238*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ARCH_BIG_ENDIAN
239*d9f75844SAndroid Build Coastguard Worker swap_network_byte_order_(false),
240*d9f75844SAndroid Build Coastguard Worker #else
241*d9f75844SAndroid Build Coastguard Worker swap_network_byte_order_(true),
242*d9f75844SAndroid Build Coastguard Worker #endif
243*d9f75844SAndroid Build Coastguard Worker read_buffer_(),
244*d9f75844SAndroid Build Coastguard Worker packets_by_ssrc_(),
245*d9f75844SAndroid Build Coastguard Worker packets_(),
246*d9f75844SAndroid Build Coastguard Worker next_packet_it_() {
247*d9f75844SAndroid Build Coastguard Worker }
248*d9f75844SAndroid Build Coastguard Worker
~PcapReader()249*d9f75844SAndroid Build Coastguard Worker ~PcapReader() override {
250*d9f75844SAndroid Build Coastguard Worker if (file_ != nullptr) {
251*d9f75844SAndroid Build Coastguard Worker fclose(file_);
252*d9f75844SAndroid Build Coastguard Worker file_ = nullptr;
253*d9f75844SAndroid Build Coastguard Worker }
254*d9f75844SAndroid Build Coastguard Worker }
255*d9f75844SAndroid Build Coastguard Worker
256*d9f75844SAndroid Build Coastguard Worker PcapReader(const PcapReader&) = delete;
257*d9f75844SAndroid Build Coastguard Worker PcapReader& operator=(const PcapReader&) = delete;
258*d9f75844SAndroid Build Coastguard Worker
Init(FILE * file,const std::set<uint32_t> & ssrc_filter)259*d9f75844SAndroid Build Coastguard Worker bool Init(FILE* file, const std::set<uint32_t>& ssrc_filter) override {
260*d9f75844SAndroid Build Coastguard Worker return Initialize(file, ssrc_filter) == kResultSuccess;
261*d9f75844SAndroid Build Coastguard Worker }
262*d9f75844SAndroid Build Coastguard Worker
Initialize(FILE * file,const std::set<uint32_t> & ssrc_filter)263*d9f75844SAndroid Build Coastguard Worker int Initialize(FILE* file, const std::set<uint32_t>& ssrc_filter) {
264*d9f75844SAndroid Build Coastguard Worker file_ = file;
265*d9f75844SAndroid Build Coastguard Worker
266*d9f75844SAndroid Build Coastguard Worker if (ReadGlobalHeader() < 0) {
267*d9f75844SAndroid Build Coastguard Worker return kResultFail;
268*d9f75844SAndroid Build Coastguard Worker }
269*d9f75844SAndroid Build Coastguard Worker
270*d9f75844SAndroid Build Coastguard Worker int total_packet_count = 0;
271*d9f75844SAndroid Build Coastguard Worker uint32_t stream_start_ms = 0;
272*d9f75844SAndroid Build Coastguard Worker int32_t next_packet_pos = ftell(file_);
273*d9f75844SAndroid Build Coastguard Worker for (;;) {
274*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET));
275*d9f75844SAndroid Build Coastguard Worker int result = ReadPacket(&next_packet_pos, stream_start_ms,
276*d9f75844SAndroid Build Coastguard Worker ++total_packet_count, ssrc_filter);
277*d9f75844SAndroid Build Coastguard Worker if (result == kResultFail) {
278*d9f75844SAndroid Build Coastguard Worker break;
279*d9f75844SAndroid Build Coastguard Worker } else if (result == kResultSuccess && packets_.size() == 1) {
280*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(stream_start_ms, 0);
281*d9f75844SAndroid Build Coastguard Worker PacketIterator it = packets_.begin();
282*d9f75844SAndroid Build Coastguard Worker stream_start_ms = it->time_offset_ms;
283*d9f75844SAndroid Build Coastguard Worker it->time_offset_ms = 0;
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker }
286*d9f75844SAndroid Build Coastguard Worker
287*d9f75844SAndroid Build Coastguard Worker if (feof(file_) == 0) {
288*d9f75844SAndroid Build Coastguard Worker printf("Failed reading file!\n");
289*d9f75844SAndroid Build Coastguard Worker return kResultFail;
290*d9f75844SAndroid Build Coastguard Worker }
291*d9f75844SAndroid Build Coastguard Worker
292*d9f75844SAndroid Build Coastguard Worker printf("Total packets in file: %d\n", total_packet_count);
293*d9f75844SAndroid Build Coastguard Worker printf("Total RTP/RTCP packets: %zu\n", packets_.size());
294*d9f75844SAndroid Build Coastguard Worker
295*d9f75844SAndroid Build Coastguard Worker for (SsrcMapIterator mit = packets_by_ssrc_.begin();
296*d9f75844SAndroid Build Coastguard Worker mit != packets_by_ssrc_.end(); ++mit) {
297*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = mit->first;
298*d9f75844SAndroid Build Coastguard Worker const std::vector<uint32_t>& packet_indices = mit->second;
299*d9f75844SAndroid Build Coastguard Worker int pt = packets_[packet_indices[0]].payload_type;
300*d9f75844SAndroid Build Coastguard Worker printf("SSRC: %08x, %zu packets, pt=%d\n", ssrc, packet_indices.size(),
301*d9f75844SAndroid Build Coastguard Worker pt);
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker
304*d9f75844SAndroid Build Coastguard Worker // TODO(solenberg): Better validation of identified SSRC streams.
305*d9f75844SAndroid Build Coastguard Worker //
306*d9f75844SAndroid Build Coastguard Worker // Since we're dealing with raw network data here, we will wrongly identify
307*d9f75844SAndroid Build Coastguard Worker // some packets as RTP. When these packets are consumed by RtpPlayer, they
308*d9f75844SAndroid Build Coastguard Worker // are unlikely to cause issues as they will ultimately be filtered out by
309*d9f75844SAndroid Build Coastguard Worker // the RtpRtcp module. However, we should really do better filtering here,
310*d9f75844SAndroid Build Coastguard Worker // which we can accomplish in a number of ways, e.g.:
311*d9f75844SAndroid Build Coastguard Worker //
312*d9f75844SAndroid Build Coastguard Worker // - Verify that the time stamps and sequence numbers for RTP packets are
313*d9f75844SAndroid Build Coastguard Worker // both increasing/decreasing. If they move in different directions, the
314*d9f75844SAndroid Build Coastguard Worker // SSRC is likely bogus and can be dropped. (Normally they should be inc-
315*d9f75844SAndroid Build Coastguard Worker // reasing but we must allow packet reordering).
316*d9f75844SAndroid Build Coastguard Worker // - If RTP sequence number is not changing, drop the stream.
317*d9f75844SAndroid Build Coastguard Worker // - Can also use srcip:port->dstip:port pairs, assuming few SSRC collisions
318*d9f75844SAndroid Build Coastguard Worker // for up/down streams.
319*d9f75844SAndroid Build Coastguard Worker
320*d9f75844SAndroid Build Coastguard Worker next_packet_it_ = packets_.begin();
321*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker
NextPacket(RtpPacket * packet)324*d9f75844SAndroid Build Coastguard Worker bool NextPacket(RtpPacket* packet) override {
325*d9f75844SAndroid Build Coastguard Worker uint32_t length = RtpPacket::kMaxPacketBufferSize;
326*d9f75844SAndroid Build Coastguard Worker if (NextPcap(packet->data, &length, &packet->time_ms) != kResultSuccess)
327*d9f75844SAndroid Build Coastguard Worker return false;
328*d9f75844SAndroid Build Coastguard Worker packet->length = static_cast<size_t>(length);
329*d9f75844SAndroid Build Coastguard Worker packet->original_length = packet->length;
330*d9f75844SAndroid Build Coastguard Worker return true;
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker
NextPcap(uint8_t * data,uint32_t * length,uint32_t * time_ms)333*d9f75844SAndroid Build Coastguard Worker virtual int NextPcap(uint8_t* data, uint32_t* length, uint32_t* time_ms) {
334*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(data);
335*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(length);
336*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(time_ms);
337*d9f75844SAndroid Build Coastguard Worker
338*d9f75844SAndroid Build Coastguard Worker if (next_packet_it_ == packets_.end()) {
339*d9f75844SAndroid Build Coastguard Worker return -1;
340*d9f75844SAndroid Build Coastguard Worker }
341*d9f75844SAndroid Build Coastguard Worker if (*length < next_packet_it_->payload_length) {
342*d9f75844SAndroid Build Coastguard Worker return -1;
343*d9f75844SAndroid Build Coastguard Worker }
344*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(fseek(file_, next_packet_it_->pos_in_file, SEEK_SET));
345*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(data, next_packet_it_->payload_length));
346*d9f75844SAndroid Build Coastguard Worker *length = next_packet_it_->payload_length;
347*d9f75844SAndroid Build Coastguard Worker *time_ms = next_packet_it_->time_offset_ms;
348*d9f75844SAndroid Build Coastguard Worker next_packet_it_++;
349*d9f75844SAndroid Build Coastguard Worker
350*d9f75844SAndroid Build Coastguard Worker return 0;
351*d9f75844SAndroid Build Coastguard Worker }
352*d9f75844SAndroid Build Coastguard Worker
353*d9f75844SAndroid Build Coastguard Worker private:
354*d9f75844SAndroid Build Coastguard Worker // A marker of an RTP packet within the file.
355*d9f75844SAndroid Build Coastguard Worker struct RtpPacketMarker {
356*d9f75844SAndroid Build Coastguard Worker uint32_t packet_number; // One-based index (like in WireShark)
357*d9f75844SAndroid Build Coastguard Worker uint32_t time_offset_ms;
358*d9f75844SAndroid Build Coastguard Worker uint32_t source_ip;
359*d9f75844SAndroid Build Coastguard Worker uint32_t dest_ip;
360*d9f75844SAndroid Build Coastguard Worker uint16_t source_port;
361*d9f75844SAndroid Build Coastguard Worker uint16_t dest_port;
362*d9f75844SAndroid Build Coastguard Worker // Payload type of the RTP packet,
363*d9f75844SAndroid Build Coastguard Worker // or RTCP packet type of the first RTCP packet in a compound RTCP packet.
364*d9f75844SAndroid Build Coastguard Worker int payload_type;
365*d9f75844SAndroid Build Coastguard Worker int32_t pos_in_file; // Byte offset of payload from start of file.
366*d9f75844SAndroid Build Coastguard Worker uint32_t payload_length;
367*d9f75844SAndroid Build Coastguard Worker };
368*d9f75844SAndroid Build Coastguard Worker
369*d9f75844SAndroid Build Coastguard Worker typedef std::vector<RtpPacketMarker>::iterator PacketIterator;
370*d9f75844SAndroid Build Coastguard Worker typedef std::map<uint32_t, std::vector<uint32_t> > SsrcMap;
371*d9f75844SAndroid Build Coastguard Worker typedef std::map<uint32_t, std::vector<uint32_t> >::iterator SsrcMapIterator;
372*d9f75844SAndroid Build Coastguard Worker
ReadGlobalHeader()373*d9f75844SAndroid Build Coastguard Worker int ReadGlobalHeader() {
374*d9f75844SAndroid Build Coastguard Worker uint32_t magic;
375*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&magic, false));
376*d9f75844SAndroid Build Coastguard Worker if (magic == kPcapBOMSwapOrder) {
377*d9f75844SAndroid Build Coastguard Worker swap_pcap_byte_order_ = true;
378*d9f75844SAndroid Build Coastguard Worker } else if (magic == kPcapBOMNoSwapOrder) {
379*d9f75844SAndroid Build Coastguard Worker swap_pcap_byte_order_ = false;
380*d9f75844SAndroid Build Coastguard Worker } else {
381*d9f75844SAndroid Build Coastguard Worker return kResultFail;
382*d9f75844SAndroid Build Coastguard Worker }
383*d9f75844SAndroid Build Coastguard Worker
384*d9f75844SAndroid Build Coastguard Worker uint16_t version_major;
385*d9f75844SAndroid Build Coastguard Worker uint16_t version_minor;
386*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&version_major, false));
387*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&version_minor, false));
388*d9f75844SAndroid Build Coastguard Worker if (version_major != kPcapVersionMajor ||
389*d9f75844SAndroid Build Coastguard Worker version_minor != kPcapVersionMinor) {
390*d9f75844SAndroid Build Coastguard Worker return kResultFail;
391*d9f75844SAndroid Build Coastguard Worker }
392*d9f75844SAndroid Build Coastguard Worker
393*d9f75844SAndroid Build Coastguard Worker int32_t this_zone; // GMT to local correction.
394*d9f75844SAndroid Build Coastguard Worker uint32_t sigfigs; // Accuracy of timestamps.
395*d9f75844SAndroid Build Coastguard Worker uint32_t snaplen; // Max length of captured packets, in octets.
396*d9f75844SAndroid Build Coastguard Worker uint32_t network; // Data link type.
397*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&this_zone, false));
398*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&sigfigs, false));
399*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&snaplen, false));
400*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&network, false));
401*d9f75844SAndroid Build Coastguard Worker
402*d9f75844SAndroid Build Coastguard Worker // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET.
403*d9f75844SAndroid Build Coastguard Worker // See: http://www.tcpdump.org/linktypes.html
404*d9f75844SAndroid Build Coastguard Worker if (network != kLinktypeNull && network != kLinktypeEthernet) {
405*d9f75844SAndroid Build Coastguard Worker return kResultFail;
406*d9f75844SAndroid Build Coastguard Worker }
407*d9f75844SAndroid Build Coastguard Worker
408*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
409*d9f75844SAndroid Build Coastguard Worker }
410*d9f75844SAndroid Build Coastguard Worker
ReadPacket(int32_t * next_packet_pos,uint32_t stream_start_ms,uint32_t number,const std::set<uint32_t> & ssrc_filter)411*d9f75844SAndroid Build Coastguard Worker int ReadPacket(int32_t* next_packet_pos,
412*d9f75844SAndroid Build Coastguard Worker uint32_t stream_start_ms,
413*d9f75844SAndroid Build Coastguard Worker uint32_t number,
414*d9f75844SAndroid Build Coastguard Worker const std::set<uint32_t>& ssrc_filter) {
415*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(next_packet_pos);
416*d9f75844SAndroid Build Coastguard Worker
417*d9f75844SAndroid Build Coastguard Worker uint32_t ts_sec; // Timestamp seconds.
418*d9f75844SAndroid Build Coastguard Worker uint32_t ts_usec; // Timestamp microseconds.
419*d9f75844SAndroid Build Coastguard Worker uint32_t incl_len; // Number of octets of packet saved in file.
420*d9f75844SAndroid Build Coastguard Worker uint32_t orig_len; // Actual length of packet.
421*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&ts_sec, false));
422*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&ts_usec, false));
423*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&incl_len, false));
424*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&orig_len, false));
425*d9f75844SAndroid Build Coastguard Worker
426*d9f75844SAndroid Build Coastguard Worker *next_packet_pos = ftell(file_) + incl_len;
427*d9f75844SAndroid Build Coastguard Worker
428*d9f75844SAndroid Build Coastguard Worker RtpPacketMarker marker = {0};
429*d9f75844SAndroid Build Coastguard Worker marker.packet_number = number;
430*d9f75844SAndroid Build Coastguard Worker marker.time_offset_ms = CalcTimeDelta(ts_sec, ts_usec, stream_start_ms);
431*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(ReadPacketHeader(&marker));
432*d9f75844SAndroid Build Coastguard Worker marker.pos_in_file = ftell(file_);
433*d9f75844SAndroid Build Coastguard Worker
434*d9f75844SAndroid Build Coastguard Worker if (marker.payload_length > sizeof(read_buffer_)) {
435*d9f75844SAndroid Build Coastguard Worker printf("Packet too large!\n");
436*d9f75844SAndroid Build Coastguard Worker return kResultFail;
437*d9f75844SAndroid Build Coastguard Worker }
438*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(read_buffer_, marker.payload_length));
439*d9f75844SAndroid Build Coastguard Worker
440*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const uint8_t> packet(read_buffer_, marker.payload_length);
441*d9f75844SAndroid Build Coastguard Worker if (IsRtcpPacket(packet)) {
442*d9f75844SAndroid Build Coastguard Worker marker.payload_type = packet[1];
443*d9f75844SAndroid Build Coastguard Worker packets_.push_back(marker);
444*d9f75844SAndroid Build Coastguard Worker } else if (IsRtpPacket(packet)) {
445*d9f75844SAndroid Build Coastguard Worker uint32_t ssrc = ParseRtpSsrc(packet);
446*d9f75844SAndroid Build Coastguard Worker marker.payload_type = ParseRtpPayloadType(packet);
447*d9f75844SAndroid Build Coastguard Worker if (ssrc_filter.empty() || ssrc_filter.find(ssrc) != ssrc_filter.end()) {
448*d9f75844SAndroid Build Coastguard Worker packets_by_ssrc_[ssrc].push_back(
449*d9f75844SAndroid Build Coastguard Worker static_cast<uint32_t>(packets_.size()));
450*d9f75844SAndroid Build Coastguard Worker packets_.push_back(marker);
451*d9f75844SAndroid Build Coastguard Worker } else {
452*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
453*d9f75844SAndroid Build Coastguard Worker }
454*d9f75844SAndroid Build Coastguard Worker } else {
455*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Not recognized as RTP/RTCP";
456*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
457*d9f75844SAndroid Build Coastguard Worker }
458*d9f75844SAndroid Build Coastguard Worker
459*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
460*d9f75844SAndroid Build Coastguard Worker }
461*d9f75844SAndroid Build Coastguard Worker
ReadPacketHeader(RtpPacketMarker * marker)462*d9f75844SAndroid Build Coastguard Worker int ReadPacketHeader(RtpPacketMarker* marker) {
463*d9f75844SAndroid Build Coastguard Worker int32_t file_pos = ftell(file_);
464*d9f75844SAndroid Build Coastguard Worker
465*d9f75844SAndroid Build Coastguard Worker // Check for BSD null/loopback frame header. The header is just 4 bytes in
466*d9f75844SAndroid Build Coastguard Worker // native byte order, so we check for both versions as we don't care about
467*d9f75844SAndroid Build Coastguard Worker // the header as such and will likely fail reading the IP header if this is
468*d9f75844SAndroid Build Coastguard Worker // something else than null/loopback.
469*d9f75844SAndroid Build Coastguard Worker uint32_t protocol;
470*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&protocol, true));
471*d9f75844SAndroid Build Coastguard Worker if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) {
472*d9f75844SAndroid Build Coastguard Worker int result = ReadXxpIpHeader(marker);
473*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Recognized loopback frame";
474*d9f75844SAndroid Build Coastguard Worker if (result != kResultSkip) {
475*d9f75844SAndroid Build Coastguard Worker return result;
476*d9f75844SAndroid Build Coastguard Worker }
477*d9f75844SAndroid Build Coastguard Worker }
478*d9f75844SAndroid Build Coastguard Worker
479*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(fseek(file_, file_pos, SEEK_SET));
480*d9f75844SAndroid Build Coastguard Worker
481*d9f75844SAndroid Build Coastguard Worker // Check for Ethernet II, IP frame header.
482*d9f75844SAndroid Build Coastguard Worker uint16_t type;
483*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Skip(kEthernetIIHeaderMacSkip)); // Source+destination MAC.
484*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&type, true));
485*d9f75844SAndroid Build Coastguard Worker if (type == kEthertypeIp) {
486*d9f75844SAndroid Build Coastguard Worker int result = ReadXxpIpHeader(marker);
487*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Recognized ethernet 2 frame";
488*d9f75844SAndroid Build Coastguard Worker if (result != kResultSkip) {
489*d9f75844SAndroid Build Coastguard Worker return result;
490*d9f75844SAndroid Build Coastguard Worker }
491*d9f75844SAndroid Build Coastguard Worker }
492*d9f75844SAndroid Build Coastguard Worker
493*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
494*d9f75844SAndroid Build Coastguard Worker }
495*d9f75844SAndroid Build Coastguard Worker
CalcTimeDelta(uint32_t ts_sec,uint32_t ts_usec,uint32_t start_ms)496*d9f75844SAndroid Build Coastguard Worker uint32_t CalcTimeDelta(uint32_t ts_sec, uint32_t ts_usec, uint32_t start_ms) {
497*d9f75844SAndroid Build Coastguard Worker // Round to nearest ms.
498*d9f75844SAndroid Build Coastguard Worker uint64_t t2_ms =
499*d9f75844SAndroid Build Coastguard Worker ((static_cast<uint64_t>(ts_sec) * 1000000) + ts_usec + 500) / 1000;
500*d9f75844SAndroid Build Coastguard Worker uint64_t t1_ms = static_cast<uint64_t>(start_ms);
501*d9f75844SAndroid Build Coastguard Worker if (t2_ms < t1_ms) {
502*d9f75844SAndroid Build Coastguard Worker return 0;
503*d9f75844SAndroid Build Coastguard Worker } else {
504*d9f75844SAndroid Build Coastguard Worker return t2_ms - t1_ms;
505*d9f75844SAndroid Build Coastguard Worker }
506*d9f75844SAndroid Build Coastguard Worker }
507*d9f75844SAndroid Build Coastguard Worker
ReadXxpIpHeader(RtpPacketMarker * marker)508*d9f75844SAndroid Build Coastguard Worker int ReadXxpIpHeader(RtpPacketMarker* marker) {
509*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(marker);
510*d9f75844SAndroid Build Coastguard Worker
511*d9f75844SAndroid Build Coastguard Worker uint16_t version;
512*d9f75844SAndroid Build Coastguard Worker uint16_t length;
513*d9f75844SAndroid Build Coastguard Worker uint16_t id;
514*d9f75844SAndroid Build Coastguard Worker uint16_t fragment;
515*d9f75844SAndroid Build Coastguard Worker uint16_t protocol;
516*d9f75844SAndroid Build Coastguard Worker uint16_t checksum;
517*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&version, true));
518*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&length, true));
519*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&id, true));
520*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&fragment, true));
521*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&protocol, true));
522*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&checksum, true));
523*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&marker->source_ip, true));
524*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&marker->dest_ip, true));
525*d9f75844SAndroid Build Coastguard Worker
526*d9f75844SAndroid Build Coastguard Worker if (((version >> 12) & 0x000f) != kIpVersion4) {
527*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "IP header is not IPv4";
528*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
529*d9f75844SAndroid Build Coastguard Worker }
530*d9f75844SAndroid Build Coastguard Worker
531*d9f75844SAndroid Build Coastguard Worker if (fragment != kFragmentOffsetClear &&
532*d9f75844SAndroid Build Coastguard Worker fragment != kFragmentOffsetDoNotFragment) {
533*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "IP fragments cannot be handled";
534*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
535*d9f75844SAndroid Build Coastguard Worker }
536*d9f75844SAndroid Build Coastguard Worker
537*d9f75844SAndroid Build Coastguard Worker // Skip remaining fields of IP header.
538*d9f75844SAndroid Build Coastguard Worker uint16_t header_length = (version & 0x0f00) >> (8 - 2);
539*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_GE(header_length, kMinIpHeaderLength);
540*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Skip(header_length - kMinIpHeaderLength));
541*d9f75844SAndroid Build Coastguard Worker
542*d9f75844SAndroid Build Coastguard Worker protocol = protocol & 0x00ff;
543*d9f75844SAndroid Build Coastguard Worker if (protocol == kProtocolTcp) {
544*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "TCP packets are not handled";
545*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
546*d9f75844SAndroid Build Coastguard Worker } else if (protocol == kProtocolUdp) {
547*d9f75844SAndroid Build Coastguard Worker uint16_t length;
548*d9f75844SAndroid Build Coastguard Worker uint16_t checksum;
549*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&marker->source_port, true));
550*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&marker->dest_port, true));
551*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&length, true));
552*d9f75844SAndroid Build Coastguard Worker TRY_PCAP(Read(&checksum, true));
553*d9f75844SAndroid Build Coastguard Worker marker->payload_length = length - kUdpHeaderLength;
554*d9f75844SAndroid Build Coastguard Worker } else {
555*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Unknown transport (expected UDP or TCP)";
556*d9f75844SAndroid Build Coastguard Worker return kResultSkip;
557*d9f75844SAndroid Build Coastguard Worker }
558*d9f75844SAndroid Build Coastguard Worker
559*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
560*d9f75844SAndroid Build Coastguard Worker }
561*d9f75844SAndroid Build Coastguard Worker
Read(uint32_t * out,bool expect_network_order)562*d9f75844SAndroid Build Coastguard Worker int Read(uint32_t* out, bool expect_network_order) {
563*d9f75844SAndroid Build Coastguard Worker uint32_t tmp = 0;
564*d9f75844SAndroid Build Coastguard Worker if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
565*d9f75844SAndroid Build Coastguard Worker return kResultFail;
566*d9f75844SAndroid Build Coastguard Worker }
567*d9f75844SAndroid Build Coastguard Worker if ((!expect_network_order && swap_pcap_byte_order_) ||
568*d9f75844SAndroid Build Coastguard Worker (expect_network_order && swap_network_byte_order_)) {
569*d9f75844SAndroid Build Coastguard Worker tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) |
570*d9f75844SAndroid Build Coastguard Worker ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000);
571*d9f75844SAndroid Build Coastguard Worker }
572*d9f75844SAndroid Build Coastguard Worker *out = tmp;
573*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
574*d9f75844SAndroid Build Coastguard Worker }
575*d9f75844SAndroid Build Coastguard Worker
Read(uint16_t * out,bool expect_network_order)576*d9f75844SAndroid Build Coastguard Worker int Read(uint16_t* out, bool expect_network_order) {
577*d9f75844SAndroid Build Coastguard Worker uint16_t tmp = 0;
578*d9f75844SAndroid Build Coastguard Worker if (fread(&tmp, 1, sizeof(uint16_t), file_) != sizeof(uint16_t)) {
579*d9f75844SAndroid Build Coastguard Worker return kResultFail;
580*d9f75844SAndroid Build Coastguard Worker }
581*d9f75844SAndroid Build Coastguard Worker if ((!expect_network_order && swap_pcap_byte_order_) ||
582*d9f75844SAndroid Build Coastguard Worker (expect_network_order && swap_network_byte_order_)) {
583*d9f75844SAndroid Build Coastguard Worker tmp = ((tmp >> 8) & 0x00ff) | (tmp << 8);
584*d9f75844SAndroid Build Coastguard Worker }
585*d9f75844SAndroid Build Coastguard Worker *out = tmp;
586*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
587*d9f75844SAndroid Build Coastguard Worker }
588*d9f75844SAndroid Build Coastguard Worker
Read(uint8_t * out,uint32_t count)589*d9f75844SAndroid Build Coastguard Worker int Read(uint8_t* out, uint32_t count) {
590*d9f75844SAndroid Build Coastguard Worker if (fread(out, 1, count, file_) != count) {
591*d9f75844SAndroid Build Coastguard Worker return kResultFail;
592*d9f75844SAndroid Build Coastguard Worker }
593*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
594*d9f75844SAndroid Build Coastguard Worker }
595*d9f75844SAndroid Build Coastguard Worker
Read(int32_t * out,bool expect_network_order)596*d9f75844SAndroid Build Coastguard Worker int Read(int32_t* out, bool expect_network_order) {
597*d9f75844SAndroid Build Coastguard Worker int32_t tmp = 0;
598*d9f75844SAndroid Build Coastguard Worker if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
599*d9f75844SAndroid Build Coastguard Worker return kResultFail;
600*d9f75844SAndroid Build Coastguard Worker }
601*d9f75844SAndroid Build Coastguard Worker if ((!expect_network_order && swap_pcap_byte_order_) ||
602*d9f75844SAndroid Build Coastguard Worker (expect_network_order && swap_network_byte_order_)) {
603*d9f75844SAndroid Build Coastguard Worker tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) |
604*d9f75844SAndroid Build Coastguard Worker ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000);
605*d9f75844SAndroid Build Coastguard Worker }
606*d9f75844SAndroid Build Coastguard Worker *out = tmp;
607*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
608*d9f75844SAndroid Build Coastguard Worker }
609*d9f75844SAndroid Build Coastguard Worker
Skip(uint32_t length)610*d9f75844SAndroid Build Coastguard Worker int Skip(uint32_t length) {
611*d9f75844SAndroid Build Coastguard Worker if (fseek(file_, length, SEEK_CUR) != 0) {
612*d9f75844SAndroid Build Coastguard Worker return kResultFail;
613*d9f75844SAndroid Build Coastguard Worker }
614*d9f75844SAndroid Build Coastguard Worker return kResultSuccess;
615*d9f75844SAndroid Build Coastguard Worker }
616*d9f75844SAndroid Build Coastguard Worker
617*d9f75844SAndroid Build Coastguard Worker FILE* file_;
618*d9f75844SAndroid Build Coastguard Worker bool swap_pcap_byte_order_;
619*d9f75844SAndroid Build Coastguard Worker const bool swap_network_byte_order_;
620*d9f75844SAndroid Build Coastguard Worker uint8_t read_buffer_[kMaxReadBufferSize];
621*d9f75844SAndroid Build Coastguard Worker
622*d9f75844SAndroid Build Coastguard Worker SsrcMap packets_by_ssrc_;
623*d9f75844SAndroid Build Coastguard Worker std::vector<RtpPacketMarker> packets_;
624*d9f75844SAndroid Build Coastguard Worker PacketIterator next_packet_it_;
625*d9f75844SAndroid Build Coastguard Worker };
626*d9f75844SAndroid Build Coastguard Worker
CreateReaderForFormat(RtpFileReader::FileFormat format)627*d9f75844SAndroid Build Coastguard Worker RtpFileReaderImpl* CreateReaderForFormat(RtpFileReader::FileFormat format) {
628*d9f75844SAndroid Build Coastguard Worker RtpFileReaderImpl* reader = nullptr;
629*d9f75844SAndroid Build Coastguard Worker switch (format) {
630*d9f75844SAndroid Build Coastguard Worker case RtpFileReader::kPcap:
631*d9f75844SAndroid Build Coastguard Worker reader = new PcapReader();
632*d9f75844SAndroid Build Coastguard Worker break;
633*d9f75844SAndroid Build Coastguard Worker case RtpFileReader::kRtpDump:
634*d9f75844SAndroid Build Coastguard Worker reader = new RtpDumpReader();
635*d9f75844SAndroid Build Coastguard Worker break;
636*d9f75844SAndroid Build Coastguard Worker case RtpFileReader::kLengthPacketInterleaved:
637*d9f75844SAndroid Build Coastguard Worker reader = new InterleavedRtpFileReader();
638*d9f75844SAndroid Build Coastguard Worker break;
639*d9f75844SAndroid Build Coastguard Worker }
640*d9f75844SAndroid Build Coastguard Worker return reader;
641*d9f75844SAndroid Build Coastguard Worker }
642*d9f75844SAndroid Build Coastguard Worker
Create(FileFormat format,const uint8_t * data,size_t size,const std::set<uint32_t> & ssrc_filter)643*d9f75844SAndroid Build Coastguard Worker RtpFileReader* RtpFileReader::Create(FileFormat format,
644*d9f75844SAndroid Build Coastguard Worker const uint8_t* data,
645*d9f75844SAndroid Build Coastguard Worker size_t size,
646*d9f75844SAndroid Build Coastguard Worker const std::set<uint32_t>& ssrc_filter) {
647*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<RtpFileReaderImpl> reader(CreateReaderForFormat(format));
648*d9f75844SAndroid Build Coastguard Worker
649*d9f75844SAndroid Build Coastguard Worker FILE* file = tmpfile();
650*d9f75844SAndroid Build Coastguard Worker if (file == nullptr) {
651*d9f75844SAndroid Build Coastguard Worker printf("ERROR: Can't open file from memory buffer\n");
652*d9f75844SAndroid Build Coastguard Worker return nullptr;
653*d9f75844SAndroid Build Coastguard Worker }
654*d9f75844SAndroid Build Coastguard Worker
655*d9f75844SAndroid Build Coastguard Worker if (fwrite(reinterpret_cast<const void*>(data), sizeof(uint8_t), size,
656*d9f75844SAndroid Build Coastguard Worker file) != size) {
657*d9f75844SAndroid Build Coastguard Worker return nullptr;
658*d9f75844SAndroid Build Coastguard Worker }
659*d9f75844SAndroid Build Coastguard Worker rewind(file);
660*d9f75844SAndroid Build Coastguard Worker
661*d9f75844SAndroid Build Coastguard Worker if (!reader->Init(file, ssrc_filter)) {
662*d9f75844SAndroid Build Coastguard Worker return nullptr;
663*d9f75844SAndroid Build Coastguard Worker }
664*d9f75844SAndroid Build Coastguard Worker return reader.release();
665*d9f75844SAndroid Build Coastguard Worker }
666*d9f75844SAndroid Build Coastguard Worker
Create(FileFormat format,absl::string_view filename,const std::set<uint32_t> & ssrc_filter)667*d9f75844SAndroid Build Coastguard Worker RtpFileReader* RtpFileReader::Create(FileFormat format,
668*d9f75844SAndroid Build Coastguard Worker absl::string_view filename,
669*d9f75844SAndroid Build Coastguard Worker const std::set<uint32_t>& ssrc_filter) {
670*d9f75844SAndroid Build Coastguard Worker RtpFileReaderImpl* reader = CreateReaderForFormat(format);
671*d9f75844SAndroid Build Coastguard Worker std::string filename_str = std::string(filename);
672*d9f75844SAndroid Build Coastguard Worker FILE* file = fopen(filename_str.c_str(), "rb");
673*d9f75844SAndroid Build Coastguard Worker if (file == nullptr) {
674*d9f75844SAndroid Build Coastguard Worker printf("ERROR: Can't open file: %s\n", filename_str.c_str());
675*d9f75844SAndroid Build Coastguard Worker return nullptr;
676*d9f75844SAndroid Build Coastguard Worker }
677*d9f75844SAndroid Build Coastguard Worker
678*d9f75844SAndroid Build Coastguard Worker if (!reader->Init(file, ssrc_filter)) {
679*d9f75844SAndroid Build Coastguard Worker delete reader;
680*d9f75844SAndroid Build Coastguard Worker return nullptr;
681*d9f75844SAndroid Build Coastguard Worker }
682*d9f75844SAndroid Build Coastguard Worker return reader;
683*d9f75844SAndroid Build Coastguard Worker }
684*d9f75844SAndroid Build Coastguard Worker
Create(FileFormat format,absl::string_view filename)685*d9f75844SAndroid Build Coastguard Worker RtpFileReader* RtpFileReader::Create(FileFormat format,
686*d9f75844SAndroid Build Coastguard Worker absl::string_view filename) {
687*d9f75844SAndroid Build Coastguard Worker return RtpFileReader::Create(format, filename, std::set<uint32_t>());
688*d9f75844SAndroid Build Coastguard Worker }
689*d9f75844SAndroid Build Coastguard Worker
690*d9f75844SAndroid Build Coastguard Worker } // namespace test
691*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
692