• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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