tor-browser

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

rtp_analyze.cc (7732B)


      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 <algorithm>
     12 #include <cstdint>
     13 #include <cstdio>
     14 #include <memory>
     15 #include <string>
     16 #include <vector>
     17 
     18 #include "absl/flags/flag.h"
     19 #include "absl/flags/parse.h"
     20 #include "api/rtp_headers.h"
     21 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
     22 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
     23 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
     24 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
     25 #include "rtc_base/checks.h"
     26 
     27 ABSL_FLAG(int, red, 117, "RTP payload type for RED");
     28 ABSL_FLAG(int,
     29          audio_level,
     30          -1,
     31          "Extension ID for audio level (RFC 6464); "
     32          "-1 not to print audio level");
     33 ABSL_FLAG(int,
     34          abs_send_time,
     35          -1,
     36          "Extension ID for absolute sender time; "
     37          "-1 not to print absolute send time");
     38 
     39 namespace {
     40 
     41 struct RedHeader {
     42  uint32_t rtp_timestamp;
     43  int payload_type;
     44 };
     45 std::vector<RedHeader> ExtractRedHeaders(const webrtc::RtpPacket& packet) {
     46  //
     47  //  0                   1                    2                   3
     48  //  0 1 2 3 4 5 6 7 8 9 0 1 2 3  4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     49  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     50  // |1|   block PT  |  timestamp offset         |   block length    |
     51  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     52  // |1|    ...                                                      |
     53  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     54  // |0|   block PT  |
     55  // +-+-+-+-+-+-+-+-+
     56  //
     57  const uint8_t* payload_ptr = packet.payload().data();
     58  const uint8_t* payload_end_ptr =
     59      packet.payload().data() + packet.payload().size();
     60 
     61  // Find all RED headers with the extension bit set to 1. That is, all headers
     62  // but the last one.
     63  std::vector<RedHeader> red_headers;
     64  while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
     65    RedHeader header;
     66    header.payload_type = payload_ptr[0] & 0x7F;
     67    uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
     68    header.rtp_timestamp = packet.Timestamp() - offset;
     69    red_headers.push_back(header);
     70    payload_ptr += 4;
     71  }
     72  // Last header.
     73  RTC_DCHECK_LT(payload_ptr, payload_end_ptr);
     74  if (payload_ptr >= payload_end_ptr) {
     75    return {};  // Payload too short.
     76  }
     77  RedHeader header;
     78  header.payload_type = payload_ptr[0] & 0x7F;
     79  header.rtp_timestamp = packet.Timestamp();
     80  red_headers.push_back(header);
     81  std::reverse(red_headers.begin(), red_headers.end());
     82  return red_headers;
     83 }
     84 
     85 }  // namespace
     86 
     87 int main(int argc, char* argv[]) {
     88  std::vector<char*> args = absl::ParseCommandLine(argc, argv);
     89  std::string usage =
     90      "Tool for parsing an RTP dump file to text output.\n"
     91      "Example usage:\n"
     92      "./rtp_analyze input.rtp output.txt\n\n"
     93      "Output is sent to stdout if no output file is given. "
     94      "Note that this tool can read files with or without payloads.\n";
     95  if (args.size() != 2 && args.size() != 3) {
     96    printf("%s", usage.c_str());
     97    return 1;
     98  }
     99 
    100  RTC_CHECK(absl::GetFlag(FLAGS_red) >= 0 &&
    101            absl::GetFlag(FLAGS_red) <= 127);          // Payload type
    102  RTC_CHECK(absl::GetFlag(FLAGS_audio_level) == -1 ||  // Default
    103            (absl::GetFlag(FLAGS_audio_level) > 0 &&
    104             absl::GetFlag(FLAGS_audio_level) <= 255));  // Extension ID
    105  RTC_CHECK(absl::GetFlag(FLAGS_abs_send_time) == -1 ||  // Default
    106            (absl::GetFlag(FLAGS_abs_send_time) > 0 &&
    107             absl::GetFlag(FLAGS_abs_send_time) <= 255));  // Extension ID
    108 
    109  printf("Input file: %s\n", args[1]);
    110  std::unique_ptr<webrtc::test::RtpFileSource> file_source(
    111      webrtc::test::RtpFileSource::Create(args[1]));
    112  RTC_DCHECK(file_source.get());
    113  // Set RTP extension IDs.
    114  bool print_audio_level = false;
    115  if (absl::GetFlag(FLAGS_audio_level) != -1) {
    116    print_audio_level = true;
    117    file_source->RegisterRtpHeaderExtension(webrtc::kRtpExtensionAudioLevel,
    118                                            absl::GetFlag(FLAGS_audio_level));
    119  }
    120  bool print_abs_send_time = false;
    121  if (absl::GetFlag(FLAGS_abs_send_time) != -1) {
    122    print_abs_send_time = true;
    123    file_source->RegisterRtpHeaderExtension(
    124        webrtc::kRtpExtensionAbsoluteSendTime,
    125        absl::GetFlag(FLAGS_abs_send_time));
    126  }
    127 
    128  FILE* out_file;
    129  if (args.size() == 3) {
    130    out_file = fopen(args[2], "wt");
    131    if (!out_file) {
    132      printf("Cannot open output file %s\n", args[2]);
    133      return -1;
    134    }
    135    printf("Output file: %s\n\n", args[2]);
    136  } else {
    137    out_file = stdout;
    138  }
    139 
    140  // Print file header.
    141  fprintf(out_file, "SeqNo  TimeStamp   SendTime  Size    PT  M       SSRC");
    142  if (print_audio_level) {
    143    fprintf(out_file, " AuLvl (V)");
    144  }
    145  if (print_abs_send_time) {
    146    fprintf(out_file, " AbsSendTime");
    147  }
    148  fprintf(out_file, "\n");
    149 
    150  uint32_t max_abs_send_time = 0;
    151  int cycles = -1;
    152  std::unique_ptr<webrtc::RtpPacketReceived> packet;
    153  while (true) {
    154    packet = file_source->NextPacket();
    155    if (!packet) {
    156      // End of file reached.
    157      break;
    158    }
    159    // Write packet data to file. Use virtual_packet_length_bytes so that the
    160    // correct packet sizes are printed also for RTP header-only dumps.
    161    fprintf(out_file, "%5u %10u %10i %5zu %5i %2i %#08X",
    162            packet->SequenceNumber(), packet->Timestamp(),
    163            packet->arrival_time().ms<int>(), packet->size(),
    164            packet->PayloadType(), packet->Marker(), packet->Ssrc());
    165    webrtc::AudioLevel audio_level;
    166    if (print_audio_level &&
    167        packet->GetExtension<webrtc::AudioLevelExtension>(&audio_level)) {
    168      fprintf(out_file, " %5d (%1i)", audio_level.level(),
    169              audio_level.voice_activity());
    170    }
    171    uint32_t abs_sent_time;
    172    if (print_abs_send_time &&
    173        packet->GetExtension<webrtc::AbsoluteSendTime>(&abs_sent_time)) {
    174      if (cycles == -1) {
    175        // Initialize.
    176        max_abs_send_time = abs_sent_time;
    177        cycles = 0;
    178      }
    179      // Abs sender time is 24 bit 6.18 fixed point. Shift by 8 to normalize to
    180      // 32 bits (unsigned). Calculate the difference between this packet's
    181      // send time and the maximum observed. Cast to signed 32-bit to get the
    182      // desired wrap-around behavior.
    183      if (static_cast<int32_t>((abs_sent_time << 8) -
    184                               (max_abs_send_time << 8)) >= 0) {
    185        // The difference is non-negative, meaning that this packet is newer
    186        // than the previously observed maximum absolute send time.
    187        if (abs_sent_time < max_abs_send_time) {
    188          // Wrap detected.
    189          cycles++;
    190        }
    191        max_abs_send_time = abs_sent_time;
    192      }
    193      // Abs sender time is 24 bit 6.18 fixed point. Divide by 2^18 to convert
    194      // to floating point representation.
    195      double send_time_seconds =
    196          static_cast<double>(abs_sent_time) / 262144 + 64.0 * cycles;
    197      fprintf(out_file, " %11f", send_time_seconds);
    198    }
    199    fprintf(out_file, "\n");
    200 
    201    if (packet->PayloadType() == absl::GetFlag(FLAGS_red)) {
    202      for (const RedHeader& red : ExtractRedHeaders(*packet)) {
    203        fprintf(out_file, "* %5u %10u %10i %5i\n", packet->SequenceNumber(),
    204                red.rtp_timestamp, packet->arrival_time().ms<int>(),
    205                red.payload_type);
    206      }
    207    }
    208  }
    209 
    210  fclose(out_file);
    211 
    212  return 0;
    213 }