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