tor-browser

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

TestVADDTX.cc (8876B)


      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/TestVADDTX.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstdio>
     16 #include <cstring>
     17 #include <map>
     18 #include <memory>
     19 #include <optional>
     20 #include <string>
     21 #include <utility>
     22 
     23 #include "absl/strings/match.h"
     24 #include "absl/strings/string_view.h"
     25 #include "api/audio/audio_frame.h"
     26 #include "api/audio_codecs/audio_decoder_factory_template.h"
     27 #include "api/audio_codecs/audio_encoder.h"
     28 #include "api/audio_codecs/audio_encoder_factory_template.h"
     29 #include "api/audio_codecs/audio_format.h"
     30 #include "api/audio_codecs/opus/audio_decoder_opus.h"
     31 #include "api/audio_codecs/opus/audio_encoder_opus.h"
     32 #include "api/environment/environment_factory.h"
     33 #include "api/neteq/default_neteq_factory.h"
     34 #include "api/neteq/neteq.h"
     35 #include "common_audio/vad/include/vad.h"
     36 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
     37 #include "modules/audio_coding/include/audio_coding_module.h"
     38 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
     39 #include "modules/audio_coding/test/Channel.h"
     40 #include "modules/audio_coding/test/PCMFile.h"
     41 #include "rtc_base/strings/string_builder.h"
     42 #include "test/gtest.h"
     43 #include "test/testsupport/file_utils.h"
     44 
     45 namespace webrtc {
     46 
     47 MonitoringAudioPacketizationCallback::MonitoringAudioPacketizationCallback(
     48    AudioPacketizationCallback* next)
     49    : next_(next) {
     50  ResetStatistics();
     51 }
     52 
     53 int32_t MonitoringAudioPacketizationCallback::SendData(
     54    AudioFrameType frame_type,
     55    uint8_t payload_type,
     56    uint32_t timestamp,
     57    const uint8_t* payload_data,
     58    size_t payload_len_bytes,
     59    int64_t absolute_capture_timestamp_ms) {
     60  counter_[static_cast<int>(frame_type)]++;
     61  return next_->SendData(frame_type, payload_type, timestamp, payload_data,
     62                         payload_len_bytes, absolute_capture_timestamp_ms);
     63 }
     64 
     65 void MonitoringAudioPacketizationCallback::PrintStatistics() {
     66  printf("\n");
     67  printf("kEmptyFrame       %u\n",
     68         counter_[static_cast<int>(AudioFrameType::kEmptyFrame)]);
     69  printf("kAudioFrameSpeech %u\n",
     70         counter_[static_cast<int>(AudioFrameType::kAudioFrameSpeech)]);
     71  printf("kAudioFrameCN     %u\n",
     72         counter_[static_cast<int>(AudioFrameType::kAudioFrameCN)]);
     73  printf("\n\n");
     74 }
     75 
     76 void MonitoringAudioPacketizationCallback::ResetStatistics() {
     77  memset(counter_, 0, sizeof(counter_));
     78 }
     79 
     80 void MonitoringAudioPacketizationCallback::GetStatistics(uint32_t* counter) {
     81  memcpy(counter, counter_, sizeof(counter_));
     82 }
     83 
     84 TestVadDtx::TestVadDtx()
     85    : env_(CreateEnvironment()),
     86      encoder_factory_(CreateAudioEncoderFactory<AudioEncoderOpus>()),
     87      decoder_factory_(CreateAudioDecoderFactory<AudioDecoderOpus>()),
     88      acm_send_(AudioCodingModule::Create()),
     89      neteq_(DefaultNetEqFactory().Create(env_,
     90                                          NetEq::Config(),
     91                                          decoder_factory_)),
     92      channel_(std::make_unique<Channel>()),
     93      packetization_callback_(
     94          std::make_unique<MonitoringAudioPacketizationCallback>(
     95              channel_.get())) {
     96  EXPECT_EQ(
     97      0, acm_send_->RegisterTransportCallback(packetization_callback_.get()));
     98  channel_->RegisterReceiverNetEq(neteq_.get());
     99 }
    100 
    101 bool TestVadDtx::RegisterCodec(const SdpAudioFormat& codec_format,
    102                               std::optional<Vad::Aggressiveness> vad_mode) {
    103  constexpr int payload_type = 17, cn_payload_type = 117;
    104  bool added_comfort_noise = false;
    105 
    106  auto encoder = encoder_factory_->Create(env_, codec_format,
    107                                          {.payload_type = payload_type});
    108  if (vad_mode.has_value() &&
    109      !absl::EqualsIgnoreCase(codec_format.name, "opus")) {
    110    AudioEncoderCngConfig config;
    111    config.speech_encoder = std::move(encoder);
    112    config.num_channels = 1;
    113    config.payload_type = cn_payload_type;
    114    config.vad_mode = vad_mode.value();
    115    encoder = CreateComfortNoiseEncoder(std::move(config));
    116    added_comfort_noise = true;
    117  }
    118  channel_->SetIsStereo(encoder->NumChannels() > 1);
    119  acm_send_->SetEncoder(std::move(encoder));
    120 
    121  std::map<int, SdpAudioFormat> receive_codecs = {{payload_type, codec_format}};
    122  neteq_->SetCodecs(receive_codecs);
    123 
    124  return added_comfort_noise;
    125 }
    126 
    127 // Encoding a file and see if the numbers that various packets occur follow
    128 // the expectation.
    129 void TestVadDtx::Run(absl::string_view in_filename,
    130                     int frequency,
    131                     int channels,
    132                     absl::string_view out_filename,
    133                     bool append,
    134                     const int* expects) {
    135  packetization_callback_->ResetStatistics();
    136 
    137  PCMFile in_file;
    138  in_file.Open(in_filename, frequency, "rb");
    139  in_file.ReadStereo(channels > 1);
    140  // Set test length to 1000 ms (100 blocks of 10 ms each).
    141  in_file.SetNum10MsBlocksToRead(100);
    142  // Fast-forward both files 500 ms (50 blocks). The first second of the file is
    143  // silence, but we want to keep half of that to test silence periods.
    144  in_file.FastForward(50);
    145 
    146  PCMFile out_file;
    147  if (append) {
    148    out_file.Open(out_filename, kOutputFreqHz, "ab");
    149  } else {
    150    out_file.Open(out_filename, kOutputFreqHz, "wb");
    151  }
    152 
    153  uint16_t frame_size_samples = in_file.PayloadLength10Ms();
    154  AudioFrame audio_frame;
    155  while (!in_file.EndOfFile()) {
    156    in_file.Read10MsData(audio_frame);
    157    audio_frame.timestamp_ = time_stamp_;
    158    time_stamp_ += frame_size_samples;
    159    EXPECT_GE(acm_send_->Add10MsData(audio_frame), 0);
    160    bool muted;
    161    neteq_->GetAudio(&audio_frame, &muted);
    162    resampler_helper_.MaybeResample(kOutputFreqHz, &audio_frame);
    163    ASSERT_FALSE(muted);
    164    out_file.Write10MsData(audio_frame);
    165  }
    166 
    167  in_file.Close();
    168  out_file.Close();
    169 
    170 #ifdef PRINT_STAT
    171  packetization_callback_->PrintStatistics();
    172 #endif
    173 
    174  uint32_t stats[3];
    175  packetization_callback_->GetStatistics(stats);
    176  packetization_callback_->ResetStatistics();
    177 
    178  for (const auto& st : stats) {
    179    int i = &st - stats;  // Calculate the current position in stats.
    180    switch (expects[i]) {
    181      case 0: {
    182        EXPECT_EQ(0u, st) << "stats[" << i << "] error.";
    183        break;
    184      }
    185      case 1: {
    186        EXPECT_GT(st, 0u) << "stats[" << i << "] error.";
    187        break;
    188      }
    189    }
    190  }
    191 }
    192 
    193 // Following is the implementation of TestWebRtcVadDtx.
    194 TestWebRtcVadDtx::TestWebRtcVadDtx() : output_file_num_(0) {}
    195 
    196 void TestWebRtcVadDtx::Perform() {
    197  RunTestCases({"opus", 48000, 2});
    198 }
    199 
    200 // Test various configurations on VAD/DTX.
    201 void TestWebRtcVadDtx::RunTestCases(const SdpAudioFormat& codec_format) {
    202  Test(/*new_outfile=*/true,
    203       /*expect_dtx_enabled=*/RegisterCodec(codec_format, std::nullopt));
    204 
    205  Test(/*new_outfile=*/false,
    206       /*expect_dtx_enabled=*/RegisterCodec(codec_format, Vad::kVadAggressive));
    207 
    208  Test(/*new_outfile=*/false,
    209       /*expect_dtx_enabled=*/RegisterCodec(codec_format, Vad::kVadLowBitrate));
    210 
    211  Test(/*new_outfile=*/false, /*expect_dtx_enabled=*/RegisterCodec(
    212           codec_format, Vad::kVadVeryAggressive));
    213 
    214  Test(/*new_outfile=*/false,
    215       /*expect_dtx_enabled=*/RegisterCodec(codec_format, Vad::kVadNormal));
    216 }
    217 
    218 // Set the expectation and run the test.
    219 void TestWebRtcVadDtx::Test(bool new_outfile, bool expect_dtx_enabled) {
    220  int expects[] = {-1, 1, expect_dtx_enabled, 0, 0};
    221  if (new_outfile) {
    222    output_file_num_++;
    223  }
    224  StringBuilder out_filename;
    225  out_filename << test::OutputPath() << "testWebRtcVadDtx_outFile_"
    226               << output_file_num_ << ".pcm";
    227  Run(test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 32000, 1,
    228      out_filename.str(), !new_outfile, expects);
    229 }
    230 
    231 // Following is the implementation of TestOpusDtx.
    232 void TestOpusDtx::Perform() {
    233  int expects[] = {0, 1, 0, 0, 0};
    234 
    235  // Register Opus as send codec
    236  std::string out_filename =
    237      test::OutputPath() + "testOpusDtx_outFile_mono.pcm";
    238  RegisterCodec({"opus", 48000, 2}, std::nullopt);
    239  acm_send_->ModifyEncoder([](std::unique_ptr<AudioEncoder>* encoder_ptr) {
    240    (*encoder_ptr)->SetDtx(false);
    241  });
    242 
    243  Run(test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 32000, 1,
    244      out_filename, false, expects);
    245 
    246  acm_send_->ModifyEncoder([](std::unique_ptr<AudioEncoder>* encoder_ptr) {
    247    (*encoder_ptr)->SetDtx(true);
    248  });
    249  expects[static_cast<int>(AudioFrameType::kEmptyFrame)] = 1;
    250  expects[static_cast<int>(AudioFrameType::kAudioFrameCN)] = 1;
    251  Run(test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 32000, 1,
    252      out_filename, true, expects);
    253 }
    254 
    255 }  // namespace webrtc