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