• 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 #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 
ParseRTPHeader(WebRtcRTPHeader * rtpInfo,const uint8_t * rtpHeader)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 
MakeRTPheader(uint8_t * rtpHeader,uint8_t payloadType,int16_t seqNo,uint32_t timeStamp,uint32_t ssrc)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 
RTPPacket(uint8_t payloadType,uint32_t timeStamp,int16_t seqNo,const uint8_t * payloadData,size_t payloadSize,uint32_t frequency)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 
~RTPPacket()74 RTPPacket::~RTPPacket() {
75   delete[] payloadData;
76 }
77 
RTPBuffer()78 RTPBuffer::RTPBuffer() {
79   _queueRWLock = RWLockWrapper::CreateRWLock();
80 }
81 
~RTPBuffer()82 RTPBuffer::~RTPBuffer() {
83   delete _queueRWLock;
84 }
85 
Write(const uint8_t payloadType,const uint32_t timeStamp,const int16_t seqNo,const uint8_t * payloadData,const size_t payloadSize,uint32_t frequency)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 
Read(WebRtcRTPHeader * rtpInfo,uint8_t * payloadData,size_t payloadSize,uint32_t * offset)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 
EndOfFile() const117 bool RTPBuffer::EndOfFile() const {
118   _queueRWLock->AcquireLockShared();
119   bool eof = _rtpQueue.empty();
120   _queueRWLock->ReleaseLockShared();
121   return eof;
122 }
123 
Open(const char * filename,const char * mode)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 
Close()132 void RTPFile::Close() {
133   if (_rtpFile != NULL) {
134     fclose(_rtpFile);
135     _rtpFile = NULL;
136   }
137 }
138 
WriteHeader()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 
ReadHeader()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 
Write(const uint8_t payloadType,const uint32_t timeStamp,const int16_t seqNo,const uint8_t * payloadData,const size_t payloadSize,uint32_t frequency)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 
Read(WebRtcRTPHeader * rtpInfo,uint8_t * payloadData,size_t payloadSize,uint32_t * offset)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
228