tor-browser

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

neteq_rtpplay.cc (16603B)


      1 /*
      2 *  Copyright (c) 2013 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 <cerrno>
     12 #include <climits>
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstdio>
     16 #include <cstdlib>
     17 #include <iostream>
     18 #include <memory>
     19 #include <optional>
     20 #include <string>
     21 #include <vector>
     22 
     23 #include "absl/flags/flag.h"
     24 #include "absl/flags/parse.h"
     25 #include "absl/strings/string_view.h"
     26 #include "modules/audio_coding/neteq/tools/neteq_test.h"
     27 #include "modules/audio_coding/neteq/tools/neteq_test_factory.h"
     28 #include "rtc_base/checks.h"
     29 #include "rtc_base/strings/string_builder.h"
     30 
     31 using TestConfig = webrtc::test::NetEqTestFactory::Config;
     32 
     33 ABSL_FLAG(bool,
     34          codec_map,
     35          false,
     36          "Prints the mapping between RTP payload type and "
     37          "codec");
     38 ABSL_FLAG(std::string,
     39          force_fieldtrials,
     40          "",
     41          "Field trials control experimental feature code which can be forced. "
     42          "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
     43          " will assign the group Enable to field trial WebRTC-FooFeature.");
     44 ABSL_FLAG(int, pcmu, TestConfig::default_pcmu(), "RTP payload type for PCM-u");
     45 ABSL_FLAG(int, pcma, TestConfig::default_pcma(), "RTP payload type for PCM-a");
     46 ABSL_FLAG(int, isac, TestConfig::default_isac(), "RTP payload type for iSAC");
     47 ABSL_FLAG(int,
     48          isac_swb,
     49          TestConfig::default_isac_swb(),
     50          "RTP payload type for iSAC-swb (32 kHz)");
     51 ABSL_FLAG(int, opus, TestConfig::default_opus(), "RTP payload type for Opus");
     52 ABSL_FLAG(int,
     53          pcm16b,
     54          TestConfig::default_pcm16b(),
     55          "RTP payload type for PCM16b-nb (8 kHz)");
     56 ABSL_FLAG(int,
     57          pcm16b_wb,
     58          TestConfig::default_pcm16b_wb(),
     59          "RTP payload type for PCM16b-wb (16 kHz)");
     60 ABSL_FLAG(int,
     61          pcm16b_swb32,
     62          TestConfig::default_pcm16b_swb32(),
     63          "RTP payload type for PCM16b-swb32 (32 kHz)");
     64 ABSL_FLAG(int,
     65          pcm16b_swb48,
     66          TestConfig::default_pcm16b_swb48(),
     67          "RTP payload type for PCM16b-swb48 (48 kHz)");
     68 ABSL_FLAG(int, g722, TestConfig::default_g722(), "RTP payload type for G.722");
     69 ABSL_FLAG(int,
     70          avt,
     71          TestConfig::default_avt(),
     72          "RTP payload type for AVT/DTMF (8 kHz)");
     73 ABSL_FLAG(int,
     74          avt_16,
     75          TestConfig::default_avt_16(),
     76          "RTP payload type for AVT/DTMF (16 kHz)");
     77 ABSL_FLAG(int,
     78          avt_32,
     79          TestConfig::default_avt_32(),
     80          "RTP payload type for AVT/DTMF (32 kHz)");
     81 ABSL_FLAG(int,
     82          avt_48,
     83          TestConfig::default_avt_48(),
     84          "RTP payload type for AVT/DTMF (48 kHz)");
     85 ABSL_FLAG(int,
     86          red,
     87          TestConfig::default_red(),
     88          "RTP payload type for redundant audio (RED, 8kHz)");
     89 ABSL_FLAG(int,
     90          opus_red,
     91          TestConfig::default_opus_red(),
     92          "RTP payload type for redundant audio (RED, 48kHz)");
     93 ABSL_FLAG(int,
     94          cn_nb,
     95          TestConfig::default_cn_nb(),
     96          "RTP payload type for comfort noise (8 kHz)");
     97 ABSL_FLAG(int,
     98          cn_wb,
     99          TestConfig::default_cn_wb(),
    100          "RTP payload type for comfort noise (16 kHz)");
    101 ABSL_FLAG(int,
    102          cn_swb32,
    103          TestConfig::default_cn_swb32(),
    104          "RTP payload type for comfort noise (32 kHz)");
    105 ABSL_FLAG(int,
    106          cn_swb48,
    107          TestConfig::default_cn_swb48(),
    108          "RTP payload type for comfort noise (48 kHz)");
    109 ABSL_FLAG(std::string,
    110          replacement_audio_file,
    111          "",
    112          "A PCM file that will be used to populate dummy"
    113          " RTP packets");
    114 ABSL_FLAG(std::string,
    115          ssrc,
    116          "",
    117          "Only use packets with this SSRC (decimal or hex, the latter "
    118          "starting with 0x)");
    119 ABSL_FLAG(int,
    120          audio_level,
    121          TestConfig::default_audio_level(),
    122          "Extension ID for audio level (RFC 6464)");
    123 ABSL_FLAG(int,
    124          abs_send_time,
    125          TestConfig::default_abs_send_time(),
    126          "Extension ID for absolute sender time");
    127 ABSL_FLAG(int,
    128          transport_seq_no,
    129          TestConfig::default_transport_seq_no(),
    130          "Extension ID for transport sequence number");
    131 ABSL_FLAG(int,
    132          video_content_type,
    133          TestConfig::default_video_content_type(),
    134          "Extension ID for video content type");
    135 ABSL_FLAG(int,
    136          video_timing,
    137          TestConfig::default_video_timing(),
    138          "Extension ID for video timing");
    139 ABSL_FLAG(std::string,
    140          output_files_base_name,
    141          "",
    142          "Custom path used as prefix for the output files - i.e., "
    143          "matlab plot, python plot, text log.");
    144 ABSL_FLAG(bool,
    145          matlabplot,
    146          false,
    147          "Generates a matlab script for plotting the delay profile");
    148 ABSL_FLAG(bool,
    149          pythonplot,
    150          false,
    151          "Generates a python script for plotting the delay profile");
    152 ABSL_FLAG(bool,
    153          textlog,
    154          false,
    155          "Generates a text log describing the simulation on a "
    156          "step-by-step basis.");
    157 ABSL_FLAG(bool, concealment_events, false, "Prints concealment events");
    158 ABSL_FLAG(int,
    159          max_nr_packets_in_buffer,
    160          TestConfig::default_max_nr_packets_in_buffer(),
    161          "Maximum allowed number of packets in the buffer");
    162 ABSL_FLAG(bool,
    163          enable_fast_accelerate,
    164          false,
    165          "Enables jitter buffer fast accelerate");
    166 
    167 namespace {
    168 
    169 // Parses the input string for a valid SSRC (at the start of the string). If a
    170 // valid SSRC is found, it is written to the output variable `ssrc`, and true is
    171 // returned. Otherwise, false is returned.
    172 bool ParseSsrc(absl::string_view str, uint32_t* ssrc) {
    173  if (str.empty())
    174    return true;
    175  int base = 10;
    176  // Look for "0x" or "0X" at the start and change base to 16 if found.
    177  if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0))
    178    base = 16;
    179  errno = 0;
    180  char* end_ptr;
    181  std::string str_str = std::string(str);
    182  unsigned long value = strtoul(str_str.c_str(), &end_ptr, base);  // NOLINT
    183  if (value == ULONG_MAX && errno == ERANGE)
    184    return false;  // Value out of range for unsigned long.
    185  if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF)  // NOLINT
    186    return false;  // Value out of range for uint32_t.
    187  if (end_ptr - str_str.c_str() < static_cast<ptrdiff_t>(str.length()))
    188    return false;  // Part of the string was not parsed.
    189  *ssrc = static_cast<uint32_t>(value);
    190  return true;
    191 }
    192 
    193 bool ValidateExtensionId(int value) {
    194  if (value > 0 && value <= 255)  // Value is ok.
    195    return true;
    196  printf("Extension ID must be between 1 and 255, not %d\n",
    197         static_cast<int>(value));
    198  return false;
    199 }
    200 
    201 // Flag validators.
    202 bool ValidatePayloadType(int value) {
    203  if (value >= 0 && value <= 127)  // Value is ok.
    204    return true;
    205  printf("Payload type must be between 0 and 127, not %d\n",
    206         static_cast<int>(value));
    207  return false;
    208 }
    209 
    210 bool ValidateSsrcValue(absl::string_view str) {
    211  uint32_t dummy_ssrc;
    212  if (ParseSsrc(str, &dummy_ssrc))  // Value is ok.
    213    return true;
    214  printf("Invalid SSRC: %.*s\n", static_cast<int>(str.size()), str.data());
    215  return false;
    216 }
    217 
    218 void PrintCodecMappingEntry(absl::string_view codec, int flag) {
    219  std::cout << codec << ": " << flag << std::endl;
    220 }
    221 
    222 void PrintCodecMapping() {
    223  PrintCodecMappingEntry("PCM-u", absl::GetFlag(FLAGS_pcmu));
    224  PrintCodecMappingEntry("PCM-a", absl::GetFlag(FLAGS_pcma));
    225  PrintCodecMappingEntry("iSAC", absl::GetFlag(FLAGS_isac));
    226  PrintCodecMappingEntry("iSAC-swb (32 kHz)", absl::GetFlag(FLAGS_isac_swb));
    227  PrintCodecMappingEntry("Opus", absl::GetFlag(FLAGS_opus));
    228  PrintCodecMappingEntry("PCM16b-nb (8 kHz)", absl::GetFlag(FLAGS_pcm16b));
    229  PrintCodecMappingEntry("PCM16b-wb (16 kHz)", absl::GetFlag(FLAGS_pcm16b_wb));
    230  PrintCodecMappingEntry("PCM16b-swb32 (32 kHz)",
    231                         absl::GetFlag(FLAGS_pcm16b_swb32));
    232  PrintCodecMappingEntry("PCM16b-swb48 (48 kHz)",
    233                         absl::GetFlag(FLAGS_pcm16b_swb48));
    234  PrintCodecMappingEntry("G.722", absl::GetFlag(FLAGS_g722));
    235  PrintCodecMappingEntry("AVT/DTMF (8 kHz)", absl::GetFlag(FLAGS_avt));
    236  PrintCodecMappingEntry("AVT/DTMF (16 kHz)", absl::GetFlag(FLAGS_avt_16));
    237  PrintCodecMappingEntry("AVT/DTMF (32 kHz)", absl::GetFlag(FLAGS_avt_32));
    238  PrintCodecMappingEntry("AVT/DTMF (48 kHz)", absl::GetFlag(FLAGS_avt_48));
    239  PrintCodecMappingEntry("redundant audio (RED 8khz)",
    240                         absl::GetFlag(FLAGS_red));
    241  PrintCodecMappingEntry("redundant audio (RED 48khz)",
    242                         absl::GetFlag(FLAGS_opus_red));
    243  PrintCodecMappingEntry("comfort noise (8 kHz)", absl::GetFlag(FLAGS_cn_nb));
    244  PrintCodecMappingEntry("comfort noise (16 kHz)", absl::GetFlag(FLAGS_cn_wb));
    245  PrintCodecMappingEntry("comfort noise (32 kHz)",
    246                         absl::GetFlag(FLAGS_cn_swb32));
    247  PrintCodecMappingEntry("comfort noise (48 kHz)",
    248                         absl::GetFlag(FLAGS_cn_swb48));
    249 }
    250 
    251 bool ValidateOutputFilesOptions(bool textlog,
    252                                bool plotting,
    253                                absl::string_view output_files_base_name,
    254                                absl::string_view output_audio_filename) {
    255  bool output_files_base_name_specified = !output_files_base_name.empty();
    256  if (!textlog && !plotting && output_files_base_name_specified) {
    257    std::cout << "Error: --output_files_base_name cannot be used without at "
    258                 "least one of the following flags: --textlog, --matlabplot, "
    259                 "--pythonplot."
    260              << std::endl;
    261    return false;
    262  }
    263  // Without `output_audio_filename`, `output_files_base_name` is required when
    264  // plotting output files must be generated (in order to form a valid output
    265  // file name).
    266  if (output_audio_filename.empty() && plotting &&
    267      !output_files_base_name_specified) {
    268    std::cout << "Error: when no output audio file is specified and "
    269                 "--matlabplot and/or --pythonplot are used, "
    270                 "--output_files_base_name must be also used."
    271              << std::endl;
    272    return false;
    273  }
    274  return true;
    275 }
    276 
    277 std::optional<std::string> CreateOptionalOutputFileName(
    278    bool output_requested,
    279    absl::string_view basename,
    280    absl::string_view output_audio_filename,
    281    absl::string_view suffix) {
    282  if (!output_requested) {
    283    return std::nullopt;
    284  }
    285  if (!basename.empty()) {
    286    // Override the automatic assignment.
    287    webrtc::StringBuilder sb(basename);
    288    sb << suffix;
    289    return sb.str();
    290  }
    291  if (!output_audio_filename.empty()) {
    292    // Automatically assign name.
    293    webrtc::StringBuilder sb(output_audio_filename);
    294    sb << suffix;
    295    return sb.str();
    296  }
    297  std::cout << "Error: invalid text log file parameters.";
    298  return std::nullopt;
    299 }
    300 
    301 }  // namespace
    302 
    303 int main(int argc, char* argv[]) {
    304  std::vector<char*> args = absl::ParseCommandLine(argc, argv);
    305  webrtc::test::NetEqTestFactory factory;
    306  std::string usage =
    307      "Tool for decoding an RTP dump file using NetEq.\n"
    308      "Example usage:\n"
    309      "./neteq_rtpplay input.rtp [output.{pcm, wav}]\n";
    310  if (absl::GetFlag(FLAGS_codec_map)) {
    311    PrintCodecMapping();
    312    exit(0);
    313  }
    314  if (args.size() != 2 &&
    315      args.size() != 3) {  // The output audio file is optional.
    316    // Print usage information.
    317    std::cout << usage;
    318    exit(0);
    319  }
    320  const std::string output_audio_filename((args.size() == 3) ? args[2] : "");
    321  const std::string output_files_base_name(
    322      absl::GetFlag(FLAGS_output_files_base_name));
    323  RTC_CHECK(ValidateOutputFilesOptions(
    324      absl::GetFlag(FLAGS_textlog),
    325      absl::GetFlag(FLAGS_matlabplot) || absl::GetFlag(FLAGS_pythonplot),
    326      output_files_base_name, output_audio_filename));
    327  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_pcmu)));
    328  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_pcma)));
    329  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_isac)));
    330  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_isac_swb)));
    331  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_opus)));
    332  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_pcm16b)));
    333  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_pcm16b_wb)));
    334  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_pcm16b_swb32)));
    335  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_pcm16b_swb48)));
    336  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_g722)));
    337  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_avt)));
    338  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_avt_16)));
    339  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_avt_32)));
    340  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_avt_48)));
    341  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_red)));
    342  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_opus_red)));
    343  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_cn_nb)));
    344  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_cn_wb)));
    345  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_cn_swb32)));
    346  RTC_CHECK(ValidatePayloadType(absl::GetFlag(FLAGS_cn_swb48)));
    347  RTC_CHECK(ValidateSsrcValue(absl::GetFlag(FLAGS_ssrc)));
    348  RTC_CHECK(ValidateExtensionId(absl::GetFlag(FLAGS_audio_level)));
    349  RTC_CHECK(ValidateExtensionId(absl::GetFlag(FLAGS_abs_send_time)));
    350  RTC_CHECK(ValidateExtensionId(absl::GetFlag(FLAGS_transport_seq_no)));
    351  RTC_CHECK(ValidateExtensionId(absl::GetFlag(FLAGS_video_content_type)));
    352  RTC_CHECK(ValidateExtensionId(absl::GetFlag(FLAGS_video_timing)));
    353 
    354  webrtc::test::NetEqTestFactory::Config config;
    355  config.field_trial_string = absl::GetFlag(FLAGS_force_fieldtrials);
    356  config.pcmu = absl::GetFlag(FLAGS_pcmu);
    357  config.pcma = absl::GetFlag(FLAGS_pcma);
    358  config.isac = absl::GetFlag(FLAGS_isac);
    359  config.isac_swb = absl::GetFlag(FLAGS_isac_swb);
    360  config.opus = absl::GetFlag(FLAGS_opus);
    361  config.pcm16b = absl::GetFlag(FLAGS_pcm16b);
    362  config.pcm16b_wb = absl::GetFlag(FLAGS_pcm16b_wb);
    363  config.pcm16b_swb32 = absl::GetFlag(FLAGS_pcm16b_swb32);
    364  config.pcm16b_swb48 = absl::GetFlag(FLAGS_pcm16b_swb48);
    365  config.g722 = absl::GetFlag(FLAGS_g722);
    366  config.avt = absl::GetFlag(FLAGS_avt);
    367  config.avt_16 = absl::GetFlag(FLAGS_avt_16);
    368  config.avt_32 = absl::GetFlag(FLAGS_avt_32);
    369  config.avt_48 = absl::GetFlag(FLAGS_avt_48);
    370  config.red = absl::GetFlag(FLAGS_red);
    371  config.opus_red = absl::GetFlag(FLAGS_opus_red);
    372  config.cn_nb = absl::GetFlag(FLAGS_cn_nb);
    373  config.cn_wb = absl::GetFlag(FLAGS_cn_wb);
    374  config.cn_swb32 = absl::GetFlag(FLAGS_cn_swb32);
    375  config.cn_swb48 = absl::GetFlag(FLAGS_cn_swb48);
    376  config.replacement_audio_file = absl::GetFlag(FLAGS_replacement_audio_file);
    377  config.audio_level = absl::GetFlag(FLAGS_audio_level);
    378  config.abs_send_time = absl::GetFlag(FLAGS_abs_send_time);
    379  config.transport_seq_no = absl::GetFlag(FLAGS_transport_seq_no);
    380  config.video_content_type = absl::GetFlag(FLAGS_video_content_type);
    381  config.video_timing = absl::GetFlag(FLAGS_video_timing);
    382  config.matlabplot = absl::GetFlag(FLAGS_matlabplot);
    383  config.pythonplot = absl::GetFlag(FLAGS_pythonplot);
    384  config.concealment_events = absl::GetFlag(FLAGS_concealment_events);
    385  config.max_nr_packets_in_buffer =
    386      absl::GetFlag(FLAGS_max_nr_packets_in_buffer);
    387  config.enable_fast_accelerate = absl::GetFlag(FLAGS_enable_fast_accelerate);
    388  if (!output_audio_filename.empty()) {
    389    config.output_audio_filename = output_audio_filename;
    390  }
    391  config.textlog = absl::GetFlag(FLAGS_textlog);
    392  config.textlog_filename = CreateOptionalOutputFileName(
    393      absl::GetFlag(FLAGS_textlog), output_files_base_name,
    394      output_audio_filename, ".text_log.txt");
    395  config.plot_scripts_basename = CreateOptionalOutputFileName(
    396      absl::GetFlag(FLAGS_matlabplot) || absl::GetFlag(FLAGS_pythonplot),
    397      output_files_base_name, output_audio_filename, "");
    398 
    399  // Check if an SSRC value was provided.
    400  if (!absl::GetFlag(FLAGS_ssrc).empty()) {
    401    uint32_t ssrc;
    402    RTC_CHECK(ParseSsrc(absl::GetFlag(FLAGS_ssrc), &ssrc))
    403        << "Flag verification has failed.";
    404    config.ssrc_filter = std::make_optional(ssrc);
    405  }
    406 
    407  std::unique_ptr<webrtc::test::NetEqTest> test =
    408      factory.InitializeTestFromFile(/*input_filename=*/args[1],
    409                                     /*factory=*/nullptr, config);
    410  RTC_CHECK(test) << "ERROR: Unable to run test";
    411  test->Run();
    412  return 0;
    413 }