blob: cd137d9c8952f3effa7fc21a547496d71b3cc0b6 [file] [log] [blame]
solenbergc7a8b082015-10-16 21:35:071/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "audio/audio_send_stream.h"
solenbergc7a8b082015-10-16 21:35:0712
13#include <string>
ossu20a4b3f2017-04-27 09:08:5214#include <utility>
15#include <vector>
solenbergc7a8b082015-10-16 21:35:0716
Niels Möllerfa4e1852018-08-14 07:43:3417#include "absl/memory/memory.h"
Yves Gerey988cc082018-10-23 10:03:0118#include "api/audio_codecs/audio_encoder.h"
19#include "api/audio_codecs/audio_encoder_factory.h"
20#include "api/audio_codecs/audio_format.h"
21#include "api/call/transport.h"
Steve Anton10542f22019-01-11 17:11:0022#include "api/crypto/frame_encryptor_interface.h"
Artem Titov741daaf2019-03-21 13:37:3623#include "api/function_view.h"
Danil Chapovalov83bbe912019-08-07 10:24:5324#include "api/rtc_event_log/rtc_event_log.h"
Niels Möller65f17ca2019-09-12 11:59:3625#include "api/transport/media/media_transport_config.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3126#include "audio/audio_state.h"
Yves Gerey988cc082018-10-23 10:03:0127#include "audio/channel_send.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3128#include "audio/conversion.h"
Yves Gerey988cc082018-10-23 10:03:0129#include "call/rtp_config.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3130#include "call/rtp_transport_controller_send_interface.h"
Yves Gerey988cc082018-10-23 10:03:0131#include "common_audio/vad/include/vad.h"
Oskar Sundbom56ef3052018-10-30 15:11:0232#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
Oskar Sundbom56ef3052018-10-30 15:11:0233#include "logging/rtc_event_log/rtc_stream_config.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3134#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
Yves Gerey988cc082018-10-23 10:03:0135#include "modules/audio_processing/include/audio_processing.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3136#include "rtc_base/checks.h"
37#include "rtc_base/event.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3138#include "rtc_base/logging.h"
Jonas Olssonabbe8412018-04-03 11:40:0539#include "rtc_base/strings/audio_format_to_string.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3140#include "rtc_base/task_queue.h"
Alex Narestcedd3512017-12-07 19:54:5541#include "system_wrappers/include/field_trial.h"
solenbergc7a8b082015-10-16 21:35:0742
43namespace webrtc {
solenbergc7a8b082015-10-16 21:35:0744namespace internal {
Fredrik Solenberg8f5787a2018-01-11 12:52:3045namespace {
eladalonedd6eea2017-05-25 07:15:3546// TODO(eladalon): Subsequent CL will make these values experiment-dependent.
elad.alond12a8e12017-03-23 18:04:4847constexpr size_t kPacketLossTrackerMaxWindowSizeMs = 15000;
48constexpr size_t kPacketLossRateMinNumAckedPackets = 50;
49constexpr size_t kRecoverablePacketLossRateMinNumAckedPairs = 40;
50
Oskar Sundbom56ef3052018-10-30 15:11:0251void UpdateEventLogStreamConfig(RtcEventLog* event_log,
52 const AudioSendStream::Config& config,
53 const AudioSendStream::Config* old_config) {
54 using SendCodecSpec = AudioSendStream::Config::SendCodecSpec;
55 // Only update if any of the things we log have changed.
56 auto payload_types_equal = [](const absl::optional<SendCodecSpec>& a,
57 const absl::optional<SendCodecSpec>& b) {
58 if (a.has_value() && b.has_value()) {
59 return a->format.name == b->format.name &&
60 a->payload_type == b->payload_type;
61 }
62 return !a.has_value() && !b.has_value();
63 };
64
65 if (old_config && config.rtp.ssrc == old_config->rtp.ssrc &&
66 config.rtp.extensions == old_config->rtp.extensions &&
67 payload_types_equal(config.send_codec_spec,
68 old_config->send_codec_spec)) {
69 return;
70 }
71
72 auto rtclog_config = absl::make_unique<rtclog::StreamConfig>();
73 rtclog_config->local_ssrc = config.rtp.ssrc;
74 rtclog_config->rtp_extensions = config.rtp.extensions;
75 if (config.send_codec_spec) {
76 rtclog_config->codecs.emplace_back(config.send_codec_spec->format.name,
77 config.send_codec_spec->payload_type, 0);
78 }
79 event_log->Log(absl::make_unique<RtcEventAudioSendStreamConfig>(
80 std::move(rtclog_config)));
81}
82
ossu20a4b3f2017-04-27 09:08:5283} // namespace
84
solenberg566ef242015-11-06 23:34:4985AudioSendStream::AudioSendStream(
Sebastian Jansson977b3352019-03-04 16:43:3486 Clock* clock,
solenberg566ef242015-11-06 23:34:4987 const webrtc::AudioSendStream::Config& config,
Stefan Holmerb86d4e42015-12-07 09:26:1888 const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
Sebastian Jansson44dd9f22019-03-08 13:50:3089 TaskQueueFactory* task_queue_factory,
Fredrik Solenberg8f5787a2018-01-11 12:52:3090 ProcessThread* module_process_thread,
Niels Möller7d76a312018-10-26 10:57:0791 RtpTransportControllerSendInterface* rtp_transport,
Niels Möller67b011d2018-10-22 11:00:4092 BitrateAllocatorInterface* bitrate_allocator,
michaelt9332b7d2016-11-30 15:51:1393 RtcEventLog* event_log,
ossuc3d4b482017-05-23 13:07:1194 RtcpRttStats* rtcp_rtt_stats,
Sam Zackrissonff058162018-11-20 16:15:1395 const absl::optional<RtpState>& suspended_rtp_state)
Sebastian Jansson977b3352019-03-04 16:43:3496 : AudioSendStream(clock,
97 config,
Fredrik Solenberg8f5787a2018-01-11 12:52:3098 audio_state,
Sebastian Jansson44dd9f22019-03-08 13:50:3099 task_queue_factory,
Niels Möller7d76a312018-10-26 10:57:07100 rtp_transport,
Fredrik Solenberg8f5787a2018-01-11 12:52:30101 bitrate_allocator,
102 event_log,
103 rtcp_rtt_stats,
104 suspended_rtp_state,
Sebastian Jansson977b3352019-03-04 16:43:34105 voe::CreateChannelSend(clock,
Sebastian Jansson44dd9f22019-03-08 13:50:30106 task_queue_factory,
Niels Möllerdced9f62018-11-19 09:27:07107 module_process_thread,
Anton Sukhanov4f08faa2019-05-21 18:12:57108 config.media_transport_config,
Anton Sukhanov626015d2019-02-04 23:16:06109 /*overhead_observer=*/this,
Niels Möllere9771992018-11-26 09:55:07110 config.send_transport,
Niels Möllerdced9f62018-11-19 09:27:07111 rtcp_rtt_stats,
112 event_log,
113 config.frame_encryptor,
114 config.crypto_options,
115 config.rtp.extmap_allow_mixed,
Erik Språng4c2c4122019-07-11 13:20:15116 config.rtcp_report_interval_ms,
117 config.rtp.ssrc)) {}
Fredrik Solenberg8f5787a2018-01-11 12:52:30118
119AudioSendStream::AudioSendStream(
Sebastian Jansson977b3352019-03-04 16:43:34120 Clock* clock,
Fredrik Solenberg8f5787a2018-01-11 12:52:30121 const webrtc::AudioSendStream::Config& config,
122 const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
Sebastian Jansson44dd9f22019-03-08 13:50:30123 TaskQueueFactory* task_queue_factory,
Niels Möller7d76a312018-10-26 10:57:07124 RtpTransportControllerSendInterface* rtp_transport,
Niels Möller67b011d2018-10-22 11:00:40125 BitrateAllocatorInterface* bitrate_allocator,
Fredrik Solenberg8f5787a2018-01-11 12:52:30126 RtcEventLog* event_log,
127 RtcpRttStats* rtcp_rtt_stats,
Danil Chapovalovb9b146c2018-06-15 10:28:07128 const absl::optional<RtpState>& suspended_rtp_state,
Niels Möllerdced9f62018-11-19 09:27:07129 std::unique_ptr<voe::ChannelSendInterface> channel_send)
Sebastian Jansson977b3352019-03-04 16:43:34130 : clock_(clock),
Sebastian Jansson0b698262019-03-07 08:17:19131 worker_queue_(rtp_transport->GetWorkerQueue()),
Anton Sukhanov4f08faa2019-05-21 18:12:57132 config_(Config(/*send_transport=*/nullptr, MediaTransportConfig())),
mflodman86cc6ff2016-07-26 11:44:06133 audio_state_(audio_state),
Niels Möllerdced9f62018-11-19 09:27:07134 channel_send_(std::move(channel_send)),
ossu20a4b3f2017-04-27 09:08:52135 event_log_(event_log),
michaeltf4caaab2017-01-17 07:55:07136 bitrate_allocator_(bitrate_allocator),
Niels Möller7d76a312018-10-26 10:57:07137 rtp_transport_(rtp_transport),
elad.alond12a8e12017-03-23 18:04:48138 packet_loss_tracker_(kPacketLossTrackerMaxWindowSizeMs,
139 kPacketLossRateMinNumAckedPackets,
ossuc3d4b482017-05-23 13:07:11140 kRecoverablePacketLossRateMinNumAckedPairs),
141 rtp_rtcp_module_(nullptr),
Sam Zackrissonff058162018-11-20 16:15:13142 suspended_rtp_state_(suspended_rtp_state) {
Jonas Olsson24ea8222018-01-25 09:14:29143 RTC_LOG(LS_INFO) << "AudioSendStream: " << config.rtp.ssrc;
Fredrik Solenberg8f5787a2018-01-11 12:52:30144 RTC_DCHECK(worker_queue_);
145 RTC_DCHECK(audio_state_);
Niels Möllerdced9f62018-11-19 09:27:07146 RTC_DCHECK(channel_send_);
Fredrik Solenberg8f5787a2018-01-11 12:52:30147 RTC_DCHECK(bitrate_allocator_);
Sebastian Jansson0b698262019-03-07 08:17:19148 // Currently we require the rtp transport even when media transport is used.
149 RTC_DCHECK(rtp_transport);
150
Niels Möller7d76a312018-10-26 10:57:07151 // TODO(nisse): Eventually, we should have only media_transport. But for the
152 // time being, we can have either. When media transport is injected, there
153 // should be no rtp_transport, and below check should be strengthened to XOR
154 // (either rtp_transport or media_transport but not both).
Anton Sukhanov4f08faa2019-05-21 18:12:57155 RTC_DCHECK(rtp_transport || config.media_transport_config.media_transport);
156 if (config.media_transport_config.media_transport) {
Anton Sukhanov626015d2019-02-04 23:16:06157 // TODO(sukhanov): Currently media transport audio overhead is considered
158 // constant, we will not get overhead_observer calls when using
159 // media_transport. In the future when we introduce RTP media transport we
160 // should make audio overhead interface consistent and work for both RTP and
161 // non-RTP implementations.
162 audio_overhead_per_packet_bytes_ =
Anton Sukhanov4f08faa2019-05-21 18:12:57163 config.media_transport_config.media_transport->GetAudioPacketOverhead();
Anton Sukhanov626015d2019-02-04 23:16:06164 }
Niels Möllerdced9f62018-11-19 09:27:07165 rtp_rtcp_module_ = channel_send_->GetRtpRtcp();
ossuc3d4b482017-05-23 13:07:11166 RTC_DCHECK(rtp_rtcp_module_);
mflodman3d7db262016-04-29 07:57:13167
ossu20a4b3f2017-04-27 09:08:52168 ConfigureStream(this, config, true);
elad.alond12a8e12017-03-23 18:04:48169
Sebastian Janssonc01367d2019-04-08 13:20:44170 pacer_thread_checker_.Detach();
Niels Möller7d76a312018-10-26 10:57:07171 if (rtp_transport_) {
172 // Signal congestion controller this object is ready for OnPacket*
173 // callbacks.
174 rtp_transport_->RegisterPacketFeedbackObserver(this);
175 }
solenbergc7a8b082015-10-16 21:35:07176}
177
178AudioSendStream::~AudioSendStream() {
Sebastian Janssonc01367d2019-04-08 13:20:44179 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Jonas Olsson24ea8222018-01-25 09:14:29180 RTC_LOG(LS_INFO) << "~AudioSendStream: " << config_.rtp.ssrc;
Fredrik Solenberg2a877972017-12-15 15:42:15181 RTC_DCHECK(!sending_);
Niels Möller7d76a312018-10-26 10:57:07182 if (rtp_transport_) {
183 rtp_transport_->DeRegisterPacketFeedbackObserver(this);
Niels Möllerdced9f62018-11-19 09:27:07184 channel_send_->ResetSenderCongestionControlObjects();
Niels Möller7d76a312018-10-26 10:57:07185 }
Sebastian Jansson8672cac2019-03-01 14:57:55186 // Blocking call to synchronize state with worker queue to ensure that there
187 // are no pending tasks left that keeps references to audio.
188 rtc::Event thread_sync_event;
189 worker_queue_->PostTask([&] { thread_sync_event.Set(); });
190 thread_sync_event.Wait(rtc::Event::kForever);
solenbergc7a8b082015-10-16 21:35:07191}
192
eladalonabbc4302017-07-26 09:09:44193const webrtc::AudioSendStream::Config& AudioSendStream::GetConfig() const {
Sebastian Janssonc01367d2019-04-08 13:20:44194 RTC_DCHECK(worker_thread_checker_.IsCurrent());
eladalonabbc4302017-07-26 09:09:44195 return config_;
196}
197
ossu20a4b3f2017-04-27 09:08:52198void AudioSendStream::Reconfigure(
199 const webrtc::AudioSendStream::Config& new_config) {
Sebastian Janssonc01367d2019-04-08 13:20:44200 RTC_DCHECK(worker_thread_checker_.IsCurrent());
ossu20a4b3f2017-04-27 09:08:52201 ConfigureStream(this, new_config, false);
202}
203
Alex Narestcedd3512017-12-07 19:54:55204AudioSendStream::ExtensionIds AudioSendStream::FindExtensionIds(
205 const std::vector<RtpExtension>& extensions) {
206 ExtensionIds ids;
207 for (const auto& extension : extensions) {
208 if (extension.uri == RtpExtension::kAudioLevelUri) {
209 ids.audio_level = extension.id;
Sebastian Jansson71c6b562019-08-14 09:31:02210 } else if (extension.uri == RtpExtension::kAbsSendTimeUri) {
211 ids.abs_send_time = extension.id;
Alex Narestcedd3512017-12-07 19:54:55212 } else if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
213 ids.transport_sequence_number = extension.id;
Steve Antonbb50ce52018-03-26 17:24:32214 } else if (extension.uri == RtpExtension::kMidUri) {
215 ids.mid = extension.id;
Amit Hilbuch77938e62018-12-21 17:23:38216 } else if (extension.uri == RtpExtension::kRidUri) {
217 ids.rid = extension.id;
218 } else if (extension.uri == RtpExtension::kRepairedRidUri) {
219 ids.repaired_rid = extension.id;
Alex Narestcedd3512017-12-07 19:54:55220 }
221 }
222 return ids;
223}
224
Sebastian Jansson470a5ea2019-01-23 11:37:49225int AudioSendStream::TransportSeqNumId(const AudioSendStream::Config& config) {
226 return FindExtensionIds(config.rtp.extensions).transport_sequence_number;
227}
228
ossu20a4b3f2017-04-27 09:08:52229void AudioSendStream::ConfigureStream(
230 webrtc::internal::AudioSendStream* stream,
231 const webrtc::AudioSendStream::Config& new_config,
232 bool first_time) {
Jonas Olsson24ea8222018-01-25 09:14:29233 RTC_LOG(LS_INFO) << "AudioSendStream::ConfigureStream: "
234 << new_config.ToString();
Oskar Sundbom56ef3052018-10-30 15:11:02235 UpdateEventLogStreamConfig(stream->event_log_, new_config,
236 first_time ? nullptr : &stream->config_);
237
Niels Möllerdced9f62018-11-19 09:27:07238 const auto& channel_send = stream->channel_send_;
ossu20a4b3f2017-04-27 09:08:52239 const auto& old_config = stream->config_;
240
Yves Gerey17048012019-07-26 15:49:52241 stream->config_cs_.Enter();
242
Niels Möllere9771992018-11-26 09:55:07243 // Configuration parameters which cannot be changed.
244 RTC_DCHECK(first_time ||
245 old_config.send_transport == new_config.send_transport);
Erik Språng70efdde2019-08-21 11:36:20246 RTC_DCHECK(first_time || old_config.rtp.ssrc == new_config.rtp.ssrc);
247 if (stream->suspended_rtp_state_ && first_time) {
Erik Språng4c2c4122019-07-11 13:20:15248 stream->rtp_rtcp_module_->SetRtpState(*stream->suspended_rtp_state_);
ossu20a4b3f2017-04-27 09:08:52249 }
250 if (first_time || old_config.rtp.c_name != new_config.rtp.c_name) {
Niels Möllerdced9f62018-11-19 09:27:07251 channel_send->SetRTCP_CNAME(new_config.rtp.c_name);
ossu20a4b3f2017-04-27 09:08:52252 }
ossu20a4b3f2017-04-27 09:08:52253
Benjamin Wright84583f62018-10-04 21:22:34254 // Enable the frame encryptor if a new frame encryptor has been provided.
255 if (first_time || new_config.frame_encryptor != old_config.frame_encryptor) {
Niels Möllerdced9f62018-11-19 09:27:07256 channel_send->SetFrameEncryptor(new_config.frame_encryptor);
Benjamin Wright84583f62018-10-04 21:22:34257 }
258
Johannes Kron9190b822018-10-29 10:22:05259 if (first_time ||
260 new_config.rtp.extmap_allow_mixed != old_config.rtp.extmap_allow_mixed) {
Niels Möllerdced9f62018-11-19 09:27:07261 channel_send->SetExtmapAllowMixed(new_config.rtp.extmap_allow_mixed);
Johannes Kron9190b822018-10-29 10:22:05262 }
263
Alex Narestcedd3512017-12-07 19:54:55264 const ExtensionIds old_ids = FindExtensionIds(old_config.rtp.extensions);
265 const ExtensionIds new_ids = FindExtensionIds(new_config.rtp.extensions);
Yves Gerey17048012019-07-26 15:49:52266
267 stream->config_cs_.Leave();
268
ossu20a4b3f2017-04-27 09:08:52269 // Audio level indication
270 if (first_time || new_ids.audio_level != old_ids.audio_level) {
Niels Möllerdced9f62018-11-19 09:27:07271 channel_send->SetSendAudioLevelIndicationStatus(new_ids.audio_level != 0,
272 new_ids.audio_level);
ossu20a4b3f2017-04-27 09:08:52273 }
Sebastian Jansson71c6b562019-08-14 09:31:02274
275 if (first_time || new_ids.abs_send_time != old_ids.abs_send_time) {
276 channel_send->GetRtpRtcp()->DeregisterSendRtpHeaderExtension(
277 kRtpExtensionAbsoluteSendTime);
278 if (new_ids.abs_send_time) {
279 channel_send->GetRtpRtcp()->RegisterSendRtpHeaderExtension(
280 kRtpExtensionAbsoluteSendTime, new_ids.abs_send_time);
281 }
282 }
283
Sebastian Jansson8d9c5402017-11-15 16:22:16284 bool transport_seq_num_id_changed =
285 new_ids.transport_sequence_number != old_ids.transport_sequence_number;
Sebastian Jansson470a5ea2019-01-23 11:37:49286 if (first_time || (transport_seq_num_id_changed &&
287 !stream->allocation_settings_.ForceNoAudioFeedback())) {
ossu1129df22017-06-30 08:38:56288 if (!first_time) {
Niels Möllerdced9f62018-11-19 09:27:07289 channel_send->ResetSenderCongestionControlObjects();
ossu20a4b3f2017-04-27 09:08:52290 }
291
Sebastian Jansson8d9c5402017-11-15 16:22:16292 RtcpBandwidthObserver* bandwidth_observer = nullptr;
Sebastian Jansson470a5ea2019-01-23 11:37:49293
Per Kjellander914351d2019-02-15 09:54:55294 if (stream->allocation_settings_.ShouldSendTransportSequenceNumber(
295 new_ids.transport_sequence_number)) {
Niels Möllerdced9f62018-11-19 09:27:07296 channel_send->EnableSendTransportSequenceNumber(
ossu20a4b3f2017-04-27 09:08:52297 new_ids.transport_sequence_number);
Sebastian Jansson8d9c5402017-11-15 16:22:16298 // Probing in application limited region is only used in combination with
299 // send side congestion control, wich depends on feedback packets which
300 // requires transport sequence numbers to be enabled.
Niels Möller7d76a312018-10-26 10:57:07301 if (stream->rtp_transport_) {
Christoffer Rodbroa3522482019-05-23 10:12:48302 // Optionally request ALR probing but do not override any existing
303 // request from other streams.
304 if (stream->allocation_settings_.RequestAlrProbing()) {
305 stream->rtp_transport_->EnablePeriodicAlrProbing(true);
306 }
Niels Möller7d76a312018-10-26 10:57:07307 bandwidth_observer = stream->rtp_transport_->GetBandwidthObserver();
308 }
ossu20a4b3f2017-04-27 09:08:52309 }
Niels Möller7d76a312018-10-26 10:57:07310 if (stream->rtp_transport_) {
Niels Möllerdced9f62018-11-19 09:27:07311 channel_send->RegisterSenderCongestionControlObjects(
Niels Möller7d76a312018-10-26 10:57:07312 stream->rtp_transport_, bandwidth_observer);
313 }
ossu20a4b3f2017-04-27 09:08:52314 }
Yves Gerey17048012019-07-26 15:49:52315 stream->config_cs_.Enter();
Steve Antonbb50ce52018-03-26 17:24:32316 // MID RTP header extension.
Steve Anton003930a2018-03-29 19:37:21317 if ((first_time || new_ids.mid != old_ids.mid ||
318 new_config.rtp.mid != old_config.rtp.mid) &&
319 new_ids.mid != 0 && !new_config.rtp.mid.empty()) {
Niels Möllerdced9f62018-11-19 09:27:07320 channel_send->SetMid(new_config.rtp.mid, new_ids.mid);
Steve Antonbb50ce52018-03-26 17:24:32321 }
322
Amit Hilbuch77938e62018-12-21 17:23:38323 // RID RTP header extension
324 if ((first_time || new_ids.rid != old_ids.rid ||
325 new_ids.repaired_rid != old_ids.repaired_rid ||
326 new_config.rtp.rid != old_config.rtp.rid)) {
327 channel_send->SetRid(new_config.rtp.rid, new_ids.rid, new_ids.repaired_rid);
328 }
329
ossu20a4b3f2017-04-27 09:08:52330 if (!ReconfigureSendCodec(stream, new_config)) {
Mirko Bonadei675513b2017-11-09 10:09:25331 RTC_LOG(LS_ERROR) << "Failed to set up send codec state.";
ossu20a4b3f2017-04-27 09:08:52332 }
333
Oskar Sundbomf85e31b2017-12-20 15:38:09334 if (stream->sending_) {
335 ReconfigureBitrateObserver(stream, new_config);
336 }
ossu20a4b3f2017-04-27 09:08:52337 stream->config_ = new_config;
Yves Gerey17048012019-07-26 15:49:52338 stream->config_cs_.Leave();
ossu20a4b3f2017-04-27 09:08:52339}
340
solenberg3a941542015-11-16 15:34:50341void AudioSendStream::Start() {
Sebastian Jansson8672cac2019-03-01 14:57:55342 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Fredrik Solenberg2a877972017-12-15 15:42:15343 if (sending_) {
344 return;
345 }
346
Sebastian Jansson470a5ea2019-01-23 11:37:49347 if (allocation_settings_.IncludeAudioInAllocationOnStart(
348 config_.min_bitrate_bps, config_.max_bitrate_bps, config_.has_dscp,
349 TransportSeqNumId(config_))) {
Erik Språngaa59eca2019-07-24 12:52:55350 rtp_transport_->AccountForAudioPacketsInPacedSender(true);
Sebastian Janssonb6863962018-10-10 08:23:13351 rtp_rtcp_module_->SetAsPartOfAllocation(true);
Sebastian Jansson8672cac2019-03-01 14:57:55352 rtc::Event thread_sync_event;
353 worker_queue_->PostTask([&] {
354 RTC_DCHECK_RUN_ON(worker_queue_);
355 ConfigureBitrateObserver();
356 thread_sync_event.Set();
357 });
358 thread_sync_event.Wait(rtc::Event::kForever);
Sebastian Janssonb6863962018-10-10 08:23:13359 } else {
360 rtp_rtcp_module_->SetAsPartOfAllocation(false);
mflodman86cc6ff2016-07-26 11:44:06361 }
Niels Möllerdced9f62018-11-19 09:27:07362 channel_send_->StartSend();
Fredrik Solenberg2a877972017-12-15 15:42:15363 sending_ = true;
364 audio_state()->AddSendingStream(this, encoder_sample_rate_hz_,
365 encoder_num_channels_);
solenberg3a941542015-11-16 15:34:50366}
367
368void AudioSendStream::Stop() {
Sebastian Janssonc01367d2019-04-08 13:20:44369 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Fredrik Solenberg2a877972017-12-15 15:42:15370 if (!sending_) {
371 return;
372 }
373
ossu20a4b3f2017-04-27 09:08:52374 RemoveBitrateObserver();
Niels Möllerdced9f62018-11-19 09:27:07375 channel_send_->StopSend();
Fredrik Solenberg2a877972017-12-15 15:42:15376 sending_ = false;
377 audio_state()->RemoveSendingStream(this);
378}
379
380void AudioSendStream::SendAudioData(std::unique_ptr<AudioFrame> audio_frame) {
381 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
Henrik Boströmd2c336f2019-07-03 15:11:10382 RTC_DCHECK_GT(audio_frame->sample_rate_hz_, 0);
383 double duration = static_cast<double>(audio_frame->samples_per_channel_) /
384 audio_frame->sample_rate_hz_;
385 {
386 // Note: SendAudioData() passes the frame further down the pipeline and it
387 // may eventually get sent. But this method is invoked even if we are not
388 // connected, as long as we have an AudioSendStream (created as a result of
389 // an O/A exchange). This means that we are calculating audio levels whether
390 // or not we are sending samples.
391 // TODO(https://crbug.com/webrtc/10771): All "media-source" related stats
392 // should move from send-streams to the local audio sources or tracks; a
393 // send-stream should not be required to read the microphone audio levels.
394 rtc::CritScope cs(&audio_level_lock_);
395 audio_level_.ComputeLevel(*audio_frame, duration);
396 }
Niels Möllerdced9f62018-11-19 09:27:07397 channel_send_->ProcessAndEncodeAudio(std::move(audio_frame));
solenberg3a941542015-11-16 15:34:50398}
399
solenbergffbbcac2016-11-17 13:25:37400bool AudioSendStream::SendTelephoneEvent(int payload_type,
Yves Gerey665174f2018-06-19 13:03:05401 int payload_frequency,
402 int event,
solenberg8842c3e2016-03-11 11:06:41403 int duration_ms) {
Sebastian Janssonc01367d2019-04-08 13:20:44404 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Niels Möller8fb1a6a2019-03-05 13:29:42405 channel_send_->SetSendTelephoneEventPayloadType(payload_type,
406 payload_frequency);
407 return channel_send_->SendTelephoneEventOutband(event, duration_ms);
Fredrik Solenbergb5727682015-12-04 14:22:19408}
409
solenberg94218532016-06-16 17:53:22410void AudioSendStream::SetMuted(bool muted) {
Sebastian Janssonc01367d2019-04-08 13:20:44411 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Niels Möllerdced9f62018-11-19 09:27:07412 channel_send_->SetInputMute(muted);
solenberg94218532016-06-16 17:53:22413}
414
solenbergc7a8b082015-10-16 21:35:07415webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
Ivo Creusen56d460902017-11-24 16:29:59416 return GetStats(true);
417}
418
419webrtc::AudioSendStream::Stats AudioSendStream::GetStats(
420 bool has_remote_tracks) const {
Sebastian Janssonc01367d2019-04-08 13:20:44421 RTC_DCHECK(worker_thread_checker_.IsCurrent());
solenberg85a04962015-10-27 10:35:21422 webrtc::AudioSendStream::Stats stats;
423 stats.local_ssrc = config_.rtp.ssrc;
Niels Möllerdced9f62018-11-19 09:27:07424 stats.target_bitrate_bps = channel_send_->GetBitrate();
solenberg85a04962015-10-27 10:35:21425
Niels Möllerdced9f62018-11-19 09:27:07426 webrtc::CallSendStatistics call_stats = channel_send_->GetRTCPStatistics();
solenberg85a04962015-10-27 10:35:21427 stats.bytes_sent = call_stats.bytesSent;
Henrik Boströmcf96e0f2019-04-17 11:51:53428 stats.retransmitted_bytes_sent = call_stats.retransmitted_bytes_sent;
solenberg85a04962015-10-27 10:35:21429 stats.packets_sent = call_stats.packetsSent;
Henrik Boströmcf96e0f2019-04-17 11:51:53430 stats.retransmitted_packets_sent = call_stats.retransmitted_packets_sent;
solenberg8b85de22015-11-16 17:48:04431 // RTT isn't known until a RTCP report is received. Until then, VoiceEngine
432 // returns 0 to indicate an error value.
433 if (call_stats.rttMs > 0) {
434 stats.rtt_ms = call_stats.rttMs;
435 }
ossu20a4b3f2017-04-27 09:08:52436 if (config_.send_codec_spec) {
437 const auto& spec = *config_.send_codec_spec;
438 stats.codec_name = spec.format.name;
Oskar Sundbom2707fb22017-11-16 09:57:35439 stats.codec_payload_type = spec.payload_type;
solenberg85a04962015-10-27 10:35:21440
441 // Get data from the last remote RTCP report.
Niels Möllerdced9f62018-11-19 09:27:07442 for (const auto& block : channel_send_->GetRemoteRTCPReportBlocks()) {
solenberg8b85de22015-11-16 17:48:04443 // Lookup report for send ssrc only.
444 if (block.source_SSRC == stats.local_ssrc) {
445 stats.packets_lost = block.cumulative_num_packets_lost;
446 stats.fraction_lost = Q8ToFloat(block.fraction_lost);
ossu20a4b3f2017-04-27 09:08:52447 // Convert timestamps to milliseconds.
448 if (spec.format.clockrate_hz / 1000 > 0) {
solenberg8b85de22015-11-16 17:48:04449 stats.jitter_ms =
ossu20a4b3f2017-04-27 09:08:52450 block.interarrival_jitter / (spec.format.clockrate_hz / 1000);
solenberg85a04962015-10-27 10:35:21451 }
solenberg8b85de22015-11-16 17:48:04452 break;
solenberg85a04962015-10-27 10:35:21453 }
454 }
455 }
456
Henrik Boströmd2c336f2019-07-03 15:11:10457 {
458 rtc::CritScope cs(&audio_level_lock_);
459 stats.audio_level = audio_level_.LevelFullRange();
460 stats.total_input_energy = audio_level_.TotalEnergy();
461 stats.total_input_duration = audio_level_.TotalDuration();
462 }
solenberg796b8f92017-03-02 01:02:23463
Fredrik Solenberg2a877972017-12-15 15:42:15464 stats.typing_noise_detected = audio_state()->typing_noise_detected();
Niels Möllerdced9f62018-11-19 09:27:07465 stats.ana_statistics = channel_send_->GetANAStatistics();
Ivo Creusen56d460902017-11-24 16:29:59466 RTC_DCHECK(audio_state_->audio_processing());
467 stats.apm_statistics =
468 audio_state_->audio_processing()->GetStatistics(has_remote_tracks);
solenberg85a04962015-10-27 10:35:21469
Henrik Boström6e436d12019-05-27 10:19:33470 stats.report_block_datas = std::move(call_stats.report_block_datas);
471
solenberg85a04962015-10-27 10:35:21472 return stats;
473}
474
Niels Möller8fb1a6a2019-03-05 13:29:42475void AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
pbos1ba8d392016-05-02 03:18:34476 // TODO(solenberg): Tests call this function on a network thread, libjingle
477 // calls on the worker thread. We should move towards always using a network
478 // thread. Then this check can be enabled.
Sebastian Janssonc01367d2019-04-08 13:20:44479 // RTC_DCHECK(!worker_thread_checker_.IsCurrent());
Niels Möller8fb1a6a2019-03-05 13:29:42480 channel_send_->ReceivedRTCPPacket(packet, length);
pbos1ba8d392016-05-02 03:18:34481}
482
Sebastian Janssonc0e4d452018-10-25 13:08:32483uint32_t AudioSendStream::OnBitrateUpdated(BitrateAllocationUpdate update) {
Daniel Lee93562522019-05-03 12:40:13484 // Pick a target bitrate between the constraints. Overrules the allocator if
485 // it 1) allocated a bitrate of zero to disable the stream or 2) allocated a
486 // higher than max to allow for e.g. extra FEC.
487 auto constraints = GetMinMaxBitrateConstraints();
488 update.target_bitrate.Clamp(constraints.min, constraints.max);
mflodman86cc6ff2016-07-26 11:44:06489
Sebastian Jansson254d8692018-11-21 18:19:00490 channel_send_->OnBitrateAllocation(update);
mflodman86cc6ff2016-07-26 11:44:06491
492 // The amount of audio protection is not exposed by the encoder, hence
493 // always returning 0.
494 return 0;
495}
496
elad.alond12a8e12017-03-23 18:04:48497void AudioSendStream::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
Sebastian Janssonc01367d2019-04-08 13:20:44498 RTC_DCHECK(pacer_thread_checker_.IsCurrent());
elad.alond12a8e12017-03-23 18:04:48499 // Only packets that belong to this stream are of interest.
Yves Gerey17048012019-07-26 15:49:52500 bool same_ssrc;
501 {
502 rtc::CritScope lock(&config_cs_);
503 same_ssrc = ssrc == config_.rtp.ssrc;
504 }
505 if (same_ssrc) {
elad.alond12a8e12017-03-23 18:04:48506 rtc::CritScope lock(&packet_loss_tracker_cs_);
eladalonedd6eea2017-05-25 07:15:35507 // TODO(eladalon): This function call could potentially reset the window,
elad.alond12a8e12017-03-23 18:04:48508 // setting both PLR and RPLR to unknown. Consider (during upcoming
509 // refactoring) passing an indication of such an event.
Sebastian Jansson977b3352019-03-04 16:43:34510 packet_loss_tracker_.OnPacketAdded(seq_num, clock_->TimeInMilliseconds());
elad.alond12a8e12017-03-23 18:04:48511 }
512}
513
514void AudioSendStream::OnPacketFeedbackVector(
515 const std::vector<PacketFeedback>& packet_feedback_vector) {
Sebastian Janssonc01367d2019-04-08 13:20:44516 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Danil Chapovalovb9b146c2018-06-15 10:28:07517 absl::optional<float> plr;
518 absl::optional<float> rplr;
elad.alond12a8e12017-03-23 18:04:48519 {
520 rtc::CritScope lock(&packet_loss_tracker_cs_);
521 packet_loss_tracker_.OnPacketFeedbackVector(packet_feedback_vector);
522 plr = packet_loss_tracker_.GetPacketLossRate();
elad.alondadb4dc2017-03-23 22:29:50523 rplr = packet_loss_tracker_.GetRecoverablePacketLossRate();
elad.alond12a8e12017-03-23 18:04:48524 }
eladalonedd6eea2017-05-25 07:15:35525 // TODO(eladalon): If R/PLR go back to unknown, no indication is given that
elad.alond12a8e12017-03-23 18:04:48526 // the previously sent value is no longer relevant. This will be taken care
527 // of with some refactoring which is now being done.
528 if (plr) {
Niels Möllerdced9f62018-11-19 09:27:07529 channel_send_->OnTwccBasedUplinkPacketLossRate(*plr);
elad.alond12a8e12017-03-23 18:04:48530 }
elad.alondadb4dc2017-03-23 22:29:50531 if (rplr) {
Niels Möllerdced9f62018-11-19 09:27:07532 channel_send_->OnRecoverableUplinkPacketLossRate(*rplr);
elad.alondadb4dc2017-03-23 22:29:50533 }
elad.alond12a8e12017-03-23 18:04:48534}
535
Anton Sukhanov626015d2019-02-04 23:16:06536void AudioSendStream::SetTransportOverhead(
537 int transport_overhead_per_packet_bytes) {
Sebastian Janssonc01367d2019-04-08 13:20:44538 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Anton Sukhanov626015d2019-02-04 23:16:06539 rtc::CritScope cs(&overhead_per_packet_lock_);
540 transport_overhead_per_packet_bytes_ = transport_overhead_per_packet_bytes;
541 UpdateOverheadForEncoder();
542}
543
544void AudioSendStream::OnOverheadChanged(
545 size_t overhead_bytes_per_packet_bytes) {
546 rtc::CritScope cs(&overhead_per_packet_lock_);
547 audio_overhead_per_packet_bytes_ = overhead_bytes_per_packet_bytes;
548 UpdateOverheadForEncoder();
549}
550
551void AudioSendStream::UpdateOverheadForEncoder() {
552 const size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
Bjorn A Mellem413ccc42019-04-26 22:41:05553 if (overhead_per_packet_bytes == 0) {
554 return; // Overhead is not known yet, do not tell the encoder.
555 }
Sebastian Jansson14a7cf92019-02-13 14:11:42556 channel_send_->CallEncoder([&](AudioEncoder* encoder) {
557 encoder->OnReceivedOverhead(overhead_per_packet_bytes);
Anton Sukhanov626015d2019-02-04 23:16:06558 });
Sebastian Jansson8672cac2019-03-01 14:57:55559 worker_queue_->PostTask([this, overhead_per_packet_bytes] {
560 RTC_DCHECK_RUN_ON(worker_queue_);
561 if (total_packet_overhead_bytes_ != overhead_per_packet_bytes) {
562 total_packet_overhead_bytes_ = overhead_per_packet_bytes;
563 if (registered_with_allocator_) {
564 ConfigureBitrateObserver();
565 }
566 }
567 });
Anton Sukhanov626015d2019-02-04 23:16:06568}
569
570size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
571 rtc::CritScope cs(&overhead_per_packet_lock_);
572 return GetPerPacketOverheadBytes();
573}
574
575size_t AudioSendStream::GetPerPacketOverheadBytes() const {
576 return transport_overhead_per_packet_bytes_ +
577 audio_overhead_per_packet_bytes_;
michaelt79e05882016-11-08 10:50:09578}
579
ossuc3d4b482017-05-23 13:07:11580RtpState AudioSendStream::GetRtpState() const {
581 return rtp_rtcp_module_->GetRtpState();
582}
583
Niels Möllerdced9f62018-11-19 09:27:07584const voe::ChannelSendInterface* AudioSendStream::GetChannel() const {
585 return channel_send_.get();
Fredrik Solenberg8f5787a2018-01-11 12:52:30586}
587
Fredrik Solenberg2a877972017-12-15 15:42:15588internal::AudioState* AudioSendStream::audio_state() {
589 internal::AudioState* audio_state =
590 static_cast<internal::AudioState*>(audio_state_.get());
591 RTC_DCHECK(audio_state);
592 return audio_state;
593}
594
595const internal::AudioState* AudioSendStream::audio_state() const {
596 internal::AudioState* audio_state =
597 static_cast<internal::AudioState*>(audio_state_.get());
598 RTC_DCHECK(audio_state);
599 return audio_state;
600}
601
Fredrik Solenberg2a877972017-12-15 15:42:15602void AudioSendStream::StoreEncoderProperties(int sample_rate_hz,
603 size_t num_channels) {
Sebastian Janssonc01367d2019-04-08 13:20:44604 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Fredrik Solenberg2a877972017-12-15 15:42:15605 encoder_sample_rate_hz_ = sample_rate_hz;
606 encoder_num_channels_ = num_channels;
607 if (sending_) {
608 // Update AudioState's information about the stream.
609 audio_state()->AddSendingStream(this, sample_rate_hz, num_channels);
610 }
611}
612
minyue7a973442016-10-20 10:27:12613// Apply current codec settings to a single voe::Channel used for sending.
ossu20a4b3f2017-04-27 09:08:52614bool AudioSendStream::SetupSendCodec(AudioSendStream* stream,
615 const Config& new_config) {
616 RTC_DCHECK(new_config.send_codec_spec);
617 const auto& spec = *new_config.send_codec_spec;
minyue48368ad2017-05-10 11:06:11618
619 RTC_DCHECK(new_config.encoder_factory);
ossu20a4b3f2017-04-27 09:08:52620 std::unique_ptr<AudioEncoder> encoder =
Karl Wiberg77490b92018-03-21 14:18:42621 new_config.encoder_factory->MakeAudioEncoder(
622 spec.payload_type, spec.format, new_config.codec_pair_id);
minyue7a973442016-10-20 10:27:12623
ossu20a4b3f2017-04-27 09:08:52624 if (!encoder) {
Jonas Olssonabbe8412018-04-03 11:40:05625 RTC_DLOG(LS_ERROR) << "Unable to create encoder for "
626 << rtc::ToString(spec.format);
ossu20a4b3f2017-04-27 09:08:52627 return false;
628 }
Alex Narestbbbe4e12018-07-13 08:32:58629
ossu20a4b3f2017-04-27 09:08:52630 // If a bitrate has been specified for the codec, use it over the
631 // codec's default.
Christoffer Rodbro110c64b2019-03-06 08:51:08632 if (spec.target_bitrate_bps) {
ossu20a4b3f2017-04-27 09:08:52633 encoder->OnReceivedTargetAudioBitrate(*spec.target_bitrate_bps);
minyue7a973442016-10-20 10:27:12634 }
635
ossu20a4b3f2017-04-27 09:08:52636 // Enable ANA if configured (currently only used by Opus).
637 if (new_config.audio_network_adaptor_config) {
638 if (encoder->EnableAudioNetworkAdaptor(
639 *new_config.audio_network_adaptor_config, stream->event_log_)) {
Jonas Olsson24ea8222018-01-25 09:14:29640 RTC_DLOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
641 << new_config.rtp.ssrc;
ossu20a4b3f2017-04-27 09:08:52642 } else {
643 RTC_NOTREACHED();
minyue6b825df2016-10-31 11:08:32644 }
minyue7a973442016-10-20 10:27:12645 }
646
ossu20a4b3f2017-04-27 09:08:52647 // Wrap the encoder in a an AudioEncoderCNG, if VAD is enabled.
648 if (spec.cng_payload_type) {
Karl Wiberg23659362018-11-01 10:13:44649 AudioEncoderCngConfig cng_config;
ossu20a4b3f2017-04-27 09:08:52650 cng_config.num_channels = encoder->NumChannels();
651 cng_config.payload_type = *spec.cng_payload_type;
652 cng_config.speech_encoder = std::move(encoder);
653 cng_config.vad_mode = Vad::kVadNormal;
Karl Wiberg23659362018-11-01 10:13:44654 encoder = CreateComfortNoiseEncoder(std::move(cng_config));
ossu3b9ff382017-04-27 15:03:42655
656 stream->RegisterCngPayloadType(
657 *spec.cng_payload_type,
658 new_config.send_codec_spec->format.clockrate_hz);
minyue7a973442016-10-20 10:27:12659 }
ossu20a4b3f2017-04-27 09:08:52660
Anton Sukhanov626015d2019-02-04 23:16:06661 // Set currently known overhead (used in ANA, opus only).
662 // If overhead changes later, it will be updated in UpdateOverheadForEncoder.
663 {
664 rtc::CritScope cs(&stream->overhead_per_packet_lock_);
Bjorn A Mellem413ccc42019-04-26 22:41:05665 if (stream->GetPerPacketOverheadBytes() > 0) {
666 encoder->OnReceivedOverhead(stream->GetPerPacketOverheadBytes());
667 }
Anton Sukhanov626015d2019-02-04 23:16:06668 }
669
Fredrik Solenberg2a877972017-12-15 15:42:15670 stream->StoreEncoderProperties(encoder->SampleRateHz(),
671 encoder->NumChannels());
Niels Möllerdced9f62018-11-19 09:27:07672 stream->channel_send_->SetEncoder(new_config.send_codec_spec->payload_type,
673 std::move(encoder));
Anton Sukhanov626015d2019-02-04 23:16:06674
minyue7a973442016-10-20 10:27:12675 return true;
676}
677
ossu20a4b3f2017-04-27 09:08:52678bool AudioSendStream::ReconfigureSendCodec(AudioSendStream* stream,
679 const Config& new_config) {
680 const auto& old_config = stream->config_;
minyue-webrtc8de18262017-07-26 12:18:40681
682 if (!new_config.send_codec_spec) {
683 // We cannot de-configure a send codec. So we will do nothing.
684 // By design, the send codec should have not been configured.
685 RTC_DCHECK(!old_config.send_codec_spec);
686 return true;
687 }
688
689 if (new_config.send_codec_spec == old_config.send_codec_spec &&
690 new_config.audio_network_adaptor_config ==
691 old_config.audio_network_adaptor_config) {
ossu20a4b3f2017-04-27 09:08:52692 return true;
693 }
694
695 // If we have no encoder, or the format or payload type's changed, create a
696 // new encoder.
697 if (!old_config.send_codec_spec ||
698 new_config.send_codec_spec->format !=
699 old_config.send_codec_spec->format ||
700 new_config.send_codec_spec->payload_type !=
701 old_config.send_codec_spec->payload_type) {
702 return SetupSendCodec(stream, new_config);
703 }
704
Danil Chapovalovb9b146c2018-06-15 10:28:07705 const absl::optional<int>& new_target_bitrate_bps =
ossu20a4b3f2017-04-27 09:08:52706 new_config.send_codec_spec->target_bitrate_bps;
707 // If a bitrate has been specified for the codec, use it over the
708 // codec's default.
Christoffer Rodbro110c64b2019-03-06 08:51:08709 if (new_target_bitrate_bps &&
ossu20a4b3f2017-04-27 09:08:52710 new_target_bitrate_bps !=
711 old_config.send_codec_spec->target_bitrate_bps) {
Sebastian Jansson14a7cf92019-02-13 14:11:42712 stream->channel_send_->CallEncoder([&](AudioEncoder* encoder) {
ossu20a4b3f2017-04-27 09:08:52713 encoder->OnReceivedTargetAudioBitrate(*new_target_bitrate_bps);
714 });
715 }
716
717 ReconfigureANA(stream, new_config);
718 ReconfigureCNG(stream, new_config);
719
Anton Sukhanov626015d2019-02-04 23:16:06720 // Set currently known overhead (used in ANA, opus only).
721 {
722 rtc::CritScope cs(&stream->overhead_per_packet_lock_);
723 stream->UpdateOverheadForEncoder();
724 }
725
ossu20a4b3f2017-04-27 09:08:52726 return true;
727}
728
729void AudioSendStream::ReconfigureANA(AudioSendStream* stream,
730 const Config& new_config) {
731 if (new_config.audio_network_adaptor_config ==
732 stream->config_.audio_network_adaptor_config) {
733 return;
734 }
735 if (new_config.audio_network_adaptor_config) {
Sebastian Jansson14a7cf92019-02-13 14:11:42736 stream->channel_send_->CallEncoder([&](AudioEncoder* encoder) {
ossu20a4b3f2017-04-27 09:08:52737 if (encoder->EnableAudioNetworkAdaptor(
738 *new_config.audio_network_adaptor_config, stream->event_log_)) {
Jonas Olsson24ea8222018-01-25 09:14:29739 RTC_DLOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
740 << new_config.rtp.ssrc;
ossu20a4b3f2017-04-27 09:08:52741 } else {
742 RTC_NOTREACHED();
743 }
744 });
745 } else {
Sebastian Jansson14a7cf92019-02-13 14:11:42746 stream->channel_send_->CallEncoder(
747 [&](AudioEncoder* encoder) { encoder->DisableAudioNetworkAdaptor(); });
Jonas Olsson24ea8222018-01-25 09:14:29748 RTC_DLOG(LS_INFO) << "Audio network adaptor disabled on SSRC "
749 << new_config.rtp.ssrc;
ossu20a4b3f2017-04-27 09:08:52750 }
751}
752
753void AudioSendStream::ReconfigureCNG(AudioSendStream* stream,
754 const Config& new_config) {
755 if (new_config.send_codec_spec->cng_payload_type ==
756 stream->config_.send_codec_spec->cng_payload_type) {
757 return;
758 }
759
ossu3b9ff382017-04-27 15:03:42760 // Register the CNG payload type if it's been added, don't do anything if CNG
761 // is removed. Payload types must not be redefined.
762 if (new_config.send_codec_spec->cng_payload_type) {
763 stream->RegisterCngPayloadType(
764 *new_config.send_codec_spec->cng_payload_type,
765 new_config.send_codec_spec->format.clockrate_hz);
766 }
767
ossu20a4b3f2017-04-27 09:08:52768 // Wrap or unwrap the encoder in an AudioEncoderCNG.
Niels Möllerdced9f62018-11-19 09:27:07769 stream->channel_send_->ModifyEncoder(
ossu20a4b3f2017-04-27 09:08:52770 [&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
771 std::unique_ptr<AudioEncoder> old_encoder(std::move(*encoder_ptr));
772 auto sub_encoders = old_encoder->ReclaimContainedEncoders();
773 if (!sub_encoders.empty()) {
774 // Replace enc with its sub encoder. We need to put the sub
775 // encoder in a temporary first, since otherwise the old value
776 // of enc would be destroyed before the new value got assigned,
777 // which would be bad since the new value is a part of the old
778 // value.
779 auto tmp = std::move(sub_encoders[0]);
780 old_encoder = std::move(tmp);
781 }
782 if (new_config.send_codec_spec->cng_payload_type) {
Karl Wiberg23659362018-11-01 10:13:44783 AudioEncoderCngConfig config;
ossu20a4b3f2017-04-27 09:08:52784 config.speech_encoder = std::move(old_encoder);
785 config.num_channels = config.speech_encoder->NumChannels();
786 config.payload_type = *new_config.send_codec_spec->cng_payload_type;
787 config.vad_mode = Vad::kVadNormal;
Karl Wiberg23659362018-11-01 10:13:44788 *encoder_ptr = CreateComfortNoiseEncoder(std::move(config));
ossu20a4b3f2017-04-27 09:08:52789 } else {
790 *encoder_ptr = std::move(old_encoder);
791 }
792 });
793}
794
795void AudioSendStream::ReconfigureBitrateObserver(
796 AudioSendStream* stream,
797 const webrtc::AudioSendStream::Config& new_config) {
Sebastian Jansson8672cac2019-03-01 14:57:55798 RTC_DCHECK_RUN_ON(&stream->worker_thread_checker_);
ossu20a4b3f2017-04-27 09:08:52799 // Since the Config's default is for both of these to be -1, this test will
800 // allow us to configure the bitrate observer if the new config has bitrate
801 // limits set, but would only have us call RemoveBitrateObserver if we were
802 // previously configured with bitrate limits.
803 if (stream->config_.min_bitrate_bps == new_config.min_bitrate_bps &&
Alex Narestcedd3512017-12-07 19:54:55804 stream->config_.max_bitrate_bps == new_config.max_bitrate_bps &&
Seth Hampson24722b32017-12-22 17:36:42805 stream->config_.bitrate_priority == new_config.bitrate_priority &&
Sebastian Jansson470a5ea2019-01-23 11:37:49806 (TransportSeqNumId(stream->config_) == TransportSeqNumId(new_config) ||
807 stream->allocation_settings_.IgnoreSeqNumIdChange())) {
ossu20a4b3f2017-04-27 09:08:52808 return;
809 }
810
Sebastian Jansson470a5ea2019-01-23 11:37:49811 if (stream->allocation_settings_.IncludeAudioInAllocationOnReconfigure(
812 new_config.min_bitrate_bps, new_config.max_bitrate_bps,
813 new_config.has_dscp, TransportSeqNumId(new_config))) {
Erik Språngaa59eca2019-07-24 12:52:55814 stream->rtp_transport_->AccountForAudioPacketsInPacedSender(true);
Sebastian Jansson8672cac2019-03-01 14:57:55815 rtc::Event thread_sync_event;
816 stream->worker_queue_->PostTask([&] {
817 RTC_DCHECK_RUN_ON(stream->worker_queue_);
818 stream->registered_with_allocator_ = true;
819 // We may get a callback immediately as the observer is registered, so
820 // make
821 // sure the bitrate limits in config_ are up-to-date.
822 stream->config_.min_bitrate_bps = new_config.min_bitrate_bps;
823 stream->config_.max_bitrate_bps = new_config.max_bitrate_bps;
824 stream->config_.bitrate_priority = new_config.bitrate_priority;
825 stream->ConfigureBitrateObserver();
826 thread_sync_event.Set();
827 });
828 thread_sync_event.Wait(rtc::Event::kForever);
Sebastian Jansson470a5ea2019-01-23 11:37:49829 stream->rtp_rtcp_module_->SetAsPartOfAllocation(true);
ossu20a4b3f2017-04-27 09:08:52830 } else {
Erik Språngaa59eca2019-07-24 12:52:55831 stream->rtp_transport_->AccountForAudioPacketsInPacedSender(false);
ossu20a4b3f2017-04-27 09:08:52832 stream->RemoveBitrateObserver();
Sebastian Janssonb6863962018-10-10 08:23:13833 stream->rtp_rtcp_module_->SetAsPartOfAllocation(false);
ossu20a4b3f2017-04-27 09:08:52834 }
835}
836
Sebastian Jansson8672cac2019-03-01 14:57:55837void AudioSendStream::ConfigureBitrateObserver() {
838 // This either updates the current observer or adds a new observer.
839 // TODO(srte): Add overhead compensation here.
Daniel Lee93562522019-05-03 12:40:13840 auto constraints = GetMinMaxBitrateConstraints();
841
Sebastian Jansson8672cac2019-03-01 14:57:55842 bitrate_allocator_->AddObserver(
Daniel Lee93562522019-05-03 12:40:13843 this,
844 MediaStreamAllocationConfig{
845 constraints.min.bps<uint32_t>(), constraints.max.bps<uint32_t>(), 0,
846 allocation_settings_.DefaultPriorityBitrate().bps(), true,
Jonas Olsson8f119ca2019-05-08 08:56:23847 allocation_settings_.BitratePriority().value_or(
848 config_.bitrate_priority)});
ossu20a4b3f2017-04-27 09:08:52849}
850
851void AudioSendStream::RemoveBitrateObserver() {
Sebastian Janssonc01367d2019-04-08 13:20:44852 RTC_DCHECK(worker_thread_checker_.IsCurrent());
Niels Möllerc572ff32018-11-07 07:43:50853 rtc::Event thread_sync_event;
ossu20a4b3f2017-04-27 09:08:52854 worker_queue_->PostTask([this, &thread_sync_event] {
Sebastian Jansson8672cac2019-03-01 14:57:55855 RTC_DCHECK_RUN_ON(worker_queue_);
856 registered_with_allocator_ = false;
ossu20a4b3f2017-04-27 09:08:52857 bitrate_allocator_->RemoveObserver(this);
858 thread_sync_event.Set();
859 });
860 thread_sync_event.Wait(rtc::Event::kForever);
861}
862
Daniel Lee93562522019-05-03 12:40:13863AudioSendStream::TargetAudioBitrateConstraints
864AudioSendStream::GetMinMaxBitrateConstraints() const {
865 TargetAudioBitrateConstraints constraints{
866 DataRate::bps(config_.min_bitrate_bps),
867 DataRate::bps(config_.max_bitrate_bps)};
868
869 // If bitrates were explicitly overriden via field trial, use those values.
870 if (allocation_settings_.MinBitrate())
871 constraints.min = *allocation_settings_.MinBitrate();
872 if (allocation_settings_.MaxBitrate())
873 constraints.max = *allocation_settings_.MaxBitrate();
874
875 RTC_DCHECK_GE(constraints.min.bps(), 0);
876 RTC_DCHECK_GE(constraints.max.bps(), 0);
877 RTC_DCHECK_GE(constraints.max.bps(), constraints.min.bps());
878
879 // TODO(srte,dklee): Replace these with proper overhead calculations.
880 if (allocation_settings_.IncludeOverheadInAudioAllocation()) {
881 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
882 const DataSize kOverheadPerPacket = DataSize::bytes(20 + 8 + 10 + 12);
883 const TimeDelta kMaxFrameLength = TimeDelta::ms(60); // Based on Opus spec
884 const DataRate kMinOverhead = kOverheadPerPacket / kMaxFrameLength;
885 constraints.min += kMinOverhead;
886 // TODO(dklee): This is obviously overly conservative to avoid exceeding max
887 // bitrate. Carefully reconsider the logic when addressing todo above.
888 constraints.max += kMinOverhead;
889 }
890 return constraints;
891}
892
ossu3b9ff382017-04-27 15:03:42893void AudioSendStream::RegisterCngPayloadType(int payload_type,
894 int clockrate_hz) {
Niels Mölleree5ccbc2019-03-06 15:47:29895 channel_send_->RegisterCngPayloadType(payload_type, clockrate_hz);
ossu3b9ff382017-04-27 15:03:42896}
solenbergc7a8b082015-10-16 21:35:07897} // namespace internal
898} // namespace webrtc