1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
12
13 #ifdef WIN32
14 #include <windows.h>
15 #include <Winsock2.h>
16 #else
17 #include <arpa/inet.h>
18 #endif
19 #include <assert.h>
20 #include <stdio.h>
21
22 #include "webrtc/modules/video_coding/main/test/rtp_player.h"
23 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
24
25 namespace webrtc {
26 namespace rtpplayer {
27
28 enum {
29 kResultFail = -1,
30 kResultSuccess = 0,
31
32 kFirstLineLength = 40, // More than needed to read the ID line.
33 kPacketHeaderSize = 8 // Rtpplay packet header size in bytes.
34 };
35
36 #if 1
37 # define DEBUG_LOG(text)
38 # define DEBUG_LOG1(text, arg)
39 #else
40 # define DEBUG_LOG(text) (printf(text "\n"))
41 # define DEBUG_LOG1(text, arg) (printf(text "\n", arg))
42 #endif
43
44 #define TRY(expr) \
45 do { \
46 if ((expr) < 0) { \
47 DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \
48 return kResultFail; \
49 } \
50 } while (0)
51
52 // Read RTP packets from file in rtpdump format, as documented at:
53 // http://www.cs.columbia.edu/irt/software/rtptools/
54 class RtpFileReaderImpl : public RtpPacketSourceInterface {
55 public:
RtpFileReaderImpl()56 RtpFileReaderImpl() : file_(NULL) {}
~RtpFileReaderImpl()57 virtual ~RtpFileReaderImpl() {
58 if (file_ != NULL) {
59 fclose(file_);
60 file_ = NULL;
61 }
62 }
63
Initialize(const std::string & filename)64 int Initialize(const std::string& filename) {
65 file_ = fopen(filename.c_str(), "rb");
66 if (file_ == NULL) {
67 printf("ERROR: Can't open file: %s\n", filename.c_str());
68 return kResultFail;
69 }
70
71 char firstline[kFirstLineLength + 1] = {0};
72 if (fgets(firstline, kFirstLineLength, file_) == NULL) {
73 DEBUG_LOG("ERROR: Can't read from file\n");
74 return kResultFail;
75 }
76 if (strncmp(firstline, "#!rtpplay", 9) == 0) {
77 if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
78 DEBUG_LOG("ERROR: wrong rtpplay version, must be 1.0\n");
79 return kResultFail;
80 }
81 } else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
82 if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
83 DEBUG_LOG("ERROR: wrong RTPencode version, must be 1.0\n");
84 return kResultFail;
85 }
86 } else {
87 DEBUG_LOG("ERROR: wrong file format of input file\n");
88 return kResultFail;
89 }
90
91 uint32_t start_sec;
92 uint32_t start_usec;
93 uint32_t source;
94 uint16_t port;
95 uint16_t padding;
96 TRY(Read(&start_sec));
97 TRY(Read(&start_usec));
98 TRY(Read(&source));
99 TRY(Read(&port));
100 TRY(Read(&padding));
101
102 return kResultSuccess;
103 }
104
NextPacket(uint8_t * rtp_data,uint32_t * length,uint32_t * time_ms)105 virtual int NextPacket(uint8_t* rtp_data, uint32_t* length,
106 uint32_t* time_ms) {
107 assert(rtp_data);
108 assert(length);
109 assert(time_ms);
110
111 uint16_t len;
112 uint16_t plen;
113 uint32_t offset;
114 TRY(Read(&len));
115 TRY(Read(&plen));
116 TRY(Read(&offset));
117
118 // Use 'len' here because a 'plen' of 0 specifies rtcp.
119 len -= kPacketHeaderSize;
120 if (*length < len) {
121 return kResultFail;
122 }
123 if (fread(rtp_data, 1, len, file_) != len) {
124 return kResultFail;
125 }
126
127 *length = len;
128 *time_ms = offset;
129 return kResultSuccess;
130 }
131
132 private:
Read(uint32_t * out)133 int Read(uint32_t* out) {
134 assert(out);
135 uint32_t tmp = 0;
136 if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
137 return kResultFail;
138 }
139 *out = ntohl(tmp);
140 return kResultSuccess;
141 }
142
Read(uint16_t * out)143 int Read(uint16_t* out) {
144 assert(out);
145 uint16_t tmp = 0;
146 if (fread(&tmp, 1, sizeof(uint16_t), file_) != sizeof(uint16_t)) {
147 return kResultFail;
148 }
149 *out = ntohs(tmp);
150 return kResultSuccess;
151 }
152
153 FILE* file_;
154
155 DISALLOW_COPY_AND_ASSIGN(RtpFileReaderImpl);
156 };
157
CreateRtpFileReader(const std::string & filename)158 RtpPacketSourceInterface* CreateRtpFileReader(const std::string& filename) {
159 scoped_ptr<RtpFileReaderImpl> impl(new RtpFileReaderImpl());
160 if (impl->Initialize(filename) != 0) {
161 return NULL;
162 }
163 return impl.release();
164 }
165 } // namespace rtpplayer
166 } // namespace webrtc
167