channel_receive_unittest.cc (10126B)
1 /* 2 * Copyright 2023 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/channel_receive.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <cstring> 16 #include <memory> 17 #include <optional> 18 #include <vector> 19 20 #include "absl/strings/string_view.h" 21 #include "api/array_view.h" 22 #include "api/audio/audio_frame.h" 23 #include "api/audio_codecs/audio_decoder_factory.h" 24 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 25 #include "api/call/transport.h" 26 #include "api/crypto/crypto_options.h" 27 #include "api/environment/environment_factory.h" 28 #include "api/make_ref_counted.h" 29 #include "api/scoped_refptr.h" 30 #include "api/test/mock_frame_transformer.h" 31 #include "api/units/time_delta.h" 32 #include "api/units/timestamp.h" 33 #include "modules/audio_device/include/mock_audio_device.h" 34 #include "modules/rtp_rtcp/source/ntp_time_util.h" 35 #include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" 36 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h" 37 #include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h" 38 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 39 #include "rtc_base/logging.h" 40 #include "rtc_base/string_encode.h" 41 #include "system_wrappers/include/ntp_time.h" 42 #include "test/gmock.h" 43 #include "test/gtest.h" 44 #include "test/mock_transport.h" 45 #include "test/time_controller/simulated_time_controller.h" 46 47 namespace webrtc { 48 namespace voe { 49 namespace { 50 51 using ::testing::NiceMock; 52 using ::testing::NotNull; 53 using ::testing::Return; 54 using ::testing::Test; 55 56 constexpr uint32_t kLocalSsrc = 1111; 57 constexpr uint32_t kRemoteSsrc = 2222; 58 // We run RTP data with 8 kHz PCMA (fixed payload type 8). 59 constexpr char kPayloadName[] = "PCMA"; 60 constexpr int kPayloadType = 8; 61 constexpr int kSampleRateHz = 8000; 62 63 class ChannelReceiveTest : public Test { 64 public: 65 ChannelReceiveTest() 66 : time_controller_(Timestamp::Seconds(5555)), 67 audio_device_module_(test::MockAudioDeviceModule::CreateNice()), 68 audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()) { 69 ON_CALL(*audio_device_module_, PlayoutDelay).WillByDefault(Return(0)); 70 } 71 72 std::unique_ptr<ChannelReceiveInterface> CreateTestChannelReceive() { 73 CryptoOptions crypto_options; 74 auto channel = CreateChannelReceive( 75 CreateEnvironment(time_controller_.GetClock()), 76 /* neteq_factory= */ nullptr, audio_device_module_.get(), &transport_, 77 kLocalSsrc, kRemoteSsrc, 78 /* jitter_buffer_max_packets= */ 0, 79 /* jitter_buffer_fast_playout= */ false, 80 /* jitter_buffer_min_delay_ms= */ 0, 81 /* enable_non_sender_rtt= */ false, audio_decoder_factory_, 82 /* codec_pair_id= */ std::nullopt, 83 /* frame_decryptor_interface= */ nullptr, crypto_options, 84 /* frame_transformer= */ nullptr); 85 channel->SetReceiveCodecs( 86 {{kPayloadType, {kPayloadName, kSampleRateHz, 1}}}); 87 return channel; 88 } 89 90 NtpTime NtpNow() { return time_controller_.GetClock()->CurrentNtpTime(); } 91 92 uint32_t RtpNow() { 93 // Note - the "random" offset of this timestamp is zero. 94 return time_controller_.GetClock()->TimeInMilliseconds() * 1000 / 95 kSampleRateHz; 96 } 97 98 RtpPacketReceived CreateRtpPacket() { 99 RtpPacketReceived packet; 100 packet.set_arrival_time(time_controller_.GetClock()->CurrentTime()); 101 packet.SetTimestamp(RtpNow()); 102 packet.SetSsrc(kLocalSsrc); 103 packet.SetPayloadType(kPayloadType); 104 // Packet size should be enough to give at least 10 ms of data. 105 // For PCMA, that's 80 bytes; this should be enough. 106 uint8_t* datapos = packet.SetPayloadSize(100); 107 memset(datapos, 0, 100); 108 return packet; 109 } 110 111 std::vector<uint8_t> CreateRtcpSenderReport() { 112 std::vector<uint8_t> packet(1024); 113 size_t pos = 0; 114 rtcp::SenderReport report; 115 report.SetSenderSsrc(kRemoteSsrc); 116 report.SetNtp(NtpNow()); 117 report.SetRtpTimestamp(RtpNow()); 118 report.SetPacketCount(0); 119 report.SetOctetCount(0); 120 report.Create(&packet[0], &pos, packet.size(), nullptr); 121 // No report blocks. 122 packet.resize(pos); 123 return packet; 124 } 125 126 std::vector<uint8_t> CreateRtcpReceiverReport() { 127 rtcp::ReportBlock block; 128 block.SetMediaSsrc(kLocalSsrc); 129 // Middle 32 bits of the NTP timestamp from received SR 130 block.SetLastSr(CompactNtp(NtpNow())); 131 block.SetDelayLastSr(0); 132 133 rtcp::ReceiverReport report; 134 report.SetSenderSsrc(kRemoteSsrc); 135 report.AddReportBlock(block); 136 137 std::vector<uint8_t> packet(1024); 138 size_t pos = 0; 139 report.Create(&packet[0], &pos, packet.size(), nullptr); 140 packet.resize(pos); 141 return packet; 142 } 143 144 void HandleGeneratedRtcp(ChannelReceiveInterface& /* channel */, 145 ArrayView<const uint8_t> packet) { 146 if (packet[1] == rtcp::ReceiverReport::kPacketType) { 147 // Ignore RR, it requires no response 148 } else { 149 RTC_LOG(LS_ERROR) << "Unexpected RTCP packet generated"; 150 RTC_LOG(LS_ERROR) << "Packet content " 151 << hex_encode_with_delimiter( 152 absl::string_view( 153 reinterpret_cast<char*>(packet.data()[0]), 154 packet.size()), 155 ' '); 156 } 157 } 158 159 int64_t ProbeCaptureStartNtpTime(ChannelReceiveInterface& channel) { 160 // Computation of the capture_start_ntp_time_ms_ occurs when the 161 // audio data is pulled, not when it is received. So we need to 162 // inject an RTP packet, and then fetch its data. 163 AudioFrame audio_frame; 164 channel.OnRtpPacket(CreateRtpPacket()); 165 channel.GetAudioFrameWithInfo(kSampleRateHz, &audio_frame); 166 ChannelReceiveStatistics stats = channel.GetRTCPStatistics(); 167 return stats.capture_start_ntp_time_ms; 168 } 169 170 protected: 171 GlobalSimulatedTimeController time_controller_; 172 scoped_refptr<test::MockAudioDeviceModule> audio_device_module_; 173 scoped_refptr<AudioDecoderFactory> audio_decoder_factory_; 174 MockTransport transport_; 175 }; 176 177 TEST_F(ChannelReceiveTest, CreateAndDestroy) { 178 auto channel = CreateTestChannelReceive(); 179 EXPECT_THAT(channel, NotNull()); 180 } 181 182 TEST_F(ChannelReceiveTest, ReceiveReportGeneratedOnTime) { 183 auto channel = CreateTestChannelReceive(); 184 185 bool receiver_report_sent = false; 186 EXPECT_CALL(transport_, SendRtcp) 187 .WillRepeatedly([&](ArrayView<const uint8_t> packet, 188 const PacketOptions& options) { 189 if (packet.size() >= 2 && 190 packet[1] == rtcp::ReceiverReport::kPacketType) { 191 receiver_report_sent = true; 192 } 193 return true; 194 }); 195 // RFC 3550 section 6.2 mentions 5 seconds as a reasonable expectation 196 // for the interval between RTCP packets. 197 time_controller_.AdvanceTime(TimeDelta::Seconds(5)); 198 199 EXPECT_TRUE(receiver_report_sent); 200 } 201 202 TEST_F(ChannelReceiveTest, CaptureStartTimeBecomesValid) { 203 auto channel = CreateTestChannelReceive(); 204 205 EXPECT_CALL(transport_, SendRtcp) 206 .WillRepeatedly( 207 [&](ArrayView<const uint8_t> packet, const PacketOptions& options) { 208 HandleGeneratedRtcp(*channel, packet); 209 return true; 210 }); 211 // Before any packets are sent, CaptureStartTime is invalid. 212 EXPECT_EQ(ProbeCaptureStartNtpTime(*channel), -1); 213 214 // Must start playout, otherwise packet is discarded. 215 channel->StartPlayout(); 216 // Send one RTP packet. This causes registration of the SSRC. 217 channel->OnRtpPacket(CreateRtpPacket()); 218 EXPECT_EQ(ProbeCaptureStartNtpTime(*channel), -1); 219 220 // Receive a sender report. 221 auto rtcp_packet_1 = CreateRtcpSenderReport(); 222 channel->ReceivedRTCPPacket(rtcp_packet_1.data(), rtcp_packet_1.size()); 223 EXPECT_EQ(ProbeCaptureStartNtpTime(*channel), -1); 224 225 time_controller_.AdvanceTime(TimeDelta::Seconds(5)); 226 227 // Receive a receiver report. This is necessary, which is odd. 228 // Presumably it is because the receiver needs to know the RTT 229 // before it can compute the capture start NTP time. 230 // The receiver report must happen before the second sender report. 231 auto rtcp_rr = CreateRtcpReceiverReport(); 232 channel->ReceivedRTCPPacket(rtcp_rr.data(), rtcp_rr.size()); 233 EXPECT_EQ(ProbeCaptureStartNtpTime(*channel), -1); 234 235 // Receive another sender report after 5 seconds. 236 // This should be enough to establish the capture start NTP time. 237 auto rtcp_packet_2 = CreateRtcpSenderReport(); 238 channel->ReceivedRTCPPacket(rtcp_packet_2.data(), rtcp_packet_2.size()); 239 240 EXPECT_NE(ProbeCaptureStartNtpTime(*channel), -1); 241 } 242 243 TEST_F(ChannelReceiveTest, SettingFrameTransformer) { 244 auto channel = CreateTestChannelReceive(); 245 246 scoped_refptr<MockFrameTransformer> mock_frame_transformer = 247 make_ref_counted<MockFrameTransformer>(); 248 249 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback); 250 channel->SetDepacketizerToDecoderFrameTransformer(mock_frame_transformer); 251 252 // Must start playout, otherwise packet is discarded. 253 channel->StartPlayout(); 254 255 RtpPacketReceived packet = CreateRtpPacket(); 256 257 // Receive one RTP packet, this should be transformed. 258 EXPECT_CALL(*mock_frame_transformer, Transform); 259 channel->OnRtpPacket(packet); 260 } 261 262 TEST_F(ChannelReceiveTest, SettingFrameTransformerMultipleTimes) { 263 auto channel = CreateTestChannelReceive(); 264 265 scoped_refptr<MockFrameTransformer> mock_frame_transformer = 266 make_ref_counted<MockFrameTransformer>(); 267 268 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback); 269 channel->SetDepacketizerToDecoderFrameTransformer(mock_frame_transformer); 270 271 // Set the same transformer again, shouldn't cause any additional callback 272 // registration calls. 273 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback) 274 .Times(0); 275 channel->SetDepacketizerToDecoderFrameTransformer(mock_frame_transformer); 276 } 277 278 } // namespace 279 } // namespace voe 280 } // namespace webrtc