xref: /aosp_15_r20/external/webrtc/audio/audio_send_stream_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2015 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/audio_send_stream.h"
12 
13 #include <memory>
14 #include <string>
15 #include <thread>
16 #include <utility>
17 #include <vector>
18 
19 #include "api/task_queue/default_task_queue_factory.h"
20 #include "api/test/mock_frame_encryptor.h"
21 #include "audio/audio_state.h"
22 #include "audio/conversion.h"
23 #include "audio/mock_voe_channel_proxy.h"
24 #include "call/test/mock_rtp_transport_controller_send.h"
25 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
26 #include "modules/audio_device/include/mock_audio_device.h"
27 #include "modules/audio_mixer/audio_mixer_impl.h"
28 #include "modules/audio_mixer/sine_wave_generator.h"
29 #include "modules/audio_processing/include/audio_processing_statistics.h"
30 #include "modules/audio_processing/include/mock_audio_processing.h"
31 #include "modules/rtp_rtcp/mocks/mock_rtcp_bandwidth_observer.h"
32 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
33 #include "modules/utility/maybe_worker_thread.h"
34 #include "system_wrappers/include/clock.h"
35 #include "test/gtest.h"
36 #include "test/mock_audio_encoder.h"
37 #include "test/mock_audio_encoder_factory.h"
38 #include "test/scoped_key_value_config.h"
39 #include "test/time_controller/real_time_controller.h"
40 
41 namespace webrtc {
42 namespace test {
43 namespace {
44 
45 using ::testing::_;
46 using ::testing::AnyNumber;
47 using ::testing::Eq;
48 using ::testing::Field;
49 using ::testing::InSequence;
50 using ::testing::Invoke;
51 using ::testing::Ne;
52 using ::testing::NiceMock;
53 using ::testing::Return;
54 using ::testing::StrEq;
55 
56 static const float kTolerance = 0.0001f;
57 
58 const uint32_t kSsrc = 1234;
59 const char* kCName = "foo_name";
60 const int kAudioLevelId = 2;
61 const int kTransportSequenceNumberId = 4;
62 const int32_t kEchoDelayMedian = 254;
63 const int32_t kEchoDelayStdDev = -3;
64 const double kDivergentFilterFraction = 0.2f;
65 const double kEchoReturnLoss = -65;
66 const double kEchoReturnLossEnhancement = 101;
67 const double kResidualEchoLikelihood = -1.0f;
68 const double kResidualEchoLikelihoodMax = 23.0f;
69 const CallSendStatistics kCallStats = {112, 12, 13456, 17890};
70 const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354};
71 const int kTelephoneEventPayloadType = 123;
72 const int kTelephoneEventPayloadFrequency = 65432;
73 const int kTelephoneEventCode = 45;
74 const int kTelephoneEventDuration = 6789;
75 constexpr int kIsacPayloadType = 103;
76 const SdpAudioFormat kIsacFormat = {"isac", 16000, 1};
77 const SdpAudioFormat kOpusFormat = {"opus", 48000, 2};
78 const SdpAudioFormat kG722Format = {"g722", 8000, 1};
79 const AudioCodecSpec kCodecSpecs[] = {
80     {kIsacFormat, {16000, 1, 32000, 10000, 32000}},
81     {kOpusFormat, {48000, 1, 32000, 6000, 510000}},
82     {kG722Format, {16000, 1, 64000}}};
83 
84 // TODO(dklee): This mirrors calculation in audio_send_stream.cc, which
85 // should be made more precise in the future. This can be changed when that
86 // logic is more accurate.
87 const DataSize kOverheadPerPacket = DataSize::Bytes(20 + 8 + 10 + 12);
88 const TimeDelta kMinFrameLength = TimeDelta::Millis(20);
89 const TimeDelta kMaxFrameLength = TimeDelta::Millis(120);
90 const DataRate kMinOverheadRate = kOverheadPerPacket / kMaxFrameLength;
91 const DataRate kMaxOverheadRate = kOverheadPerPacket / kMinFrameLength;
92 
93 class MockLimitObserver : public BitrateAllocator::LimitObserver {
94  public:
95   MOCK_METHOD(void,
96               OnAllocationLimitsChanged,
97               (BitrateAllocationLimits),
98               (override));
99 };
100 
SetupAudioEncoderMock(int payload_type,const SdpAudioFormat & format)101 std::unique_ptr<MockAudioEncoder> SetupAudioEncoderMock(
102     int payload_type,
103     const SdpAudioFormat& format) {
104   for (const auto& spec : kCodecSpecs) {
105     if (format == spec.format) {
106       std::unique_ptr<MockAudioEncoder> encoder(
107           new ::testing::NiceMock<MockAudioEncoder>());
108       ON_CALL(*encoder.get(), SampleRateHz())
109           .WillByDefault(Return(spec.info.sample_rate_hz));
110       ON_CALL(*encoder.get(), NumChannels())
111           .WillByDefault(Return(spec.info.num_channels));
112       ON_CALL(*encoder.get(), RtpTimestampRateHz())
113           .WillByDefault(Return(spec.format.clockrate_hz));
114       ON_CALL(*encoder.get(), GetFrameLengthRange())
115           .WillByDefault(Return(absl::optional<std::pair<TimeDelta, TimeDelta>>{
116               {TimeDelta::Millis(20), TimeDelta::Millis(120)}}));
117       return encoder;
118     }
119   }
120   return nullptr;
121 }
122 
SetupEncoderFactoryMock()123 rtc::scoped_refptr<MockAudioEncoderFactory> SetupEncoderFactoryMock() {
124   rtc::scoped_refptr<MockAudioEncoderFactory> factory =
125       rtc::make_ref_counted<MockAudioEncoderFactory>();
126   ON_CALL(*factory.get(), GetSupportedEncoders())
127       .WillByDefault(Return(std::vector<AudioCodecSpec>(
128           std::begin(kCodecSpecs), std::end(kCodecSpecs))));
129   ON_CALL(*factory.get(), QueryAudioEncoder(_))
130       .WillByDefault(Invoke(
131           [](const SdpAudioFormat& format) -> absl::optional<AudioCodecInfo> {
132             for (const auto& spec : kCodecSpecs) {
133               if (format == spec.format) {
134                 return spec.info;
135               }
136             }
137             return absl::nullopt;
138           }));
139   ON_CALL(*factory.get(), MakeAudioEncoderMock(_, _, _, _))
140       .WillByDefault(Invoke([](int payload_type, const SdpAudioFormat& format,
141                                absl::optional<AudioCodecPairId> codec_pair_id,
142                                std::unique_ptr<AudioEncoder>* return_value) {
143         *return_value = SetupAudioEncoderMock(payload_type, format);
144       }));
145   return factory;
146 }
147 
148 struct ConfigHelper {
ConfigHelperwebrtc::test::__anon417973d70111::ConfigHelper149   ConfigHelper(bool audio_bwe_enabled,
150                bool expect_set_encoder_call,
151                bool use_null_audio_processing)
152       : stream_config_(/*send_transport=*/nullptr),
153         audio_processing_(
154             use_null_audio_processing
155                 ? nullptr
156                 : rtc::make_ref_counted<NiceMock<MockAudioProcessing>>()),
157         bitrate_allocator_(&limit_observer_),
158         worker_queue_(field_trials,
159                       "ConfigHelper_worker_queue",
160                       time_controller_.GetTaskQueueFactory()),
161         audio_encoder_(nullptr) {
162     using ::testing::Invoke;
163 
164     AudioState::Config config;
165     config.audio_mixer = AudioMixerImpl::Create();
166     config.audio_processing = audio_processing_;
167     config.audio_device_module = rtc::make_ref_counted<MockAudioDeviceModule>();
168     audio_state_ = AudioState::Create(config);
169 
170     SetupDefaultChannelSend(audio_bwe_enabled);
171     SetupMockForSetupSendCodec(expect_set_encoder_call);
172     SetupMockForCallEncoder();
173 
174     // Use ISAC as default codec so as to prevent unnecessary `channel_proxy_`
175     // calls from the default ctor behavior.
176     stream_config_.send_codec_spec =
177         AudioSendStream::Config::SendCodecSpec(kIsacPayloadType, kIsacFormat);
178     stream_config_.rtp.ssrc = kSsrc;
179     stream_config_.rtp.c_name = kCName;
180     stream_config_.rtp.extensions.push_back(
181         RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
182     if (audio_bwe_enabled) {
183       AddBweToConfig(&stream_config_);
184     }
185     stream_config_.encoder_factory = SetupEncoderFactoryMock();
186     stream_config_.min_bitrate_bps = 10000;
187     stream_config_.max_bitrate_bps = 65000;
188   }
189 
CreateAudioSendStreamwebrtc::test::__anon417973d70111::ConfigHelper190   std::unique_ptr<internal::AudioSendStream> CreateAudioSendStream() {
191     EXPECT_CALL(rtp_transport_, GetWorkerQueue())
192         .WillRepeatedly(Return(&worker_queue_));
193     return std::unique_ptr<internal::AudioSendStream>(
194         new internal::AudioSendStream(
195             time_controller_.GetClock(), stream_config_, audio_state_,
196             time_controller_.GetTaskQueueFactory(), &rtp_transport_,
197             &bitrate_allocator_, &event_log_, absl::nullopt,
198             std::unique_ptr<voe::ChannelSendInterface>(channel_send_),
199             field_trials));
200   }
201 
configwebrtc::test::__anon417973d70111::ConfigHelper202   AudioSendStream::Config& config() { return stream_config_; }
mock_encoder_factorywebrtc::test::__anon417973d70111::ConfigHelper203   MockAudioEncoderFactory& mock_encoder_factory() {
204     return *static_cast<MockAudioEncoderFactory*>(
205         stream_config_.encoder_factory.get());
206   }
rtp_rtcpwebrtc::test::__anon417973d70111::ConfigHelper207   MockRtpRtcpInterface* rtp_rtcp() { return &rtp_rtcp_; }
channel_sendwebrtc::test::__anon417973d70111::ConfigHelper208   MockChannelSend* channel_send() { return channel_send_; }
transportwebrtc::test::__anon417973d70111::ConfigHelper209   RtpTransportControllerSendInterface* transport() { return &rtp_transport_; }
210 
AddBweToConfigwebrtc::test::__anon417973d70111::ConfigHelper211   static void AddBweToConfig(AudioSendStream::Config* config) {
212     config->rtp.extensions.push_back(RtpExtension(
213         RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
214     config->send_codec_spec->transport_cc_enabled = true;
215   }
216 
SetupDefaultChannelSendwebrtc::test::__anon417973d70111::ConfigHelper217   void SetupDefaultChannelSend(bool audio_bwe_enabled) {
218     EXPECT_TRUE(channel_send_ == nullptr);
219     channel_send_ = new ::testing::StrictMock<MockChannelSend>();
220     EXPECT_CALL(*channel_send_, GetRtpRtcp()).WillRepeatedly(Invoke([this]() {
221       return &this->rtp_rtcp_;
222     }));
223     EXPECT_CALL(rtp_rtcp_, SSRC).WillRepeatedly(Return(kSsrc));
224     EXPECT_CALL(*channel_send_, SetRTCP_CNAME(StrEq(kCName))).Times(1);
225     EXPECT_CALL(*channel_send_, SetFrameEncryptor(_)).Times(1);
226     EXPECT_CALL(*channel_send_, SetEncoderToPacketizerFrameTransformer(_))
227         .Times(1);
228     EXPECT_CALL(rtp_rtcp_, SetExtmapAllowMixed(false)).Times(1);
229     EXPECT_CALL(*channel_send_,
230                 SetSendAudioLevelIndicationStatus(true, kAudioLevelId))
231         .Times(1);
232     EXPECT_CALL(rtp_transport_, GetBandwidthObserver())
233         .WillRepeatedly(Return(&bandwidth_observer_));
234     if (audio_bwe_enabled) {
235       EXPECT_CALL(rtp_rtcp_,
236                   RegisterRtpHeaderExtension(TransportSequenceNumber::Uri(),
237                                              kTransportSequenceNumberId))
238           .Times(1);
239       EXPECT_CALL(*channel_send_,
240                   RegisterSenderCongestionControlObjects(
241                       &rtp_transport_, Eq(&bandwidth_observer_)))
242           .Times(1);
243     } else {
244       EXPECT_CALL(*channel_send_, RegisterSenderCongestionControlObjects(
245                                       &rtp_transport_, Eq(nullptr)))
246           .Times(1);
247     }
248     EXPECT_CALL(*channel_send_, ResetSenderCongestionControlObjects()).Times(1);
249   }
250 
SetupMockForSetupSendCodecwebrtc::test::__anon417973d70111::ConfigHelper251   void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
252     if (expect_set_encoder_call) {
253       EXPECT_CALL(*channel_send_, SetEncoder)
254           .WillOnce(
255               [this](int payload_type, std::unique_ptr<AudioEncoder> encoder) {
256                 this->audio_encoder_ = std::move(encoder);
257                 return true;
258               });
259     }
260   }
261 
SetupMockForCallEncoderwebrtc::test::__anon417973d70111::ConfigHelper262   void SetupMockForCallEncoder() {
263     // Let ModifyEncoder to invoke mock audio encoder.
264     EXPECT_CALL(*channel_send_, CallEncoder(_))
265         .WillRepeatedly(
266             [this](rtc::FunctionView<void(AudioEncoder*)> modifier) {
267               if (this->audio_encoder_)
268                 modifier(this->audio_encoder_.get());
269             });
270   }
271 
SetupMockForSendTelephoneEventwebrtc::test::__anon417973d70111::ConfigHelper272   void SetupMockForSendTelephoneEvent() {
273     EXPECT_TRUE(channel_send_);
274     EXPECT_CALL(*channel_send_, SetSendTelephoneEventPayloadType(
275                                     kTelephoneEventPayloadType,
276                                     kTelephoneEventPayloadFrequency));
277     EXPECT_CALL(
278         *channel_send_,
279         SendTelephoneEventOutband(kTelephoneEventCode, kTelephoneEventDuration))
280         .WillOnce(Return(true));
281   }
282 
SetupMockForGetStatswebrtc::test::__anon417973d70111::ConfigHelper283   void SetupMockForGetStats(bool use_null_audio_processing) {
284     using ::testing::DoAll;
285     using ::testing::SetArgPointee;
286     using ::testing::SetArgReferee;
287 
288     std::vector<ReportBlock> report_blocks;
289     webrtc::ReportBlock block = kReportBlock;
290     report_blocks.push_back(block);  // Has wrong SSRC.
291     block.source_SSRC = kSsrc;
292     report_blocks.push_back(block);  // Correct block.
293     block.fraction_lost = 0;
294     report_blocks.push_back(block);  // Duplicate SSRC, bad fraction_lost.
295 
296     EXPECT_TRUE(channel_send_);
297     EXPECT_CALL(*channel_send_, GetRTCPStatistics())
298         .WillRepeatedly(Return(kCallStats));
299     EXPECT_CALL(*channel_send_, GetRemoteRTCPReportBlocks())
300         .WillRepeatedly(Return(report_blocks));
301     EXPECT_CALL(*channel_send_, GetANAStatistics())
302         .WillRepeatedly(Return(ANAStats()));
303     EXPECT_CALL(*channel_send_, GetTargetBitrate()).WillRepeatedly(Return(0));
304 
305     audio_processing_stats_.echo_return_loss = kEchoReturnLoss;
306     audio_processing_stats_.echo_return_loss_enhancement =
307         kEchoReturnLossEnhancement;
308     audio_processing_stats_.delay_median_ms = kEchoDelayMedian;
309     audio_processing_stats_.delay_standard_deviation_ms = kEchoDelayStdDev;
310     audio_processing_stats_.divergent_filter_fraction =
311         kDivergentFilterFraction;
312     audio_processing_stats_.residual_echo_likelihood = kResidualEchoLikelihood;
313     audio_processing_stats_.residual_echo_likelihood_recent_max =
314         kResidualEchoLikelihoodMax;
315     if (!use_null_audio_processing) {
316       ASSERT_TRUE(audio_processing_);
317       EXPECT_CALL(*audio_processing_, GetStatistics(true))
318           .WillRepeatedly(Return(audio_processing_stats_));
319     }
320   }
321 
workerwebrtc::test::__anon417973d70111::ConfigHelper322   MaybeWorkerThread* worker() { return &worker_queue_; }
323 
324   test::ScopedKeyValueConfig field_trials;
325 
326  private:
327   RealTimeController time_controller_;
328   rtc::scoped_refptr<AudioState> audio_state_;
329   AudioSendStream::Config stream_config_;
330   ::testing::StrictMock<MockChannelSend>* channel_send_ = nullptr;
331   rtc::scoped_refptr<MockAudioProcessing> audio_processing_;
332   AudioProcessingStats audio_processing_stats_;
333   ::testing::StrictMock<MockRtcpBandwidthObserver> bandwidth_observer_;
334   ::testing::NiceMock<MockRtcEventLog> event_log_;
335   ::testing::NiceMock<MockRtpTransportControllerSend> rtp_transport_;
336   ::testing::NiceMock<MockRtpRtcpInterface> rtp_rtcp_;
337   ::testing::NiceMock<MockLimitObserver> limit_observer_;
338   BitrateAllocator bitrate_allocator_;
339   // `worker_queue` is defined last to ensure all pending tasks are cancelled
340   // and deleted before any other members.
341   MaybeWorkerThread worker_queue_;
342   std::unique_ptr<AudioEncoder> audio_encoder_;
343 };
344 
345 // The audio level ranges linearly [0,32767].
CreateAudioFrame1kHzSineWave(int16_t audio_level,int duration_ms,int sample_rate_hz,size_t num_channels)346 std::unique_ptr<AudioFrame> CreateAudioFrame1kHzSineWave(int16_t audio_level,
347                                                          int duration_ms,
348                                                          int sample_rate_hz,
349                                                          size_t num_channels) {
350   size_t samples_per_channel = sample_rate_hz / (1000 / duration_ms);
351   std::vector<int16_t> audio_data(samples_per_channel * num_channels, 0);
352   std::unique_ptr<AudioFrame> audio_frame = std::make_unique<AudioFrame>();
353   audio_frame->UpdateFrame(0 /* RTP timestamp */, &audio_data[0],
354                            samples_per_channel, sample_rate_hz,
355                            AudioFrame::SpeechType::kNormalSpeech,
356                            AudioFrame::VADActivity::kVadUnknown, num_channels);
357   SineWaveGenerator wave_generator(1000.0, audio_level);
358   wave_generator.GenerateNextFrame(audio_frame.get());
359   return audio_frame;
360 }
361 
362 }  // namespace
363 
TEST(AudioSendStreamTest,ConfigToString)364 TEST(AudioSendStreamTest, ConfigToString) {
365   AudioSendStream::Config config(/*send_transport=*/nullptr);
366   config.rtp.ssrc = kSsrc;
367   config.rtp.c_name = kCName;
368   config.min_bitrate_bps = 12000;
369   config.max_bitrate_bps = 34000;
370   config.has_dscp = true;
371   config.send_codec_spec =
372       AudioSendStream::Config::SendCodecSpec(kIsacPayloadType, kIsacFormat);
373   config.send_codec_spec->nack_enabled = true;
374   config.send_codec_spec->transport_cc_enabled = false;
375   config.send_codec_spec->cng_payload_type = 42;
376   config.send_codec_spec->red_payload_type = 43;
377   config.encoder_factory = MockAudioEncoderFactory::CreateUnusedFactory();
378   config.rtp.extmap_allow_mixed = true;
379   config.rtp.extensions.push_back(
380       RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
381   config.rtcp_report_interval_ms = 2500;
382   EXPECT_EQ(
383       "{rtp: {ssrc: 1234, extmap-allow-mixed: true, extensions: [{uri: "
384       "urn:ietf:params:rtp-hdrext:ssrc-audio-level, id: 2}], "
385       "c_name: foo_name}, rtcp_report_interval_ms: 2500, "
386       "send_transport: null, "
387       "min_bitrate_bps: 12000, max_bitrate_bps: 34000, has "
388       "audio_network_adaptor_config: false, has_dscp: true, "
389       "send_codec_spec: {nack_enabled: true, transport_cc_enabled: false, "
390       "enable_non_sender_rtt: false, cng_payload_type: 42, "
391       "red_payload_type: 43, payload_type: 103, "
392       "format: {name: isac, clockrate_hz: 16000, num_channels: 1, "
393       "parameters: {}}}}",
394       config.ToString());
395 }
396 
TEST(AudioSendStreamTest,ConstructDestruct)397 TEST(AudioSendStreamTest, ConstructDestruct) {
398   for (bool use_null_audio_processing : {false, true}) {
399     ConfigHelper helper(false, true, use_null_audio_processing);
400     auto send_stream = helper.CreateAudioSendStream();
401   }
402 }
403 
TEST(AudioSendStreamTest,SendTelephoneEvent)404 TEST(AudioSendStreamTest, SendTelephoneEvent) {
405   for (bool use_null_audio_processing : {false, true}) {
406     ConfigHelper helper(false, true, use_null_audio_processing);
407     auto send_stream = helper.CreateAudioSendStream();
408     helper.SetupMockForSendTelephoneEvent();
409     EXPECT_TRUE(send_stream->SendTelephoneEvent(
410         kTelephoneEventPayloadType, kTelephoneEventPayloadFrequency,
411         kTelephoneEventCode, kTelephoneEventDuration));
412   }
413 }
414 
TEST(AudioSendStreamTest,SetMuted)415 TEST(AudioSendStreamTest, SetMuted) {
416   for (bool use_null_audio_processing : {false, true}) {
417     ConfigHelper helper(false, true, use_null_audio_processing);
418     auto send_stream = helper.CreateAudioSendStream();
419     EXPECT_CALL(*helper.channel_send(), SetInputMute(true));
420     send_stream->SetMuted(true);
421   }
422 }
423 
TEST(AudioSendStreamTest,AudioBweCorrectObjectsOnChannelProxy)424 TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
425   for (bool use_null_audio_processing : {false, true}) {
426     ConfigHelper helper(true, true, use_null_audio_processing);
427     auto send_stream = helper.CreateAudioSendStream();
428   }
429 }
430 
TEST(AudioSendStreamTest,NoAudioBweCorrectObjectsOnChannelProxy)431 TEST(AudioSendStreamTest, NoAudioBweCorrectObjectsOnChannelProxy) {
432   for (bool use_null_audio_processing : {false, true}) {
433     ConfigHelper helper(false, true, use_null_audio_processing);
434     auto send_stream = helper.CreateAudioSendStream();
435   }
436 }
437 
TEST(AudioSendStreamTest,GetStats)438 TEST(AudioSendStreamTest, GetStats) {
439   for (bool use_null_audio_processing : {false, true}) {
440     ConfigHelper helper(false, true, use_null_audio_processing);
441     auto send_stream = helper.CreateAudioSendStream();
442     helper.SetupMockForGetStats(use_null_audio_processing);
443     AudioSendStream::Stats stats = send_stream->GetStats(true);
444     EXPECT_EQ(kSsrc, stats.local_ssrc);
445     EXPECT_EQ(kCallStats.payload_bytes_sent, stats.payload_bytes_sent);
446     EXPECT_EQ(kCallStats.header_and_padding_bytes_sent,
447               stats.header_and_padding_bytes_sent);
448     EXPECT_EQ(kCallStats.packetsSent, stats.packets_sent);
449     EXPECT_EQ(kReportBlock.cumulative_num_packets_lost, stats.packets_lost);
450     EXPECT_EQ(Q8ToFloat(kReportBlock.fraction_lost), stats.fraction_lost);
451     EXPECT_EQ(kIsacFormat.name, stats.codec_name);
452     EXPECT_EQ(static_cast<int32_t>(kReportBlock.interarrival_jitter /
453                                    (kIsacFormat.clockrate_hz / 1000)),
454               stats.jitter_ms);
455     EXPECT_EQ(kCallStats.rttMs, stats.rtt_ms);
456     EXPECT_EQ(0, stats.audio_level);
457     EXPECT_EQ(0, stats.total_input_energy);
458     EXPECT_EQ(0, stats.total_input_duration);
459 
460     if (!use_null_audio_processing) {
461       EXPECT_EQ(kEchoDelayMedian, stats.apm_statistics.delay_median_ms);
462       EXPECT_EQ(kEchoDelayStdDev,
463                 stats.apm_statistics.delay_standard_deviation_ms);
464       EXPECT_EQ(kEchoReturnLoss, stats.apm_statistics.echo_return_loss);
465       EXPECT_EQ(kEchoReturnLossEnhancement,
466                 stats.apm_statistics.echo_return_loss_enhancement);
467       EXPECT_EQ(kDivergentFilterFraction,
468                 stats.apm_statistics.divergent_filter_fraction);
469       EXPECT_EQ(kResidualEchoLikelihood,
470                 stats.apm_statistics.residual_echo_likelihood);
471       EXPECT_EQ(kResidualEchoLikelihoodMax,
472                 stats.apm_statistics.residual_echo_likelihood_recent_max);
473     }
474   }
475 }
476 
TEST(AudioSendStreamTest,GetStatsAudioLevel)477 TEST(AudioSendStreamTest, GetStatsAudioLevel) {
478   for (bool use_null_audio_processing : {false, true}) {
479     ConfigHelper helper(false, true, use_null_audio_processing);
480     auto send_stream = helper.CreateAudioSendStream();
481     helper.SetupMockForGetStats(use_null_audio_processing);
482     EXPECT_CALL(*helper.channel_send(), ProcessAndEncodeAudio)
483         .Times(AnyNumber());
484 
485     constexpr int kSampleRateHz = 48000;
486     constexpr size_t kNumChannels = 1;
487 
488     constexpr int16_t kSilentAudioLevel = 0;
489     constexpr int16_t kMaxAudioLevel = 32767;  // Audio level is [0,32767].
490     constexpr int kAudioFrameDurationMs = 10;
491 
492     // Process 10 audio frames (100 ms) of silence. After this, on the next
493     // (11-th) frame, the audio level will be updated with the maximum audio
494     // level of the first 11 frames. See AudioLevel.
495     for (size_t i = 0; i < 10; ++i) {
496       send_stream->SendAudioData(
497           CreateAudioFrame1kHzSineWave(kSilentAudioLevel, kAudioFrameDurationMs,
498                                        kSampleRateHz, kNumChannels));
499     }
500     AudioSendStream::Stats stats = send_stream->GetStats();
501     EXPECT_EQ(kSilentAudioLevel, stats.audio_level);
502     EXPECT_NEAR(0.0f, stats.total_input_energy, kTolerance);
503     EXPECT_NEAR(0.1f, stats.total_input_duration,
504                 kTolerance);  // 100 ms = 0.1 s
505 
506     // Process 10 audio frames (100 ms) of maximum audio level.
507     // Note that AudioLevel updates the audio level every 11th frame, processing
508     // 10 frames above was needed to see a non-zero audio level here.
509     for (size_t i = 0; i < 10; ++i) {
510       send_stream->SendAudioData(CreateAudioFrame1kHzSineWave(
511           kMaxAudioLevel, kAudioFrameDurationMs, kSampleRateHz, kNumChannels));
512     }
513     stats = send_stream->GetStats();
514     EXPECT_EQ(kMaxAudioLevel, stats.audio_level);
515     // Energy increases by energy*duration, where energy is audio level in
516     // [0,1].
517     EXPECT_NEAR(0.1f, stats.total_input_energy, kTolerance);  // 0.1 s of max
518     EXPECT_NEAR(0.2f, stats.total_input_duration,
519                 kTolerance);  // 200 ms = 0.2 s
520   }
521 }
522 
TEST(AudioSendStreamTest,SendCodecAppliesAudioNetworkAdaptor)523 TEST(AudioSendStreamTest, SendCodecAppliesAudioNetworkAdaptor) {
524   for (bool use_null_audio_processing : {false, true}) {
525     ConfigHelper helper(true, true, use_null_audio_processing);
526     helper.config().send_codec_spec =
527         AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
528     const std::string kAnaConfigString = "abcde";
529     const std::string kAnaReconfigString = "12345";
530 
531     helper.config().audio_network_adaptor_config = kAnaConfigString;
532 
533     EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
534         .WillOnce(Invoke([&kAnaConfigString, &kAnaReconfigString](
535                              int payload_type, const SdpAudioFormat& format,
536                              absl::optional<AudioCodecPairId> codec_pair_id,
537                              std::unique_ptr<AudioEncoder>* return_value) {
538           auto mock_encoder = SetupAudioEncoderMock(payload_type, format);
539           EXPECT_CALL(*mock_encoder,
540                       EnableAudioNetworkAdaptor(StrEq(kAnaConfigString), _))
541               .WillOnce(Return(true));
542           EXPECT_CALL(*mock_encoder,
543                       EnableAudioNetworkAdaptor(StrEq(kAnaReconfigString), _))
544               .WillOnce(Return(true));
545           *return_value = std::move(mock_encoder);
546         }));
547 
548     auto send_stream = helper.CreateAudioSendStream();
549 
550     auto stream_config = helper.config();
551     stream_config.audio_network_adaptor_config = kAnaReconfigString;
552 
553     send_stream->Reconfigure(stream_config, nullptr);
554   }
555 }
556 
TEST(AudioSendStreamTest,AudioNetworkAdaptorReceivesOverhead)557 TEST(AudioSendStreamTest, AudioNetworkAdaptorReceivesOverhead) {
558   for (bool use_null_audio_processing : {false, true}) {
559     ConfigHelper helper(true, true, use_null_audio_processing);
560     helper.config().send_codec_spec =
561         AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
562     const std::string kAnaConfigString = "abcde";
563 
564     EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
565         .WillOnce(Invoke(
566             [&kAnaConfigString](int payload_type, const SdpAudioFormat& format,
567                                 absl::optional<AudioCodecPairId> codec_pair_id,
568                                 std::unique_ptr<AudioEncoder>* return_value) {
569               auto mock_encoder = SetupAudioEncoderMock(payload_type, format);
570               InSequence s;
571               EXPECT_CALL(
572                   *mock_encoder,
573                   OnReceivedOverhead(Eq(kOverheadPerPacket.bytes<size_t>())))
574                   .Times(2);
575               EXPECT_CALL(*mock_encoder,
576                           EnableAudioNetworkAdaptor(StrEq(kAnaConfigString), _))
577                   .WillOnce(Return(true));
578               // Note: Overhead is received AFTER ANA has been enabled.
579               EXPECT_CALL(
580                   *mock_encoder,
581                   OnReceivedOverhead(Eq(kOverheadPerPacket.bytes<size_t>())))
582                   .WillOnce(Return());
583               *return_value = std::move(mock_encoder);
584             }));
585     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
586         .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
587 
588     auto send_stream = helper.CreateAudioSendStream();
589 
590     auto stream_config = helper.config();
591     stream_config.audio_network_adaptor_config = kAnaConfigString;
592 
593     send_stream->Reconfigure(stream_config, nullptr);
594   }
595 }
596 
597 // VAD is applied when codec is mono and the CNG frequency matches the codec
598 // clock rate.
TEST(AudioSendStreamTest,SendCodecCanApplyVad)599 TEST(AudioSendStreamTest, SendCodecCanApplyVad) {
600   for (bool use_null_audio_processing : {false, true}) {
601     ConfigHelper helper(false, false, use_null_audio_processing);
602     helper.config().send_codec_spec =
603         AudioSendStream::Config::SendCodecSpec(9, kG722Format);
604     helper.config().send_codec_spec->cng_payload_type = 105;
605     std::unique_ptr<AudioEncoder> stolen_encoder;
606     EXPECT_CALL(*helper.channel_send(), SetEncoder)
607         .WillOnce([&stolen_encoder](int payload_type,
608                                     std::unique_ptr<AudioEncoder> encoder) {
609           stolen_encoder = std::move(encoder);
610           return true;
611         });
612     EXPECT_CALL(*helper.channel_send(), RegisterCngPayloadType(105, 8000));
613 
614     auto send_stream = helper.CreateAudioSendStream();
615 
616     // We cannot truly determine if the encoder created is an AudioEncoderCng.
617     // It is the only reasonable implementation that will return something from
618     // ReclaimContainedEncoders, though.
619     ASSERT_TRUE(stolen_encoder);
620     EXPECT_FALSE(stolen_encoder->ReclaimContainedEncoders().empty());
621   }
622 }
623 
TEST(AudioSendStreamTest,DoesNotPassHigherBitrateThanMaxBitrate)624 TEST(AudioSendStreamTest, DoesNotPassHigherBitrateThanMaxBitrate) {
625   for (bool use_null_audio_processing : {false, true}) {
626     ConfigHelper helper(false, true, use_null_audio_processing);
627     auto send_stream = helper.CreateAudioSendStream();
628     EXPECT_CALL(
629         *helper.channel_send(),
630         OnBitrateAllocation(
631             Field(&BitrateAllocationUpdate::target_bitrate,
632                   Eq(DataRate::BitsPerSec(helper.config().max_bitrate_bps)))));
633     BitrateAllocationUpdate update;
634     update.target_bitrate =
635         DataRate::BitsPerSec(helper.config().max_bitrate_bps + 5000);
636     update.packet_loss_ratio = 0;
637     update.round_trip_time = TimeDelta::Millis(50);
638     update.bwe_period = TimeDelta::Millis(6000);
639     helper.worker()->RunSynchronous(
640         [&] { send_stream->OnBitrateUpdated(update); });
641   }
642 }
643 
TEST(AudioSendStreamTest,SSBweTargetInRangeRespected)644 TEST(AudioSendStreamTest, SSBweTargetInRangeRespected) {
645   for (bool use_null_audio_processing : {false, true}) {
646     ConfigHelper helper(true, true, use_null_audio_processing);
647     auto send_stream = helper.CreateAudioSendStream();
648     EXPECT_CALL(
649         *helper.channel_send(),
650         OnBitrateAllocation(Field(
651             &BitrateAllocationUpdate::target_bitrate,
652             Eq(DataRate::BitsPerSec(helper.config().max_bitrate_bps - 5000)))));
653     BitrateAllocationUpdate update;
654     update.target_bitrate =
655         DataRate::BitsPerSec(helper.config().max_bitrate_bps - 5000);
656     helper.worker()->RunSynchronous(
657         [&] { send_stream->OnBitrateUpdated(update); });
658   }
659 }
660 
TEST(AudioSendStreamTest,SSBweFieldTrialMinRespected)661 TEST(AudioSendStreamTest, SSBweFieldTrialMinRespected) {
662   for (bool use_null_audio_processing : {false, true}) {
663     ConfigHelper helper(true, true, use_null_audio_processing);
664     ScopedKeyValueConfig field_trials(
665         helper.field_trials, "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
666     auto send_stream = helper.CreateAudioSendStream();
667     EXPECT_CALL(
668         *helper.channel_send(),
669         OnBitrateAllocation(Field(&BitrateAllocationUpdate::target_bitrate,
670                                   Eq(DataRate::KilobitsPerSec(6)))));
671     BitrateAllocationUpdate update;
672     update.target_bitrate = DataRate::KilobitsPerSec(1);
673     helper.worker()->RunSynchronous(
674         [&] { send_stream->OnBitrateUpdated(update); });
675   }
676 }
677 
TEST(AudioSendStreamTest,SSBweFieldTrialMaxRespected)678 TEST(AudioSendStreamTest, SSBweFieldTrialMaxRespected) {
679   for (bool use_null_audio_processing : {false, true}) {
680     ConfigHelper helper(true, true, use_null_audio_processing);
681     ScopedKeyValueConfig field_trials(
682         helper.field_trials, "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
683     auto send_stream = helper.CreateAudioSendStream();
684     EXPECT_CALL(
685         *helper.channel_send(),
686         OnBitrateAllocation(Field(&BitrateAllocationUpdate::target_bitrate,
687                                   Eq(DataRate::KilobitsPerSec(64)))));
688     BitrateAllocationUpdate update;
689     update.target_bitrate = DataRate::KilobitsPerSec(128);
690     helper.worker()->RunSynchronous(
691         [&] { send_stream->OnBitrateUpdated(update); });
692   }
693 }
694 
TEST(AudioSendStreamTest,SSBweWithOverhead)695 TEST(AudioSendStreamTest, SSBweWithOverhead) {
696   for (bool use_null_audio_processing : {false, true}) {
697     ConfigHelper helper(true, true, use_null_audio_processing);
698     ScopedKeyValueConfig field_trials(helper.field_trials,
699                                       "WebRTC-Audio-LegacyOverhead/Disabled/");
700     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
701         .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
702     auto send_stream = helper.CreateAudioSendStream();
703     const DataRate bitrate =
704         DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
705         kMaxOverheadRate;
706     EXPECT_CALL(*helper.channel_send(),
707                 OnBitrateAllocation(Field(
708                     &BitrateAllocationUpdate::target_bitrate, Eq(bitrate))));
709     BitrateAllocationUpdate update;
710     update.target_bitrate = bitrate;
711     helper.worker()->RunSynchronous(
712         [&] { send_stream->OnBitrateUpdated(update); });
713   }
714 }
715 
TEST(AudioSendStreamTest,SSBweWithOverheadMinRespected)716 TEST(AudioSendStreamTest, SSBweWithOverheadMinRespected) {
717   for (bool use_null_audio_processing : {false, true}) {
718     ConfigHelper helper(true, true, use_null_audio_processing);
719     ScopedKeyValueConfig field_trials(
720         helper.field_trials,
721         "WebRTC-Audio-LegacyOverhead/Disabled/"
722         "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
723     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
724         .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
725     auto send_stream = helper.CreateAudioSendStream();
726     const DataRate bitrate = DataRate::KilobitsPerSec(6) + kMinOverheadRate;
727     EXPECT_CALL(*helper.channel_send(),
728                 OnBitrateAllocation(Field(
729                     &BitrateAllocationUpdate::target_bitrate, Eq(bitrate))));
730     BitrateAllocationUpdate update;
731     update.target_bitrate = DataRate::KilobitsPerSec(1);
732     helper.worker()->RunSynchronous(
733         [&] { send_stream->OnBitrateUpdated(update); });
734   }
735 }
736 
TEST(AudioSendStreamTest,SSBweWithOverheadMaxRespected)737 TEST(AudioSendStreamTest, SSBweWithOverheadMaxRespected) {
738   for (bool use_null_audio_processing : {false, true}) {
739     ConfigHelper helper(true, true, use_null_audio_processing);
740     ScopedKeyValueConfig field_trials(
741         helper.field_trials,
742         "WebRTC-Audio-LegacyOverhead/Disabled/"
743         "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
744     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
745         .WillRepeatedly(Return(kOverheadPerPacket.bytes<size_t>()));
746     auto send_stream = helper.CreateAudioSendStream();
747     const DataRate bitrate = DataRate::KilobitsPerSec(64) + kMaxOverheadRate;
748     EXPECT_CALL(*helper.channel_send(),
749                 OnBitrateAllocation(Field(
750                     &BitrateAllocationUpdate::target_bitrate, Eq(bitrate))));
751     BitrateAllocationUpdate update;
752     update.target_bitrate = DataRate::KilobitsPerSec(128);
753     helper.worker()->RunSynchronous(
754         [&] { send_stream->OnBitrateUpdated(update); });
755   }
756 }
757 
TEST(AudioSendStreamTest,ProbingIntervalOnBitrateUpdated)758 TEST(AudioSendStreamTest, ProbingIntervalOnBitrateUpdated) {
759   for (bool use_null_audio_processing : {false, true}) {
760     ConfigHelper helper(false, true, use_null_audio_processing);
761     auto send_stream = helper.CreateAudioSendStream();
762 
763     EXPECT_CALL(*helper.channel_send(),
764                 OnBitrateAllocation(Field(&BitrateAllocationUpdate::bwe_period,
765                                           Eq(TimeDelta::Millis(5000)))));
766     BitrateAllocationUpdate update;
767     update.target_bitrate =
768         DataRate::BitsPerSec(helper.config().max_bitrate_bps + 5000);
769     update.packet_loss_ratio = 0;
770     update.round_trip_time = TimeDelta::Millis(50);
771     update.bwe_period = TimeDelta::Millis(5000);
772     helper.worker()->RunSynchronous(
773         [&] { send_stream->OnBitrateUpdated(update); });
774   }
775 }
776 
777 // Test that AudioSendStream doesn't recreate the encoder unnecessarily.
TEST(AudioSendStreamTest,DontRecreateEncoder)778 TEST(AudioSendStreamTest, DontRecreateEncoder) {
779   for (bool use_null_audio_processing : {false, true}) {
780     ConfigHelper helper(false, false, use_null_audio_processing);
781     // WillOnce is (currently) the default used by ConfigHelper if asked to set
782     // an expectation for SetEncoder. Since this behavior is essential for this
783     // test to be correct, it's instead set-up manually here. Otherwise a simple
784     // change to ConfigHelper (say to WillRepeatedly) would silently make this
785     // test useless.
786     EXPECT_CALL(*helper.channel_send(), SetEncoder).WillOnce(Return());
787 
788     EXPECT_CALL(*helper.channel_send(), RegisterCngPayloadType(105, 8000));
789 
790     helper.config().send_codec_spec =
791         AudioSendStream::Config::SendCodecSpec(9, kG722Format);
792     helper.config().send_codec_spec->cng_payload_type = 105;
793     auto send_stream = helper.CreateAudioSendStream();
794     send_stream->Reconfigure(helper.config(), nullptr);
795   }
796 }
797 
TEST(AudioSendStreamTest,ReconfigureTransportCcResetsFirst)798 TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
799   for (bool use_null_audio_processing : {false, true}) {
800     ConfigHelper helper(false, true, use_null_audio_processing);
801     auto send_stream = helper.CreateAudioSendStream();
802     auto new_config = helper.config();
803     ConfigHelper::AddBweToConfig(&new_config);
804 
805     EXPECT_CALL(*helper.rtp_rtcp(),
806                 RegisterRtpHeaderExtension(TransportSequenceNumber::Uri(),
807                                            kTransportSequenceNumberId))
808         .Times(1);
809     {
810       ::testing::InSequence seq;
811       EXPECT_CALL(*helper.channel_send(), ResetSenderCongestionControlObjects())
812           .Times(1);
813       EXPECT_CALL(*helper.channel_send(),
814                   RegisterSenderCongestionControlObjects(helper.transport(),
815                                                          Ne(nullptr)))
816           .Times(1);
817     }
818 
819     send_stream->Reconfigure(new_config, nullptr);
820   }
821 }
822 
TEST(AudioSendStreamTest,OnTransportOverheadChanged)823 TEST(AudioSendStreamTest, OnTransportOverheadChanged) {
824   for (bool use_null_audio_processing : {false, true}) {
825     ConfigHelper helper(false, true, use_null_audio_processing);
826     auto send_stream = helper.CreateAudioSendStream();
827     auto new_config = helper.config();
828 
829     // CallEncoder will be called on overhead change.
830     EXPECT_CALL(*helper.channel_send(), CallEncoder);
831 
832     const size_t transport_overhead_per_packet_bytes = 333;
833     send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
834 
835     EXPECT_EQ(transport_overhead_per_packet_bytes,
836               send_stream->TestOnlyGetPerPacketOverheadBytes());
837   }
838 }
839 
TEST(AudioSendStreamTest,DoesntCallEncoderWhenOverheadUnchanged)840 TEST(AudioSendStreamTest, DoesntCallEncoderWhenOverheadUnchanged) {
841   for (bool use_null_audio_processing : {false, true}) {
842     ConfigHelper helper(false, true, use_null_audio_processing);
843     auto send_stream = helper.CreateAudioSendStream();
844     auto new_config = helper.config();
845 
846     // CallEncoder will be called on overhead change.
847     EXPECT_CALL(*helper.channel_send(), CallEncoder);
848     const size_t transport_overhead_per_packet_bytes = 333;
849     send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
850 
851     // Set the same overhead again, CallEncoder should not be called again.
852     EXPECT_CALL(*helper.channel_send(), CallEncoder).Times(0);
853     send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
854 
855     // New overhead, call CallEncoder again
856     EXPECT_CALL(*helper.channel_send(), CallEncoder);
857     send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes + 1);
858   }
859 }
860 
TEST(AudioSendStreamTest,AudioOverheadChanged)861 TEST(AudioSendStreamTest, AudioOverheadChanged) {
862   for (bool use_null_audio_processing : {false, true}) {
863     ConfigHelper helper(false, true, use_null_audio_processing);
864     const size_t audio_overhead_per_packet_bytes = 555;
865     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
866         .WillRepeatedly(Return(audio_overhead_per_packet_bytes));
867     auto send_stream = helper.CreateAudioSendStream();
868     auto new_config = helper.config();
869 
870     BitrateAllocationUpdate update;
871     update.target_bitrate =
872         DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
873         kMaxOverheadRate;
874     EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
875     helper.worker()->RunSynchronous(
876         [&] { send_stream->OnBitrateUpdated(update); });
877 
878     EXPECT_EQ(audio_overhead_per_packet_bytes,
879               send_stream->TestOnlyGetPerPacketOverheadBytes());
880 
881     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
882         .WillRepeatedly(Return(audio_overhead_per_packet_bytes + 20));
883     EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
884     helper.worker()->RunSynchronous(
885         [&] { send_stream->OnBitrateUpdated(update); });
886 
887     EXPECT_EQ(audio_overhead_per_packet_bytes + 20,
888               send_stream->TestOnlyGetPerPacketOverheadBytes());
889   }
890 }
891 
TEST(AudioSendStreamTest,OnAudioAndTransportOverheadChanged)892 TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
893   for (bool use_null_audio_processing : {false, true}) {
894     ConfigHelper helper(false, true, use_null_audio_processing);
895     const size_t audio_overhead_per_packet_bytes = 555;
896     EXPECT_CALL(*helper.rtp_rtcp(), ExpectedPerPacketOverhead)
897         .WillRepeatedly(Return(audio_overhead_per_packet_bytes));
898     auto send_stream = helper.CreateAudioSendStream();
899     auto new_config = helper.config();
900 
901     const size_t transport_overhead_per_packet_bytes = 333;
902     send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
903 
904     BitrateAllocationUpdate update;
905     update.target_bitrate =
906         DataRate::BitsPerSec(helper.config().max_bitrate_bps) +
907         kMaxOverheadRate;
908     EXPECT_CALL(*helper.channel_send(), OnBitrateAllocation);
909     helper.worker()->RunSynchronous(
910         [&] { send_stream->OnBitrateUpdated(update); });
911 
912     EXPECT_EQ(
913         transport_overhead_per_packet_bytes + audio_overhead_per_packet_bytes,
914         send_stream->TestOnlyGetPerPacketOverheadBytes());
915   }
916 }
917 
918 // Validates that reconfiguring the AudioSendStream with a Frame encryptor
919 // correctly reconfigures on the object without crashing.
TEST(AudioSendStreamTest,ReconfigureWithFrameEncryptor)920 TEST(AudioSendStreamTest, ReconfigureWithFrameEncryptor) {
921   for (bool use_null_audio_processing : {false, true}) {
922     ConfigHelper helper(false, true, use_null_audio_processing);
923     auto send_stream = helper.CreateAudioSendStream();
924     auto new_config = helper.config();
925 
926     rtc::scoped_refptr<FrameEncryptorInterface> mock_frame_encryptor_0(
927         rtc::make_ref_counted<MockFrameEncryptor>());
928     new_config.frame_encryptor = mock_frame_encryptor_0;
929     EXPECT_CALL(*helper.channel_send(), SetFrameEncryptor(Ne(nullptr)))
930         .Times(1);
931     send_stream->Reconfigure(new_config, nullptr);
932 
933     // Not updating the frame encryptor shouldn't force it to reconfigure.
934     EXPECT_CALL(*helper.channel_send(), SetFrameEncryptor(_)).Times(0);
935     send_stream->Reconfigure(new_config, nullptr);
936 
937     // Updating frame encryptor to a new object should force a call to the
938     // proxy.
939     rtc::scoped_refptr<FrameEncryptorInterface> mock_frame_encryptor_1(
940         rtc::make_ref_counted<MockFrameEncryptor>());
941     new_config.frame_encryptor = mock_frame_encryptor_1;
942     new_config.crypto_options.sframe.require_frame_encryption = true;
943     EXPECT_CALL(*helper.channel_send(), SetFrameEncryptor(Ne(nullptr)))
944         .Times(1);
945     send_stream->Reconfigure(new_config, nullptr);
946   }
947 }
948 }  // namespace test
949 }  // namespace webrtc
950