tor-browser

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

rtp_jitter.cc (4762B)


      1 /*
      2 *  Copyright (c) 2017 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 <algorithm>
     12 #include <cstdint>
     13 #include <cstdio>
     14 #include <fstream>
     15 #include <iostream>
     16 #include <string>
     17 #include <utility>
     18 #include <vector>
     19 
     20 #include "api/array_view.h"
     21 #include "modules/rtp_rtcp/source/byte_io.h"
     22 #include "rtc_base/buffer.h"
     23 #include "rtc_base/checks.h"
     24 
     25 namespace webrtc {
     26 namespace test {
     27 namespace {
     28 
     29 constexpr size_t kRtpDumpHeaderLength = 8;
     30 
     31 // Returns the next packet or an empty buffer if end of file was encountered.
     32 Buffer ReadNextPacket(FILE* file) {
     33  // Read the rtpdump header for the next packet.
     34  Buffer buffer;
     35  buffer.SetData(kRtpDumpHeaderLength, [&](ArrayView<uint8_t> x) {
     36    return fread(x.data(), 1, x.size(), file);
     37  });
     38  if (buffer.size() != kRtpDumpHeaderLength) {
     39    return Buffer();
     40  }
     41 
     42  // Get length field. This is the total length for this packet written to file,
     43  // including the kRtpDumpHeaderLength bytes already read.
     44  const uint16_t len = ByteReader<uint16_t>::ReadBigEndian(buffer.data());
     45  RTC_CHECK_GE(len, kRtpDumpHeaderLength);
     46 
     47  // Read remaining data from file directly into buffer.
     48  buffer.AppendData(len - kRtpDumpHeaderLength, [&](ArrayView<uint8_t> x) {
     49    return fread(x.data(), 1, x.size(), file);
     50  });
     51  if (buffer.size() != len) {
     52    buffer.Clear();
     53  }
     54  return buffer;
     55 }
     56 
     57 struct PacketAndTime {
     58  Buffer packet;
     59  int time;
     60 };
     61 
     62 void WritePacket(const PacketAndTime& packet, FILE* file) {
     63  // Write the first 4 bytes from the original packet.
     64  const auto* payload_ptr = packet.packet.data();
     65  RTC_CHECK_EQ(fwrite(payload_ptr, 4, 1, file), 1);
     66  payload_ptr += 4;
     67 
     68  // Convert the new time offset to network endian, and write to file.
     69  uint8_t time[sizeof(uint32_t)];
     70  ByteWriter<uint32_t, sizeof(uint32_t)>::WriteBigEndian(time, packet.time);
     71  RTC_CHECK_EQ(fwrite(time, sizeof(uint32_t), 1, file), 1);
     72  payload_ptr += 4;  // Skip the old time in the original payload.
     73 
     74  // Write the remaining part of the payload.
     75  RTC_DCHECK_EQ(payload_ptr - packet.packet.data(), kRtpDumpHeaderLength);
     76  RTC_CHECK_EQ(
     77      fwrite(payload_ptr, packet.packet.size() - kRtpDumpHeaderLength, 1, file),
     78      1);
     79 }
     80 
     81 int RunRtpJitter(int argc, char* argv[]) {
     82  const std::string program_name = argv[0];
     83  const std::string usage =
     84      "Tool for alternating the arrival times in an RTP dump file.\n"
     85      "Example usage:\n" +
     86      program_name + " input.rtp arrival_times_ms.txt output.rtp\n\n";
     87  if (argc != 4) {
     88    printf("%s", usage.c_str());
     89    return 1;
     90  }
     91 
     92  printf("Input RTP file: %s\n", argv[1]);
     93  FILE* in_file = fopen(argv[1], "rb");
     94  RTC_CHECK(in_file) << "Could not open file " << argv[1] << " for reading";
     95  printf("Timing file: %s\n", argv[2]);
     96  std::ifstream timing_file(argv[2]);
     97  printf("Output file: %s\n", argv[3]);
     98  FILE* out_file = fopen(argv[3], "wb");
     99  RTC_CHECK(out_file) << "Could not open file " << argv[2] << " for writing";
    100 
    101  // Copy the RTP file header to the output file.
    102  char header_string[30];
    103  RTC_CHECK(fgets(header_string, 30, in_file));
    104  fprintf(out_file, "%s", header_string);
    105  uint8_t file_header[16];
    106  RTC_CHECK_EQ(fread(file_header, sizeof(file_header), 1, in_file), 1);
    107  RTC_CHECK_EQ(fwrite(file_header, sizeof(file_header), 1, out_file), 1);
    108 
    109  // Read all time values from the timing file. Store in a vector.
    110  std::vector<int> new_arrival_times;
    111  int new_time;
    112  while (timing_file >> new_time) {
    113    new_arrival_times.push_back(new_time);
    114  }
    115 
    116  // Read all packets from the input RTP file, but no more than the number of
    117  // new time values. Store RTP packets together with new time values.
    118  auto time_it = new_arrival_times.begin();
    119  std::vector<PacketAndTime> packets;
    120  while (1) {
    121    auto packet = ReadNextPacket(in_file);
    122    if (packet.empty() || time_it == new_arrival_times.end()) {
    123      break;
    124    }
    125    packets.push_back({std::move(packet), *time_it});
    126    ++time_it;
    127  }
    128 
    129  // Sort on new time values.
    130  std::sort(packets.begin(), packets.end(),
    131            [](const PacketAndTime& a, const PacketAndTime& b) {
    132              return a.time < b.time;
    133            });
    134 
    135  // Write packets to output file.
    136  for (const auto& p : packets) {
    137    WritePacket(p, out_file);
    138  }
    139 
    140  fclose(in_file);
    141  fclose(out_file);
    142  return 0;
    143 }
    144 
    145 }  // namespace
    146 }  // namespace test
    147 }  // namespace webrtc
    148 
    149 int main(int argc, char* argv[]) {
    150  return webrtc::test::RunRtpJitter(argc, argv);
    151 }