1 /*
2 * Copyright (c) 2012 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 "RTPFile.h"
12
13 #include <stdlib.h>
14
15 #include <limits>
16
17 #ifdef WIN32
18 #include <Winsock2.h>
19 #else
20 #include <arpa/inet.h>
21 #endif
22
23 // TODO(tlegrand): Consider removing usage of gtest.
24 #include "test/gtest.h"
25
26 namespace webrtc {
27
ParseRTPHeader(RTPHeader * rtp_header,const uint8_t * rtpHeader)28 void RTPStream::ParseRTPHeader(RTPHeader* rtp_header,
29 const uint8_t* rtpHeader) {
30 rtp_header->payloadType = rtpHeader[1];
31 rtp_header->sequenceNumber =
32 (static_cast<uint16_t>(rtpHeader[2]) << 8) | rtpHeader[3];
33 rtp_header->timestamp = (static_cast<uint32_t>(rtpHeader[4]) << 24) |
34 (static_cast<uint32_t>(rtpHeader[5]) << 16) |
35 (static_cast<uint32_t>(rtpHeader[6]) << 8) |
36 rtpHeader[7];
37 rtp_header->ssrc = (static_cast<uint32_t>(rtpHeader[8]) << 24) |
38 (static_cast<uint32_t>(rtpHeader[9]) << 16) |
39 (static_cast<uint32_t>(rtpHeader[10]) << 8) |
40 rtpHeader[11];
41 }
42
MakeRTPheader(uint8_t * rtpHeader,uint8_t payloadType,int16_t seqNo,uint32_t timeStamp,uint32_t ssrc)43 void RTPStream::MakeRTPheader(uint8_t* rtpHeader,
44 uint8_t payloadType,
45 int16_t seqNo,
46 uint32_t timeStamp,
47 uint32_t ssrc) {
48 rtpHeader[0] = 0x80;
49 rtpHeader[1] = payloadType;
50 rtpHeader[2] = (seqNo >> 8) & 0xFF;
51 rtpHeader[3] = seqNo & 0xFF;
52 rtpHeader[4] = timeStamp >> 24;
53 rtpHeader[5] = (timeStamp >> 16) & 0xFF;
54 rtpHeader[6] = (timeStamp >> 8) & 0xFF;
55 rtpHeader[7] = timeStamp & 0xFF;
56 rtpHeader[8] = ssrc >> 24;
57 rtpHeader[9] = (ssrc >> 16) & 0xFF;
58 rtpHeader[10] = (ssrc >> 8) & 0xFF;
59 rtpHeader[11] = ssrc & 0xFF;
60 }
61
RTPPacket(uint8_t payloadType,uint32_t timeStamp,int16_t seqNo,const uint8_t * payloadData,size_t payloadSize,uint32_t frequency)62 RTPPacket::RTPPacket(uint8_t payloadType,
63 uint32_t timeStamp,
64 int16_t seqNo,
65 const uint8_t* payloadData,
66 size_t payloadSize,
67 uint32_t frequency)
68 : payloadType(payloadType),
69 timeStamp(timeStamp),
70 seqNo(seqNo),
71 payloadSize(payloadSize),
72 frequency(frequency) {
73 if (payloadSize > 0) {
74 this->payloadData = new uint8_t[payloadSize];
75 memcpy(this->payloadData, payloadData, payloadSize);
76 }
77 }
78
~RTPPacket()79 RTPPacket::~RTPPacket() {
80 delete[] payloadData;
81 }
82
RTPBuffer()83 RTPBuffer::RTPBuffer() {
84 _queueRWLock = RWLockWrapper::CreateRWLock();
85 }
86
~RTPBuffer()87 RTPBuffer::~RTPBuffer() {
88 delete _queueRWLock;
89 }
90
Write(const uint8_t payloadType,const uint32_t timeStamp,const int16_t seqNo,const uint8_t * payloadData,const size_t payloadSize,uint32_t frequency)91 void RTPBuffer::Write(const uint8_t payloadType,
92 const uint32_t timeStamp,
93 const int16_t seqNo,
94 const uint8_t* payloadData,
95 const size_t payloadSize,
96 uint32_t frequency) {
97 RTPPacket* packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData,
98 payloadSize, frequency);
99 _queueRWLock->AcquireLockExclusive();
100 _rtpQueue.push(packet);
101 _queueRWLock->ReleaseLockExclusive();
102 }
103
Read(RTPHeader * rtp_header,uint8_t * payloadData,size_t payloadSize,uint32_t * offset)104 size_t RTPBuffer::Read(RTPHeader* rtp_header,
105 uint8_t* payloadData,
106 size_t payloadSize,
107 uint32_t* offset) {
108 _queueRWLock->AcquireLockShared();
109 RTPPacket* packet = _rtpQueue.front();
110 _rtpQueue.pop();
111 _queueRWLock->ReleaseLockShared();
112 rtp_header->markerBit = 1;
113 rtp_header->payloadType = packet->payloadType;
114 rtp_header->sequenceNumber = packet->seqNo;
115 rtp_header->ssrc = 0;
116 rtp_header->timestamp = packet->timeStamp;
117 if (packet->payloadSize > 0 && payloadSize >= packet->payloadSize) {
118 memcpy(payloadData, packet->payloadData, packet->payloadSize);
119 } else {
120 return 0;
121 }
122 *offset = (packet->timeStamp / (packet->frequency / 1000));
123
124 return packet->payloadSize;
125 }
126
EndOfFile() const127 bool RTPBuffer::EndOfFile() const {
128 _queueRWLock->AcquireLockShared();
129 bool eof = _rtpQueue.empty();
130 _queueRWLock->ReleaseLockShared();
131 return eof;
132 }
133
Open(const char * filename,const char * mode)134 void RTPFile::Open(const char* filename, const char* mode) {
135 if ((_rtpFile = fopen(filename, mode)) == NULL) {
136 printf("Cannot write file %s.\n", filename);
137 ADD_FAILURE() << "Unable to write file";
138 exit(1);
139 }
140 }
141
Close()142 void RTPFile::Close() {
143 if (_rtpFile != NULL) {
144 fclose(_rtpFile);
145 _rtpFile = NULL;
146 }
147 }
148
WriteHeader()149 void RTPFile::WriteHeader() {
150 // Write data in a format that NetEQ and RTP Play can parse
151 fprintf(_rtpFile, "#!RTPencode%s\n", "1.0");
152 uint32_t dummy_variable = 0;
153 // should be converted to network endian format, but does not matter when 0
154 EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
155 EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
156 EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
157 EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile));
158 EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile));
159 fflush(_rtpFile);
160 }
161
ReadHeader()162 void RTPFile::ReadHeader() {
163 uint32_t start_sec, start_usec, source;
164 uint16_t port, padding;
165 char fileHeader[40];
166 EXPECT_TRUE(fgets(fileHeader, 40, _rtpFile) != 0);
167 EXPECT_EQ(1u, fread(&start_sec, 4, 1, _rtpFile));
168 start_sec = ntohl(start_sec);
169 EXPECT_EQ(1u, fread(&start_usec, 4, 1, _rtpFile));
170 start_usec = ntohl(start_usec);
171 EXPECT_EQ(1u, fread(&source, 4, 1, _rtpFile));
172 source = ntohl(source);
173 EXPECT_EQ(1u, fread(&port, 2, 1, _rtpFile));
174 port = ntohs(port);
175 EXPECT_EQ(1u, fread(&padding, 2, 1, _rtpFile));
176 padding = ntohs(padding);
177 }
178
Write(const uint8_t payloadType,const uint32_t timeStamp,const int16_t seqNo,const uint8_t * payloadData,const size_t payloadSize,uint32_t frequency)179 void RTPFile::Write(const uint8_t payloadType,
180 const uint32_t timeStamp,
181 const int16_t seqNo,
182 const uint8_t* payloadData,
183 const size_t payloadSize,
184 uint32_t frequency) {
185 /* write RTP packet to file */
186 uint8_t rtpHeader[12];
187 MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0);
188 ASSERT_LE(12 + payloadSize + 8, std::numeric_limits<u_short>::max());
189 uint16_t lengthBytes = htons(static_cast<u_short>(12 + payloadSize + 8));
190 uint16_t plen = htons(static_cast<u_short>(12 + payloadSize));
191 uint32_t offsetMs;
192
193 offsetMs = (timeStamp / (frequency / 1000));
194 offsetMs = htonl(offsetMs);
195 EXPECT_EQ(1u, fwrite(&lengthBytes, 2, 1, _rtpFile));
196 EXPECT_EQ(1u, fwrite(&plen, 2, 1, _rtpFile));
197 EXPECT_EQ(1u, fwrite(&offsetMs, 4, 1, _rtpFile));
198 EXPECT_EQ(1u, fwrite(&rtpHeader, 12, 1, _rtpFile));
199 EXPECT_EQ(payloadSize, fwrite(payloadData, 1, payloadSize, _rtpFile));
200 }
201
Read(RTPHeader * rtp_header,uint8_t * payloadData,size_t payloadSize,uint32_t * offset)202 size_t RTPFile::Read(RTPHeader* rtp_header,
203 uint8_t* payloadData,
204 size_t payloadSize,
205 uint32_t* offset) {
206 uint16_t lengthBytes;
207 uint16_t plen;
208 uint8_t rtpHeader[12];
209 size_t read_len = fread(&lengthBytes, 2, 1, _rtpFile);
210 /* Check if we have reached end of file. */
211 if ((read_len == 0) && feof(_rtpFile)) {
212 _rtpEOF = true;
213 return 0;
214 }
215 EXPECT_EQ(1u, fread(&plen, 2, 1, _rtpFile));
216 EXPECT_EQ(1u, fread(offset, 4, 1, _rtpFile));
217 lengthBytes = ntohs(lengthBytes);
218 plen = ntohs(plen);
219 *offset = ntohl(*offset);
220 EXPECT_GT(plen, 11);
221
222 EXPECT_EQ(1u, fread(rtpHeader, 12, 1, _rtpFile));
223 ParseRTPHeader(rtp_header, rtpHeader);
224 EXPECT_EQ(lengthBytes, plen + 8);
225
226 if (plen == 0) {
227 return 0;
228 }
229 if (lengthBytes < 20) {
230 return 0;
231 }
232 if (payloadSize < static_cast<size_t>((lengthBytes - 20))) {
233 return 0;
234 }
235 lengthBytes -= 20;
236 EXPECT_EQ(lengthBytes, fread(payloadData, 1, lengthBytes, _rtpFile));
237 return lengthBytes;
238 }
239
240 } // namespace webrtc
241