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 228