channel_send_unittest.cc (20363B)
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_send.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <memory> 16 #include <optional> 17 #include <utility> 18 #include <vector> 19 20 #include "api/array_view.h" 21 #include "api/audio/audio_frame.h" 22 #include "api/audio_codecs/audio_encoder.h" 23 #include "api/audio_codecs/audio_encoder_factory.h" 24 #include "api/audio_codecs/audio_format.h" 25 #include "api/audio_codecs/builtin_audio_encoder_factory.h" 26 #include "api/call/bitrate_allocation.h" 27 #include "api/call/transport.h" 28 #include "api/crypto/crypto_options.h" 29 #include "api/environment/environment.h" 30 #include "api/field_trials.h" 31 #include "api/frame_transformer_interface.h" 32 #include "api/make_ref_counted.h" 33 #include "api/rtp_headers.h" 34 #include "api/scoped_refptr.h" 35 #include "api/test/mock_frame_transformer.h" 36 #include "api/test/mock_transformable_audio_frame.h" 37 #include "api/test/rtc_error_matchers.h" 38 #include "api/transport/bitrate_settings.h" 39 #include "api/units/data_rate.h" 40 #include "api/units/time_delta.h" 41 #include "api/units/timestamp.h" 42 #include "call/rtp_transport_config.h" 43 #include "call/rtp_transport_controller_send.h" 44 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 45 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 46 #include "test/create_test_environment.h" 47 #include "test/create_test_field_trials.h" 48 #include "test/gmock.h" 49 #include "test/gtest.h" 50 #include "test/mock_transport.h" 51 #include "test/time_controller/simulated_time_controller.h" 52 #include "test/wait_until.h" 53 54 namespace webrtc { 55 namespace voe { 56 namespace { 57 58 using ::testing::Eq; 59 using ::testing::Invoke; 60 using ::testing::IsTrue; 61 using ::testing::NiceMock; 62 using ::testing::Return; 63 using ::testing::SaveArg; 64 65 constexpr int kRtcpIntervalMs = 1000; 66 constexpr int kSsrc = 333; 67 constexpr int kPayloadType = 1; 68 constexpr int kSampleRateHz = 48000; 69 constexpr int kRtpRateHz = 48000; 70 71 BitrateConstraints GetBitrateConfig() { 72 BitrateConstraints bitrate_config; 73 bitrate_config.min_bitrate_bps = 10000; 74 bitrate_config.start_bitrate_bps = 100000; 75 bitrate_config.max_bitrate_bps = 1000000; 76 return bitrate_config; 77 } 78 79 class ChannelSendTest : public ::testing::Test { 80 protected: 81 ChannelSendTest() 82 : time_controller_(Timestamp::Seconds(1)), 83 field_trials_(CreateTestFieldTrials()), 84 env_(CreateTestEnvironment( 85 {.field_trials = &field_trials_, .time = &time_controller_})), 86 transport_controller_( 87 RtpTransportConfig{.env = env_, 88 .bitrate_config = GetBitrateConfig()}) { 89 channel_ = voe::CreateChannelSend(env_, &transport_, nullptr, nullptr, 90 crypto_options_, false, kRtcpIntervalMs, 91 kSsrc, nullptr, &transport_controller_); 92 encoder_factory_ = CreateBuiltinAudioEncoderFactory(); 93 SdpAudioFormat opus = SdpAudioFormat("opus", kRtpRateHz, 2); 94 std::unique_ptr<AudioEncoder> encoder = 95 encoder_factory_->Create(env_, opus, {.payload_type = kPayloadType}); 96 channel_->SetEncoder(kPayloadType, opus, std::move(encoder)); 97 transport_controller_.EnsureStarted(); 98 channel_->RegisterSenderCongestionControlObjects(&transport_controller_); 99 ON_CALL(transport_, SendRtcp).WillByDefault(Return(true)); 100 ON_CALL(transport_, SendRtp).WillByDefault(Return(true)); 101 } 102 103 std::unique_ptr<AudioFrame> CreateAudioFrame(uint8_t data_init_value = 0) { 104 auto frame = std::make_unique<AudioFrame>(); 105 frame->sample_rate_hz_ = kSampleRateHz; 106 frame->samples_per_channel_ = kSampleRateHz / 100; 107 frame->num_channels_ = 1; 108 frame->set_absolute_capture_timestamp_ms( 109 time_controller_.GetClock()->TimeInMilliseconds()); 110 int16_t* dest = frame->mutable_data(); 111 for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_; 112 i++, dest++) { 113 *dest = data_init_value; 114 } 115 return frame; 116 } 117 118 void ProcessNextFrame(std::unique_ptr<AudioFrame> audio_frame) { 119 channel_->ProcessAndEncodeAudio(std::move(audio_frame)); 120 // Advance time to process the task queue. 121 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 122 } 123 124 void ProcessNextFrame() { ProcessNextFrame(CreateAudioFrame()); } 125 126 GlobalSimulatedTimeController time_controller_; 127 FieldTrials field_trials_; 128 Environment env_; 129 NiceMock<MockTransport> transport_; 130 CryptoOptions crypto_options_; 131 RtpTransportControllerSend transport_controller_; 132 std::unique_ptr<ChannelSendInterface> channel_; 133 scoped_refptr<AudioEncoderFactory> encoder_factory_; 134 }; 135 136 TEST_F(ChannelSendTest, StopSendShouldResetEncoder) { 137 channel_->StartSend(); 138 // Insert two frames which should trigger a new packet. 139 EXPECT_CALL(transport_, SendRtp).Times(1); 140 ProcessNextFrame(); 141 ProcessNextFrame(); 142 143 EXPECT_CALL(transport_, SendRtp).Times(0); 144 ProcessNextFrame(); 145 // StopSend should clear the previous audio frame stored in the encoder. 146 channel_->StopSend(); 147 148 channel_->StartSend(); 149 // The following frame should not trigger a new packet since the encoder 150 // needs 20 ms audio. 151 EXPECT_CALL(transport_, SendRtp).Times(0); 152 ProcessNextFrame(); 153 } 154 155 TEST_F(ChannelSendTest, IncreaseRtpTimestampByPauseDuration) { 156 channel_->StartSend(); 157 uint32_t timestamp; 158 int sent_packets = 0; 159 auto send_rtp = [&](ArrayView<const uint8_t> data, 160 const PacketOptions& /* options */) { 161 ++sent_packets; 162 RtpPacketReceived packet; 163 packet.Parse(data); 164 timestamp = packet.Timestamp(); 165 return true; 166 }; 167 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(send_rtp)); 168 ProcessNextFrame(); 169 ProcessNextFrame(); 170 EXPECT_EQ(sent_packets, 1); 171 uint32_t first_timestamp = timestamp; 172 channel_->StopSend(); 173 time_controller_.AdvanceTime(TimeDelta::Seconds(10)); 174 channel_->StartSend(); 175 176 ProcessNextFrame(); 177 ProcessNextFrame(); 178 EXPECT_EQ(sent_packets, 2); 179 int64_t timestamp_gap_ms = 180 static_cast<int64_t>(timestamp - first_timestamp) * 1000 / kRtpRateHz; 181 EXPECT_EQ(timestamp_gap_ms, 10020); 182 } 183 184 TEST_F(ChannelSendTest, FrameTransformerGetsCorrectTimestamp) { 185 scoped_refptr<MockFrameTransformer> mock_frame_transformer = 186 make_ref_counted<MockFrameTransformer>(); 187 channel_->SetEncoderToPacketizerFrameTransformer(mock_frame_transformer); 188 scoped_refptr<TransformedFrameCallback> callback; 189 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback) 190 .WillOnce(SaveArg<0>(&callback)); 191 EXPECT_CALL(*mock_frame_transformer, UnregisterTransformedFrameCallback); 192 193 std::optional<uint32_t> sent_timestamp; 194 auto send_rtp = [&](ArrayView<const uint8_t> data, 195 const PacketOptions& /* options */) { 196 RtpPacketReceived packet; 197 packet.Parse(data); 198 if (!sent_timestamp) { 199 sent_timestamp = packet.Timestamp(); 200 } 201 return true; 202 }; 203 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(send_rtp)); 204 205 channel_->StartSend(); 206 int64_t transformable_frame_timestamp = -1; 207 EXPECT_CALL(*mock_frame_transformer, Transform) 208 .WillOnce([&](std::unique_ptr<TransformableFrameInterface> frame) { 209 transformable_frame_timestamp = frame->GetTimestamp(); 210 callback->OnTransformedFrame(std::move(frame)); 211 }); 212 // Insert two frames which should trigger a new packet. 213 ProcessNextFrame(); 214 ProcessNextFrame(); 215 216 // Ensure the RTP timestamp on the frame passed to the transformer 217 // includes the RTP offset and matches the actual RTP timestamp on the sent 218 // packet. 219 EXPECT_THAT( 220 WaitUntil([&] { return 0 + channel_->GetRtpRtcp()->StartTimestamp(); }, 221 Eq(transformable_frame_timestamp)), 222 IsRtcOk()); 223 EXPECT_THAT(WaitUntil([&] { return sent_timestamp; }, IsTrue()), IsRtcOk()); 224 EXPECT_EQ(*sent_timestamp, transformable_frame_timestamp); 225 } 226 227 // Ensure that AudioLevel calculations are performed correctly per-packet even 228 // if there's an async Encoded Frame Transform happening. 229 TEST_F(ChannelSendTest, AudioLevelsAttachedToCorrectTransformedFrame) { 230 channel_->SetSendAudioLevelIndicationStatus(true, /*id=*/1); 231 RtpPacketReceived::ExtensionManager extension_manager; 232 extension_manager.RegisterByType(1, kRtpExtensionAudioLevel); 233 234 scoped_refptr<MockFrameTransformer> mock_frame_transformer = 235 make_ref_counted<MockFrameTransformer>(); 236 channel_->SetEncoderToPacketizerFrameTransformer(mock_frame_transformer); 237 scoped_refptr<TransformedFrameCallback> callback; 238 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback) 239 .WillOnce(SaveArg<0>(&callback)); 240 EXPECT_CALL(*mock_frame_transformer, UnregisterTransformedFrameCallback); 241 242 std::vector<uint8_t> sent_audio_levels; 243 auto send_rtp = [&](ArrayView<const uint8_t> data, 244 const PacketOptions& /* options */) { 245 RtpPacketReceived packet(&extension_manager); 246 packet.Parse(data); 247 RTPHeader header; 248 packet.GetHeader(&header); 249 sent_audio_levels.push_back(header.extension.audio_level()->level()); 250 return true; 251 }; 252 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(send_rtp)); 253 254 channel_->StartSend(); 255 std::vector<std::unique_ptr<TransformableFrameInterface>> frames; 256 EXPECT_CALL(*mock_frame_transformer, Transform) 257 .Times(2) 258 .WillRepeatedly([&](std::unique_ptr<TransformableFrameInterface> frame) { 259 frames.push_back(std::move(frame)); 260 }); 261 262 // Insert two frames of 7s which should trigger a new packet. 263 ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/7)); 264 ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/7)); 265 266 // Insert two more frames of 3s, meaning a second packet is 267 // prepared and sent to the transform before the first packet has 268 // been sent. 269 ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/3)); 270 ProcessNextFrame(CreateAudioFrame(/*data_init_value=*/3)); 271 272 // Wait for both packets to be encoded and sent to the transform. 273 EXPECT_THAT(WaitUntil([&] { return frames.size(); }, Eq(2ul)), IsRtcOk()); 274 // Complete the transforms on both frames at the same time 275 callback->OnTransformedFrame(std::move(frames[0])); 276 callback->OnTransformedFrame(std::move(frames[1])); 277 278 // Allow things posted back to the encoder queue to run. 279 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 280 281 // Ensure the audio levels on both sent packets is present and 282 // matches their contents. 283 EXPECT_THAT(WaitUntil([&] { return sent_audio_levels.size(); }, Eq(2ul)), 284 IsRtcOk()); 285 // rms dbov of the packet with raw audio of 7s is 73. 286 EXPECT_EQ(sent_audio_levels[0], 73); 287 // rms dbov of the second packet with raw audio of 3s is 81. 288 EXPECT_EQ(sent_audio_levels[1], 81); 289 } 290 291 // Ensure that AudioLevels are attached to frames injected into the 292 // Encoded Frame transform. 293 TEST_F(ChannelSendTest, AudioLevelsAttachedToInsertedTransformedFrame) { 294 channel_->SetSendAudioLevelIndicationStatus(true, /*id=*/1); 295 RtpPacketReceived::ExtensionManager extension_manager; 296 extension_manager.RegisterByType(1, kRtpExtensionAudioLevel); 297 298 scoped_refptr<MockFrameTransformer> mock_frame_transformer = 299 make_ref_counted<MockFrameTransformer>(); 300 channel_->SetEncoderToPacketizerFrameTransformer(mock_frame_transformer); 301 scoped_refptr<TransformedFrameCallback> callback; 302 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback) 303 .WillOnce(SaveArg<0>(&callback)); 304 EXPECT_CALL(*mock_frame_transformer, UnregisterTransformedFrameCallback); 305 306 std::optional<uint8_t> sent_audio_level; 307 auto send_rtp = [&](ArrayView<const uint8_t> data, 308 const PacketOptions& /* options */) { 309 RtpPacketReceived packet(&extension_manager); 310 packet.Parse(data); 311 RTPHeader header; 312 packet.GetHeader(&header); 313 sent_audio_level = header.extension.audio_level()->level(); 314 return true; 315 }; 316 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(send_rtp)); 317 318 channel_->StartSend(); 319 320 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 321 // Inject a frame encoded elsewhere. 322 auto mock_frame = std::make_unique<NiceMock<MockTransformableAudioFrame>>(); 323 uint8_t audio_level = 67; 324 ON_CALL(*mock_frame, AudioLevel()).WillByDefault(Return(audio_level)); 325 uint8_t payload[10]; 326 ON_CALL(*mock_frame, GetData()) 327 .WillByDefault(Return(ArrayView<uint8_t>(&payload[0], 10))); 328 EXPECT_THAT(WaitUntil([&] { return callback; }, IsTrue()), IsRtcOk()); 329 callback->OnTransformedFrame(std::move(mock_frame)); 330 331 // Allow things posted back to the encoder queue to run. 332 time_controller_.AdvanceTime(TimeDelta::Millis(10)); 333 334 // Ensure the audio levels is set on the sent packet. 335 EXPECT_THAT(WaitUntil([&] { return sent_audio_level; }, IsTrue()), IsRtcOk()); 336 EXPECT_EQ(*sent_audio_level, audio_level); 337 } 338 339 // Ensure that GetUsedRate returns null if no frames are coded. 340 TEST_F(ChannelSendTest, NoUsedRateInitially) { 341 channel_->StartSend(); 342 auto used_rate = channel_->GetUsedRate(); 343 EXPECT_EQ(used_rate, std::nullopt); 344 } 345 346 // Ensure that GetUsedRate returns value with one coded frame. 347 TEST_F(ChannelSendTest, ValidUsedRateWithOneCodedFrame) { 348 channel_->StartSend(); 349 EXPECT_CALL(transport_, SendRtp).Times(1); 350 ProcessNextFrame(); 351 ProcessNextFrame(); 352 auto used_rate = channel_->GetUsedRate(); 353 EXPECT_GT(used_rate.value().bps(), 0); 354 } 355 356 // Ensure that GetUsedRate returns value with one coded frame. 357 TEST_F(ChannelSendTest, UsedRateIsLargerofLastTwoFrames) { 358 channel_->StartSend(); 359 channel_->CallEncoder( 360 [&](AudioEncoder* encoder) { encoder->OnReceivedOverhead(72); }); 361 DataRate lowrate = DataRate::BitsPerSec(40000); 362 DataRate highrate = DataRate::BitsPerSec(80000); 363 BitrateAllocationUpdate update; 364 update.bwe_period = TimeDelta::Millis(100); 365 366 update.target_bitrate = lowrate; 367 channel_->OnBitrateAllocation(update); 368 EXPECT_CALL(transport_, SendRtp).Times(1); 369 ProcessNextFrame(); 370 ProcessNextFrame(); 371 // Last two frames have rates [32kbps, -], yielding 32kbps. 372 auto used_rate_1 = channel_->GetUsedRate(); 373 374 update.target_bitrate = highrate; 375 channel_->OnBitrateAllocation(update); 376 EXPECT_CALL(transport_, SendRtp).Times(1); 377 ProcessNextFrame(); 378 ProcessNextFrame(); 379 // Last two frames have rates [54kbps, 32kbps], yielding 54kbps 380 auto used_rate_2 = channel_->GetUsedRate(); 381 382 update.target_bitrate = lowrate; 383 channel_->OnBitrateAllocation(update); 384 EXPECT_CALL(transport_, SendRtp).Times(1); 385 ProcessNextFrame(); 386 ProcessNextFrame(); 387 // Last two frames have rates [32kbps 54kbps], yielding 54kbps 388 auto used_rate_3 = channel_->GetUsedRate(); 389 390 EXPECT_GT(used_rate_2, used_rate_1); 391 EXPECT_EQ(used_rate_3, used_rate_2); 392 } 393 394 // Test that we gracefully handle packets while the congestion control objects 395 // are not configured. This can happen during calls 396 // AudioSendStream::ConfigureStream 397 TEST_F(ChannelSendTest, EnqueuePacketsGracefullyHandlesNonInitializedPacer) { 398 EXPECT_CALL(transport_, SendRtp).Times(1); 399 channel_->StartSend(); 400 channel_->ResetSenderCongestionControlObjects(); 401 // This should trigger a packet, but congestion control is not configured 402 // so it should be dropped 403 ProcessNextFrame(); 404 ProcessNextFrame(); 405 406 channel_->RegisterSenderCongestionControlObjects(&transport_controller_); 407 // Now that we reconfigured the congestion control objects the new frame 408 // should be processed 409 ProcessNextFrame(); 410 ProcessNextFrame(); 411 } 412 413 TEST_F(ChannelSendTest, ConfiguredCsrcsAreIncludedInRtpPackets) { 414 channel_->StartSend(); 415 std::vector<uint32_t> expected_csrcs = {1, 2, 3}; 416 channel_->SetCsrcs(expected_csrcs); 417 418 std::vector<uint32_t> csrcs; 419 auto send_rtp = [&](ArrayView<const uint8_t> data, 420 const PacketOptions& /* options */) { 421 RtpPacketReceived packet; 422 packet.Parse(data); 423 csrcs = packet.Csrcs(); 424 return true; 425 }; 426 427 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(send_rtp)); 428 ProcessNextFrame(); 429 ProcessNextFrame(); 430 431 EXPECT_EQ(csrcs, expected_csrcs); 432 } 433 434 // Creates a frame with the given CSRCs where other values are copied from the 435 // template. 436 std::unique_ptr<TransformableAudioFrameInterface> CreateMockFrameWithCsrcs( 437 const TransformableAudioFrameInterface* frame_template, 438 const std::vector<uint32_t>& csrcs) { 439 std::unique_ptr<MockTransformableAudioFrame> mock_frame = 440 std::make_unique<MockTransformableAudioFrame>(); 441 EXPECT_CALL(*mock_frame, GetContributingSources) 442 .WillRepeatedly(Return(csrcs)); 443 444 std::vector<uint8_t> frame_data = std::vector( 445 frame_template->GetData().begin(), frame_template->GetData().end()); 446 ON_CALL(*mock_frame, GetData).WillByDefault(Return(frame_data)); 447 448 ON_CALL(*mock_frame, GetTimestamp) 449 .WillByDefault(Return(frame_template->GetTimestamp())); 450 ON_CALL(*mock_frame, GetPayloadType) 451 .WillByDefault(Return(frame_template->GetPayloadType())); 452 ON_CALL(*mock_frame, GetSsrc) 453 .WillByDefault(Return(frame_template->GetSsrc())); 454 ON_CALL(*mock_frame, GetMimeType) 455 .WillByDefault(Return(frame_template->GetMimeType())); 456 ON_CALL(*mock_frame, SequenceNumber) 457 .WillByDefault(Return(frame_template->SequenceNumber())); 458 ON_CALL(*mock_frame, GetDirection) 459 .WillByDefault(Return(frame_template->GetDirection())); 460 ON_CALL(*mock_frame, AbsoluteCaptureTimestamp) 461 .WillByDefault(Return(frame_template->AbsoluteCaptureTimestamp())); 462 ON_CALL(*mock_frame, Type).WillByDefault(Return(frame_template->Type())); 463 ON_CALL(*mock_frame, AudioLevel) 464 .WillByDefault(Return(frame_template->AudioLevel())); 465 ON_CALL(*mock_frame, ReceiveTime) 466 .WillByDefault(Return(frame_template->ReceiveTime())); 467 ON_CALL(*mock_frame, CaptureTime) 468 .WillByDefault(Return(frame_template->CaptureTime())); 469 ON_CALL(*mock_frame, SenderCaptureTimeOffset) 470 .WillByDefault(Return(frame_template->SenderCaptureTimeOffset())); 471 return mock_frame; 472 } 473 474 TEST_F(ChannelSendTest, FrameTransformerTakesPrecedenceOverSetCsrcs) { 475 scoped_refptr<MockFrameTransformer> mock_frame_transformer = 476 make_ref_counted<MockFrameTransformer>(); 477 scoped_refptr<TransformedFrameCallback> callback; 478 EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback) 479 .WillOnce(SaveArg<0>(&callback)); 480 EXPECT_CALL(*mock_frame_transformer, UnregisterTransformedFrameCallback); 481 channel_->SetEncoderToPacketizerFrameTransformer(mock_frame_transformer); 482 483 // Configure the mock frame transformer to return a frame with different CSRCs 484 // than it is provided. 485 std::vector<uint32_t> csrcs_provided_to_frame_transformer; 486 std::vector<uint32_t> csrcs_output_by_frame_transformer = {1, 2, 3}; 487 EXPECT_CALL(*mock_frame_transformer, Transform) 488 .WillRepeatedly( 489 Invoke([&](std::unique_ptr<TransformableFrameInterface> frame) { 490 auto audio_frame = 491 static_cast<TransformableAudioFrameInterface*>(frame.get()); 492 csrcs_provided_to_frame_transformer.assign( 493 audio_frame->GetContributingSources().begin(), 494 audio_frame->GetContributingSources().end()); 495 callback->OnTransformedFrame(CreateMockFrameWithCsrcs( 496 audio_frame, csrcs_output_by_frame_transformer)); 497 })); 498 499 std::vector<uint32_t> set_csrcs = {4, 5, 6}; 500 channel_->SetCsrcs(set_csrcs); 501 channel_->StartSend(); 502 503 std::vector<uint32_t> sent_csrcs; 504 auto send_rtp = [&](ArrayView<const uint8_t> data, 505 const PacketOptions& /* options */) { 506 RtpPacketReceived packet; 507 packet.Parse(data); 508 sent_csrcs = packet.Csrcs(); 509 return true; 510 }; 511 512 EXPECT_CALL(transport_, SendRtp).WillRepeatedly(Invoke(send_rtp)); 513 ProcessNextFrame(); 514 ProcessNextFrame(); 515 516 EXPECT_EQ(csrcs_provided_to_frame_transformer, set_csrcs) 517 << "The CSRCs configured in ChannelSend should be passed to the frame " 518 "transformer."; 519 EXPECT_EQ(sent_csrcs, csrcs_output_by_frame_transformer) 520 << "CSRCs provided by the frame transformer should propagate to the RTP " 521 "packet."; 522 } 523 524 } // namespace 525 } // namespace voe 526 } // namespace webrtc