xref: /aosp_15_r20/external/webrtc/test/scenario/audio_stream.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #include "test/scenario/audio_stream.h"
11*d9f75844SAndroid Build Coastguard Worker 
12*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
13*d9f75844SAndroid Build Coastguard Worker #include "test/call_test.h"
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #if WEBRTC_ENABLE_PROTOBUF
16*d9f75844SAndroid Build Coastguard Worker RTC_PUSH_IGNORING_WUNDEF()
17*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
18*d9f75844SAndroid Build Coastguard Worker #include "external/webrtc/webrtc/modules/audio_coding/audio_network_adaptor/config.pb.h"
19*d9f75844SAndroid Build Coastguard Worker #else
20*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/audio_network_adaptor/config.pb.h"
21*d9f75844SAndroid Build Coastguard Worker #endif
22*d9f75844SAndroid Build Coastguard Worker RTC_POP_IGNORING_WUNDEF()
23*d9f75844SAndroid Build Coastguard Worker #endif
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
26*d9f75844SAndroid Build Coastguard Worker namespace test {
27*d9f75844SAndroid Build Coastguard Worker namespace {
28*d9f75844SAndroid Build Coastguard Worker enum : int {  // The first valid value is 1.
29*d9f75844SAndroid Build Coastguard Worker   kTransportSequenceNumberExtensionId = 1,
30*d9f75844SAndroid Build Coastguard Worker   kAbsSendTimeExtensionId
31*d9f75844SAndroid Build Coastguard Worker };
32*d9f75844SAndroid Build Coastguard Worker 
CreateAdaptationString(AudioStreamConfig::NetworkAdaptation config)33*d9f75844SAndroid Build Coastguard Worker absl::optional<std::string> CreateAdaptationString(
34*d9f75844SAndroid Build Coastguard Worker     AudioStreamConfig::NetworkAdaptation config) {
35*d9f75844SAndroid Build Coastguard Worker #if WEBRTC_ENABLE_PROTOBUF
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker   audio_network_adaptor::config::ControllerManager cont_conf;
38*d9f75844SAndroid Build Coastguard Worker   if (config.frame.max_rate_for_60_ms.IsFinite()) {
39*d9f75844SAndroid Build Coastguard Worker     auto controller =
40*d9f75844SAndroid Build Coastguard Worker         cont_conf.add_controllers()->mutable_frame_length_controller();
41*d9f75844SAndroid Build Coastguard Worker     controller->set_fl_decreasing_packet_loss_fraction(
42*d9f75844SAndroid Build Coastguard Worker         config.frame.min_packet_loss_for_decrease);
43*d9f75844SAndroid Build Coastguard Worker     controller->set_fl_increasing_packet_loss_fraction(
44*d9f75844SAndroid Build Coastguard Worker         config.frame.max_packet_loss_for_increase);
45*d9f75844SAndroid Build Coastguard Worker 
46*d9f75844SAndroid Build Coastguard Worker     controller->set_fl_20ms_to_60ms_bandwidth_bps(
47*d9f75844SAndroid Build Coastguard Worker         config.frame.min_rate_for_20_ms.bps<int32_t>());
48*d9f75844SAndroid Build Coastguard Worker     controller->set_fl_60ms_to_20ms_bandwidth_bps(
49*d9f75844SAndroid Build Coastguard Worker         config.frame.max_rate_for_60_ms.bps<int32_t>());
50*d9f75844SAndroid Build Coastguard Worker 
51*d9f75844SAndroid Build Coastguard Worker     if (config.frame.max_rate_for_120_ms.IsFinite()) {
52*d9f75844SAndroid Build Coastguard Worker       controller->set_fl_60ms_to_120ms_bandwidth_bps(
53*d9f75844SAndroid Build Coastguard Worker           config.frame.min_rate_for_60_ms.bps<int32_t>());
54*d9f75844SAndroid Build Coastguard Worker       controller->set_fl_120ms_to_60ms_bandwidth_bps(
55*d9f75844SAndroid Build Coastguard Worker           config.frame.max_rate_for_120_ms.bps<int32_t>());
56*d9f75844SAndroid Build Coastguard Worker     }
57*d9f75844SAndroid Build Coastguard Worker   }
58*d9f75844SAndroid Build Coastguard Worker   cont_conf.add_controllers()->mutable_bitrate_controller();
59*d9f75844SAndroid Build Coastguard Worker   std::string config_string = cont_conf.SerializeAsString();
60*d9f75844SAndroid Build Coastguard Worker   return config_string;
61*d9f75844SAndroid Build Coastguard Worker #else
62*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_ERROR) << "audio_network_adaptation is enabled"
63*d9f75844SAndroid Build Coastguard Worker                        " but WEBRTC_ENABLE_PROTOBUF is false.\n"
64*d9f75844SAndroid Build Coastguard Worker                        "Ignoring settings.";
65*d9f75844SAndroid Build Coastguard Worker   return absl::nullopt;
66*d9f75844SAndroid Build Coastguard Worker #endif  // WEBRTC_ENABLE_PROTOBUF
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker }  // namespace
69*d9f75844SAndroid Build Coastguard Worker 
SendAudioStream(CallClient * sender,AudioStreamConfig config,rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,Transport * send_transport)70*d9f75844SAndroid Build Coastguard Worker SendAudioStream::SendAudioStream(
71*d9f75844SAndroid Build Coastguard Worker     CallClient* sender,
72*d9f75844SAndroid Build Coastguard Worker     AudioStreamConfig config,
73*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
74*d9f75844SAndroid Build Coastguard Worker     Transport* send_transport)
75*d9f75844SAndroid Build Coastguard Worker     : sender_(sender), config_(config) {
76*d9f75844SAndroid Build Coastguard Worker   AudioSendStream::Config send_config(send_transport);
77*d9f75844SAndroid Build Coastguard Worker   ssrc_ = sender->GetNextAudioSsrc();
78*d9f75844SAndroid Build Coastguard Worker   send_config.rtp.ssrc = ssrc_;
79*d9f75844SAndroid Build Coastguard Worker   SdpAudioFormat::Parameters sdp_params;
80*d9f75844SAndroid Build Coastguard Worker   if (config.source.channels == 2)
81*d9f75844SAndroid Build Coastguard Worker     sdp_params["stereo"] = "1";
82*d9f75844SAndroid Build Coastguard Worker   if (config.encoder.initial_frame_length != TimeDelta::Millis(20))
83*d9f75844SAndroid Build Coastguard Worker     sdp_params["ptime"] =
84*d9f75844SAndroid Build Coastguard Worker         std::to_string(config.encoder.initial_frame_length.ms());
85*d9f75844SAndroid Build Coastguard Worker   if (config.encoder.enable_dtx)
86*d9f75844SAndroid Build Coastguard Worker     sdp_params["usedtx"] = "1";
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker   // SdpAudioFormat::num_channels indicates that the encoder is capable of
89*d9f75844SAndroid Build Coastguard Worker   // stereo, but the actual channel count used is based on the "stereo"
90*d9f75844SAndroid Build Coastguard Worker   // parameter.
91*d9f75844SAndroid Build Coastguard Worker   send_config.send_codec_spec = AudioSendStream::Config::SendCodecSpec(
92*d9f75844SAndroid Build Coastguard Worker       CallTest::kAudioSendPayloadType, {"opus", 48000, 2, sdp_params});
93*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_LE(config.source.channels, 2);
94*d9f75844SAndroid Build Coastguard Worker   send_config.encoder_factory = encoder_factory;
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker   if (config.encoder.fixed_rate)
97*d9f75844SAndroid Build Coastguard Worker     send_config.send_codec_spec->target_bitrate_bps =
98*d9f75844SAndroid Build Coastguard Worker         config.encoder.fixed_rate->bps();
99*d9f75844SAndroid Build Coastguard Worker   if (!config.adapt.binary_proto.empty()) {
100*d9f75844SAndroid Build Coastguard Worker     send_config.audio_network_adaptor_config = config.adapt.binary_proto;
101*d9f75844SAndroid Build Coastguard Worker   } else if (config.network_adaptation) {
102*d9f75844SAndroid Build Coastguard Worker     send_config.audio_network_adaptor_config =
103*d9f75844SAndroid Build Coastguard Worker         CreateAdaptationString(config.adapt);
104*d9f75844SAndroid Build Coastguard Worker   }
105*d9f75844SAndroid Build Coastguard Worker   if (config.encoder.allocate_bitrate ||
106*d9f75844SAndroid Build Coastguard Worker       config.stream.in_bandwidth_estimation) {
107*d9f75844SAndroid Build Coastguard Worker     DataRate min_rate = DataRate::Infinity();
108*d9f75844SAndroid Build Coastguard Worker     DataRate max_rate = DataRate::Infinity();
109*d9f75844SAndroid Build Coastguard Worker     if (config.encoder.fixed_rate) {
110*d9f75844SAndroid Build Coastguard Worker       min_rate = *config.encoder.fixed_rate;
111*d9f75844SAndroid Build Coastguard Worker       max_rate = *config.encoder.fixed_rate;
112*d9f75844SAndroid Build Coastguard Worker     } else {
113*d9f75844SAndroid Build Coastguard Worker       min_rate = *config.encoder.min_rate;
114*d9f75844SAndroid Build Coastguard Worker       max_rate = *config.encoder.max_rate;
115*d9f75844SAndroid Build Coastguard Worker     }
116*d9f75844SAndroid Build Coastguard Worker     send_config.min_bitrate_bps = min_rate.bps();
117*d9f75844SAndroid Build Coastguard Worker     send_config.max_bitrate_bps = max_rate.bps();
118*d9f75844SAndroid Build Coastguard Worker   }
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   if (config.stream.in_bandwidth_estimation) {
121*d9f75844SAndroid Build Coastguard Worker     send_config.send_codec_spec->transport_cc_enabled = true;
122*d9f75844SAndroid Build Coastguard Worker     send_config.rtp.extensions = {{RtpExtension::kTransportSequenceNumberUri,
123*d9f75844SAndroid Build Coastguard Worker                                    kTransportSequenceNumberExtensionId}};
124*d9f75844SAndroid Build Coastguard Worker   }
125*d9f75844SAndroid Build Coastguard Worker   if (config.stream.abs_send_time) {
126*d9f75844SAndroid Build Coastguard Worker     send_config.rtp.extensions.push_back(
127*d9f75844SAndroid Build Coastguard Worker         {RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId});
128*d9f75844SAndroid Build Coastguard Worker   }
129*d9f75844SAndroid Build Coastguard Worker 
130*d9f75844SAndroid Build Coastguard Worker   sender_->SendTask([&] {
131*d9f75844SAndroid Build Coastguard Worker     send_stream_ = sender_->call_->CreateAudioSendStream(send_config);
132*d9f75844SAndroid Build Coastguard Worker     sender->call_->OnAudioTransportOverheadChanged(
133*d9f75844SAndroid Build Coastguard Worker         sender_->transport_->packet_overhead().bytes());
134*d9f75844SAndroid Build Coastguard Worker   });
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker 
~SendAudioStream()137*d9f75844SAndroid Build Coastguard Worker SendAudioStream::~SendAudioStream() {
138*d9f75844SAndroid Build Coastguard Worker   sender_->SendTask(
139*d9f75844SAndroid Build Coastguard Worker       [this] { sender_->call_->DestroyAudioSendStream(send_stream_); });
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker 
Start()142*d9f75844SAndroid Build Coastguard Worker void SendAudioStream::Start() {
143*d9f75844SAndroid Build Coastguard Worker   sender_->SendTask([this] {
144*d9f75844SAndroid Build Coastguard Worker     send_stream_->Start();
145*d9f75844SAndroid Build Coastguard Worker     sender_->call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
146*d9f75844SAndroid Build Coastguard Worker   });
147*d9f75844SAndroid Build Coastguard Worker }
148*d9f75844SAndroid Build Coastguard Worker 
Stop()149*d9f75844SAndroid Build Coastguard Worker void SendAudioStream::Stop() {
150*d9f75844SAndroid Build Coastguard Worker   sender_->SendTask([this] { send_stream_->Stop(); });
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker 
SetMuted(bool mute)153*d9f75844SAndroid Build Coastguard Worker void SendAudioStream::SetMuted(bool mute) {
154*d9f75844SAndroid Build Coastguard Worker   sender_->SendTask([this, mute] { send_stream_->SetMuted(mute); });
155*d9f75844SAndroid Build Coastguard Worker }
156*d9f75844SAndroid Build Coastguard Worker 
StatsPrinter()157*d9f75844SAndroid Build Coastguard Worker ColumnPrinter SendAudioStream::StatsPrinter() {
158*d9f75844SAndroid Build Coastguard Worker   return ColumnPrinter::Lambda(
159*d9f75844SAndroid Build Coastguard Worker       "audio_target_rate",
160*d9f75844SAndroid Build Coastguard Worker       [this](rtc::SimpleStringBuilder& sb) {
161*d9f75844SAndroid Build Coastguard Worker         sender_->SendTask([this, &sb] {
162*d9f75844SAndroid Build Coastguard Worker           AudioSendStream::Stats stats = send_stream_->GetStats();
163*d9f75844SAndroid Build Coastguard Worker           sb.AppendFormat("%.0lf", stats.target_bitrate_bps / 8.0);
164*d9f75844SAndroid Build Coastguard Worker         });
165*d9f75844SAndroid Build Coastguard Worker       },
166*d9f75844SAndroid Build Coastguard Worker       64);
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker 
ReceiveAudioStream(CallClient * receiver,AudioStreamConfig config,SendAudioStream * send_stream,rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,Transport * feedback_transport)169*d9f75844SAndroid Build Coastguard Worker ReceiveAudioStream::ReceiveAudioStream(
170*d9f75844SAndroid Build Coastguard Worker     CallClient* receiver,
171*d9f75844SAndroid Build Coastguard Worker     AudioStreamConfig config,
172*d9f75844SAndroid Build Coastguard Worker     SendAudioStream* send_stream,
173*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
174*d9f75844SAndroid Build Coastguard Worker     Transport* feedback_transport)
175*d9f75844SAndroid Build Coastguard Worker     : receiver_(receiver), config_(config) {
176*d9f75844SAndroid Build Coastguard Worker   AudioReceiveStreamInterface::Config recv_config;
177*d9f75844SAndroid Build Coastguard Worker   recv_config.rtp.local_ssrc = receiver_->GetNextAudioLocalSsrc();
178*d9f75844SAndroid Build Coastguard Worker   recv_config.rtcp_send_transport = feedback_transport;
179*d9f75844SAndroid Build Coastguard Worker   recv_config.rtp.remote_ssrc = send_stream->ssrc_;
180*d9f75844SAndroid Build Coastguard Worker   receiver->ssrc_media_types_[recv_config.rtp.remote_ssrc] = MediaType::AUDIO;
181*d9f75844SAndroid Build Coastguard Worker   if (config.stream.in_bandwidth_estimation) {
182*d9f75844SAndroid Build Coastguard Worker     recv_config.rtp.transport_cc = true;
183*d9f75844SAndroid Build Coastguard Worker     recv_config.rtp.extensions = {{RtpExtension::kTransportSequenceNumberUri,
184*d9f75844SAndroid Build Coastguard Worker                                    kTransportSequenceNumberExtensionId}};
185*d9f75844SAndroid Build Coastguard Worker   }
186*d9f75844SAndroid Build Coastguard Worker   recv_config.decoder_factory = decoder_factory;
187*d9f75844SAndroid Build Coastguard Worker   recv_config.decoder_map = {
188*d9f75844SAndroid Build Coastguard Worker       {CallTest::kAudioSendPayloadType, {"opus", 48000, 2}}};
189*d9f75844SAndroid Build Coastguard Worker   recv_config.sync_group = config.render.sync_group;
190*d9f75844SAndroid Build Coastguard Worker   receiver_->SendTask([&] {
191*d9f75844SAndroid Build Coastguard Worker     receive_stream_ = receiver_->call_->CreateAudioReceiveStream(recv_config);
192*d9f75844SAndroid Build Coastguard Worker   });
193*d9f75844SAndroid Build Coastguard Worker }
~ReceiveAudioStream()194*d9f75844SAndroid Build Coastguard Worker ReceiveAudioStream::~ReceiveAudioStream() {
195*d9f75844SAndroid Build Coastguard Worker   receiver_->SendTask(
196*d9f75844SAndroid Build Coastguard Worker       [&] { receiver_->call_->DestroyAudioReceiveStream(receive_stream_); });
197*d9f75844SAndroid Build Coastguard Worker }
198*d9f75844SAndroid Build Coastguard Worker 
Start()199*d9f75844SAndroid Build Coastguard Worker void ReceiveAudioStream::Start() {
200*d9f75844SAndroid Build Coastguard Worker   receiver_->SendTask([&] {
201*d9f75844SAndroid Build Coastguard Worker     receive_stream_->Start();
202*d9f75844SAndroid Build Coastguard Worker     receiver_->call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
203*d9f75844SAndroid Build Coastguard Worker   });
204*d9f75844SAndroid Build Coastguard Worker }
205*d9f75844SAndroid Build Coastguard Worker 
Stop()206*d9f75844SAndroid Build Coastguard Worker void ReceiveAudioStream::Stop() {
207*d9f75844SAndroid Build Coastguard Worker   receiver_->SendTask([&] { receive_stream_->Stop(); });
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker 
GetStats() const210*d9f75844SAndroid Build Coastguard Worker AudioReceiveStreamInterface::Stats ReceiveAudioStream::GetStats() const {
211*d9f75844SAndroid Build Coastguard Worker   AudioReceiveStreamInterface::Stats result;
212*d9f75844SAndroid Build Coastguard Worker   receiver_->SendTask([&] {
213*d9f75844SAndroid Build Coastguard Worker     result = receive_stream_->GetStats(/*get_and_clear_legacy_stats=*/true);
214*d9f75844SAndroid Build Coastguard Worker   });
215*d9f75844SAndroid Build Coastguard Worker   return result;
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker 
218*d9f75844SAndroid Build Coastguard Worker AudioStreamPair::~AudioStreamPair() = default;
219*d9f75844SAndroid Build Coastguard Worker 
AudioStreamPair(CallClient * sender,rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,CallClient * receiver,rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,AudioStreamConfig config)220*d9f75844SAndroid Build Coastguard Worker AudioStreamPair::AudioStreamPair(
221*d9f75844SAndroid Build Coastguard Worker     CallClient* sender,
222*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
223*d9f75844SAndroid Build Coastguard Worker     CallClient* receiver,
224*d9f75844SAndroid Build Coastguard Worker     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
225*d9f75844SAndroid Build Coastguard Worker     AudioStreamConfig config)
226*d9f75844SAndroid Build Coastguard Worker     : config_(config),
227*d9f75844SAndroid Build Coastguard Worker       send_stream_(sender, config, encoder_factory, sender->transport_.get()),
228*d9f75844SAndroid Build Coastguard Worker       receive_stream_(receiver,
229*d9f75844SAndroid Build Coastguard Worker                       config,
230*d9f75844SAndroid Build Coastguard Worker                       &send_stream_,
231*d9f75844SAndroid Build Coastguard Worker                       decoder_factory,
232*d9f75844SAndroid Build Coastguard Worker                       receiver->transport_.get()) {}
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker }  // namespace test
235*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
236