Home | History | Annotate | Download | only in test
      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