tor-browser

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

TestAllCodecs.cc (13195B)


      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 "modules/audio_coding/test/TestAllCodecs.h"
     12 
     13 #include <cstdint>
     14 #include <cstdio>
     15 #include <cstring>
     16 #include <limits>
     17 #include <string>
     18 
     19 #include "absl/strings/match.h"
     20 #include "absl/strings/str_cat.h"
     21 #include "api/array_view.h"
     22 #include "api/audio_codecs/audio_format.h"
     23 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
     24 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
     25 #include "api/environment/environment_factory.h"
     26 #include "api/neteq/default_neteq_factory.h"
     27 #include "api/neteq/neteq.h"
     28 #include "api/rtp_headers.h"
     29 #include "api/units/timestamp.h"
     30 #include "modules/audio_coding/acm2/acm_resampler.h"
     31 #include "modules/audio_coding/include/audio_coding_module.h"
     32 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
     33 #include "rtc_base/checks.h"
     34 #include "rtc_base/strings/string_builder.h"
     35 #include "test/gtest.h"
     36 #include "test/testsupport/file_utils.h"
     37 
     38 // Description of the test:
     39 // In this test we set up a one-way communication channel from a participant
     40 // called "a" to a participant called "b".
     41 // a -> channel_a_to_b -> b
     42 //
     43 // The test loops through all available mono codecs, encode at "a" sends over
     44 // the channel, and decodes at "b".
     45 
     46 #define CHECK_ERROR(f)                      \
     47  do {                                      \
     48    EXPECT_GE(f, 0) << "Error Calling API"; \
     49  } while (0)
     50 
     51 namespace {
     52 const size_t kVariableSize = std::numeric_limits<size_t>::max();
     53 }  // namespace
     54 
     55 namespace webrtc {
     56 
     57 // Class for simulating packet handling.
     58 TestPack::TestPack()
     59    : neteq_(nullptr),
     60      sequence_number_(0),
     61      timestamp_diff_(0),
     62      last_in_timestamp_(0),
     63      total_bytes_(0),
     64      payload_size_(0) {}
     65 
     66 TestPack::~TestPack() {}
     67 
     68 void TestPack::RegisterReceiverNetEq(NetEq* neteq) {
     69  neteq_ = neteq;
     70 }
     71 
     72 int32_t TestPack::SendData(AudioFrameType frame_type,
     73                           uint8_t payload_type,
     74                           uint32_t timestamp,
     75                           const uint8_t* payload_data,
     76                           size_t payload_size,
     77                           int64_t /* absolute_capture_timestamp_ms */) {
     78  RTPHeader rtp_header;
     79  int32_t status;
     80 
     81  rtp_header.markerBit = false;
     82  rtp_header.ssrc = 0;
     83  rtp_header.sequenceNumber = sequence_number_++;
     84  rtp_header.payloadType = payload_type;
     85  rtp_header.timestamp = timestamp;
     86 
     87  if (frame_type == AudioFrameType::kEmptyFrame) {
     88    // Skip this frame.
     89    return 0;
     90  }
     91 
     92  // Only run mono for all test cases.
     93  memcpy(payload_data_, payload_data, payload_size);
     94 
     95  status = neteq_->InsertPacket(
     96      rtp_header, ArrayView<const uint8_t>(payload_data_, payload_size),
     97      /*receive_time=*/Timestamp::MinusInfinity());
     98 
     99  payload_size_ = payload_size;
    100  timestamp_diff_ = timestamp - last_in_timestamp_;
    101  last_in_timestamp_ = timestamp;
    102  total_bytes_ += payload_size;
    103  return status;
    104 }
    105 
    106 size_t TestPack::payload_size() {
    107  return payload_size_;
    108 }
    109 
    110 uint32_t TestPack::timestamp_diff() {
    111  return timestamp_diff_;
    112 }
    113 
    114 void TestPack::reset_payload_size() {
    115  payload_size_ = 0;
    116 }
    117 
    118 TestAllCodecs::TestAllCodecs()
    119    : env_(CreateEnvironment()),
    120      acm_a_(AudioCodingModule::Create()),
    121      neteq_(DefaultNetEqFactory().Create(env_,
    122                                          NetEq::Config(),
    123                                          CreateBuiltinAudioDecoderFactory())),
    124      channel_a_to_b_(nullptr),
    125      test_count_(0),
    126      packet_size_samples_(0),
    127      packet_size_bytes_(0) {}
    128 
    129 TestAllCodecs::~TestAllCodecs() {
    130  if (channel_a_to_b_ != nullptr) {
    131    delete channel_a_to_b_;
    132    channel_a_to_b_ = nullptr;
    133  }
    134 }
    135 
    136 void TestAllCodecs::Perform() {
    137  const std::string file_name =
    138      test::ResourcePath("audio_coding/testfile32kHz", "pcm");
    139  infile_a_.Open(file_name, 32000, "rb");
    140 
    141  neteq_->SetCodecs({{107, {"L16", 8000, 1}},
    142                     {108, {"L16", 16000, 1}},
    143                     {109, {"L16", 32000, 1}},
    144                     {111, {"L16", 8000, 2}},
    145                     {112, {"L16", 16000, 2}},
    146                     {113, {"L16", 32000, 2}},
    147                     {0, {"PCMU", 8000, 1}},
    148                     {110, {"PCMU", 8000, 2}},
    149                     {8, {"PCMA", 8000, 1}},
    150                     {118, {"PCMA", 8000, 2}},
    151                     {9, {"G722", 8000, 1}},
    152                     {119, {"G722", 8000, 2}},
    153                     {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}},
    154                     {13, {"CN", 8000, 1}},
    155                     {98, {"CN", 16000, 1}},
    156                     {99, {"CN", 32000, 1}}});
    157 
    158  // Create and connect the channel
    159  channel_a_to_b_ = new TestPack;
    160  acm_a_->RegisterTransportCallback(channel_a_to_b_);
    161  channel_a_to_b_->RegisterReceiverNetEq(neteq_.get());
    162 
    163  // All codecs are tested for all allowed sampling frequencies, rates and
    164  // packet sizes.
    165 
    166 // TODO(bugs.webrtc.org/345525069): Either fix/enable or remove G722.
    167 #if defined(__has_feature) && !__has_feature(undefined_behavior_sanitizer)
    168  test_count_++;
    169  OpenOutFile(test_count_);
    170  char codec_g722[] = "G722";
    171  RegisterSendCodec(codec_g722, 16000, 64000, 160, 0);
    172  Run(channel_a_to_b_);
    173  RegisterSendCodec(codec_g722, 16000, 64000, 320, 0);
    174  Run(channel_a_to_b_);
    175  RegisterSendCodec(codec_g722, 16000, 64000, 480, 0);
    176  Run(channel_a_to_b_);
    177  RegisterSendCodec(codec_g722, 16000, 64000, 640, 0);
    178  Run(channel_a_to_b_);
    179  RegisterSendCodec(codec_g722, 16000, 64000, 800, 0);
    180  Run(channel_a_to_b_);
    181  RegisterSendCodec(codec_g722, 16000, 64000, 960, 0);
    182  Run(channel_a_to_b_);
    183  outfile_b_.Close();
    184 #endif
    185  test_count_++;
    186  OpenOutFile(test_count_);
    187  char codec_l16[] = "L16";
    188  RegisterSendCodec(codec_l16, 8000, 128000, 80, 0);
    189  Run(channel_a_to_b_);
    190  RegisterSendCodec(codec_l16, 8000, 128000, 160, 0);
    191  Run(channel_a_to_b_);
    192  RegisterSendCodec(codec_l16, 8000, 128000, 240, 0);
    193  Run(channel_a_to_b_);
    194  RegisterSendCodec(codec_l16, 8000, 128000, 320, 0);
    195  Run(channel_a_to_b_);
    196  outfile_b_.Close();
    197 
    198  test_count_++;
    199  OpenOutFile(test_count_);
    200  RegisterSendCodec(codec_l16, 16000, 256000, 160, 0);
    201  Run(channel_a_to_b_);
    202  RegisterSendCodec(codec_l16, 16000, 256000, 320, 0);
    203  Run(channel_a_to_b_);
    204  RegisterSendCodec(codec_l16, 16000, 256000, 480, 0);
    205  Run(channel_a_to_b_);
    206  RegisterSendCodec(codec_l16, 16000, 256000, 640, 0);
    207  Run(channel_a_to_b_);
    208  outfile_b_.Close();
    209 
    210  test_count_++;
    211  OpenOutFile(test_count_);
    212  RegisterSendCodec(codec_l16, 32000, 512000, 320, 0);
    213  Run(channel_a_to_b_);
    214  RegisterSendCodec(codec_l16, 32000, 512000, 640, 0);
    215  Run(channel_a_to_b_);
    216  outfile_b_.Close();
    217 
    218  test_count_++;
    219  OpenOutFile(test_count_);
    220  char codec_pcma[] = "PCMA";
    221  RegisterSendCodec(codec_pcma, 8000, 64000, 80, 0);
    222  Run(channel_a_to_b_);
    223  RegisterSendCodec(codec_pcma, 8000, 64000, 160, 0);
    224  Run(channel_a_to_b_);
    225  RegisterSendCodec(codec_pcma, 8000, 64000, 240, 0);
    226  Run(channel_a_to_b_);
    227  RegisterSendCodec(codec_pcma, 8000, 64000, 320, 0);
    228  Run(channel_a_to_b_);
    229  RegisterSendCodec(codec_pcma, 8000, 64000, 400, 0);
    230  Run(channel_a_to_b_);
    231  RegisterSendCodec(codec_pcma, 8000, 64000, 480, 0);
    232  Run(channel_a_to_b_);
    233 
    234  char codec_pcmu[] = "PCMU";
    235  RegisterSendCodec(codec_pcmu, 8000, 64000, 80, 0);
    236  Run(channel_a_to_b_);
    237  RegisterSendCodec(codec_pcmu, 8000, 64000, 160, 0);
    238  Run(channel_a_to_b_);
    239  RegisterSendCodec(codec_pcmu, 8000, 64000, 240, 0);
    240  Run(channel_a_to_b_);
    241  RegisterSendCodec(codec_pcmu, 8000, 64000, 320, 0);
    242  Run(channel_a_to_b_);
    243  RegisterSendCodec(codec_pcmu, 8000, 64000, 400, 0);
    244  Run(channel_a_to_b_);
    245  RegisterSendCodec(codec_pcmu, 8000, 64000, 480, 0);
    246  Run(channel_a_to_b_);
    247  outfile_b_.Close();
    248 #ifdef WEBRTC_CODEC_OPUS
    249  test_count_++;
    250  OpenOutFile(test_count_);
    251  char codec_opus[] = "OPUS";
    252  RegisterSendCodec(codec_opus, 48000, 6000, 480, kVariableSize);
    253  Run(channel_a_to_b_);
    254  RegisterSendCodec(codec_opus, 48000, 20000, 480 * 2, kVariableSize);
    255  Run(channel_a_to_b_);
    256  RegisterSendCodec(codec_opus, 48000, 32000, 480 * 4, kVariableSize);
    257  Run(channel_a_to_b_);
    258  RegisterSendCodec(codec_opus, 48000, 48000, 480, kVariableSize);
    259  Run(channel_a_to_b_);
    260  RegisterSendCodec(codec_opus, 48000, 64000, 480 * 4, kVariableSize);
    261  Run(channel_a_to_b_);
    262  RegisterSendCodec(codec_opus, 48000, 96000, 480 * 6, kVariableSize);
    263  Run(channel_a_to_b_);
    264  RegisterSendCodec(codec_opus, 48000, 500000, 480 * 2, kVariableSize);
    265  Run(channel_a_to_b_);
    266  outfile_b_.Close();
    267 #endif
    268 }
    269 
    270 // Register Codec to use in the test
    271 //
    272 // Input:  codec_name       - name to use when register the codec
    273 //         sampling_freq_hz - sampling frequency in Herz
    274 //         rate             - bitrate in bytes
    275 //         packet_size      - packet size in samples
    276 //         extra_byte       - if extra bytes needed compared to the bitrate
    277 //                            used when registering, can be an internal header
    278 //                            set to kVariableSize if the codec is a variable
    279 //                            rate codec
    280 void TestAllCodecs::RegisterSendCodec(char* codec_name,
    281                                      int32_t sampling_freq_hz,
    282                                      int rate,
    283                                      int packet_size,
    284                                      size_t extra_byte) {
    285  // Store packet-size in samples, used to validate the received packet.
    286  // If G.722, store half the size to compensate for the timestamp bug in the
    287  // RFC for G.722.
    288  int clockrate_hz = sampling_freq_hz;
    289  size_t num_channels = 1;
    290  if (absl::EqualsIgnoreCase(codec_name, "G722")) {
    291    packet_size_samples_ = packet_size / 2;
    292    clockrate_hz = sampling_freq_hz / 2;
    293  } else if (absl::EqualsIgnoreCase(codec_name, "OPUS")) {
    294    packet_size_samples_ = packet_size;
    295    num_channels = 2;
    296  } else {
    297    packet_size_samples_ = packet_size;
    298  }
    299 
    300  // Store the expected packet size in bytes, used to validate the received
    301  // packet. If variable rate codec (extra_byte == -1), set to -1.
    302  if (extra_byte != kVariableSize) {
    303    // Add 0.875 to always round up to a whole byte
    304    packet_size_bytes_ =
    305        static_cast<size_t>(static_cast<float>(packet_size * rate) /
    306                                static_cast<float>(sampling_freq_hz * 8) +
    307                            0.875) +
    308        extra_byte;
    309  } else {
    310    // Packets will have a variable size.
    311    packet_size_bytes_ = kVariableSize;
    312  }
    313 
    314  auto factory = CreateBuiltinAudioEncoderFactory();
    315  SdpAudioFormat format = {codec_name, clockrate_hz, num_channels};
    316  format.parameters["ptime"] = absl::StrCat(
    317      CheckedDivExact(packet_size, CheckedDivExact(sampling_freq_hz, 1000)));
    318  acm_a_->SetEncoder(factory->Create(env_, format, {.payload_type = 17}));
    319 }
    320 
    321 void TestAllCodecs::Run(TestPack* channel) {
    322  AudioFrame audio_frame;
    323  acm2::ResamplerHelper resampler_helper;
    324 
    325  int32_t out_freq_hz = outfile_b_.SamplingFrequency();
    326  size_t receive_size;
    327  uint32_t timestamp_diff;
    328  channel->reset_payload_size();
    329  int error_count = 0;
    330  int counter = 0;
    331  // Set test length to 500 ms (50 blocks of 10 ms each).
    332  infile_a_.SetNum10MsBlocksToRead(50);
    333  // Fast-forward 1 second (100 blocks) since the file starts with silence.
    334  infile_a_.FastForward(100);
    335 
    336  while (!infile_a_.EndOfFile()) {
    337    // Add 10 msec to ACM.
    338    infile_a_.Read10MsData(audio_frame);
    339    CHECK_ERROR(acm_a_->Add10MsData(audio_frame));
    340 
    341    // Verify that the received packet size matches the settings.
    342    receive_size = channel->payload_size();
    343    if (receive_size) {
    344      if ((receive_size != packet_size_bytes_) &&
    345          (packet_size_bytes_ != kVariableSize)) {
    346        error_count++;
    347      }
    348 
    349      // Verify that the timestamp is updated with expected length. The counter
    350      // is used to avoid problems when switching codec or frame size in the
    351      // test.
    352      timestamp_diff = channel->timestamp_diff();
    353      if ((counter > 10) &&
    354          (static_cast<int>(timestamp_diff) != packet_size_samples_) &&
    355          (packet_size_samples_ > -1))
    356        error_count++;
    357    }
    358 
    359    // Run received side of ACM.
    360    bool muted;
    361    CHECK_ERROR(neteq_->GetAudio(&audio_frame, &muted));
    362    ASSERT_FALSE(muted);
    363    EXPECT_TRUE(resampler_helper.MaybeResample(out_freq_hz, &audio_frame));
    364 
    365    // Write output speech to file.
    366    outfile_b_.Write10MsData(audio_frame.data(),
    367                             audio_frame.samples_per_channel_);
    368 
    369    // Update loop counter
    370    counter++;
    371  }
    372 
    373  EXPECT_EQ(0, error_count);
    374 
    375  if (infile_a_.EndOfFile()) {
    376    infile_a_.Rewind();
    377  }
    378 }
    379 
    380 void TestAllCodecs::OpenOutFile(int test_number) {
    381  std::string filename = test::OutputPath();
    382  StringBuilder test_number_str;
    383  test_number_str << test_number;
    384  filename += "testallcodecs_out_";
    385  filename += test_number_str.str();
    386  filename += ".pcm";
    387  outfile_b_.Open(filename, 32000, "wb");
    388 }
    389 
    390 }  // namespace webrtc