tor-browser

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

audio_ingress_unittest.cc (9064B)


      1 /*
      2 *  Copyright (c) 2020 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 "audio/voip/audio_ingress.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <memory>
     16 
     17 #include "api/array_view.h"
     18 #include "api/audio/audio_frame.h"
     19 #include "api/audio/audio_mixer.h"
     20 #include "api/audio_codecs/audio_decoder_factory.h"
     21 #include "api/audio_codecs/audio_encoder_factory.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.h"
     26 #include "api/environment/environment_factory.h"
     27 #include "api/rtp_headers.h"
     28 #include "api/scoped_refptr.h"
     29 #include "api/units/time_delta.h"
     30 #include "api/units/timestamp.h"
     31 #include "audio/voip/audio_egress.h"
     32 #include "modules/audio_mixer/sine_wave_generator.h"
     33 #include "modules/rtp_rtcp/include/receive_statistics.h"
     34 #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
     35 #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h"
     36 #include "rtc_base/event.h"
     37 #include "test/gmock.h"
     38 #include "test/gtest.h"
     39 #include "test/mock_transport.h"
     40 #include "test/time_controller/simulated_time_controller.h"
     41 
     42 namespace webrtc {
     43 namespace {
     44 
     45 using ::testing::Invoke;
     46 using ::testing::NiceMock;
     47 using ::testing::Unused;
     48 
     49 constexpr int16_t kAudioLevel = 3004;  // Used for sine wave level.
     50 
     51 class AudioIngressTest : public ::testing::Test {
     52 public:
     53  const SdpAudioFormat kPcmuFormat = {"pcmu", 8000, 1};
     54 
     55  AudioIngressTest() : wave_generator_(1000.0, kAudioLevel) {
     56    receive_statistics_ =
     57        ReceiveStatistics::Create(time_controller_.GetClock());
     58 
     59    RtpRtcpInterface::Configuration rtp_config;
     60    rtp_config.audio = true;
     61    rtp_config.receive_statistics = receive_statistics_.get();
     62    rtp_config.rtcp_report_interval_ms = 5000;
     63    rtp_config.outgoing_transport = &transport_;
     64    rtp_config.local_media_ssrc = 0xdeadc0de;
     65    rtp_rtcp_ = std::make_unique<ModuleRtpRtcpImpl2>(env_, rtp_config);
     66 
     67    rtp_rtcp_->SetSendingMediaStatus(false);
     68    rtp_rtcp_->SetRTCPStatus(RtcpMode::kCompound);
     69 
     70    encoder_factory_ = CreateBuiltinAudioEncoderFactory();
     71    decoder_factory_ = CreateBuiltinAudioDecoderFactory();
     72  }
     73 
     74  void SetUp() override {
     75    constexpr int kPcmuPayload = 0;
     76    ingress_ = std::make_unique<AudioIngress>(
     77        env_, rtp_rtcp_.get(), receive_statistics_.get(), decoder_factory_);
     78    ingress_->SetReceiveCodecs({{kPcmuPayload, kPcmuFormat}});
     79 
     80    egress_ = std::make_unique<AudioEgress>(env_, rtp_rtcp_.get());
     81    egress_->SetEncoder(kPcmuPayload, kPcmuFormat,
     82                        encoder_factory_->Create(
     83                            env_, kPcmuFormat, {.payload_type = kPcmuPayload}));
     84    egress_->StartSend();
     85    ingress_->StartPlay();
     86    rtp_rtcp_->SetSendingStatus(true);
     87  }
     88 
     89  void TearDown() override {
     90    rtp_rtcp_->SetSendingStatus(false);
     91    ingress_->StopPlay();
     92    egress_->StopSend();
     93    egress_.reset();
     94    ingress_.reset();
     95  }
     96 
     97  std::unique_ptr<AudioFrame> GetAudioFrame(int order) {
     98    auto frame = std::make_unique<AudioFrame>();
     99    frame->sample_rate_hz_ = kPcmuFormat.clockrate_hz;
    100    frame->samples_per_channel_ = kPcmuFormat.clockrate_hz / 100;  // 10 ms.
    101    frame->num_channels_ = kPcmuFormat.num_channels;
    102    frame->timestamp_ = frame->samples_per_channel_ * order;
    103    wave_generator_.GenerateNextFrame(frame.get());
    104    return frame;
    105  }
    106 
    107  GlobalSimulatedTimeController time_controller_{Timestamp::Micros(123456789)};
    108  const Environment env_ =
    109      CreateEnvironment(time_controller_.GetClock(),
    110                        time_controller_.GetTaskQueueFactory());
    111  SineWaveGenerator wave_generator_;
    112  NiceMock<MockTransport> transport_;
    113  std::unique_ptr<ReceiveStatistics> receive_statistics_;
    114  std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp_;
    115  scoped_refptr<AudioEncoderFactory> encoder_factory_;
    116  scoped_refptr<AudioDecoderFactory> decoder_factory_;
    117  std::unique_ptr<AudioIngress> ingress_;
    118  std::unique_ptr<AudioEgress> egress_;
    119 };
    120 
    121 TEST_F(AudioIngressTest, PlayingAfterStartAndStop) {
    122  EXPECT_EQ(ingress_->IsPlaying(), true);
    123  ingress_->StopPlay();
    124  EXPECT_EQ(ingress_->IsPlaying(), false);
    125 }
    126 
    127 TEST_F(AudioIngressTest, GetAudioFrameAfterRtpReceived) {
    128  Event event;
    129  auto handle_rtp = [&](ArrayView<const uint8_t> packet, Unused) {
    130    ingress_->ReceivedRTPPacket(packet);
    131    event.Set();
    132    return true;
    133  };
    134  EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(handle_rtp));
    135  egress_->SendAudioData(GetAudioFrame(0));
    136  egress_->SendAudioData(GetAudioFrame(1));
    137  time_controller_.AdvanceTime(TimeDelta::Zero());
    138  ASSERT_TRUE(event.Wait(TimeDelta::Seconds(1)));
    139 
    140  AudioFrame audio_frame;
    141  EXPECT_EQ(
    142      ingress_->GetAudioFrameWithInfo(kPcmuFormat.clockrate_hz, &audio_frame),
    143      AudioMixer::Source::AudioFrameInfo::kNormal);
    144  EXPECT_FALSE(audio_frame.muted());
    145  EXPECT_EQ(audio_frame.num_channels_, 1u);
    146  EXPECT_EQ(audio_frame.samples_per_channel_,
    147            static_cast<size_t>(kPcmuFormat.clockrate_hz / 100));
    148  EXPECT_EQ(audio_frame.sample_rate_hz_, kPcmuFormat.clockrate_hz);
    149  EXPECT_NE(audio_frame.timestamp_, 0u);
    150  EXPECT_EQ(audio_frame.elapsed_time_ms_, 0);
    151 }
    152 
    153 TEST_F(AudioIngressTest, TestSpeechOutputLevelAndEnergyDuration) {
    154  // Per audio_level's kUpdateFrequency, we need more than 10 audio samples to
    155  // get audio level from output source.
    156  constexpr int kNumRtp = 6;
    157  int rtp_count = 0;
    158  Event event;
    159  auto handle_rtp = [&](ArrayView<const uint8_t> packet, Unused) {
    160    ingress_->ReceivedRTPPacket(packet);
    161    if (++rtp_count == kNumRtp) {
    162      event.Set();
    163    }
    164    return true;
    165  };
    166  EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(handle_rtp));
    167  for (int i = 0; i < kNumRtp * 2; i++) {
    168    egress_->SendAudioData(GetAudioFrame(i));
    169    time_controller_.AdvanceTime(TimeDelta::Millis(10));
    170  }
    171  event.Wait(/*give_up_after=*/TimeDelta::Seconds(1));
    172 
    173  for (int i = 0; i < kNumRtp * 2; ++i) {
    174    AudioFrame audio_frame;
    175    EXPECT_EQ(
    176        ingress_->GetAudioFrameWithInfo(kPcmuFormat.clockrate_hz, &audio_frame),
    177        AudioMixer::Source::AudioFrameInfo::kNormal);
    178  }
    179  EXPECT_EQ(ingress_->GetOutputAudioLevel(), kAudioLevel);
    180 
    181  constexpr double kExpectedEnergy = 0.00016809565587789564;
    182  constexpr double kExpectedDuration = 0.11999999999999998;
    183 
    184  EXPECT_DOUBLE_EQ(ingress_->GetOutputTotalEnergy(), kExpectedEnergy);
    185  EXPECT_DOUBLE_EQ(ingress_->GetOutputTotalDuration(), kExpectedDuration);
    186 }
    187 
    188 TEST_F(AudioIngressTest, PreferredSampleRate) {
    189  Event event;
    190  auto handle_rtp = [&](ArrayView<const uint8_t> packet, Unused) {
    191    ingress_->ReceivedRTPPacket(packet);
    192    event.Set();
    193    return true;
    194  };
    195  EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(handle_rtp));
    196  egress_->SendAudioData(GetAudioFrame(0));
    197  egress_->SendAudioData(GetAudioFrame(1));
    198  time_controller_.AdvanceTime(TimeDelta::Zero());
    199  ASSERT_TRUE(event.Wait(TimeDelta::Seconds(1)));
    200 
    201  AudioFrame audio_frame;
    202  EXPECT_EQ(
    203      ingress_->GetAudioFrameWithInfo(kPcmuFormat.clockrate_hz, &audio_frame),
    204      AudioMixer::Source::AudioFrameInfo::kNormal);
    205  EXPECT_EQ(ingress_->PreferredSampleRate(), kPcmuFormat.clockrate_hz);
    206 }
    207 
    208 // This test highlights the case where caller invokes StopPlay() which then
    209 // AudioIngress should play silence frame afterwards.
    210 TEST_F(AudioIngressTest, GetMutedAudioFrameAfterRtpReceivedAndStopPlay) {
    211  // StopPlay before we start sending RTP packet with sine wave.
    212  ingress_->StopPlay();
    213 
    214  // Send 6 RTP packets to generate more than 100 ms audio sample to get
    215  // valid speech level.
    216  constexpr int kNumRtp = 6;
    217  int rtp_count = 0;
    218  Event event;
    219  auto handle_rtp = [&](ArrayView<const uint8_t> packet, Unused) {
    220    ingress_->ReceivedRTPPacket(packet);
    221    if (++rtp_count == kNumRtp) {
    222      event.Set();
    223    }
    224    return true;
    225  };
    226  EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(handle_rtp));
    227  for (int i = 0; i < kNumRtp * 2; i++) {
    228    egress_->SendAudioData(GetAudioFrame(i));
    229    time_controller_.AdvanceTime(TimeDelta::Millis(10));
    230  }
    231  event.Wait(/*give_up_after=*/TimeDelta::Seconds(1));
    232 
    233  for (int i = 0; i < kNumRtp * 2; ++i) {
    234    AudioFrame audio_frame;
    235    EXPECT_EQ(
    236        ingress_->GetAudioFrameWithInfo(kPcmuFormat.clockrate_hz, &audio_frame),
    237        AudioMixer::Source::AudioFrameInfo::kMuted);
    238    const int16_t* audio_data = audio_frame.data();
    239    size_t length =
    240        audio_frame.samples_per_channel_ * audio_frame.num_channels_;
    241    for (size_t j = 0; j < length; ++j) {
    242      EXPECT_EQ(audio_data[j], 0);
    243    }
    244  }
    245 
    246  // Now we should still see valid speech output level as StopPlay won't affect
    247  // the measurement.
    248  EXPECT_EQ(ingress_->GetOutputAudioLevel(), kAudioLevel);
    249 }
    250 
    251 }  // namespace
    252 }  // namespace webrtc