audio_channel_unittest.cc (15460B)
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_channel.h" 12 13 #include <cstdint> 14 #include <cstring> 15 #include <memory> 16 #include <optional> 17 #include <utility> 18 19 #include "absl/functional/any_invocable.h" 20 #include "api/array_view.h" 21 #include "api/audio/audio_frame.h" 22 #include "api/audio/audio_mixer.h" 23 #include "api/audio_codecs/audio_decoder_factory.h" 24 #include "api/audio_codecs/audio_encoder_factory.h" 25 #include "api/audio_codecs/audio_format.h" 26 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 27 #include "api/audio_codecs/builtin_audio_encoder_factory.h" 28 #include "api/environment/environment.h" 29 #include "api/environment/environment_factory.h" 30 #include "api/make_ref_counted.h" 31 #include "api/scoped_refptr.h" 32 #include "api/voip/voip_statistics.h" 33 #include "audio/voip/test/mock_task_queue.h" 34 #include "modules/audio_mixer/audio_mixer_impl.h" 35 #include "modules/audio_mixer/sine_wave_generator.h" 36 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 37 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 38 #include "system_wrappers/include/clock.h" 39 #include "test/gmock.h" 40 #include "test/gtest.h" 41 #include "test/mock_transport.h" 42 43 namespace webrtc { 44 namespace { 45 46 using ::testing::Invoke; 47 using ::testing::NiceMock; 48 using ::testing::Return; 49 using ::testing::Unused; 50 using ::testing::WithArg; 51 52 constexpr uint64_t kStartTime = 123456789; 53 constexpr uint32_t kLocalSsrc = 0xdeadc0de; 54 constexpr int16_t kAudioLevel = 3004; // used for sine wave level 55 constexpr int kPcmuPayload = 0; 56 57 class AudioChannelTest : public ::testing::Test { 58 public: 59 const SdpAudioFormat kPcmuFormat = {"pcmu", 8000, 1}; 60 61 AudioChannelTest() 62 : fake_clock_(kStartTime), 63 wave_generator_(1000.0, kAudioLevel), 64 env_(CreateEnvironment( 65 &fake_clock_, 66 std::make_unique<MockTaskQueueFactory>(&task_queue_))) { 67 audio_mixer_ = AudioMixerImpl::Create(); 68 encoder_factory_ = CreateBuiltinAudioEncoderFactory(); 69 decoder_factory_ = CreateBuiltinAudioDecoderFactory(); 70 71 // By default, run the queued task immediately. 72 ON_CALL(task_queue_, PostTaskImpl) 73 .WillByDefault(WithArg<0>( 74 [](absl::AnyInvocable<void()&&> task) { std::move(task)(); })); 75 } 76 77 void SetUp() override { audio_channel_ = CreateAudioChannel(kLocalSsrc); } 78 79 void TearDown() override { audio_channel_ = nullptr; } 80 81 scoped_refptr<AudioChannel> CreateAudioChannel(uint32_t ssrc) { 82 // Use same audio mixer here for simplicity sake as we are not checking 83 // audio activity of RTP in our testcases. If we need to do test on audio 84 // signal activity then we need to assign audio mixer for each channel. 85 // Also this uses the same transport object for different audio channel to 86 // simplify network routing logic. 87 scoped_refptr<AudioChannel> audio_channel = make_ref_counted<AudioChannel>( 88 env_, &transport_, ssrc, audio_mixer_.get(), decoder_factory_); 89 audio_channel->SetEncoder( 90 kPcmuPayload, kPcmuFormat, 91 encoder_factory_->Create(env_, kPcmuFormat, 92 {.payload_type = kPcmuPayload})); 93 audio_channel->SetReceiveCodecs({{kPcmuPayload, kPcmuFormat}}); 94 audio_channel->StartSend(); 95 audio_channel->StartPlay(); 96 return audio_channel; 97 } 98 99 std::unique_ptr<AudioFrame> GetAudioFrame(int order) { 100 auto frame = std::make_unique<AudioFrame>(); 101 frame->sample_rate_hz_ = kPcmuFormat.clockrate_hz; 102 frame->samples_per_channel_ = kPcmuFormat.clockrate_hz / 100; // 10 ms. 103 frame->num_channels_ = kPcmuFormat.num_channels; 104 frame->timestamp_ = frame->samples_per_channel_ * order; 105 wave_generator_.GenerateNextFrame(frame.get()); 106 return frame; 107 } 108 109 SimulatedClock fake_clock_; 110 SineWaveGenerator wave_generator_; 111 NiceMock<MockTransport> transport_; 112 NiceMock<MockTaskQueue> task_queue_; 113 const Environment env_; 114 scoped_refptr<AudioMixer> audio_mixer_; 115 scoped_refptr<AudioDecoderFactory> decoder_factory_; 116 scoped_refptr<AudioEncoderFactory> encoder_factory_; 117 scoped_refptr<AudioChannel> audio_channel_; 118 }; 119 120 // Validate RTP packet generation by feeding audio frames with sine wave. 121 // Resulted RTP packet is looped back into AudioChannel and gets decoded into 122 // audio frame to see if it has some signal to indicate its validity. 123 TEST_F(AudioChannelTest, PlayRtpByLocalLoop) { 124 auto loop_rtp = [&](ArrayView<const uint8_t> packet, Unused) { 125 audio_channel_->ReceivedRTPPacket(packet); 126 return true; 127 }; 128 EXPECT_CALL(transport_, SendRtp).WillOnce(Invoke(loop_rtp)); 129 130 auto audio_sender = audio_channel_->GetAudioSender(); 131 audio_sender->SendAudioData(GetAudioFrame(0)); 132 audio_sender->SendAudioData(GetAudioFrame(1)); 133 134 AudioFrame empty_frame, audio_frame; 135 empty_frame.Mute(); 136 empty_frame.mutable_data(); // This will zero out the data. 137 audio_frame.CopyFrom(empty_frame); 138 audio_mixer_->Mix(/*number_of_channels*/ 1, &audio_frame); 139 140 // We expect now audio frame to pick up something. 141 EXPECT_NE(memcmp(empty_frame.data(), audio_frame.data(), 142 AudioFrame::kMaxDataSizeBytes), 143 0); 144 } 145 146 // Validate assigned local SSRC is resulted in RTP packet. 147 TEST_F(AudioChannelTest, VerifyLocalSsrcAsAssigned) { 148 RtpPacketReceived rtp; 149 auto loop_rtp = [&](ArrayView<const uint8_t> packet, Unused) { 150 rtp.Parse(packet); 151 return true; 152 }; 153 EXPECT_CALL(transport_, SendRtp).WillOnce(Invoke(loop_rtp)); 154 155 auto audio_sender = audio_channel_->GetAudioSender(); 156 audio_sender->SendAudioData(GetAudioFrame(0)); 157 audio_sender->SendAudioData(GetAudioFrame(1)); 158 159 EXPECT_EQ(rtp.Ssrc(), kLocalSsrc); 160 } 161 162 // Check metrics after processing an RTP packet. 163 TEST_F(AudioChannelTest, TestIngressStatistics) { 164 auto loop_rtp = [&](ArrayView<const uint8_t> packet, Unused) { 165 audio_channel_->ReceivedRTPPacket(packet); 166 return true; 167 }; 168 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(loop_rtp)); 169 170 auto audio_sender = audio_channel_->GetAudioSender(); 171 audio_sender->SendAudioData(GetAudioFrame(0)); 172 audio_sender->SendAudioData(GetAudioFrame(1)); 173 174 AudioFrame audio_frame; 175 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 176 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 177 178 std::optional<IngressStatistics> ingress_stats = 179 audio_channel_->GetIngressStatistics(); 180 EXPECT_TRUE(ingress_stats); 181 EXPECT_EQ(ingress_stats->neteq_stats.total_samples_received, 160ULL); 182 EXPECT_EQ(ingress_stats->neteq_stats.concealed_samples, 0ULL); 183 EXPECT_EQ(ingress_stats->neteq_stats.concealment_events, 0ULL); 184 EXPECT_EQ(ingress_stats->neteq_stats.inserted_samples_for_deceleration, 0ULL); 185 EXPECT_EQ(ingress_stats->neteq_stats.removed_samples_for_acceleration, 0ULL); 186 EXPECT_EQ(ingress_stats->neteq_stats.silent_concealed_samples, 0ULL); 187 // To extract the jitter buffer length in millisecond, jitter_buffer_delay_ms 188 // needs to be divided by jitter_buffer_emitted_count (number of samples). 189 EXPECT_EQ(ingress_stats->neteq_stats.jitter_buffer_delay_ms, 1600ULL); 190 EXPECT_EQ(ingress_stats->neteq_stats.jitter_buffer_emitted_count, 160ULL); 191 EXPECT_GT(ingress_stats->neteq_stats.jitter_buffer_target_delay_ms, 0ULL); 192 EXPECT_EQ(ingress_stats->neteq_stats.interruption_count, 0); 193 EXPECT_EQ(ingress_stats->neteq_stats.total_interruption_duration_ms, 0); 194 EXPECT_DOUBLE_EQ(ingress_stats->total_duration, 0.02); 195 196 // Now without any RTP pending in jitter buffer pull more. 197 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 198 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 199 200 // Send another RTP packet to intentionally break PLC. 201 audio_sender->SendAudioData(GetAudioFrame(2)); 202 audio_sender->SendAudioData(GetAudioFrame(3)); 203 204 ingress_stats = audio_channel_->GetIngressStatistics(); 205 EXPECT_TRUE(ingress_stats); 206 EXPECT_EQ(ingress_stats->neteq_stats.total_samples_received, 320ULL); 207 EXPECT_EQ(ingress_stats->neteq_stats.concealed_samples, 168ULL); 208 EXPECT_EQ(ingress_stats->neteq_stats.concealment_events, 1ULL); 209 EXPECT_EQ(ingress_stats->neteq_stats.inserted_samples_for_deceleration, 0ULL); 210 EXPECT_EQ(ingress_stats->neteq_stats.removed_samples_for_acceleration, 0ULL); 211 EXPECT_EQ(ingress_stats->neteq_stats.silent_concealed_samples, 0ULL); 212 EXPECT_EQ(ingress_stats->neteq_stats.jitter_buffer_delay_ms, 1600ULL); 213 EXPECT_EQ(ingress_stats->neteq_stats.jitter_buffer_emitted_count, 160ULL); 214 EXPECT_GT(ingress_stats->neteq_stats.jitter_buffer_target_delay_ms, 0ULL); 215 EXPECT_EQ(ingress_stats->neteq_stats.interruption_count, 0); 216 EXPECT_EQ(ingress_stats->neteq_stats.total_interruption_duration_ms, 0); 217 EXPECT_DOUBLE_EQ(ingress_stats->total_duration, 0.04); 218 219 // Pull the last RTP packet. 220 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 221 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 222 223 ingress_stats = audio_channel_->GetIngressStatistics(); 224 EXPECT_TRUE(ingress_stats); 225 EXPECT_EQ(ingress_stats->neteq_stats.total_samples_received, 480ULL); 226 EXPECT_EQ(ingress_stats->neteq_stats.concealed_samples, 168ULL); 227 EXPECT_EQ(ingress_stats->neteq_stats.concealment_events, 1ULL); 228 EXPECT_EQ(ingress_stats->neteq_stats.inserted_samples_for_deceleration, 0ULL); 229 EXPECT_EQ(ingress_stats->neteq_stats.removed_samples_for_acceleration, 0ULL); 230 EXPECT_EQ(ingress_stats->neteq_stats.silent_concealed_samples, 0ULL); 231 EXPECT_EQ(ingress_stats->neteq_stats.jitter_buffer_delay_ms, 3200ULL); 232 EXPECT_EQ(ingress_stats->neteq_stats.jitter_buffer_emitted_count, 320ULL); 233 EXPECT_GT(ingress_stats->neteq_stats.jitter_buffer_target_delay_ms, 0ULL); 234 EXPECT_EQ(ingress_stats->neteq_stats.interruption_count, 0); 235 EXPECT_EQ(ingress_stats->neteq_stats.total_interruption_duration_ms, 0); 236 EXPECT_DOUBLE_EQ(ingress_stats->total_duration, 0.06); 237 } 238 239 // Check ChannelStatistics metric after processing RTP and RTCP packets. 240 TEST_F(AudioChannelTest, TestChannelStatistics) { 241 auto loop_rtp = [&](ArrayView<const uint8_t> packet, Unused) { 242 audio_channel_->ReceivedRTPPacket(packet); 243 return true; 244 }; 245 auto loop_rtcp = [&](ArrayView<const uint8_t> packet, Unused) { 246 audio_channel_->ReceivedRTCPPacket(packet); 247 return true; 248 }; 249 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(loop_rtp)); 250 EXPECT_CALL(transport_, SendRtcp).WillRepeatedly(Invoke(loop_rtcp)); 251 252 // Simulate microphone giving audio frame (10 ms). This will trigger transport 253 // to send RTP as handled in loop_rtp above. 254 auto audio_sender = audio_channel_->GetAudioSender(); 255 audio_sender->SendAudioData(GetAudioFrame(0)); 256 audio_sender->SendAudioData(GetAudioFrame(1)); 257 258 // Simulate speaker requesting audio frame (10 ms). This will trigger VoIP 259 // engine to fetch audio samples from RTP packets stored in jitter buffer. 260 AudioFrame audio_frame; 261 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 262 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 263 264 // Force sending RTCP SR report in order to have remote_rtcp field available 265 // in channel statistics. This will trigger transport to send RTCP as handled 266 // in loop_rtcp above. 267 audio_channel_->SendRTCPReportForTesting(kRtcpSr); 268 269 std::optional<ChannelStatistics> channel_stats = 270 audio_channel_->GetChannelStatistics(); 271 EXPECT_TRUE(channel_stats); 272 273 EXPECT_EQ(channel_stats->packets_sent, 1ULL); 274 EXPECT_EQ(channel_stats->bytes_sent, 160ULL); 275 276 EXPECT_EQ(channel_stats->packets_received, 1ULL); 277 EXPECT_EQ(channel_stats->bytes_received, 160ULL); 278 EXPECT_EQ(channel_stats->jitter, 0); 279 EXPECT_EQ(channel_stats->packets_lost, 0); 280 EXPECT_EQ(channel_stats->remote_ssrc.value(), kLocalSsrc); 281 282 EXPECT_TRUE(channel_stats->remote_rtcp.has_value()); 283 284 EXPECT_EQ(channel_stats->remote_rtcp->jitter, 0); 285 EXPECT_EQ(channel_stats->remote_rtcp->packets_lost, 0); 286 EXPECT_EQ(channel_stats->remote_rtcp->fraction_lost, 0); 287 EXPECT_GT(channel_stats->remote_rtcp->last_report_received_timestamp_ms, 0); 288 EXPECT_FALSE(channel_stats->remote_rtcp->round_trip_time.has_value()); 289 } 290 291 // Check ChannelStatistics RTT metric after processing RTP and RTCP packets 292 // using three audio channels where each represents media endpoint. 293 // 294 // 1) AC1 <- RTP/RTCP -> AC2 295 // 2) AC1 <- RTP/RTCP -> AC3 296 // 297 // During step 1), AC1 should be able to check RTT from AC2's SSRC. 298 // During step 2), AC1 should be able to check RTT from AC3's SSRC. 299 TEST_F(AudioChannelTest, RttIsAvailableAfterChangeOfRemoteSsrc) { 300 // Create AC2 and AC3. 301 constexpr uint32_t kAc2Ssrc = 0xdeadbeef; 302 constexpr uint32_t kAc3Ssrc = 0xdeafbeef; 303 304 auto ac_2 = CreateAudioChannel(kAc2Ssrc); 305 auto ac_3 = CreateAudioChannel(kAc3Ssrc); 306 307 auto send_recv_rtp = [&](scoped_refptr<AudioChannel> rtp_sender, 308 scoped_refptr<AudioChannel> rtp_receiver) { 309 // Setup routing logic via transport_. 310 auto route_rtp = [&](ArrayView<const uint8_t> packet, Unused) { 311 rtp_receiver->ReceivedRTPPacket(packet); 312 return true; 313 }; 314 ON_CALL(transport_, SendRtp).WillByDefault(route_rtp); 315 316 // This will trigger route_rtp callback via transport_. 317 rtp_sender->GetAudioSender()->SendAudioData(GetAudioFrame(0)); 318 rtp_sender->GetAudioSender()->SendAudioData(GetAudioFrame(1)); 319 320 // Process received RTP in receiver. 321 AudioFrame audio_frame; 322 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 323 audio_mixer_->Mix(/*number_of_channels=*/1, &audio_frame); 324 325 // Revert to default to avoid using reference in route_rtp lambda. 326 ON_CALL(transport_, SendRtp).WillByDefault(Return(true)); 327 }; 328 329 auto send_recv_rtcp = [&](scoped_refptr<AudioChannel> rtcp_sender, 330 scoped_refptr<AudioChannel> rtcp_receiver) { 331 // Setup routing logic via transport_. 332 auto route_rtcp = [&](ArrayView<const uint8_t> packet, Unused) { 333 rtcp_receiver->ReceivedRTCPPacket(packet); 334 return true; 335 }; 336 ON_CALL(transport_, SendRtcp).WillByDefault(route_rtcp); 337 338 // This will trigger route_rtcp callback via transport_. 339 rtcp_sender->SendRTCPReportForTesting(kRtcpSr); 340 341 // Revert to default to avoid using reference in route_rtcp lambda. 342 ON_CALL(transport_, SendRtcp).WillByDefault(Return(true)); 343 }; 344 345 // AC1 <-- RTP/RTCP --> AC2 346 send_recv_rtp(audio_channel_, ac_2); 347 send_recv_rtp(ac_2, audio_channel_); 348 send_recv_rtcp(audio_channel_, ac_2); 349 send_recv_rtcp(ac_2, audio_channel_); 350 351 std::optional<ChannelStatistics> channel_stats = 352 audio_channel_->GetChannelStatistics(); 353 ASSERT_TRUE(channel_stats); 354 EXPECT_EQ(channel_stats->remote_ssrc, kAc2Ssrc); 355 ASSERT_TRUE(channel_stats->remote_rtcp); 356 EXPECT_GT(channel_stats->remote_rtcp->round_trip_time, 0.0); 357 358 // AC1 <-- RTP/RTCP --> AC3 359 send_recv_rtp(audio_channel_, ac_3); 360 send_recv_rtp(ac_3, audio_channel_); 361 send_recv_rtcp(audio_channel_, ac_3); 362 send_recv_rtcp(ac_3, audio_channel_); 363 364 channel_stats = audio_channel_->GetChannelStatistics(); 365 ASSERT_TRUE(channel_stats); 366 EXPECT_EQ(channel_stats->remote_ssrc, kAc3Ssrc); 367 ASSERT_TRUE(channel_stats->remote_rtcp); 368 EXPECT_GT(channel_stats->remote_rtcp->round_trip_time, 0.0); 369 } 370 371 } // namespace 372 } // namespace webrtc