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