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 
     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