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