xref: /aosp_15_r20/external/webrtc/audio/audio_send_stream.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2015 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 
11*d9f75844SAndroid Build Coastguard Worker #include "audio/audio_send_stream.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <string>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker #include <vector>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/audio_encoder.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/audio_encoder_factory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/audio_format.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/call/transport.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/crypto/frame_encryptor_interface.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/function_view.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_event_log/rtc_event_log.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
26*d9f75844SAndroid Build Coastguard Worker #include "audio/audio_state.h"
27*d9f75844SAndroid Build Coastguard Worker #include "audio/channel_send.h"
28*d9f75844SAndroid Build Coastguard Worker #include "audio/conversion.h"
29*d9f75844SAndroid Build Coastguard Worker #include "call/rtp_config.h"
30*d9f75844SAndroid Build Coastguard Worker #include "call/rtp_transport_controller_send_interface.h"
31*d9f75844SAndroid Build Coastguard Worker #include "common_audio/vad/include/vad.h"
32*d9f75844SAndroid Build Coastguard Worker #include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
33*d9f75844SAndroid Build Coastguard Worker #include "logging/rtc_event_log/rtc_stream_config.h"
34*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_channel.h"
35*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
36*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
37*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing.h"
38*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
39*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
40*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
41*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/audio_format_to_string.h"
42*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
43*d9f75844SAndroid Build Coastguard Worker 
44*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
45*d9f75844SAndroid Build Coastguard Worker namespace {
46*d9f75844SAndroid Build Coastguard Worker 
UpdateEventLogStreamConfig(RtcEventLog * event_log,const AudioSendStream::Config & config,const AudioSendStream::Config * old_config)47*d9f75844SAndroid Build Coastguard Worker void UpdateEventLogStreamConfig(RtcEventLog* event_log,
48*d9f75844SAndroid Build Coastguard Worker                                 const AudioSendStream::Config& config,
49*d9f75844SAndroid Build Coastguard Worker                                 const AudioSendStream::Config* old_config) {
50*d9f75844SAndroid Build Coastguard Worker   using SendCodecSpec = AudioSendStream::Config::SendCodecSpec;
51*d9f75844SAndroid Build Coastguard Worker   // Only update if any of the things we log have changed.
52*d9f75844SAndroid Build Coastguard Worker   auto payload_types_equal = [](const absl::optional<SendCodecSpec>& a,
53*d9f75844SAndroid Build Coastguard Worker                                 const absl::optional<SendCodecSpec>& b) {
54*d9f75844SAndroid Build Coastguard Worker     if (a.has_value() && b.has_value()) {
55*d9f75844SAndroid Build Coastguard Worker       return a->format.name == b->format.name &&
56*d9f75844SAndroid Build Coastguard Worker              a->payload_type == b->payload_type;
57*d9f75844SAndroid Build Coastguard Worker     }
58*d9f75844SAndroid Build Coastguard Worker     return !a.has_value() && !b.has_value();
59*d9f75844SAndroid Build Coastguard Worker   };
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker   if (old_config && config.rtp.ssrc == old_config->rtp.ssrc &&
62*d9f75844SAndroid Build Coastguard Worker       config.rtp.extensions == old_config->rtp.extensions &&
63*d9f75844SAndroid Build Coastguard Worker       payload_types_equal(config.send_codec_spec,
64*d9f75844SAndroid Build Coastguard Worker                           old_config->send_codec_spec)) {
65*d9f75844SAndroid Build Coastguard Worker     return;
66*d9f75844SAndroid Build Coastguard Worker   }
67*d9f75844SAndroid Build Coastguard Worker 
68*d9f75844SAndroid Build Coastguard Worker   auto rtclog_config = std::make_unique<rtclog::StreamConfig>();
69*d9f75844SAndroid Build Coastguard Worker   rtclog_config->local_ssrc = config.rtp.ssrc;
70*d9f75844SAndroid Build Coastguard Worker   rtclog_config->rtp_extensions = config.rtp.extensions;
71*d9f75844SAndroid Build Coastguard Worker   if (config.send_codec_spec) {
72*d9f75844SAndroid Build Coastguard Worker     rtclog_config->codecs.emplace_back(config.send_codec_spec->format.name,
73*d9f75844SAndroid Build Coastguard Worker                                        config.send_codec_spec->payload_type, 0);
74*d9f75844SAndroid Build Coastguard Worker   }
75*d9f75844SAndroid Build Coastguard Worker   event_log->Log(std::make_unique<RtcEventAudioSendStreamConfig>(
76*d9f75844SAndroid Build Coastguard Worker       std::move(rtclog_config)));
77*d9f75844SAndroid Build Coastguard Worker }
78*d9f75844SAndroid Build Coastguard Worker 
79*d9f75844SAndroid Build Coastguard Worker }  // namespace
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker constexpr char AudioAllocationConfig::kKey[];
82*d9f75844SAndroid Build Coastguard Worker 
Parser()83*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<StructParametersParser> AudioAllocationConfig::Parser() {
84*d9f75844SAndroid Build Coastguard Worker   return StructParametersParser::Create(       //
85*d9f75844SAndroid Build Coastguard Worker       "min", &min_bitrate,                     //
86*d9f75844SAndroid Build Coastguard Worker       "max", &max_bitrate,                     //
87*d9f75844SAndroid Build Coastguard Worker       "prio_rate", &priority_bitrate,          //
88*d9f75844SAndroid Build Coastguard Worker       "prio_rate_raw", &priority_bitrate_raw,  //
89*d9f75844SAndroid Build Coastguard Worker       "rate_prio", &bitrate_priority);
90*d9f75844SAndroid Build Coastguard Worker }
91*d9f75844SAndroid Build Coastguard Worker 
AudioAllocationConfig(const FieldTrialsView & field_trials)92*d9f75844SAndroid Build Coastguard Worker AudioAllocationConfig::AudioAllocationConfig(
93*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials) {
94*d9f75844SAndroid Build Coastguard Worker   Parser()->Parse(field_trials.Lookup(kKey));
95*d9f75844SAndroid Build Coastguard Worker   if (priority_bitrate_raw && !priority_bitrate.IsZero()) {
96*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "'priority_bitrate' and '_raw' are mutually "
97*d9f75844SAndroid Build Coastguard Worker                            "exclusive but both were configured.";
98*d9f75844SAndroid Build Coastguard Worker   }
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker namespace internal {
AudioSendStream(Clock * clock,const webrtc::AudioSendStream::Config & config,const rtc::scoped_refptr<webrtc::AudioState> & audio_state,TaskQueueFactory * task_queue_factory,RtpTransportControllerSendInterface * rtp_transport,BitrateAllocatorInterface * bitrate_allocator,RtcEventLog * event_log,RtcpRttStats * rtcp_rtt_stats,const absl::optional<RtpState> & suspended_rtp_state,const FieldTrialsView & field_trials)102*d9f75844SAndroid Build Coastguard Worker AudioSendStream::AudioSendStream(
103*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
104*d9f75844SAndroid Build Coastguard Worker     const webrtc::AudioSendStream::Config& config,
105*d9f75844SAndroid Build Coastguard Worker     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
106*d9f75844SAndroid Build Coastguard Worker     TaskQueueFactory* task_queue_factory,
107*d9f75844SAndroid Build Coastguard Worker     RtpTransportControllerSendInterface* rtp_transport,
108*d9f75844SAndroid Build Coastguard Worker     BitrateAllocatorInterface* bitrate_allocator,
109*d9f75844SAndroid Build Coastguard Worker     RtcEventLog* event_log,
110*d9f75844SAndroid Build Coastguard Worker     RtcpRttStats* rtcp_rtt_stats,
111*d9f75844SAndroid Build Coastguard Worker     const absl::optional<RtpState>& suspended_rtp_state,
112*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials)
113*d9f75844SAndroid Build Coastguard Worker     : AudioSendStream(
114*d9f75844SAndroid Build Coastguard Worker           clock,
115*d9f75844SAndroid Build Coastguard Worker           config,
116*d9f75844SAndroid Build Coastguard Worker           audio_state,
117*d9f75844SAndroid Build Coastguard Worker           task_queue_factory,
118*d9f75844SAndroid Build Coastguard Worker           rtp_transport,
119*d9f75844SAndroid Build Coastguard Worker           bitrate_allocator,
120*d9f75844SAndroid Build Coastguard Worker           event_log,
121*d9f75844SAndroid Build Coastguard Worker           suspended_rtp_state,
122*d9f75844SAndroid Build Coastguard Worker           voe::CreateChannelSend(clock,
123*d9f75844SAndroid Build Coastguard Worker                                  task_queue_factory,
124*d9f75844SAndroid Build Coastguard Worker                                  config.send_transport,
125*d9f75844SAndroid Build Coastguard Worker                                  rtcp_rtt_stats,
126*d9f75844SAndroid Build Coastguard Worker                                  event_log,
127*d9f75844SAndroid Build Coastguard Worker                                  config.frame_encryptor.get(),
128*d9f75844SAndroid Build Coastguard Worker                                  config.crypto_options,
129*d9f75844SAndroid Build Coastguard Worker                                  config.rtp.extmap_allow_mixed,
130*d9f75844SAndroid Build Coastguard Worker                                  config.rtcp_report_interval_ms,
131*d9f75844SAndroid Build Coastguard Worker                                  config.rtp.ssrc,
132*d9f75844SAndroid Build Coastguard Worker                                  config.frame_transformer,
133*d9f75844SAndroid Build Coastguard Worker                                  rtp_transport->transport_feedback_observer(),
134*d9f75844SAndroid Build Coastguard Worker                                  field_trials),
135*d9f75844SAndroid Build Coastguard Worker           field_trials) {}
136*d9f75844SAndroid Build Coastguard Worker 
AudioSendStream(Clock * clock,const webrtc::AudioSendStream::Config & config,const rtc::scoped_refptr<webrtc::AudioState> & audio_state,TaskQueueFactory * task_queue_factory,RtpTransportControllerSendInterface * rtp_transport,BitrateAllocatorInterface * bitrate_allocator,RtcEventLog * event_log,const absl::optional<RtpState> & suspended_rtp_state,std::unique_ptr<voe::ChannelSendInterface> channel_send,const FieldTrialsView & field_trials)137*d9f75844SAndroid Build Coastguard Worker AudioSendStream::AudioSendStream(
138*d9f75844SAndroid Build Coastguard Worker     Clock* clock,
139*d9f75844SAndroid Build Coastguard Worker     const webrtc::AudioSendStream::Config& config,
140*d9f75844SAndroid Build Coastguard Worker     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
141*d9f75844SAndroid Build Coastguard Worker     TaskQueueFactory* task_queue_factory,
142*d9f75844SAndroid Build Coastguard Worker     RtpTransportControllerSendInterface* rtp_transport,
143*d9f75844SAndroid Build Coastguard Worker     BitrateAllocatorInterface* bitrate_allocator,
144*d9f75844SAndroid Build Coastguard Worker     RtcEventLog* event_log,
145*d9f75844SAndroid Build Coastguard Worker     const absl::optional<RtpState>& suspended_rtp_state,
146*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<voe::ChannelSendInterface> channel_send,
147*d9f75844SAndroid Build Coastguard Worker     const FieldTrialsView& field_trials)
148*d9f75844SAndroid Build Coastguard Worker     : clock_(clock),
149*d9f75844SAndroid Build Coastguard Worker       field_trials_(field_trials),
150*d9f75844SAndroid Build Coastguard Worker       rtp_transport_queue_(rtp_transport->GetWorkerQueue()),
151*d9f75844SAndroid Build Coastguard Worker       allocate_audio_without_feedback_(
152*d9f75844SAndroid Build Coastguard Worker           field_trials_.IsEnabled("WebRTC-Audio-ABWENoTWCC")),
153*d9f75844SAndroid Build Coastguard Worker       enable_audio_alr_probing_(
154*d9f75844SAndroid Build Coastguard Worker           !field_trials_.IsDisabled("WebRTC-Audio-AlrProbing")),
155*d9f75844SAndroid Build Coastguard Worker       allocation_settings_(field_trials_),
156*d9f75844SAndroid Build Coastguard Worker       config_(Config(/*send_transport=*/nullptr)),
157*d9f75844SAndroid Build Coastguard Worker       audio_state_(audio_state),
158*d9f75844SAndroid Build Coastguard Worker       channel_send_(std::move(channel_send)),
159*d9f75844SAndroid Build Coastguard Worker       event_log_(event_log),
160*d9f75844SAndroid Build Coastguard Worker       use_legacy_overhead_calculation_(
161*d9f75844SAndroid Build Coastguard Worker           field_trials_.IsEnabled("WebRTC-Audio-LegacyOverhead")),
162*d9f75844SAndroid Build Coastguard Worker       bitrate_allocator_(bitrate_allocator),
163*d9f75844SAndroid Build Coastguard Worker       rtp_transport_(rtp_transport),
164*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_module_(channel_send_->GetRtpRtcp()),
165*d9f75844SAndroid Build Coastguard Worker       suspended_rtp_state_(suspended_rtp_state) {
166*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "AudioSendStream: " << config.rtp.ssrc;
167*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(rtp_transport_queue_);
168*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(audio_state_);
169*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(channel_send_);
170*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(bitrate_allocator_);
171*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(rtp_transport);
172*d9f75844SAndroid Build Coastguard Worker 
173*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(rtp_rtcp_module_);
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
176*d9f75844SAndroid Build Coastguard Worker   ConfigureStream(config, true, nullptr);
177*d9f75844SAndroid Build Coastguard Worker   UpdateCachedTargetAudioBitrateConstraints();
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker 
~AudioSendStream()180*d9f75844SAndroid Build Coastguard Worker AudioSendStream::~AudioSendStream() {
181*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
182*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "~AudioSendStream: " << config_.rtp.ssrc;
183*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!sending_);
184*d9f75844SAndroid Build Coastguard Worker   channel_send_->ResetSenderCongestionControlObjects();
185*d9f75844SAndroid Build Coastguard Worker 
186*d9f75844SAndroid Build Coastguard Worker   // Blocking call to synchronize state with worker queue to ensure that there
187*d9f75844SAndroid Build Coastguard Worker   // are no pending tasks left that keeps references to audio.
188*d9f75844SAndroid Build Coastguard Worker   rtp_transport_queue_->RunSynchronous([] {});
189*d9f75844SAndroid Build Coastguard Worker }
190*d9f75844SAndroid Build Coastguard Worker 
GetConfig() const191*d9f75844SAndroid Build Coastguard Worker const webrtc::AudioSendStream::Config& AudioSendStream::GetConfig() const {
192*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
193*d9f75844SAndroid Build Coastguard Worker   return config_;
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker 
Reconfigure(const webrtc::AudioSendStream::Config & new_config,SetParametersCallback callback)196*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::Reconfigure(
197*d9f75844SAndroid Build Coastguard Worker     const webrtc::AudioSendStream::Config& new_config,
198*d9f75844SAndroid Build Coastguard Worker     SetParametersCallback callback) {
199*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
200*d9f75844SAndroid Build Coastguard Worker   ConfigureStream(new_config, false, std::move(callback));
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker 
FindExtensionIds(const std::vector<RtpExtension> & extensions)203*d9f75844SAndroid Build Coastguard Worker AudioSendStream::ExtensionIds AudioSendStream::FindExtensionIds(
204*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpExtension>& extensions) {
205*d9f75844SAndroid Build Coastguard Worker   ExtensionIds ids;
206*d9f75844SAndroid Build Coastguard Worker   for (const auto& extension : extensions) {
207*d9f75844SAndroid Build Coastguard Worker     if (extension.uri == RtpExtension::kAudioLevelUri) {
208*d9f75844SAndroid Build Coastguard Worker       ids.audio_level = extension.id;
209*d9f75844SAndroid Build Coastguard Worker     } else if (extension.uri == RtpExtension::kAbsSendTimeUri) {
210*d9f75844SAndroid Build Coastguard Worker       ids.abs_send_time = extension.id;
211*d9f75844SAndroid Build Coastguard Worker     } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
212*d9f75844SAndroid Build Coastguard Worker       ids.transport_sequence_number = extension.id;
213*d9f75844SAndroid Build Coastguard Worker     } else if (extension.uri == RtpExtension::kMidUri) {
214*d9f75844SAndroid Build Coastguard Worker       ids.mid = extension.id;
215*d9f75844SAndroid Build Coastguard Worker     } else if (extension.uri == RtpExtension::kRidUri) {
216*d9f75844SAndroid Build Coastguard Worker       ids.rid = extension.id;
217*d9f75844SAndroid Build Coastguard Worker     } else if (extension.uri == RtpExtension::kRepairedRidUri) {
218*d9f75844SAndroid Build Coastguard Worker       ids.repaired_rid = extension.id;
219*d9f75844SAndroid Build Coastguard Worker     } else if (extension.uri == RtpExtension::kAbsoluteCaptureTimeUri) {
220*d9f75844SAndroid Build Coastguard Worker       ids.abs_capture_time = extension.id;
221*d9f75844SAndroid Build Coastguard Worker     }
222*d9f75844SAndroid Build Coastguard Worker   }
223*d9f75844SAndroid Build Coastguard Worker   return ids;
224*d9f75844SAndroid Build Coastguard Worker }
225*d9f75844SAndroid Build Coastguard Worker 
TransportSeqNumId(const AudioSendStream::Config & config)226*d9f75844SAndroid Build Coastguard Worker int AudioSendStream::TransportSeqNumId(const AudioSendStream::Config& config) {
227*d9f75844SAndroid Build Coastguard Worker   return FindExtensionIds(config.rtp.extensions).transport_sequence_number;
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker 
ConfigureStream(const webrtc::AudioSendStream::Config & new_config,bool first_time,SetParametersCallback callback)230*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::ConfigureStream(
231*d9f75844SAndroid Build Coastguard Worker     const webrtc::AudioSendStream::Config& new_config,
232*d9f75844SAndroid Build Coastguard Worker     bool first_time,
233*d9f75844SAndroid Build Coastguard Worker     SetParametersCallback callback) {
234*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "AudioSendStream::ConfigureStream: "
235*d9f75844SAndroid Build Coastguard Worker                    << new_config.ToString();
236*d9f75844SAndroid Build Coastguard Worker   UpdateEventLogStreamConfig(event_log_, new_config,
237*d9f75844SAndroid Build Coastguard Worker                              first_time ? nullptr : &config_);
238*d9f75844SAndroid Build Coastguard Worker 
239*d9f75844SAndroid Build Coastguard Worker   const auto& old_config = config_;
240*d9f75844SAndroid Build Coastguard Worker 
241*d9f75844SAndroid Build Coastguard Worker   // Configuration parameters which cannot be changed.
242*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(first_time ||
243*d9f75844SAndroid Build Coastguard Worker              old_config.send_transport == new_config.send_transport);
244*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(first_time || old_config.rtp.ssrc == new_config.rtp.ssrc);
245*d9f75844SAndroid Build Coastguard Worker   if (suspended_rtp_state_ && first_time) {
246*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetRtpState(*suspended_rtp_state_);
247*d9f75844SAndroid Build Coastguard Worker   }
248*d9f75844SAndroid Build Coastguard Worker   if (first_time || old_config.rtp.c_name != new_config.rtp.c_name) {
249*d9f75844SAndroid Build Coastguard Worker     channel_send_->SetRTCP_CNAME(new_config.rtp.c_name);
250*d9f75844SAndroid Build Coastguard Worker   }
251*d9f75844SAndroid Build Coastguard Worker 
252*d9f75844SAndroid Build Coastguard Worker   // Enable the frame encryptor if a new frame encryptor has been provided.
253*d9f75844SAndroid Build Coastguard Worker   if (first_time || new_config.frame_encryptor != old_config.frame_encryptor) {
254*d9f75844SAndroid Build Coastguard Worker     channel_send_->SetFrameEncryptor(new_config.frame_encryptor);
255*d9f75844SAndroid Build Coastguard Worker   }
256*d9f75844SAndroid Build Coastguard Worker 
257*d9f75844SAndroid Build Coastguard Worker   if (first_time ||
258*d9f75844SAndroid Build Coastguard Worker       new_config.frame_transformer != old_config.frame_transformer) {
259*d9f75844SAndroid Build Coastguard Worker     channel_send_->SetEncoderToPacketizerFrameTransformer(
260*d9f75844SAndroid Build Coastguard Worker         new_config.frame_transformer);
261*d9f75844SAndroid Build Coastguard Worker   }
262*d9f75844SAndroid Build Coastguard Worker 
263*d9f75844SAndroid Build Coastguard Worker   if (first_time ||
264*d9f75844SAndroid Build Coastguard Worker       new_config.rtp.extmap_allow_mixed != old_config.rtp.extmap_allow_mixed) {
265*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetExtmapAllowMixed(new_config.rtp.extmap_allow_mixed);
266*d9f75844SAndroid Build Coastguard Worker   }
267*d9f75844SAndroid Build Coastguard Worker 
268*d9f75844SAndroid Build Coastguard Worker   const ExtensionIds old_ids = FindExtensionIds(old_config.rtp.extensions);
269*d9f75844SAndroid Build Coastguard Worker   const ExtensionIds new_ids = FindExtensionIds(new_config.rtp.extensions);
270*d9f75844SAndroid Build Coastguard Worker 
271*d9f75844SAndroid Build Coastguard Worker   // Audio level indication
272*d9f75844SAndroid Build Coastguard Worker   if (first_time || new_ids.audio_level != old_ids.audio_level) {
273*d9f75844SAndroid Build Coastguard Worker     channel_send_->SetSendAudioLevelIndicationStatus(new_ids.audio_level != 0,
274*d9f75844SAndroid Build Coastguard Worker                                                      new_ids.audio_level);
275*d9f75844SAndroid Build Coastguard Worker   }
276*d9f75844SAndroid Build Coastguard Worker 
277*d9f75844SAndroid Build Coastguard Worker   if (first_time || new_ids.abs_send_time != old_ids.abs_send_time) {
278*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri = AbsoluteSendTime::Uri();
279*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->DeregisterSendRtpHeaderExtension(uri);
280*d9f75844SAndroid Build Coastguard Worker     if (new_ids.abs_send_time) {
281*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_module_->RegisterRtpHeaderExtension(uri, new_ids.abs_send_time);
282*d9f75844SAndroid Build Coastguard Worker     }
283*d9f75844SAndroid Build Coastguard Worker   }
284*d9f75844SAndroid Build Coastguard Worker 
285*d9f75844SAndroid Build Coastguard Worker   bool transport_seq_num_id_changed =
286*d9f75844SAndroid Build Coastguard Worker       new_ids.transport_sequence_number != old_ids.transport_sequence_number;
287*d9f75844SAndroid Build Coastguard Worker   if (first_time ||
288*d9f75844SAndroid Build Coastguard Worker       (transport_seq_num_id_changed && !allocate_audio_without_feedback_)) {
289*d9f75844SAndroid Build Coastguard Worker     if (!first_time) {
290*d9f75844SAndroid Build Coastguard Worker       channel_send_->ResetSenderCongestionControlObjects();
291*d9f75844SAndroid Build Coastguard Worker     }
292*d9f75844SAndroid Build Coastguard Worker 
293*d9f75844SAndroid Build Coastguard Worker     RtcpBandwidthObserver* bandwidth_observer = nullptr;
294*d9f75844SAndroid Build Coastguard Worker 
295*d9f75844SAndroid Build Coastguard Worker     if (!allocate_audio_without_feedback_ &&
296*d9f75844SAndroid Build Coastguard Worker         new_ids.transport_sequence_number != 0) {
297*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_module_->RegisterRtpHeaderExtension(
298*d9f75844SAndroid Build Coastguard Worker           TransportSequenceNumber::Uri(), new_ids.transport_sequence_number);
299*d9f75844SAndroid Build Coastguard Worker       // Probing in application limited region is only used in combination with
300*d9f75844SAndroid Build Coastguard Worker       // send side congestion control, wich depends on feedback packets which
301*d9f75844SAndroid Build Coastguard Worker       // requires transport sequence numbers to be enabled.
302*d9f75844SAndroid Build Coastguard Worker       // Optionally request ALR probing but do not override any existing
303*d9f75844SAndroid Build Coastguard Worker       // request from other streams.
304*d9f75844SAndroid Build Coastguard Worker       if (enable_audio_alr_probing_) {
305*d9f75844SAndroid Build Coastguard Worker         rtp_transport_->EnablePeriodicAlrProbing(true);
306*d9f75844SAndroid Build Coastguard Worker       }
307*d9f75844SAndroid Build Coastguard Worker       bandwidth_observer = rtp_transport_->GetBandwidthObserver();
308*d9f75844SAndroid Build Coastguard Worker     }
309*d9f75844SAndroid Build Coastguard Worker     channel_send_->RegisterSenderCongestionControlObjects(rtp_transport_,
310*d9f75844SAndroid Build Coastguard Worker                                                           bandwidth_observer);
311*d9f75844SAndroid Build Coastguard Worker   }
312*d9f75844SAndroid Build Coastguard Worker   // MID RTP header extension.
313*d9f75844SAndroid Build Coastguard Worker   if ((first_time || new_ids.mid != old_ids.mid ||
314*d9f75844SAndroid Build Coastguard Worker        new_config.rtp.mid != old_config.rtp.mid) &&
315*d9f75844SAndroid Build Coastguard Worker       new_ids.mid != 0 && !new_config.rtp.mid.empty()) {
316*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->RegisterRtpHeaderExtension(RtpMid::Uri(), new_ids.mid);
317*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetMid(new_config.rtp.mid);
318*d9f75844SAndroid Build Coastguard Worker   }
319*d9f75844SAndroid Build Coastguard Worker 
320*d9f75844SAndroid Build Coastguard Worker   if (first_time || new_ids.abs_capture_time != old_ids.abs_capture_time) {
321*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri = AbsoluteCaptureTimeExtension::Uri();
322*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->DeregisterSendRtpHeaderExtension(uri);
323*d9f75844SAndroid Build Coastguard Worker     if (new_ids.abs_capture_time) {
324*d9f75844SAndroid Build Coastguard Worker       rtp_rtcp_module_->RegisterRtpHeaderExtension(uri,
325*d9f75844SAndroid Build Coastguard Worker                                                    new_ids.abs_capture_time);
326*d9f75844SAndroid Build Coastguard Worker     }
327*d9f75844SAndroid Build Coastguard Worker   }
328*d9f75844SAndroid Build Coastguard Worker 
329*d9f75844SAndroid Build Coastguard Worker   if (!ReconfigureSendCodec(new_config)) {
330*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Failed to set up send codec state.";
331*d9f75844SAndroid Build Coastguard Worker 
332*d9f75844SAndroid Build Coastguard Worker     webrtc::InvokeSetParametersCallback(
333*d9f75844SAndroid Build Coastguard Worker         callback, webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR,
334*d9f75844SAndroid Build Coastguard Worker                                    "Failed to set up send codec state."));
335*d9f75844SAndroid Build Coastguard Worker   }
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker   // Set currently known overhead (used in ANA, opus only).
338*d9f75844SAndroid Build Coastguard Worker   {
339*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&overhead_per_packet_lock_);
340*d9f75844SAndroid Build Coastguard Worker     UpdateOverheadForEncoder();
341*d9f75844SAndroid Build Coastguard Worker   }
342*d9f75844SAndroid Build Coastguard Worker 
343*d9f75844SAndroid Build Coastguard Worker   channel_send_->CallEncoder([this](AudioEncoder* encoder) {
344*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(&worker_thread_checker_);
345*d9f75844SAndroid Build Coastguard Worker     if (!encoder) {
346*d9f75844SAndroid Build Coastguard Worker       return;
347*d9f75844SAndroid Build Coastguard Worker     }
348*d9f75844SAndroid Build Coastguard Worker     frame_length_range_ = encoder->GetFrameLengthRange();
349*d9f75844SAndroid Build Coastguard Worker     UpdateCachedTargetAudioBitrateConstraints();
350*d9f75844SAndroid Build Coastguard Worker   });
351*d9f75844SAndroid Build Coastguard Worker 
352*d9f75844SAndroid Build Coastguard Worker   if (sending_) {
353*d9f75844SAndroid Build Coastguard Worker     ReconfigureBitrateObserver(new_config);
354*d9f75844SAndroid Build Coastguard Worker   }
355*d9f75844SAndroid Build Coastguard Worker 
356*d9f75844SAndroid Build Coastguard Worker   config_ = new_config;
357*d9f75844SAndroid Build Coastguard Worker   if (!first_time) {
358*d9f75844SAndroid Build Coastguard Worker     UpdateCachedTargetAudioBitrateConstraints();
359*d9f75844SAndroid Build Coastguard Worker   }
360*d9f75844SAndroid Build Coastguard Worker 
361*d9f75844SAndroid Build Coastguard Worker   webrtc::InvokeSetParametersCallback(callback, webrtc::RTCError::OK());
362*d9f75844SAndroid Build Coastguard Worker }
363*d9f75844SAndroid Build Coastguard Worker 
Start()364*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::Start() {
365*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
366*d9f75844SAndroid Build Coastguard Worker   if (sending_) {
367*d9f75844SAndroid Build Coastguard Worker     return;
368*d9f75844SAndroid Build Coastguard Worker   }
369*d9f75844SAndroid Build Coastguard Worker   if (!config_.has_dscp && config_.min_bitrate_bps != -1 &&
370*d9f75844SAndroid Build Coastguard Worker       config_.max_bitrate_bps != -1 &&
371*d9f75844SAndroid Build Coastguard Worker       (allocate_audio_without_feedback_ || TransportSeqNumId(config_) != 0)) {
372*d9f75844SAndroid Build Coastguard Worker     rtp_transport_->AccountForAudioPacketsInPacedSender(true);
373*d9f75844SAndroid Build Coastguard Worker     rtp_transport_->IncludeOverheadInPacedSender();
374*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetAsPartOfAllocation(true);
375*d9f75844SAndroid Build Coastguard Worker     ConfigureBitrateObserver();
376*d9f75844SAndroid Build Coastguard Worker   } else {
377*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetAsPartOfAllocation(false);
378*d9f75844SAndroid Build Coastguard Worker   }
379*d9f75844SAndroid Build Coastguard Worker   channel_send_->StartSend();
380*d9f75844SAndroid Build Coastguard Worker   sending_ = true;
381*d9f75844SAndroid Build Coastguard Worker   audio_state()->AddSendingStream(this, encoder_sample_rate_hz_,
382*d9f75844SAndroid Build Coastguard Worker                                   encoder_num_channels_);
383*d9f75844SAndroid Build Coastguard Worker }
384*d9f75844SAndroid Build Coastguard Worker 
Stop()385*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::Stop() {
386*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
387*d9f75844SAndroid Build Coastguard Worker   if (!sending_) {
388*d9f75844SAndroid Build Coastguard Worker     return;
389*d9f75844SAndroid Build Coastguard Worker   }
390*d9f75844SAndroid Build Coastguard Worker 
391*d9f75844SAndroid Build Coastguard Worker   RemoveBitrateObserver();
392*d9f75844SAndroid Build Coastguard Worker   channel_send_->StopSend();
393*d9f75844SAndroid Build Coastguard Worker   sending_ = false;
394*d9f75844SAndroid Build Coastguard Worker   audio_state()->RemoveSendingStream(this);
395*d9f75844SAndroid Build Coastguard Worker }
396*d9f75844SAndroid Build Coastguard Worker 
SendAudioData(std::unique_ptr<AudioFrame> audio_frame)397*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::SendAudioData(std::unique_ptr<AudioFrame> audio_frame) {
398*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
399*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(audio_frame->sample_rate_hz_, 0);
400*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "AudioSendStream::SendAudioData");
401*d9f75844SAndroid Build Coastguard Worker   double duration = static_cast<double>(audio_frame->samples_per_channel_) /
402*d9f75844SAndroid Build Coastguard Worker                     audio_frame->sample_rate_hz_;
403*d9f75844SAndroid Build Coastguard Worker   {
404*d9f75844SAndroid Build Coastguard Worker     // Note: SendAudioData() passes the frame further down the pipeline and it
405*d9f75844SAndroid Build Coastguard Worker     // may eventually get sent. But this method is invoked even if we are not
406*d9f75844SAndroid Build Coastguard Worker     // connected, as long as we have an AudioSendStream (created as a result of
407*d9f75844SAndroid Build Coastguard Worker     // an O/A exchange). This means that we are calculating audio levels whether
408*d9f75844SAndroid Build Coastguard Worker     // or not we are sending samples.
409*d9f75844SAndroid Build Coastguard Worker     // TODO(https://crbug.com/webrtc/10771): All "media-source" related stats
410*d9f75844SAndroid Build Coastguard Worker     // should move from send-streams to the local audio sources or tracks; a
411*d9f75844SAndroid Build Coastguard Worker     // send-stream should not be required to read the microphone audio levels.
412*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&audio_level_lock_);
413*d9f75844SAndroid Build Coastguard Worker     audio_level_.ComputeLevel(*audio_frame, duration);
414*d9f75844SAndroid Build Coastguard Worker   }
415*d9f75844SAndroid Build Coastguard Worker   channel_send_->ProcessAndEncodeAudio(std::move(audio_frame));
416*d9f75844SAndroid Build Coastguard Worker }
417*d9f75844SAndroid Build Coastguard Worker 
SendTelephoneEvent(int payload_type,int payload_frequency,int event,int duration_ms)418*d9f75844SAndroid Build Coastguard Worker bool AudioSendStream::SendTelephoneEvent(int payload_type,
419*d9f75844SAndroid Build Coastguard Worker                                          int payload_frequency,
420*d9f75844SAndroid Build Coastguard Worker                                          int event,
421*d9f75844SAndroid Build Coastguard Worker                                          int duration_ms) {
422*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
423*d9f75844SAndroid Build Coastguard Worker   channel_send_->SetSendTelephoneEventPayloadType(payload_type,
424*d9f75844SAndroid Build Coastguard Worker                                                   payload_frequency);
425*d9f75844SAndroid Build Coastguard Worker   return channel_send_->SendTelephoneEventOutband(event, duration_ms);
426*d9f75844SAndroid Build Coastguard Worker }
427*d9f75844SAndroid Build Coastguard Worker 
SetMuted(bool muted)428*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::SetMuted(bool muted) {
429*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
430*d9f75844SAndroid Build Coastguard Worker   channel_send_->SetInputMute(muted);
431*d9f75844SAndroid Build Coastguard Worker }
432*d9f75844SAndroid Build Coastguard Worker 
GetStats() const433*d9f75844SAndroid Build Coastguard Worker webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
434*d9f75844SAndroid Build Coastguard Worker   return GetStats(true);
435*d9f75844SAndroid Build Coastguard Worker }
436*d9f75844SAndroid Build Coastguard Worker 
GetStats(bool has_remote_tracks) const437*d9f75844SAndroid Build Coastguard Worker webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
438*d9f75844SAndroid Build Coastguard Worker     bool has_remote_tracks) const {
439*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
440*d9f75844SAndroid Build Coastguard Worker   webrtc::AudioSendStream::Stats stats;
441*d9f75844SAndroid Build Coastguard Worker   stats.local_ssrc = config_.rtp.ssrc;
442*d9f75844SAndroid Build Coastguard Worker   stats.target_bitrate_bps = channel_send_->GetTargetBitrate();
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker   webrtc::CallSendStatistics call_stats = channel_send_->GetRTCPStatistics();
445*d9f75844SAndroid Build Coastguard Worker   stats.payload_bytes_sent = call_stats.payload_bytes_sent;
446*d9f75844SAndroid Build Coastguard Worker   stats.header_and_padding_bytes_sent =
447*d9f75844SAndroid Build Coastguard Worker       call_stats.header_and_padding_bytes_sent;
448*d9f75844SAndroid Build Coastguard Worker   stats.retransmitted_bytes_sent = call_stats.retransmitted_bytes_sent;
449*d9f75844SAndroid Build Coastguard Worker   stats.packets_sent = call_stats.packetsSent;
450*d9f75844SAndroid Build Coastguard Worker   stats.total_packet_send_delay = call_stats.total_packet_send_delay;
451*d9f75844SAndroid Build Coastguard Worker   stats.retransmitted_packets_sent = call_stats.retransmitted_packets_sent;
452*d9f75844SAndroid Build Coastguard Worker   // RTT isn't known until a RTCP report is received. Until then, VoiceEngine
453*d9f75844SAndroid Build Coastguard Worker   // returns 0 to indicate an error value.
454*d9f75844SAndroid Build Coastguard Worker   if (call_stats.rttMs > 0) {
455*d9f75844SAndroid Build Coastguard Worker     stats.rtt_ms = call_stats.rttMs;
456*d9f75844SAndroid Build Coastguard Worker   }
457*d9f75844SAndroid Build Coastguard Worker   if (config_.send_codec_spec) {
458*d9f75844SAndroid Build Coastguard Worker     const auto& spec = *config_.send_codec_spec;
459*d9f75844SAndroid Build Coastguard Worker     stats.codec_name = spec.format.name;
460*d9f75844SAndroid Build Coastguard Worker     stats.codec_payload_type = spec.payload_type;
461*d9f75844SAndroid Build Coastguard Worker 
462*d9f75844SAndroid Build Coastguard Worker     // Get data from the last remote RTCP report.
463*d9f75844SAndroid Build Coastguard Worker     for (const auto& block : channel_send_->GetRemoteRTCPReportBlocks()) {
464*d9f75844SAndroid Build Coastguard Worker       // Lookup report for send ssrc only.
465*d9f75844SAndroid Build Coastguard Worker       if (block.source_SSRC == stats.local_ssrc) {
466*d9f75844SAndroid Build Coastguard Worker         stats.packets_lost = block.cumulative_num_packets_lost;
467*d9f75844SAndroid Build Coastguard Worker         stats.fraction_lost = Q8ToFloat(block.fraction_lost);
468*d9f75844SAndroid Build Coastguard Worker         // Convert timestamps to milliseconds.
469*d9f75844SAndroid Build Coastguard Worker         if (spec.format.clockrate_hz / 1000 > 0) {
470*d9f75844SAndroid Build Coastguard Worker           stats.jitter_ms =
471*d9f75844SAndroid Build Coastguard Worker               block.interarrival_jitter / (spec.format.clockrate_hz / 1000);
472*d9f75844SAndroid Build Coastguard Worker         }
473*d9f75844SAndroid Build Coastguard Worker         break;
474*d9f75844SAndroid Build Coastguard Worker       }
475*d9f75844SAndroid Build Coastguard Worker     }
476*d9f75844SAndroid Build Coastguard Worker   }
477*d9f75844SAndroid Build Coastguard Worker 
478*d9f75844SAndroid Build Coastguard Worker   {
479*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&audio_level_lock_);
480*d9f75844SAndroid Build Coastguard Worker     stats.audio_level = audio_level_.LevelFullRange();
481*d9f75844SAndroid Build Coastguard Worker     stats.total_input_energy = audio_level_.TotalEnergy();
482*d9f75844SAndroid Build Coastguard Worker     stats.total_input_duration = audio_level_.TotalDuration();
483*d9f75844SAndroid Build Coastguard Worker   }
484*d9f75844SAndroid Build Coastguard Worker 
485*d9f75844SAndroid Build Coastguard Worker   stats.ana_statistics = channel_send_->GetANAStatistics();
486*d9f75844SAndroid Build Coastguard Worker 
487*d9f75844SAndroid Build Coastguard Worker   AudioProcessing* ap = audio_state_->audio_processing();
488*d9f75844SAndroid Build Coastguard Worker   if (ap) {
489*d9f75844SAndroid Build Coastguard Worker     stats.apm_statistics = ap->GetStatistics(has_remote_tracks);
490*d9f75844SAndroid Build Coastguard Worker   }
491*d9f75844SAndroid Build Coastguard Worker 
492*d9f75844SAndroid Build Coastguard Worker   stats.report_block_datas = std::move(call_stats.report_block_datas);
493*d9f75844SAndroid Build Coastguard Worker 
494*d9f75844SAndroid Build Coastguard Worker   stats.nacks_rcvd = call_stats.nacks_rcvd;
495*d9f75844SAndroid Build Coastguard Worker 
496*d9f75844SAndroid Build Coastguard Worker   return stats;
497*d9f75844SAndroid Build Coastguard Worker }
498*d9f75844SAndroid Build Coastguard Worker 
DeliverRtcp(const uint8_t * packet,size_t length)499*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
500*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
501*d9f75844SAndroid Build Coastguard Worker   channel_send_->ReceivedRTCPPacket(packet, length);
502*d9f75844SAndroid Build Coastguard Worker 
503*d9f75844SAndroid Build Coastguard Worker   {
504*d9f75844SAndroid Build Coastguard Worker     // Poll if overhead has changed, which it can do if ack triggers us to stop
505*d9f75844SAndroid Build Coastguard Worker     // sending mid/rid.
506*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&overhead_per_packet_lock_);
507*d9f75844SAndroid Build Coastguard Worker     UpdateOverheadForEncoder();
508*d9f75844SAndroid Build Coastguard Worker   }
509*d9f75844SAndroid Build Coastguard Worker   UpdateCachedTargetAudioBitrateConstraints();
510*d9f75844SAndroid Build Coastguard Worker }
511*d9f75844SAndroid Build Coastguard Worker 
OnBitrateUpdated(BitrateAllocationUpdate update)512*d9f75844SAndroid Build Coastguard Worker uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) {
513*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(rtp_transport_queue_);
514*d9f75844SAndroid Build Coastguard Worker 
515*d9f75844SAndroid Build Coastguard Worker   // Pick a target bitrate between the constraints. Overrules the allocator if
516*d9f75844SAndroid Build Coastguard Worker   // it 1) allocated a bitrate of zero to disable the stream or 2) allocated a
517*d9f75844SAndroid Build Coastguard Worker   // higher than max to allow for e.g. extra FEC.
518*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(cached_constraints_.has_value());
519*d9f75844SAndroid Build Coastguard Worker   update.target_bitrate.Clamp(cached_constraints_->min,
520*d9f75844SAndroid Build Coastguard Worker                               cached_constraints_->max);
521*d9f75844SAndroid Build Coastguard Worker   update.stable_target_bitrate.Clamp(cached_constraints_->min,
522*d9f75844SAndroid Build Coastguard Worker                                      cached_constraints_->max);
523*d9f75844SAndroid Build Coastguard Worker 
524*d9f75844SAndroid Build Coastguard Worker   channel_send_->OnBitrateAllocation(update);
525*d9f75844SAndroid Build Coastguard Worker 
526*d9f75844SAndroid Build Coastguard Worker   // The amount of audio protection is not exposed by the encoder, hence
527*d9f75844SAndroid Build Coastguard Worker   // always returning 0.
528*d9f75844SAndroid Build Coastguard Worker   return 0;
529*d9f75844SAndroid Build Coastguard Worker }
530*d9f75844SAndroid Build Coastguard Worker 
SetTransportOverhead(int transport_overhead_per_packet_bytes)531*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::SetTransportOverhead(
532*d9f75844SAndroid Build Coastguard Worker     int transport_overhead_per_packet_bytes) {
533*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
534*d9f75844SAndroid Build Coastguard Worker   {
535*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&overhead_per_packet_lock_);
536*d9f75844SAndroid Build Coastguard Worker     transport_overhead_per_packet_bytes_ = transport_overhead_per_packet_bytes;
537*d9f75844SAndroid Build Coastguard Worker     UpdateOverheadForEncoder();
538*d9f75844SAndroid Build Coastguard Worker   }
539*d9f75844SAndroid Build Coastguard Worker   UpdateCachedTargetAudioBitrateConstraints();
540*d9f75844SAndroid Build Coastguard Worker }
541*d9f75844SAndroid Build Coastguard Worker 
UpdateOverheadForEncoder()542*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::UpdateOverheadForEncoder() {
543*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
544*d9f75844SAndroid Build Coastguard Worker   size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
545*d9f75844SAndroid Build Coastguard Worker   if (overhead_per_packet_ == overhead_per_packet_bytes) {
546*d9f75844SAndroid Build Coastguard Worker     return;
547*d9f75844SAndroid Build Coastguard Worker   }
548*d9f75844SAndroid Build Coastguard Worker   overhead_per_packet_ = overhead_per_packet_bytes;
549*d9f75844SAndroid Build Coastguard Worker 
550*d9f75844SAndroid Build Coastguard Worker   channel_send_->CallEncoder([&](AudioEncoder* encoder) {
551*d9f75844SAndroid Build Coastguard Worker     encoder->OnReceivedOverhead(overhead_per_packet_bytes);
552*d9f75844SAndroid Build Coastguard Worker   });
553*d9f75844SAndroid Build Coastguard Worker   if (total_packet_overhead_bytes_ != overhead_per_packet_bytes) {
554*d9f75844SAndroid Build Coastguard Worker     total_packet_overhead_bytes_ = overhead_per_packet_bytes;
555*d9f75844SAndroid Build Coastguard Worker     if (registered_with_allocator_) {
556*d9f75844SAndroid Build Coastguard Worker       ConfigureBitrateObserver();
557*d9f75844SAndroid Build Coastguard Worker     }
558*d9f75844SAndroid Build Coastguard Worker   }
559*d9f75844SAndroid Build Coastguard Worker }
560*d9f75844SAndroid Build Coastguard Worker 
TestOnlyGetPerPacketOverheadBytes() const561*d9f75844SAndroid Build Coastguard Worker size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
562*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&overhead_per_packet_lock_);
563*d9f75844SAndroid Build Coastguard Worker   return GetPerPacketOverheadBytes();
564*d9f75844SAndroid Build Coastguard Worker }
565*d9f75844SAndroid Build Coastguard Worker 
GetPerPacketOverheadBytes() const566*d9f75844SAndroid Build Coastguard Worker size_t AudioSendStream::GetPerPacketOverheadBytes() const {
567*d9f75844SAndroid Build Coastguard Worker   return transport_overhead_per_packet_bytes_ +
568*d9f75844SAndroid Build Coastguard Worker          rtp_rtcp_module_->ExpectedPerPacketOverhead();
569*d9f75844SAndroid Build Coastguard Worker }
570*d9f75844SAndroid Build Coastguard Worker 
GetRtpState() const571*d9f75844SAndroid Build Coastguard Worker RtpState AudioSendStream::GetRtpState() const {
572*d9f75844SAndroid Build Coastguard Worker   return rtp_rtcp_module_->GetRtpState();
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker 
GetChannel() const575*d9f75844SAndroid Build Coastguard Worker const voe::ChannelSendInterface* AudioSendStream::GetChannel() const {
576*d9f75844SAndroid Build Coastguard Worker   return channel_send_.get();
577*d9f75844SAndroid Build Coastguard Worker }
578*d9f75844SAndroid Build Coastguard Worker 
audio_state()579*d9f75844SAndroid Build Coastguard Worker internal::AudioState* AudioSendStream::audio_state() {
580*d9f75844SAndroid Build Coastguard Worker   internal::AudioState* audio_state =
581*d9f75844SAndroid Build Coastguard Worker       static_cast<internal::AudioState*>(audio_state_.get());
582*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(audio_state);
583*d9f75844SAndroid Build Coastguard Worker   return audio_state;
584*d9f75844SAndroid Build Coastguard Worker }
585*d9f75844SAndroid Build Coastguard Worker 
audio_state() const586*d9f75844SAndroid Build Coastguard Worker const internal::AudioState* AudioSendStream::audio_state() const {
587*d9f75844SAndroid Build Coastguard Worker   internal::AudioState* audio_state =
588*d9f75844SAndroid Build Coastguard Worker       static_cast<internal::AudioState*>(audio_state_.get());
589*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(audio_state);
590*d9f75844SAndroid Build Coastguard Worker   return audio_state;
591*d9f75844SAndroid Build Coastguard Worker }
592*d9f75844SAndroid Build Coastguard Worker 
StoreEncoderProperties(int sample_rate_hz,size_t num_channels)593*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::StoreEncoderProperties(int sample_rate_hz,
594*d9f75844SAndroid Build Coastguard Worker                                              size_t num_channels) {
595*d9f75844SAndroid Build Coastguard Worker   encoder_sample_rate_hz_ = sample_rate_hz;
596*d9f75844SAndroid Build Coastguard Worker   encoder_num_channels_ = num_channels;
597*d9f75844SAndroid Build Coastguard Worker   if (sending_) {
598*d9f75844SAndroid Build Coastguard Worker     // Update AudioState's information about the stream.
599*d9f75844SAndroid Build Coastguard Worker     audio_state()->AddSendingStream(this, sample_rate_hz, num_channels);
600*d9f75844SAndroid Build Coastguard Worker   }
601*d9f75844SAndroid Build Coastguard Worker }
602*d9f75844SAndroid Build Coastguard Worker 
603*d9f75844SAndroid Build Coastguard Worker // Apply current codec settings to a single voe::Channel used for sending.
SetupSendCodec(const Config & new_config)604*d9f75844SAndroid Build Coastguard Worker bool AudioSendStream::SetupSendCodec(const Config& new_config) {
605*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(new_config.send_codec_spec);
606*d9f75844SAndroid Build Coastguard Worker   const auto& spec = *new_config.send_codec_spec;
607*d9f75844SAndroid Build Coastguard Worker 
608*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(new_config.encoder_factory);
609*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<AudioEncoder> encoder =
610*d9f75844SAndroid Build Coastguard Worker       new_config.encoder_factory->MakeAudioEncoder(
611*d9f75844SAndroid Build Coastguard Worker           spec.payload_type, spec.format, new_config.codec_pair_id);
612*d9f75844SAndroid Build Coastguard Worker 
613*d9f75844SAndroid Build Coastguard Worker   if (!encoder) {
614*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_ERROR) << "Unable to create encoder for "
615*d9f75844SAndroid Build Coastguard Worker                        << rtc::ToString(spec.format);
616*d9f75844SAndroid Build Coastguard Worker     return false;
617*d9f75844SAndroid Build Coastguard Worker   }
618*d9f75844SAndroid Build Coastguard Worker 
619*d9f75844SAndroid Build Coastguard Worker   // If a bitrate has been specified for the codec, use it over the
620*d9f75844SAndroid Build Coastguard Worker   // codec's default.
621*d9f75844SAndroid Build Coastguard Worker   if (spec.target_bitrate_bps) {
622*d9f75844SAndroid Build Coastguard Worker     encoder->OnReceivedTargetAudioBitrate(*spec.target_bitrate_bps);
623*d9f75844SAndroid Build Coastguard Worker   }
624*d9f75844SAndroid Build Coastguard Worker 
625*d9f75844SAndroid Build Coastguard Worker   // Enable ANA if configured (currently only used by Opus).
626*d9f75844SAndroid Build Coastguard Worker   if (new_config.audio_network_adaptor_config) {
627*d9f75844SAndroid Build Coastguard Worker     if (encoder->EnableAudioNetworkAdaptor(
628*d9f75844SAndroid Build Coastguard Worker             *new_config.audio_network_adaptor_config, event_log_)) {
629*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
630*d9f75844SAndroid Build Coastguard Worker                        << new_config.rtp.ssrc;
631*d9f75844SAndroid Build Coastguard Worker     } else {
632*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "Failed to enable Audio network adaptor on SSRC "
633*d9f75844SAndroid Build Coastguard Worker                        << new_config.rtp.ssrc;
634*d9f75844SAndroid Build Coastguard Worker     }
635*d9f75844SAndroid Build Coastguard Worker   }
636*d9f75844SAndroid Build Coastguard Worker 
637*d9f75844SAndroid Build Coastguard Worker   // Wrap the encoder in an AudioEncoderCNG, if VAD is enabled.
638*d9f75844SAndroid Build Coastguard Worker   if (spec.cng_payload_type) {
639*d9f75844SAndroid Build Coastguard Worker     AudioEncoderCngConfig cng_config;
640*d9f75844SAndroid Build Coastguard Worker     cng_config.num_channels = encoder->NumChannels();
641*d9f75844SAndroid Build Coastguard Worker     cng_config.payload_type = *spec.cng_payload_type;
642*d9f75844SAndroid Build Coastguard Worker     cng_config.speech_encoder = std::move(encoder);
643*d9f75844SAndroid Build Coastguard Worker     cng_config.vad_mode = Vad::kVadNormal;
644*d9f75844SAndroid Build Coastguard Worker     encoder = CreateComfortNoiseEncoder(std::move(cng_config));
645*d9f75844SAndroid Build Coastguard Worker 
646*d9f75844SAndroid Build Coastguard Worker     RegisterCngPayloadType(*spec.cng_payload_type,
647*d9f75844SAndroid Build Coastguard Worker                            new_config.send_codec_spec->format.clockrate_hz);
648*d9f75844SAndroid Build Coastguard Worker   }
649*d9f75844SAndroid Build Coastguard Worker 
650*d9f75844SAndroid Build Coastguard Worker   // Wrap the encoder in a RED encoder, if RED is enabled.
651*d9f75844SAndroid Build Coastguard Worker   if (spec.red_payload_type) {
652*d9f75844SAndroid Build Coastguard Worker     AudioEncoderCopyRed::Config red_config;
653*d9f75844SAndroid Build Coastguard Worker     red_config.payload_type = *spec.red_payload_type;
654*d9f75844SAndroid Build Coastguard Worker     red_config.speech_encoder = std::move(encoder);
655*d9f75844SAndroid Build Coastguard Worker     encoder = std::make_unique<AudioEncoderCopyRed>(std::move(red_config),
656*d9f75844SAndroid Build Coastguard Worker                                                     field_trials_);
657*d9f75844SAndroid Build Coastguard Worker   }
658*d9f75844SAndroid Build Coastguard Worker 
659*d9f75844SAndroid Build Coastguard Worker   // Set currently known overhead (used in ANA, opus only).
660*d9f75844SAndroid Build Coastguard Worker   // If overhead changes later, it will be updated in UpdateOverheadForEncoder.
661*d9f75844SAndroid Build Coastguard Worker   {
662*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&overhead_per_packet_lock_);
663*d9f75844SAndroid Build Coastguard Worker     size_t overhead = GetPerPacketOverheadBytes();
664*d9f75844SAndroid Build Coastguard Worker     if (overhead > 0) {
665*d9f75844SAndroid Build Coastguard Worker       encoder->OnReceivedOverhead(overhead);
666*d9f75844SAndroid Build Coastguard Worker     }
667*d9f75844SAndroid Build Coastguard Worker   }
668*d9f75844SAndroid Build Coastguard Worker 
669*d9f75844SAndroid Build Coastguard Worker   StoreEncoderProperties(encoder->SampleRateHz(), encoder->NumChannels());
670*d9f75844SAndroid Build Coastguard Worker   channel_send_->SetEncoder(new_config.send_codec_spec->payload_type,
671*d9f75844SAndroid Build Coastguard Worker                             std::move(encoder));
672*d9f75844SAndroid Build Coastguard Worker 
673*d9f75844SAndroid Build Coastguard Worker   return true;
674*d9f75844SAndroid Build Coastguard Worker }
675*d9f75844SAndroid Build Coastguard Worker 
ReconfigureSendCodec(const Config & new_config)676*d9f75844SAndroid Build Coastguard Worker bool AudioSendStream::ReconfigureSendCodec(const Config& new_config) {
677*d9f75844SAndroid Build Coastguard Worker   const auto& old_config = config_;
678*d9f75844SAndroid Build Coastguard Worker 
679*d9f75844SAndroid Build Coastguard Worker   if (!new_config.send_codec_spec) {
680*d9f75844SAndroid Build Coastguard Worker     // We cannot de-configure a send codec. So we will do nothing.
681*d9f75844SAndroid Build Coastguard Worker     // By design, the send codec should have not been configured.
682*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!old_config.send_codec_spec);
683*d9f75844SAndroid Build Coastguard Worker     return true;
684*d9f75844SAndroid Build Coastguard Worker   }
685*d9f75844SAndroid Build Coastguard Worker 
686*d9f75844SAndroid Build Coastguard Worker   if (new_config.send_codec_spec == old_config.send_codec_spec &&
687*d9f75844SAndroid Build Coastguard Worker       new_config.audio_network_adaptor_config ==
688*d9f75844SAndroid Build Coastguard Worker           old_config.audio_network_adaptor_config) {
689*d9f75844SAndroid Build Coastguard Worker     return true;
690*d9f75844SAndroid Build Coastguard Worker   }
691*d9f75844SAndroid Build Coastguard Worker 
692*d9f75844SAndroid Build Coastguard Worker   // If we have no encoder, or the format or payload type's changed, create a
693*d9f75844SAndroid Build Coastguard Worker   // new encoder.
694*d9f75844SAndroid Build Coastguard Worker   if (!old_config.send_codec_spec ||
695*d9f75844SAndroid Build Coastguard Worker       new_config.send_codec_spec->format !=
696*d9f75844SAndroid Build Coastguard Worker           old_config.send_codec_spec->format ||
697*d9f75844SAndroid Build Coastguard Worker       new_config.send_codec_spec->payload_type !=
698*d9f75844SAndroid Build Coastguard Worker           old_config.send_codec_spec->payload_type ||
699*d9f75844SAndroid Build Coastguard Worker       new_config.send_codec_spec->red_payload_type !=
700*d9f75844SAndroid Build Coastguard Worker           old_config.send_codec_spec->red_payload_type) {
701*d9f75844SAndroid Build Coastguard Worker     return SetupSendCodec(new_config);
702*d9f75844SAndroid Build Coastguard Worker   }
703*d9f75844SAndroid Build Coastguard Worker 
704*d9f75844SAndroid Build Coastguard Worker   const absl::optional<int>& new_target_bitrate_bps =
705*d9f75844SAndroid Build Coastguard Worker       new_config.send_codec_spec->target_bitrate_bps;
706*d9f75844SAndroid Build Coastguard Worker   // If a bitrate has been specified for the codec, use it over the
707*d9f75844SAndroid Build Coastguard Worker   // codec's default.
708*d9f75844SAndroid Build Coastguard Worker   if (new_target_bitrate_bps &&
709*d9f75844SAndroid Build Coastguard Worker       new_target_bitrate_bps !=
710*d9f75844SAndroid Build Coastguard Worker           old_config.send_codec_spec->target_bitrate_bps) {
711*d9f75844SAndroid Build Coastguard Worker     channel_send_->CallEncoder([&](AudioEncoder* encoder) {
712*d9f75844SAndroid Build Coastguard Worker       encoder->OnReceivedTargetAudioBitrate(*new_target_bitrate_bps);
713*d9f75844SAndroid Build Coastguard Worker     });
714*d9f75844SAndroid Build Coastguard Worker   }
715*d9f75844SAndroid Build Coastguard Worker 
716*d9f75844SAndroid Build Coastguard Worker   ReconfigureANA(new_config);
717*d9f75844SAndroid Build Coastguard Worker   ReconfigureCNG(new_config);
718*d9f75844SAndroid Build Coastguard Worker 
719*d9f75844SAndroid Build Coastguard Worker   return true;
720*d9f75844SAndroid Build Coastguard Worker }
721*d9f75844SAndroid Build Coastguard Worker 
ReconfigureANA(const Config & new_config)722*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::ReconfigureANA(const Config& new_config) {
723*d9f75844SAndroid Build Coastguard Worker   if (new_config.audio_network_adaptor_config ==
724*d9f75844SAndroid Build Coastguard Worker       config_.audio_network_adaptor_config) {
725*d9f75844SAndroid Build Coastguard Worker     return;
726*d9f75844SAndroid Build Coastguard Worker   }
727*d9f75844SAndroid Build Coastguard Worker   if (new_config.audio_network_adaptor_config) {
728*d9f75844SAndroid Build Coastguard Worker     // This lock needs to be acquired before CallEncoder, since it aquires
729*d9f75844SAndroid Build Coastguard Worker     // another lock and we need to maintain the same order at all call sites to
730*d9f75844SAndroid Build Coastguard Worker     // avoid deadlock.
731*d9f75844SAndroid Build Coastguard Worker     MutexLock lock(&overhead_per_packet_lock_);
732*d9f75844SAndroid Build Coastguard Worker     size_t overhead = GetPerPacketOverheadBytes();
733*d9f75844SAndroid Build Coastguard Worker     channel_send_->CallEncoder([&](AudioEncoder* encoder) {
734*d9f75844SAndroid Build Coastguard Worker       if (encoder->EnableAudioNetworkAdaptor(
735*d9f75844SAndroid Build Coastguard Worker               *new_config.audio_network_adaptor_config, event_log_)) {
736*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
737*d9f75844SAndroid Build Coastguard Worker                          << new_config.rtp.ssrc;
738*d9f75844SAndroid Build Coastguard Worker         if (overhead > 0) {
739*d9f75844SAndroid Build Coastguard Worker           encoder->OnReceivedOverhead(overhead);
740*d9f75844SAndroid Build Coastguard Worker         }
741*d9f75844SAndroid Build Coastguard Worker       } else {
742*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << "Failed to enable Audio network adaptor on SSRC "
743*d9f75844SAndroid Build Coastguard Worker                          << new_config.rtp.ssrc;
744*d9f75844SAndroid Build Coastguard Worker       }
745*d9f75844SAndroid Build Coastguard Worker     });
746*d9f75844SAndroid Build Coastguard Worker   } else {
747*d9f75844SAndroid Build Coastguard Worker     channel_send_->CallEncoder(
748*d9f75844SAndroid Build Coastguard Worker         [&](AudioEncoder* encoder) { encoder->DisableAudioNetworkAdaptor(); });
749*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << "Audio network adaptor disabled on SSRC "
750*d9f75844SAndroid Build Coastguard Worker                      << new_config.rtp.ssrc;
751*d9f75844SAndroid Build Coastguard Worker   }
752*d9f75844SAndroid Build Coastguard Worker }
753*d9f75844SAndroid Build Coastguard Worker 
ReconfigureCNG(const Config & new_config)754*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::ReconfigureCNG(const Config& new_config) {
755*d9f75844SAndroid Build Coastguard Worker   if (new_config.send_codec_spec->cng_payload_type ==
756*d9f75844SAndroid Build Coastguard Worker       config_.send_codec_spec->cng_payload_type) {
757*d9f75844SAndroid Build Coastguard Worker     return;
758*d9f75844SAndroid Build Coastguard Worker   }
759*d9f75844SAndroid Build Coastguard Worker 
760*d9f75844SAndroid Build Coastguard Worker   // Register the CNG payload type if it's been added, don't do anything if CNG
761*d9f75844SAndroid Build Coastguard Worker   // is removed. Payload types must not be redefined.
762*d9f75844SAndroid Build Coastguard Worker   if (new_config.send_codec_spec->cng_payload_type) {
763*d9f75844SAndroid Build Coastguard Worker     RegisterCngPayloadType(*new_config.send_codec_spec->cng_payload_type,
764*d9f75844SAndroid Build Coastguard Worker                            new_config.send_codec_spec->format.clockrate_hz);
765*d9f75844SAndroid Build Coastguard Worker   }
766*d9f75844SAndroid Build Coastguard Worker 
767*d9f75844SAndroid Build Coastguard Worker   // Wrap or unwrap the encoder in an AudioEncoderCNG.
768*d9f75844SAndroid Build Coastguard Worker   channel_send_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
769*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<AudioEncoder> old_encoder(std::move(*encoder_ptr));
770*d9f75844SAndroid Build Coastguard Worker     auto sub_encoders = old_encoder->ReclaimContainedEncoders();
771*d9f75844SAndroid Build Coastguard Worker     if (!sub_encoders.empty()) {
772*d9f75844SAndroid Build Coastguard Worker       // Replace enc with its sub encoder. We need to put the sub
773*d9f75844SAndroid Build Coastguard Worker       // encoder in a temporary first, since otherwise the old value
774*d9f75844SAndroid Build Coastguard Worker       // of enc would be destroyed before the new value got assigned,
775*d9f75844SAndroid Build Coastguard Worker       // which would be bad since the new value is a part of the old
776*d9f75844SAndroid Build Coastguard Worker       // value.
777*d9f75844SAndroid Build Coastguard Worker       auto tmp = std::move(sub_encoders[0]);
778*d9f75844SAndroid Build Coastguard Worker       old_encoder = std::move(tmp);
779*d9f75844SAndroid Build Coastguard Worker     }
780*d9f75844SAndroid Build Coastguard Worker     if (new_config.send_codec_spec->cng_payload_type) {
781*d9f75844SAndroid Build Coastguard Worker       AudioEncoderCngConfig config;
782*d9f75844SAndroid Build Coastguard Worker       config.speech_encoder = std::move(old_encoder);
783*d9f75844SAndroid Build Coastguard Worker       config.num_channels = config.speech_encoder->NumChannels();
784*d9f75844SAndroid Build Coastguard Worker       config.payload_type = *new_config.send_codec_spec->cng_payload_type;
785*d9f75844SAndroid Build Coastguard Worker       config.vad_mode = Vad::kVadNormal;
786*d9f75844SAndroid Build Coastguard Worker       *encoder_ptr = CreateComfortNoiseEncoder(std::move(config));
787*d9f75844SAndroid Build Coastguard Worker     } else {
788*d9f75844SAndroid Build Coastguard Worker       *encoder_ptr = std::move(old_encoder);
789*d9f75844SAndroid Build Coastguard Worker     }
790*d9f75844SAndroid Build Coastguard Worker   });
791*d9f75844SAndroid Build Coastguard Worker }
792*d9f75844SAndroid Build Coastguard Worker 
ReconfigureBitrateObserver(const webrtc::AudioSendStream::Config & new_config)793*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::ReconfigureBitrateObserver(
794*d9f75844SAndroid Build Coastguard Worker     const webrtc::AudioSendStream::Config& new_config) {
795*d9f75844SAndroid Build Coastguard Worker   // Since the Config's default is for both of these to be -1, this test will
796*d9f75844SAndroid Build Coastguard Worker   // allow us to configure the bitrate observer if the new config has bitrate
797*d9f75844SAndroid Build Coastguard Worker   // limits set, but would only have us call RemoveBitrateObserver if we were
798*d9f75844SAndroid Build Coastguard Worker   // previously configured with bitrate limits.
799*d9f75844SAndroid Build Coastguard Worker   if (config_.min_bitrate_bps == new_config.min_bitrate_bps &&
800*d9f75844SAndroid Build Coastguard Worker       config_.max_bitrate_bps == new_config.max_bitrate_bps &&
801*d9f75844SAndroid Build Coastguard Worker       config_.bitrate_priority == new_config.bitrate_priority &&
802*d9f75844SAndroid Build Coastguard Worker       TransportSeqNumId(config_) == TransportSeqNumId(new_config) &&
803*d9f75844SAndroid Build Coastguard Worker       config_.audio_network_adaptor_config ==
804*d9f75844SAndroid Build Coastguard Worker           new_config.audio_network_adaptor_config) {
805*d9f75844SAndroid Build Coastguard Worker     return;
806*d9f75844SAndroid Build Coastguard Worker   }
807*d9f75844SAndroid Build Coastguard Worker 
808*d9f75844SAndroid Build Coastguard Worker   if (!new_config.has_dscp && new_config.min_bitrate_bps != -1 &&
809*d9f75844SAndroid Build Coastguard Worker       new_config.max_bitrate_bps != -1 && TransportSeqNumId(new_config) != 0) {
810*d9f75844SAndroid Build Coastguard Worker     rtp_transport_->AccountForAudioPacketsInPacedSender(true);
811*d9f75844SAndroid Build Coastguard Worker     rtp_transport_->IncludeOverheadInPacedSender();
812*d9f75844SAndroid Build Coastguard Worker     // We may get a callback immediately as the observer is registered, so
813*d9f75844SAndroid Build Coastguard Worker     // make sure the bitrate limits in config_ are up-to-date.
814*d9f75844SAndroid Build Coastguard Worker     config_.min_bitrate_bps = new_config.min_bitrate_bps;
815*d9f75844SAndroid Build Coastguard Worker     config_.max_bitrate_bps = new_config.max_bitrate_bps;
816*d9f75844SAndroid Build Coastguard Worker 
817*d9f75844SAndroid Build Coastguard Worker     config_.bitrate_priority = new_config.bitrate_priority;
818*d9f75844SAndroid Build Coastguard Worker     ConfigureBitrateObserver();
819*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetAsPartOfAllocation(true);
820*d9f75844SAndroid Build Coastguard Worker   } else {
821*d9f75844SAndroid Build Coastguard Worker     rtp_transport_->AccountForAudioPacketsInPacedSender(false);
822*d9f75844SAndroid Build Coastguard Worker     RemoveBitrateObserver();
823*d9f75844SAndroid Build Coastguard Worker     rtp_rtcp_module_->SetAsPartOfAllocation(false);
824*d9f75844SAndroid Build Coastguard Worker   }
825*d9f75844SAndroid Build Coastguard Worker }
826*d9f75844SAndroid Build Coastguard Worker 
ConfigureBitrateObserver()827*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::ConfigureBitrateObserver() {
828*d9f75844SAndroid Build Coastguard Worker   // This either updates the current observer or adds a new observer.
829*d9f75844SAndroid Build Coastguard Worker   // TODO(srte): Add overhead compensation here.
830*d9f75844SAndroid Build Coastguard Worker   auto constraints = GetMinMaxBitrateConstraints();
831*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(constraints.has_value());
832*d9f75844SAndroid Build Coastguard Worker 
833*d9f75844SAndroid Build Coastguard Worker   DataRate priority_bitrate = allocation_settings_.priority_bitrate;
834*d9f75844SAndroid Build Coastguard Worker   if (use_legacy_overhead_calculation_) {
835*d9f75844SAndroid Build Coastguard Worker     // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
836*d9f75844SAndroid Build Coastguard Worker     constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
837*d9f75844SAndroid Build Coastguard Worker     const TimeDelta kMinPacketDuration = TimeDelta::Millis(20);
838*d9f75844SAndroid Build Coastguard Worker     DataRate max_overhead =
839*d9f75844SAndroid Build Coastguard Worker         DataSize::Bytes(kOverheadPerPacket) / kMinPacketDuration;
840*d9f75844SAndroid Build Coastguard Worker     priority_bitrate += max_overhead;
841*d9f75844SAndroid Build Coastguard Worker   } else {
842*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(frame_length_range_);
843*d9f75844SAndroid Build Coastguard Worker     const DataSize overhead_per_packet =
844*d9f75844SAndroid Build Coastguard Worker         DataSize::Bytes(total_packet_overhead_bytes_);
845*d9f75844SAndroid Build Coastguard Worker     DataRate min_overhead = overhead_per_packet / frame_length_range_->second;
846*d9f75844SAndroid Build Coastguard Worker     priority_bitrate += min_overhead;
847*d9f75844SAndroid Build Coastguard Worker   }
848*d9f75844SAndroid Build Coastguard Worker 
849*d9f75844SAndroid Build Coastguard Worker   if (allocation_settings_.priority_bitrate_raw)
850*d9f75844SAndroid Build Coastguard Worker     priority_bitrate = *allocation_settings_.priority_bitrate_raw;
851*d9f75844SAndroid Build Coastguard Worker 
852*d9f75844SAndroid Build Coastguard Worker   rtp_transport_queue_->RunOrPost([this, constraints, priority_bitrate,
853*d9f75844SAndroid Build Coastguard Worker                                    config_bitrate_priority =
854*d9f75844SAndroid Build Coastguard Worker                                        config_.bitrate_priority] {
855*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(rtp_transport_queue_);
856*d9f75844SAndroid Build Coastguard Worker     bitrate_allocator_->AddObserver(
857*d9f75844SAndroid Build Coastguard Worker         this,
858*d9f75844SAndroid Build Coastguard Worker         MediaStreamAllocationConfig{
859*d9f75844SAndroid Build Coastguard Worker             constraints->min.bps<uint32_t>(), constraints->max.bps<uint32_t>(),
860*d9f75844SAndroid Build Coastguard Worker             0, priority_bitrate.bps(), true,
861*d9f75844SAndroid Build Coastguard Worker             allocation_settings_.bitrate_priority.value_or(
862*d9f75844SAndroid Build Coastguard Worker                 config_bitrate_priority)});
863*d9f75844SAndroid Build Coastguard Worker   });
864*d9f75844SAndroid Build Coastguard Worker   registered_with_allocator_ = true;
865*d9f75844SAndroid Build Coastguard Worker }
866*d9f75844SAndroid Build Coastguard Worker 
RemoveBitrateObserver()867*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::RemoveBitrateObserver() {
868*d9f75844SAndroid Build Coastguard Worker   registered_with_allocator_ = false;
869*d9f75844SAndroid Build Coastguard Worker   rtp_transport_queue_->RunSynchronous([this] {
870*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(rtp_transport_queue_);
871*d9f75844SAndroid Build Coastguard Worker     bitrate_allocator_->RemoveObserver(this);
872*d9f75844SAndroid Build Coastguard Worker   });
873*d9f75844SAndroid Build Coastguard Worker }
874*d9f75844SAndroid Build Coastguard Worker 
875*d9f75844SAndroid Build Coastguard Worker absl::optional<AudioSendStream::TargetAudioBitrateConstraints>
GetMinMaxBitrateConstraints() const876*d9f75844SAndroid Build Coastguard Worker AudioSendStream::GetMinMaxBitrateConstraints() const {
877*d9f75844SAndroid Build Coastguard Worker   if (config_.min_bitrate_bps < 0 || config_.max_bitrate_bps < 0) {
878*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Config is invalid: min_bitrate_bps="
879*d9f75844SAndroid Build Coastguard Worker                         << config_.min_bitrate_bps
880*d9f75844SAndroid Build Coastguard Worker                         << "; max_bitrate_bps=" << config_.max_bitrate_bps
881*d9f75844SAndroid Build Coastguard Worker                         << "; both expected greater or equal to 0";
882*d9f75844SAndroid Build Coastguard Worker     return absl::nullopt;
883*d9f75844SAndroid Build Coastguard Worker   }
884*d9f75844SAndroid Build Coastguard Worker   TargetAudioBitrateConstraints constraints{
885*d9f75844SAndroid Build Coastguard Worker       DataRate::BitsPerSec(config_.min_bitrate_bps),
886*d9f75844SAndroid Build Coastguard Worker       DataRate::BitsPerSec(config_.max_bitrate_bps)};
887*d9f75844SAndroid Build Coastguard Worker 
888*d9f75844SAndroid Build Coastguard Worker   // If bitrates were explicitly overriden via field trial, use those values.
889*d9f75844SAndroid Build Coastguard Worker   if (allocation_settings_.min_bitrate)
890*d9f75844SAndroid Build Coastguard Worker     constraints.min = *allocation_settings_.min_bitrate;
891*d9f75844SAndroid Build Coastguard Worker   if (allocation_settings_.max_bitrate)
892*d9f75844SAndroid Build Coastguard Worker     constraints.max = *allocation_settings_.max_bitrate;
893*d9f75844SAndroid Build Coastguard Worker 
894*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(constraints.min, DataRate::Zero());
895*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(constraints.max, DataRate::Zero());
896*d9f75844SAndroid Build Coastguard Worker   if (constraints.max < constraints.min) {
897*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "TargetAudioBitrateConstraints::max is less than "
898*d9f75844SAndroid Build Coastguard Worker                         << "TargetAudioBitrateConstraints::min";
899*d9f75844SAndroid Build Coastguard Worker     return absl::nullopt;
900*d9f75844SAndroid Build Coastguard Worker   }
901*d9f75844SAndroid Build Coastguard Worker   if (use_legacy_overhead_calculation_) {
902*d9f75844SAndroid Build Coastguard Worker     // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
903*d9f75844SAndroid Build Coastguard Worker     const DataSize kOverheadPerPacket = DataSize::Bytes(20 + 8 + 10 + 12);
904*d9f75844SAndroid Build Coastguard Worker     const TimeDelta kMaxFrameLength =
905*d9f75844SAndroid Build Coastguard Worker         TimeDelta::Millis(60);  // Based on Opus spec
906*d9f75844SAndroid Build Coastguard Worker     const DataRate kMinOverhead = kOverheadPerPacket / kMaxFrameLength;
907*d9f75844SAndroid Build Coastguard Worker     constraints.min += kMinOverhead;
908*d9f75844SAndroid Build Coastguard Worker     constraints.max += kMinOverhead;
909*d9f75844SAndroid Build Coastguard Worker   } else {
910*d9f75844SAndroid Build Coastguard Worker     if (!frame_length_range_.has_value()) {
911*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "frame_length_range_ is not set";
912*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
913*d9f75844SAndroid Build Coastguard Worker     }
914*d9f75844SAndroid Build Coastguard Worker     const DataSize kOverheadPerPacket =
915*d9f75844SAndroid Build Coastguard Worker         DataSize::Bytes(total_packet_overhead_bytes_);
916*d9f75844SAndroid Build Coastguard Worker     constraints.min += kOverheadPerPacket / frame_length_range_->second;
917*d9f75844SAndroid Build Coastguard Worker     constraints.max += kOverheadPerPacket / frame_length_range_->first;
918*d9f75844SAndroid Build Coastguard Worker   }
919*d9f75844SAndroid Build Coastguard Worker   return constraints;
920*d9f75844SAndroid Build Coastguard Worker }
921*d9f75844SAndroid Build Coastguard Worker 
RegisterCngPayloadType(int payload_type,int clockrate_hz)922*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::RegisterCngPayloadType(int payload_type,
923*d9f75844SAndroid Build Coastguard Worker                                              int clockrate_hz) {
924*d9f75844SAndroid Build Coastguard Worker   channel_send_->RegisterCngPayloadType(payload_type, clockrate_hz);
925*d9f75844SAndroid Build Coastguard Worker }
926*d9f75844SAndroid Build Coastguard Worker 
UpdateCachedTargetAudioBitrateConstraints()927*d9f75844SAndroid Build Coastguard Worker void AudioSendStream::UpdateCachedTargetAudioBitrateConstraints() {
928*d9f75844SAndroid Build Coastguard Worker   absl::optional<AudioSendStream::TargetAudioBitrateConstraints>
929*d9f75844SAndroid Build Coastguard Worker       new_constraints = GetMinMaxBitrateConstraints();
930*d9f75844SAndroid Build Coastguard Worker   if (!new_constraints.has_value()) {
931*d9f75844SAndroid Build Coastguard Worker     return;
932*d9f75844SAndroid Build Coastguard Worker   }
933*d9f75844SAndroid Build Coastguard Worker   rtp_transport_queue_->RunOrPost([this, new_constraints]() {
934*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_RUN_ON(rtp_transport_queue_);
935*d9f75844SAndroid Build Coastguard Worker     cached_constraints_ = new_constraints;
936*d9f75844SAndroid Build Coastguard Worker   });
937*d9f75844SAndroid Build Coastguard Worker }
938*d9f75844SAndroid Build Coastguard Worker 
939*d9f75844SAndroid Build Coastguard Worker }  // namespace internal
940*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
941