tor-browser

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

rtc_event_log2rtp_dump.cc (9296B)


      1 /*
      2 *  Copyright (c) 2015 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 <cstdint>
     12 #include <cstring>
     13 #include <iostream>
     14 #include <memory>
     15 #include <optional>
     16 #include <string>
     17 #include <vector>
     18 
     19 #include "absl/flags/flag.h"
     20 #include "absl/flags/parse.h"
     21 #include "absl/flags/usage.h"
     22 #include "absl/strings/string_view.h"
     23 #include "api/array_view.h"
     24 #include "api/rtp_headers.h"
     25 #include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
     26 #include "logging/rtc_event_log/rtc_event_log_parser.h"
     27 #include "logging/rtc_event_log/rtc_event_processor.h"
     28 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
     29 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
     30 #include "modules/rtp_rtcp/source/rtp_packet.h"
     31 #include "rtc_base/checks.h"
     32 #include "rtc_base/string_to_number.h"
     33 #include "test/rtp_file_reader.h"
     34 #include "test/rtp_file_writer.h"
     35 
     36 ABSL_FLAG(
     37    bool,
     38    audio,
     39    true,
     40    "Use --noaudio to exclude audio packets from the converted RTPdump file.");
     41 ABSL_FLAG(
     42    bool,
     43    video,
     44    true,
     45    "Use --novideo to exclude video packets from the converted RTPdump file.");
     46 ABSL_FLAG(
     47    bool,
     48    data,
     49    true,
     50    "Use --nodata to exclude data packets from the converted RTPdump file.");
     51 ABSL_FLAG(
     52    bool,
     53    rtp,
     54    true,
     55    "Use --nortp to exclude RTP packets from the converted RTPdump file.");
     56 ABSL_FLAG(
     57    bool,
     58    rtcp,
     59    true,
     60    "Use --nortcp to exclude RTCP packets from the converted RTPdump file.");
     61 ABSL_FLAG(std::string,
     62          ssrc,
     63          "",
     64          "Store only packets with this SSRC (decimal or hex, the latter "
     65          "starting with 0x).");
     66 
     67 namespace {
     68 
     69 using MediaType = webrtc::ParsedRtcEventLog::MediaType;
     70 
     71 // Parses the input string for a valid SSRC. If a valid SSRC is found, it is
     72 // written to the output variable `ssrc`, and true is returned. Otherwise,
     73 // false is returned.
     74 // The empty string must be validated as true, because it is the default value
     75 // of the command-line flag. In this case, no value is written to the output
     76 // variable.
     77 std::optional<uint32_t> ParseSsrc(absl::string_view str) {
     78  // Set `base` to 0 to allow detection of the "0x" prefix in case hex is used.
     79  return webrtc::StringToNumber<uint32_t>(str, 0);
     80 }
     81 
     82 bool ShouldSkipStream(MediaType media_type,
     83                      uint32_t ssrc,
     84                      std::optional<uint32_t> ssrc_filter) {
     85  if (!absl::GetFlag(FLAGS_audio) && media_type == MediaType::AUDIO)
     86    return true;
     87  if (!absl::GetFlag(FLAGS_video) && media_type == MediaType::VIDEO)
     88    return true;
     89  if (!absl::GetFlag(FLAGS_data) && media_type == MediaType::DATA)
     90    return true;
     91  if (ssrc_filter.has_value() && ssrc != *ssrc_filter)
     92    return true;
     93  return false;
     94 }
     95 
     96 // Convert a LoggedRtpPacketIncoming to a test::RtpPacket. Header extension IDs
     97 // are allocated according to the provided extension map. This might not match
     98 // the extension map used in the actual call.
     99 void ConvertRtpPacket(
    100    const webrtc::LoggedRtpPacketIncoming& incoming,
    101    const webrtc::RtpHeaderExtensionMap& default_extension_map,
    102    webrtc::test::RtpPacket* packet) {
    103  webrtc::RtpPacket reconstructed_packet(&default_extension_map);
    104 
    105  reconstructed_packet.SetMarker(incoming.rtp.header.markerBit);
    106  reconstructed_packet.SetPayloadType(incoming.rtp.header.payloadType);
    107  reconstructed_packet.SetSequenceNumber(incoming.rtp.header.sequenceNumber);
    108  reconstructed_packet.SetTimestamp(incoming.rtp.header.timestamp);
    109  reconstructed_packet.SetSsrc(incoming.rtp.header.ssrc);
    110  if (incoming.rtp.header.numCSRCs > 0) {
    111    reconstructed_packet.SetCsrcs(webrtc::ArrayView<const uint32_t>(
    112        incoming.rtp.header.arrOfCSRCs, incoming.rtp.header.numCSRCs));
    113  }
    114 
    115  // Set extensions.
    116  if (incoming.rtp.header.extension.hasTransmissionTimeOffset)
    117    reconstructed_packet.SetExtension<webrtc::TransmissionOffset>(
    118        incoming.rtp.header.extension.transmissionTimeOffset);
    119  if (incoming.rtp.header.extension.hasAbsoluteSendTime)
    120    reconstructed_packet.SetExtension<webrtc::AbsoluteSendTime>(
    121        incoming.rtp.header.extension.absoluteSendTime);
    122  if (incoming.rtp.header.extension.hasTransportSequenceNumber)
    123    reconstructed_packet.SetExtension<webrtc::TransportSequenceNumber>(
    124        incoming.rtp.header.extension.transportSequenceNumber);
    125  if (incoming.rtp.header.extension.audio_level())
    126    reconstructed_packet.SetExtension<webrtc::AudioLevelExtension>(
    127        *incoming.rtp.header.extension.audio_level());
    128  if (incoming.rtp.header.extension.hasVideoRotation)
    129    reconstructed_packet.SetExtension<webrtc::VideoOrientation>(
    130        incoming.rtp.header.extension.videoRotation);
    131  if (incoming.rtp.header.extension.hasVideoContentType)
    132    reconstructed_packet.SetExtension<webrtc::VideoContentTypeExtension>(
    133        incoming.rtp.header.extension.videoContentType);
    134  if (incoming.rtp.header.extension.has_video_timing)
    135    reconstructed_packet.SetExtension<webrtc::VideoTimingExtension>(
    136        incoming.rtp.header.extension.video_timing);
    137 
    138  RTC_DCHECK_EQ(reconstructed_packet.size(), incoming.rtp.header_length);
    139  RTC_DCHECK_EQ(reconstructed_packet.headers_size(),
    140                incoming.rtp.header_length);
    141  memcpy(packet->data, reconstructed_packet.data(),
    142         reconstructed_packet.headers_size());
    143  packet->length = reconstructed_packet.headers_size();
    144  packet->original_length = incoming.rtp.total_length;
    145  packet->time_ms = incoming.log_time_ms();
    146  // Set padding bit.
    147  if (incoming.rtp.header.paddingLength > 0)
    148    packet->data[0] = packet->data[0] | 0x20;
    149 }
    150 
    151 }  // namespace
    152 
    153 // This utility will convert a stored event log to the rtpdump format.
    154 int main(int argc, char* argv[]) {
    155  absl::SetProgramUsageMessage(
    156      "Tool for converting an RtcEventLog file to an "
    157      "RTP dump file.\n"
    158      "Example usage:\n"
    159      "./rtc_event_log2rtp_dump input.rel output.rtp\n");
    160  std::vector<char*> args = absl::ParseCommandLine(argc, argv);
    161  if (args.size() != 3) {
    162    std::cout << absl::ProgramUsageMessage();
    163    return 1;
    164  }
    165 
    166  std::string input_file = args[1];
    167  std::string output_file = args[2];
    168 
    169  std::optional<uint32_t> ssrc_filter;
    170  if (!absl::GetFlag(FLAGS_ssrc).empty()) {
    171    ssrc_filter = ParseSsrc(absl::GetFlag(FLAGS_ssrc));
    172    RTC_CHECK(ssrc_filter.has_value()) << "Failed to read SSRC filter flag.";
    173  }
    174 
    175  webrtc::ParsedRtcEventLog parsed_stream;
    176  auto status = parsed_stream.ParseFile(input_file);
    177  if (!status.ok()) {
    178    std::cerr << "Failed to parse event log " << input_file << ": "
    179              << status.message() << std::endl;
    180    return -1;
    181  }
    182 
    183  std::unique_ptr<webrtc::test::RtpFileWriter> rtp_writer(
    184      webrtc::test::RtpFileWriter::Create(
    185          webrtc::test::RtpFileWriter::FileFormat::kRtpDump, output_file));
    186 
    187  if (!rtp_writer) {
    188    std::cerr << "Error while opening output file: " << output_file
    189              << std::endl;
    190    return -1;
    191  }
    192 
    193  int rtp_counter = 0, rtcp_counter = 0;
    194  bool header_only = false;
    195 
    196  webrtc::RtpHeaderExtensionMap default_extension_map =
    197      webrtc::ParsedRtcEventLog::GetDefaultHeaderExtensionMap();
    198  auto handle_rtp = [&default_extension_map, &rtp_writer, &rtp_counter](
    199                        const webrtc::LoggedRtpPacketIncoming& incoming) {
    200    webrtc::test::RtpPacket packet;
    201    ConvertRtpPacket(incoming, default_extension_map, &packet);
    202 
    203    rtp_writer->WritePacket(&packet);
    204    rtp_counter++;
    205  };
    206 
    207  auto handle_rtcp = [&rtp_writer, &rtcp_counter](
    208                         const webrtc::LoggedRtcpPacketIncoming& incoming) {
    209    webrtc::test::RtpPacket packet;
    210    memcpy(packet.data, incoming.rtcp.raw_data.data(),
    211           incoming.rtcp.raw_data.size());
    212    packet.length = incoming.rtcp.raw_data.size();
    213    // For RTCP packets the original_length should be set to 0 in the
    214    // RTPdump format.
    215    packet.original_length = 0;
    216    packet.time_ms = incoming.log_time_ms();
    217 
    218    rtp_writer->WritePacket(&packet);
    219    rtcp_counter++;
    220  };
    221 
    222  webrtc::RtcEventProcessor event_processor;
    223  for (const auto& stream : parsed_stream.incoming_rtp_packets_by_ssrc()) {
    224    MediaType media_type =
    225        parsed_stream.GetMediaType(stream.ssrc, webrtc::kIncomingPacket);
    226    if (ShouldSkipStream(media_type, stream.ssrc, ssrc_filter))
    227      continue;
    228    event_processor.AddEvents(stream.incoming_packets, handle_rtp);
    229  }
    230  // Note that `packet_ssrc` is the sender SSRC. An RTCP message may contain
    231  // report blocks for many streams, thus several SSRCs and they don't
    232  // necessarily have to be of the same media type. We therefore don't
    233  // support filtering of RTCP based on SSRC and media type.
    234  event_processor.AddEvents(parsed_stream.incoming_rtcp_packets(), handle_rtcp);
    235 
    236  event_processor.ProcessEventsInOrder();
    237 
    238  std::cout << "Wrote " << rtp_counter << (header_only ? " header-only" : "")
    239            << " RTP packets and " << rtcp_counter
    240            << " RTCP packets to the "
    241               "output file."
    242            << std::endl;
    243  return 0;
    244 }