tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RTPFile.cc (7799B)


      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 <sys/types.h>
     14 
     15 #include <cstdint>
     16 #include <cstdio>
     17 #include <cstdlib>
     18 #include <cstring>
     19 #include <limits>
     20 #include <string>
     21 
     22 #include "absl/strings/string_view.h"
     23 #include "api/rtp_headers.h"
     24 #include "rtc_base/ip_address.h"
     25 #include "rtc_base/synchronization/mutex.h"
     26 
     27 #ifdef WIN32
     28 #include <Winsock2.h>
     29 #else
     30 #endif
     31 
     32 // TODO(tlegrand): Consider removing usage of gtest.
     33 #include "test/gtest.h"
     34 
     35 namespace webrtc {
     36 
     37 void RTPStream::ParseRTPHeader(RTPHeader* rtp_header,
     38                               const uint8_t* rtpHeader) {
     39  rtp_header->payloadType = rtpHeader[1];
     40  rtp_header->sequenceNumber =
     41      (static_cast<uint16_t>(rtpHeader[2]) << 8) | rtpHeader[3];
     42  rtp_header->timestamp = (static_cast<uint32_t>(rtpHeader[4]) << 24) |
     43                          (static_cast<uint32_t>(rtpHeader[5]) << 16) |
     44                          (static_cast<uint32_t>(rtpHeader[6]) << 8) |
     45                          rtpHeader[7];
     46  rtp_header->ssrc = (static_cast<uint32_t>(rtpHeader[8]) << 24) |
     47                     (static_cast<uint32_t>(rtpHeader[9]) << 16) |
     48                     (static_cast<uint32_t>(rtpHeader[10]) << 8) |
     49                     rtpHeader[11];
     50 }
     51 
     52 void RTPStream::MakeRTPheader(uint8_t* rtpHeader,
     53                              uint8_t payloadType,
     54                              int16_t seqNo,
     55                              uint32_t timeStamp,
     56                              uint32_t ssrc) {
     57  rtpHeader[0] = 0x80;
     58  rtpHeader[1] = payloadType;
     59  rtpHeader[2] = (seqNo >> 8) & 0xFF;
     60  rtpHeader[3] = seqNo & 0xFF;
     61  rtpHeader[4] = timeStamp >> 24;
     62  rtpHeader[5] = (timeStamp >> 16) & 0xFF;
     63  rtpHeader[6] = (timeStamp >> 8) & 0xFF;
     64  rtpHeader[7] = timeStamp & 0xFF;
     65  rtpHeader[8] = ssrc >> 24;
     66  rtpHeader[9] = (ssrc >> 16) & 0xFF;
     67  rtpHeader[10] = (ssrc >> 8) & 0xFF;
     68  rtpHeader[11] = ssrc & 0xFF;
     69 }
     70 
     71 RTPPacket::RTPPacket(uint8_t payloadType,
     72                     uint32_t timeStamp,
     73                     int16_t seqNo,
     74                     const uint8_t* payloadData,
     75                     size_t payloadSize,
     76                     uint32_t frequency)
     77    : payloadType(payloadType),
     78      timeStamp(timeStamp),
     79      seqNo(seqNo),
     80      payloadSize(payloadSize),
     81      frequency(frequency) {
     82  if (payloadSize > 0) {
     83    this->payloadData = new uint8_t[payloadSize];
     84    memcpy(this->payloadData, payloadData, payloadSize);
     85  }
     86 }
     87 
     88 RTPPacket::~RTPPacket() {
     89  delete[] payloadData;
     90 }
     91 
     92 void RTPBuffer::Write(const uint8_t payloadType,
     93                      const uint32_t timeStamp,
     94                      const int16_t seqNo,
     95                      const uint8_t* payloadData,
     96                      const size_t payloadSize,
     97                      uint32_t frequency) {
     98  RTPPacket* packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData,
     99                                    payloadSize, frequency);
    100  MutexLock lock(&mutex_);
    101  _rtpQueue.push(packet);
    102 }
    103 
    104 size_t RTPBuffer::Read(RTPHeader* rtp_header,
    105                       uint8_t* payloadData,
    106                       size_t payloadSize,
    107                       uint32_t* offset) {
    108  RTPPacket* packet;
    109  {
    110    MutexLock lock(&mutex_);
    111    packet = _rtpQueue.front();
    112    _rtpQueue.pop();
    113  }
    114  rtp_header->markerBit = 1;
    115  rtp_header->payloadType = packet->payloadType;
    116  rtp_header->sequenceNumber = packet->seqNo;
    117  rtp_header->ssrc = 0;
    118  rtp_header->timestamp = packet->timeStamp;
    119  if (packet->payloadSize > 0 && payloadSize >= packet->payloadSize) {
    120    memcpy(payloadData, packet->payloadData, packet->payloadSize);
    121  } else {
    122    return 0;
    123  }
    124  *offset = (packet->timeStamp / (packet->frequency / 1000));
    125 
    126  return packet->payloadSize;
    127 }
    128 
    129 bool RTPBuffer::EndOfFile() const {
    130  MutexLock lock(&mutex_);
    131  return _rtpQueue.empty();
    132 }
    133 
    134 void RTPFile::Open(absl::string_view filename, absl::string_view mode) {
    135  std::string filename_str = std::string(filename);
    136  if ((_rtpFile = fopen(filename_str.c_str(), std::string(mode).c_str())) ==
    137      nullptr) {
    138    printf("Cannot write file %s.\n", filename_str.c_str());
    139    ADD_FAILURE() << "Unable to write file";
    140    exit(1);
    141  }
    142 }
    143 
    144 void RTPFile::Close() {
    145  if (_rtpFile != nullptr) {
    146    fclose(_rtpFile);
    147    _rtpFile = nullptr;
    148  }
    149 }
    150 
    151 void RTPFile::WriteHeader() {
    152  // Write data in a format that NetEQ and RTP Play can parse
    153  fprintf(_rtpFile, "#!RTPencode%s\n", "1.0");
    154  uint32_t dummy_variable = 0;
    155  // should be converted to network endian format, but does not matter when 0
    156  EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
    157  EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
    158  EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
    159  EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile));
    160  EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile));
    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) != nullptr);
    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,
    182                    const uint32_t timeStamp,
    183                    const int16_t seqNo,
    184                    const uint8_t* payloadData,
    185                    const size_t payloadSize,
    186                    uint32_t frequency) {
    187  /* write RTP packet to file */
    188  uint8_t rtpHeader[12];
    189  MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0);
    190  ASSERT_LE(12 + payloadSize + 8, std::numeric_limits<u_short>::max());
    191  uint16_t lengthBytes = htons(static_cast<u_short>(12 + payloadSize + 8));
    192  uint16_t plen = htons(static_cast<u_short>(12 + payloadSize));
    193  uint32_t offsetMs;
    194 
    195  offsetMs = (timeStamp / (frequency / 1000));
    196  offsetMs = htonl(offsetMs);
    197  EXPECT_EQ(1u, fwrite(&lengthBytes, 2, 1, _rtpFile));
    198  EXPECT_EQ(1u, fwrite(&plen, 2, 1, _rtpFile));
    199  EXPECT_EQ(1u, fwrite(&offsetMs, 4, 1, _rtpFile));
    200  EXPECT_EQ(1u, fwrite(&rtpHeader, 12, 1, _rtpFile));
    201  EXPECT_EQ(payloadSize, fwrite(payloadData, 1, payloadSize, _rtpFile));
    202 }
    203 
    204 size_t RTPFile::Read(RTPHeader* rtp_header,
    205                     uint8_t* payloadData,
    206                     size_t payloadSize,
    207                     uint32_t* offset) {
    208  uint16_t lengthBytes;
    209  uint16_t plen;
    210  uint8_t rtpHeader[12];
    211  size_t read_len = fread(&lengthBytes, 2, 1, _rtpFile);
    212  /* Check if we have reached end of file. */
    213  if ((read_len == 0) && feof(_rtpFile)) {
    214    _rtpEOF = true;
    215    return 0;
    216  }
    217  EXPECT_EQ(1u, fread(&plen, 2, 1, _rtpFile));
    218  EXPECT_EQ(1u, fread(offset, 4, 1, _rtpFile));
    219  lengthBytes = ntohs(lengthBytes);
    220  plen = ntohs(plen);
    221  *offset = ntohl(*offset);
    222  EXPECT_GT(plen, 11);
    223 
    224  EXPECT_EQ(1u, fread(rtpHeader, 12, 1, _rtpFile));
    225  ParseRTPHeader(rtp_header, rtpHeader);
    226  EXPECT_EQ(lengthBytes, plen + 8);
    227 
    228  if (plen == 0) {
    229    return 0;
    230  }
    231  if (lengthBytes < 20) {
    232    return 0;
    233  }
    234  if (payloadSize < static_cast<size_t>((lengthBytes - 20))) {
    235    return 0;
    236  }
    237  lengthBytes -= 20;
    238  EXPECT_EQ(lengthBytes, fread(payloadData, 1, lengthBytes, _rtpFile));
    239  return lengthBytes;
    240 }
    241 
    242 }  // namespace webrtc