blob: d8d4b520eb200e217f3384bcf15b8d469ad26135 [file] [log] [blame]
deadbeef6979b022015-09-24 23:47:531/*
kjellanderb24317b2016-02-10 15:54:432 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
deadbeef6979b022015-09-24 23:47:533 *
kjellanderb24317b2016-02-10 15:54:434 * 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.
deadbeef6979b022015-09-24 23:47:539 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "pc/rtp_sender.h"
deadbeef6979b022015-09-24 23:47:5312
Harald Alvestrand5761e7b2021-01-29 14:45:0813#include <algorithm>
Yves Gereycb11a312019-07-26 16:51:5914#include <atomic>
Harald Alvestrandc24a2182022-02-23 13:44:5915#include <string>
Benjamin Wrightd81ac952018-08-30 00:02:1016#include <utility>
Steve Anton36b29d12017-10-30 16:57:4217#include <vector>
18
Harald Alvestrand5761e7b2021-01-29 14:45:0819#include "absl/algorithm/container.h"
Yves Gerey3e707812018-11-28 15:47:4920#include "api/audio_options.h"
Steve Anton10542f22019-01-11 17:11:0021#include "api/media_stream_interface.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0822#include "api/priority.h"
Steve Anton10542f22019-01-11 17:11:0023#include "media/base/media_engine.h"
Harald Alvestrand445e6b02020-09-29 14:21:4724#include "pc/stats_collector_interface.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3125#include "rtc_base/checks.h"
26#include "rtc_base/helpers.h"
Yves Gerey3e707812018-11-28 15:47:4927#include "rtc_base/location.h"
28#include "rtc_base/logging.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0829#include "rtc_base/ref_counted_object.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3130#include "rtc_base/trace_event.h"
deadbeef70ab1a12015-09-28 23:53:5531
32namespace webrtc {
33
Harald Alvestrandc72af932018-01-11 16:18:1934namespace {
35
Yves Gereycb11a312019-07-26 16:51:5936// This function is only expected to be called on the signaling thread.
37// On the other hand, some test or even production setups may use
38// several signaling threads.
Harald Alvestrandc72af932018-01-11 16:18:1939int GenerateUniqueId() {
Yves Gereycb11a312019-07-26 16:51:5940 static std::atomic<int> g_unique_id{0};
Harald Alvestrandc72af932018-01-11 16:18:1941
42 return ++g_unique_id;
43}
44
Seth Hampson2d2c8882018-05-16 23:02:3245// Returns true if a "per-sender" encoding parameter contains a value that isn't
46// its default. Currently max_bitrate_bps and bitrate_priority both are
47// implemented "per-sender," meaning that these encoding parameters
48// are used for the RtpSender as a whole, not for a specific encoding layer.
49// This is done by setting these encoding parameters at index 0 of
50// RtpParameters.encodings. This function can be used to check if these
51// parameters are set at any index other than 0 of RtpParameters.encodings,
52// because they are currently unimplemented to be used for a specific encoding
53// layer.
54bool PerSenderRtpEncodingParameterHasValue(
55 const RtpEncodingParameters& encoding_params) {
Tim Haloun648d28a2018-10-18 23:52:2256 if (encoding_params.bitrate_priority != kDefaultBitratePriority ||
Taylor Brandstetter3f1aee32020-02-27 19:59:2357 encoding_params.network_priority != Priority::kLow) {
Seth Hampson2d2c8882018-05-16 23:02:3258 return true;
59 }
60 return false;
61}
62
Amit Hilbuch2297d332019-02-19 20:49:2263void RemoveEncodingLayers(const std::vector<std::string>& rids,
64 std::vector<RtpEncodingParameters>* encodings) {
65 RTC_DCHECK(encodings);
66 encodings->erase(
67 std::remove_if(encodings->begin(), encodings->end(),
68 [&rids](const RtpEncodingParameters& encoding) {
69 return absl::c_linear_search(rids, encoding.rid);
70 }),
71 encodings->end());
72}
73
74RtpParameters RestoreEncodingLayers(
75 const RtpParameters& parameters,
76 const std::vector<std::string>& removed_rids,
77 const std::vector<RtpEncodingParameters>& all_layers) {
78 RTC_DCHECK_EQ(parameters.encodings.size() + removed_rids.size(),
79 all_layers.size());
80 RtpParameters result(parameters);
81 result.encodings.clear();
82 size_t index = 0;
83 for (const RtpEncodingParameters& encoding : all_layers) {
84 if (absl::c_linear_search(removed_rids, encoding.rid)) {
85 result.encodings.push_back(encoding);
86 continue;
87 }
88 result.encodings.push_back(parameters.encodings[index++]);
89 }
90 return result;
91}
92
Florent Castelli892acf02018-10-01 20:47:2093} // namespace
94
Seth Hampson2d2c8882018-05-16 23:02:3295// Returns true if any RtpParameters member that isn't implemented contains a
96// value.
97bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 14:00:2898 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 23:02:3299 return true;
100 }
101 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
Seth Hampson2d2c8882018-05-16 23:02:32102 // Encoding parameters that are per-sender should only contain value at
103 // index 0.
104 if (i != 0 &&
105 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
106 return true;
107 }
108 }
109 return false;
110}
111
Guido Urdaneta1ff16c82019-05-20 17:31:53112RtpSenderBase::RtpSenderBase(rtc::Thread* worker_thread,
113 const std::string& id,
114 SetStreamsObserver* set_streams_observer)
Tomas Gunnarssonfe328ca2022-02-16 19:02:12115 : signaling_thread_(rtc::Thread::Current()),
116 worker_thread_(worker_thread),
Guido Urdaneta1ff16c82019-05-20 17:31:53117 id_(id),
118 set_streams_observer_(set_streams_observer) {
Steve Anton47136dd2018-01-12 18:49:35119 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 20:47:20120 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-02 04:27:00121}
deadbeeffac06552015-11-25 19:26:01122
Amit Hilbuchea7ef2a2019-02-19 23:20:21123void RtpSenderBase::SetFrameEncryptor(
Benjamin Wrightd81ac952018-08-30 00:02:10124 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12125 RTC_DCHECK_RUN_ON(signaling_thread_);
Benjamin Wrightd81ac952018-08-30 00:02:10126 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-10 00:29:54127 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 20:16:16128 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-10 00:29:54129 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
130 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
131 });
132 }
Benjamin Wrightd81ac952018-08-30 00:02:10133}
134
Jonas Oreland65455162022-06-08 09:25:46135void RtpSenderBase::SetEncoderSelector(
136 std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface>
137 encoder_selector) {
138 RTC_DCHECK_RUN_ON(signaling_thread_);
139 encoder_selector_ = std::move(encoder_selector);
140 SetEncoderSelectorOnChannel();
141}
142
143void RtpSenderBase::SetEncoderSelectorOnChannel() {
144 RTC_DCHECK_RUN_ON(signaling_thread_);
145 if (media_channel_ && ssrc_ && !stopped_) {
146 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
147 media_channel_->SetEncoderSelector(ssrc_, encoder_selector_.get());
148 });
149 }
150}
151
Amit Hilbuchea7ef2a2019-02-19 23:20:21152void RtpSenderBase::SetMediaChannel(cricket::MediaChannel* media_channel) {
Amit Hilbuchdd9390c2018-11-14 00:26:05153 RTC_DCHECK(media_channel == nullptr ||
154 media_channel->media_type() == media_type());
Amit Hilbuchea7ef2a2019-02-19 23:20:21155 media_channel_ = media_channel;
Benjamin Wrightbfd412e2018-09-10 21:06:02156}
157
Amit Hilbuch619b2942019-02-26 23:55:19158RtpParameters RtpSenderBase::GetParametersInternal() const {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12159 RTC_DCHECK_RUN_ON(signaling_thread_);
Florent Castelli892acf02018-10-01 20:47:20160 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 23:30:35161 return RtpParameters();
162 }
Amit Hilbuchaa584152019-02-07 01:09:52163 if (!media_channel_ || !ssrc_) {
Amit Hilbuch619b2942019-02-26 23:55:19164 return init_parameters_;
Florent Castelli892acf02018-10-01 20:47:20165 }
Steve Anton47136dd2018-01-12 18:49:35166 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 13:31:53167 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
Amit Hilbuch2297d332019-02-19 20:49:22168 RemoveEncodingLayers(disabled_rids_, &result.encodings);
Florent Castellicebf50f2018-05-03 13:31:53169 return result;
Steve Anton47136dd2018-01-12 18:49:35170 });
deadbeefa601f5c2016-06-06 21:27:39171}
172
Amit Hilbuch619b2942019-02-26 23:55:19173RtpParameters RtpSenderBase::GetParameters() const {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12174 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuch619b2942019-02-26 23:55:19175 RtpParameters result = GetParametersInternal();
176 last_transaction_id_ = rtc::CreateRandomUuid();
177 result.transaction_id = last_transaction_id_.value();
178 return result;
179}
180
181RTCError RtpSenderBase::SetParametersInternal(const RtpParameters& parameters) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12182 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuch619b2942019-02-26 23:55:19183 RTC_DCHECK(!stopped_);
Florent Castellicebf50f2018-05-03 13:31:53184
Seth Hampson2d2c8882018-05-16 23:02:32185 if (UnimplementedRtpParameterHasValue(parameters)) {
186 LOG_AND_RETURN_ERROR(
187 RTCErrorType::UNSUPPORTED_PARAMETER,
188 "Attempted to set an unimplemented parameter of RtpParameters.");
189 }
Amit Hilbuchaa584152019-02-07 01:09:52190 if (!media_channel_ || !ssrc_) {
Florent Castellic1a0bcb2019-01-29 13:26:48191 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
192 init_parameters_, parameters);
Florent Castelli892acf02018-10-01 20:47:20193 if (result.ok()) {
194 init_parameters_ = parameters;
195 }
196 return result;
197 }
Zach Steinba37b4b2018-01-23 23:02:36198 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Amit Hilbuch2297d332019-02-19 20:49:22199 RtpParameters rtp_parameters = parameters;
200 if (!disabled_rids_.empty()) {
201 // Need to add the inactive layers.
202 RtpParameters old_parameters =
203 media_channel_->GetRtpSendParameters(ssrc_);
204 rtp_parameters = RestoreEncodingLayers(parameters, disabled_rids_,
205 old_parameters.encodings);
206 }
Amit Hilbuch619b2942019-02-26 23:55:19207 return media_channel_->SetRtpSendParameters(ssrc_, rtp_parameters);
Steve Anton47136dd2018-01-12 18:49:35208 });
deadbeefa601f5c2016-06-06 21:27:39209}
210
Amit Hilbuch619b2942019-02-26 23:55:19211RTCError RtpSenderBase::SetParameters(const RtpParameters& parameters) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12212 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuch619b2942019-02-26 23:55:19213 TRACE_EVENT0("webrtc", "RtpSenderBase::SetParameters");
Harald Alvestrand6060df52020-08-11 07:54:02214 if (is_transceiver_stopped_) {
215 LOG_AND_RETURN_ERROR(
216 RTCErrorType::INVALID_STATE,
217 "Cannot set parameters on sender of a stopped transceiver.");
218 }
219 if (stopped_) {
220 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
221 "Cannot set parameters on a stopped sender.");
222 }
Amit Hilbuch619b2942019-02-26 23:55:19223 if (stopped_) {
224 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
225 "Cannot set parameters on a stopped sender.");
226 }
227 if (!last_transaction_id_) {
228 LOG_AND_RETURN_ERROR(
229 RTCErrorType::INVALID_STATE,
230 "Failed to set parameters since getParameters() has never been called"
231 " on this sender");
232 }
233 if (last_transaction_id_ != parameters.transaction_id) {
234 LOG_AND_RETURN_ERROR(
235 RTCErrorType::INVALID_MODIFICATION,
236 "Failed to set parameters since the transaction_id doesn't match"
237 " the last value returned from getParameters()");
238 }
239
240 RTCError result = SetParametersInternal(parameters);
241 last_transaction_id_.reset();
242 return result;
243}
244
Guido Urdaneta1ff16c82019-05-20 17:31:53245void RtpSenderBase::SetStreams(const std::vector<std::string>& stream_ids) {
246 set_stream_ids(stream_ids);
247 if (set_streams_observer_)
248 set_streams_observer_->OnSetStreams();
249}
250
Amit Hilbuchea7ef2a2019-02-19 23:20:21251bool RtpSenderBase::SetTrack(MediaStreamTrackInterface* track) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12252 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21253 TRACE_EVENT0("webrtc", "RtpSenderBase::SetTrack");
254 if (stopped_) {
255 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
256 return false;
Benjamin Wright6cc9cca2018-10-10 00:29:54257 }
Amit Hilbuchea7ef2a2019-02-19 23:20:21258 if (track && track->kind() != track_kind()) {
259 RTC_LOG(LS_ERROR) << "SetTrack with " << track->kind()
260 << " called on RtpSender with " << track_kind()
261 << " track.";
262 return false;
263 }
264
265 // Detach from old track.
266 if (track_) {
267 DetachTrack();
268 track_->UnregisterObserver(this);
269 RemoveTrackFromStats();
270 }
271
272 // Attach to new track.
273 bool prev_can_send_track = can_send_track();
274 // Keep a reference to the old track to keep it alive until we call SetSend.
275 rtc::scoped_refptr<MediaStreamTrackInterface> old_track = track_;
276 track_ = track;
277 if (track_) {
278 track_->RegisterObserver(this);
279 AttachTrack();
280 }
281
282 // Update channel.
283 if (can_send_track()) {
284 SetSend();
285 AddTrackToStats();
286 } else if (prev_can_send_track) {
287 ClearSend();
288 }
289 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
290 return true;
Benjamin Wrightd81ac952018-08-30 00:02:10291}
292
Amit Hilbuchea7ef2a2019-02-19 23:20:21293void RtpSenderBase::SetSsrc(uint32_t ssrc) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12294 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21295 TRACE_EVENT0("webrtc", "RtpSenderBase::SetSsrc");
deadbeeffac06552015-11-25 19:26:01296 if (stopped_ || ssrc == ssrc_) {
297 return;
298 }
299 // If we are already sending with a particular SSRC, stop sending.
300 if (can_send_track()) {
Amit Hilbuchea7ef2a2019-02-19 23:20:21301 ClearSend();
302 RemoveTrackFromStats();
deadbeeffac06552015-11-25 19:26:01303 }
304 ssrc_ = ssrc;
305 if (can_send_track()) {
Amit Hilbuchea7ef2a2019-02-19 23:20:21306 SetSend();
307 AddTrackToStats();
deadbeeffac06552015-11-25 19:26:01308 }
Florent Castelli892acf02018-10-01 20:47:20309 if (!init_parameters_.encodings.empty()) {
310 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
311 RTC_DCHECK(media_channel_);
312 // Get the current parameters, which are constructed from the SDP.
313 // The number of layers in the SDP is currently authoritative to support
314 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
315 // lines as described in RFC 5576.
316 // All fields should be default constructed and the SSRC field set, which
317 // we need to copy.
318 RtpParameters current_parameters =
319 media_channel_->GetRtpSendParameters(ssrc_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21320 RTC_DCHECK_GE(current_parameters.encodings.size(),
321 init_parameters_.encodings.size());
Florent Castelli892acf02018-10-01 20:47:20322 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
323 init_parameters_.encodings[i].ssrc =
324 current_parameters.encodings[i].ssrc;
Amit Hilbuch2297d332019-02-19 20:49:22325 init_parameters_.encodings[i].rid = current_parameters.encodings[i].rid;
Florent Castelli892acf02018-10-01 20:47:20326 current_parameters.encodings[i] = init_parameters_.encodings[i];
327 }
328 current_parameters.degradation_preference =
329 init_parameters_.degradation_preference;
330 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
331 init_parameters_.encodings.clear();
332 });
333 }
Amit Hilbuchea7ef2a2019-02-19 23:20:21334 // Attempt to attach the frame decryptor to the current media channel.
335 if (frame_encryptor_) {
336 SetFrameEncryptor(frame_encryptor_);
337 }
Marina Cioceae77912b2020-02-27 15:16:55338 if (frame_transformer_) {
339 SetEncoderToPacketizerFrameTransformer(frame_transformer_);
340 }
Jonas Oreland65455162022-06-08 09:25:46341 if (encoder_selector_) {
342 SetEncoderSelectorOnChannel();
343 }
deadbeeffac06552015-11-25 19:26:01344}
345
Amit Hilbuchea7ef2a2019-02-19 23:20:21346void RtpSenderBase::Stop() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12347 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21348 TRACE_EVENT0("webrtc", "RtpSenderBase::Stop");
deadbeef70ab1a12015-09-28 23:53:55349 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 19:26:01350 if (stopped_) {
deadbeef70ab1a12015-09-28 23:53:55351 return;
352 }
deadbeeffac06552015-11-25 19:26:01353 if (track_) {
Amit Hilbuchea7ef2a2019-02-19 23:20:21354 DetachTrack();
deadbeeffac06552015-11-25 19:26:01355 track_->UnregisterObserver(this);
356 }
357 if (can_send_track()) {
Amit Hilbuchea7ef2a2019-02-19 23:20:21358 ClearSend();
359 RemoveTrackFromStats();
deadbeeffac06552015-11-25 19:26:01360 }
Harald Alvestrand3d976f62018-03-19 18:05:06361 media_channel_ = nullptr;
Guido Urdaneta1ff16c82019-05-20 17:31:53362 set_streams_observer_ = nullptr;
deadbeeffac06552015-11-25 19:26:01363 stopped_ = true;
deadbeef70ab1a12015-09-28 23:53:55364}
365
Amit Hilbuchea7ef2a2019-02-19 23:20:21366RTCError RtpSenderBase::DisableEncodingLayers(
Amit Hilbuch2297d332019-02-19 20:49:22367 const std::vector<std::string>& rids) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12368 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuch2297d332019-02-19 20:49:22369 if (stopped_) {
Amit Hilbuch619b2942019-02-26 23:55:19370 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
371 "Cannot disable encodings on a stopped sender.");
Amit Hilbuch2297d332019-02-19 20:49:22372 }
373
Amit Hilbuch619b2942019-02-26 23:55:19374 if (rids.empty()) {
Amit Hilbuch2297d332019-02-19 20:49:22375 return RTCError::OK();
376 }
377
378 // Check that all the specified layers exist and disable them in the channel.
Amit Hilbuch619b2942019-02-26 23:55:19379 RtpParameters parameters = GetParametersInternal();
Amit Hilbuch2297d332019-02-19 20:49:22380 for (const std::string& rid : rids) {
Amit Hilbuch619b2942019-02-26 23:55:19381 if (absl::c_none_of(parameters.encodings,
382 [&rid](const RtpEncodingParameters& encoding) {
383 return encoding.rid == rid;
384 })) {
385 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
386 "RID: " + rid + " does not refer to a valid layer.");
Amit Hilbuch2297d332019-02-19 20:49:22387 }
Amit Hilbuch2297d332019-02-19 20:49:22388 }
389
Amit Hilbuch619b2942019-02-26 23:55:19390 if (!media_channel_ || !ssrc_) {
391 RemoveEncodingLayers(rids, &init_parameters_.encodings);
392 // Invalidate any transaction upon success.
393 last_transaction_id_.reset();
394 return RTCError::OK();
395 }
396
397 for (RtpEncodingParameters& encoding : parameters.encodings) {
398 // Remain active if not in the disable list.
399 encoding.active &= absl::c_none_of(
400 rids,
401 [&encoding](const std::string& rid) { return encoding.rid == rid; });
402 }
403
404 RTCError result = SetParametersInternal(parameters);
Amit Hilbuch2297d332019-02-19 20:49:22405 if (result.ok()) {
406 disabled_rids_.insert(disabled_rids_.end(), rids.begin(), rids.end());
Amit Hilbuch619b2942019-02-26 23:55:19407 // Invalidate any transaction upon success.
408 last_transaction_id_.reset();
Amit Hilbuch2297d332019-02-19 20:49:22409 }
410 return result;
411}
412
Marina Cioceae77912b2020-02-27 15:16:55413void RtpSenderBase::SetEncoderToPacketizerFrameTransformer(
414 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12415 RTC_DCHECK_RUN_ON(signaling_thread_);
Marina Cioceae77912b2020-02-27 15:16:55416 frame_transformer_ = std::move(frame_transformer);
417 if (media_channel_ && ssrc_ && !stopped_) {
418 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
419 media_channel_->SetEncoderToPacketizerFrameTransformer(
420 ssrc_, frame_transformer_);
421 });
422 }
423}
424
Amit Hilbuchea7ef2a2019-02-19 23:20:21425LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
426
427LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
Markus Handell6fcd0f82020-07-07 17:08:53428 MutexLock lock(&lock_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21429 if (sink_)
430 sink_->OnClose();
431}
432
Minyue Li99d6d812020-01-29 09:25:12433void LocalAudioSinkAdapter::OnData(
434 const void* audio_data,
435 int bits_per_sample,
436 int sample_rate,
437 size_t number_of_channels,
438 size_t number_of_frames,
439 absl::optional<int64_t> absolute_capture_timestamp_ms) {
Markus Handell6fcd0f82020-07-07 17:08:53440 MutexLock lock(&lock_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21441 if (sink_) {
442 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
Minyue Li99d6d812020-01-29 09:25:12443 number_of_frames, absolute_capture_timestamp_ms);
Gustaf Ullberg46ea5d72020-12-15 14:12:16444 num_preferred_channels_ = sink_->NumPreferredChannels();
Amit Hilbuchea7ef2a2019-02-19 23:20:21445 }
446}
447
448void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
Markus Handell6fcd0f82020-07-07 17:08:53449 MutexLock lock(&lock_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21450 RTC_DCHECK(!sink || !sink_);
451 sink_ = sink;
452}
453
454rtc::scoped_refptr<AudioRtpSender> AudioRtpSender::Create(
455 rtc::Thread* worker_thread,
456 const std::string& id,
Harald Alvestrand445e6b02020-09-29 14:21:47457 StatsCollectorInterface* stats,
Guido Urdaneta1ff16c82019-05-20 17:31:53458 SetStreamsObserver* set_streams_observer) {
Tommi87f70902021-04-27 12:43:08459 return rtc::make_ref_counted<AudioRtpSender>(worker_thread, id, stats,
460 set_streams_observer);
Amit Hilbuchea7ef2a2019-02-19 23:20:21461}
462
463AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
464 const std::string& id,
Harald Alvestrand445e6b02020-09-29 14:21:47465 StatsCollectorInterface* stats,
Guido Urdaneta1ff16c82019-05-20 17:31:53466 SetStreamsObserver* set_streams_observer)
467 : RtpSenderBase(worker_thread, id, set_streams_observer),
Amit Hilbuchea7ef2a2019-02-19 23:20:21468 stats_(stats),
469 dtmf_sender_proxy_(DtmfSenderProxy::Create(
470 rtc::Thread::Current(),
471 DtmfSender::Create(rtc::Thread::Current(), this))),
472 sink_adapter_(new LocalAudioSinkAdapter()) {}
473
474AudioRtpSender::~AudioRtpSender() {
475 // For DtmfSender.
476 SignalDestroyed();
477 Stop();
478}
479
480bool AudioRtpSender::CanInsertDtmf() {
481 if (!media_channel_) {
482 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
483 return false;
484 }
485 // Check that this RTP sender is active (description has been applied that
486 // matches an SSRC to its ID).
487 if (!ssrc_) {
488 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
489 return false;
490 }
491 return worker_thread_->Invoke<bool>(
492 RTC_FROM_HERE, [&] { return voice_media_channel()->CanInsertDtmf(); });
493}
494
495bool AudioRtpSender::InsertDtmf(int code, int duration) {
496 if (!media_channel_) {
497 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
498 return false;
499 }
500 if (!ssrc_) {
501 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
502 return false;
503 }
504 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
505 return voice_media_channel()->InsertDtmf(ssrc_, code, duration);
506 });
507 if (!success) {
508 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
509 }
510 return success;
511}
512
513sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
514 return &SignalDestroyed;
515}
516
517void AudioRtpSender::OnChanged() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12518 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21519 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
520 RTC_DCHECK(!stopped_);
521 if (cached_track_enabled_ != track_->enabled()) {
522 cached_track_enabled_ = track_->enabled();
523 if (can_send_track()) {
524 SetSend();
525 }
526 }
527}
528
529void AudioRtpSender::DetachTrack() {
530 RTC_DCHECK(track_);
531 audio_track()->RemoveSink(sink_adapter_.get());
532}
533
534void AudioRtpSender::AttachTrack() {
535 RTC_DCHECK(track_);
536 cached_track_enabled_ = track_->enabled();
537 audio_track()->AddSink(sink_adapter_.get());
538}
539
540void AudioRtpSender::AddTrackToStats() {
541 if (can_send_track() && stats_) {
542 stats_->AddLocalAudioTrack(audio_track().get(), ssrc_);
543 }
544}
545
546void AudioRtpSender::RemoveTrackFromStats() {
547 if (can_send_track() && stats_) {
548 stats_->RemoveLocalAudioTrack(audio_track().get(), ssrc_);
549 }
550}
551
552rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12553 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21554 return dtmf_sender_proxy_;
555}
556
557void AudioRtpSender::SetSend() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12558 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21559 RTC_DCHECK(!stopped_);
560 RTC_DCHECK(can_send_track());
561 if (!media_channel_) {
562 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
563 return;
564 }
565 cricket::AudioOptions options;
566#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
567 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
568 // PeerConnection. This is a bit of a strange way to apply local audio
569 // options since it is also applied to all streams/channels, local or remote.
570 if (track_->enabled() && audio_track()->GetSource() &&
571 !audio_track()->GetSource()->remote()) {
572 options = audio_track()->GetSource()->options();
573 }
574#endif
575
Artem Titovcfea2182021-08-09 23:22:31576 // `track_->enabled()` hops to the signaling thread, so call it before we hop
Amit Hilbuchea7ef2a2019-02-19 23:20:21577 // to the worker thread or else it will deadlock.
578 bool track_enabled = track_->enabled();
579 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
580 return voice_media_channel()->SetAudioSend(ssrc_, track_enabled, &options,
581 sink_adapter_.get());
582 });
583 if (!success) {
584 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
585 }
586}
587
588void AudioRtpSender::ClearSend() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12589 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21590 RTC_DCHECK(ssrc_ != 0);
591 RTC_DCHECK(!stopped_);
592 if (!media_channel_) {
593 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
594 return;
595 }
596 cricket::AudioOptions options;
597 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
598 return voice_media_channel()->SetAudioSend(ssrc_, false, &options, nullptr);
599 });
600 if (!success) {
601 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
602 }
603}
604
605rtc::scoped_refptr<VideoRtpSender> VideoRtpSender::Create(
606 rtc::Thread* worker_thread,
Guido Urdaneta1ff16c82019-05-20 17:31:53607 const std::string& id,
608 SetStreamsObserver* set_streams_observer) {
Tommi87f70902021-04-27 12:43:08609 return rtc::make_ref_counted<VideoRtpSender>(worker_thread, id,
610 set_streams_observer);
Amit Hilbuchea7ef2a2019-02-19 23:20:21611}
612
613VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Guido Urdaneta1ff16c82019-05-20 17:31:53614 const std::string& id,
615 SetStreamsObserver* set_streams_observer)
616 : RtpSenderBase(worker_thread, id, set_streams_observer) {}
Amit Hilbuchea7ef2a2019-02-19 23:20:21617
618VideoRtpSender::~VideoRtpSender() {
619 Stop();
620}
621
622void VideoRtpSender::OnChanged() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12623 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21624 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
625 RTC_DCHECK(!stopped_);
Tomas Gunnarssondfd69c22022-02-15 12:56:50626
627 auto content_hint = video_track()->content_hint();
628 if (cached_track_content_hint_ != content_hint) {
629 cached_track_content_hint_ = content_hint;
Amit Hilbuchea7ef2a2019-02-19 23:20:21630 if (can_send_track()) {
631 SetSend();
632 }
633 }
634}
635
636void VideoRtpSender::AttachTrack() {
637 RTC_DCHECK(track_);
638 cached_track_content_hint_ = video_track()->content_hint();
639}
640
641rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12642 RTC_DCHECK_RUN_ON(signaling_thread_);
643 RTC_DLOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
Amit Hilbuchea7ef2a2019-02-19 23:20:21644 return nullptr;
645}
646
647void VideoRtpSender::SetSend() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12648 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21649 RTC_DCHECK(!stopped_);
650 RTC_DCHECK(can_send_track());
651 if (!media_channel_) {
652 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
653 return;
654 }
655 cricket::VideoOptions options;
656 VideoTrackSourceInterface* source = video_track()->GetSource();
657 if (source) {
658 options.is_screencast = source->is_screencast();
659 options.video_noise_reduction = source->needs_denoising();
660 }
Florent Castellib05ca4b2020-03-05 12:39:55661 options.content_hint = cached_track_content_hint_;
Amit Hilbuchea7ef2a2019-02-19 23:20:21662 switch (cached_track_content_hint_) {
663 case VideoTrackInterface::ContentHint::kNone:
664 break;
665 case VideoTrackInterface::ContentHint::kFluid:
666 options.is_screencast = false;
667 break;
668 case VideoTrackInterface::ContentHint::kDetailed:
669 case VideoTrackInterface::ContentHint::kText:
670 options.is_screencast = true;
671 break;
672 }
673 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerafb246b2022-04-20 12:26:50674 return video_media_channel()->SetVideoSend(ssrc_, &options,
675 video_track().get());
Amit Hilbuchea7ef2a2019-02-19 23:20:21676 });
677 RTC_DCHECK(success);
678}
679
680void VideoRtpSender::ClearSend() {
Tomas Gunnarssonfe328ca2022-02-16 19:02:12681 RTC_DCHECK_RUN_ON(signaling_thread_);
Amit Hilbuchea7ef2a2019-02-19 23:20:21682 RTC_DCHECK(ssrc_ != 0);
683 RTC_DCHECK(!stopped_);
684 if (!media_channel_) {
685 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
686 return;
687 }
Artem Titov880fa812021-07-30 20:30:23688 // Allow SetVideoSend to fail since `enable` is false and `source` is null.
Amit Hilbuchea7ef2a2019-02-19 23:20:21689 // This the normal case when the underlying media channel has already been
690 // deleted.
691 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
692 return video_media_channel()->SetVideoSend(ssrc_, nullptr, nullptr);
693 });
694}
695
deadbeef70ab1a12015-09-28 23:53:55696} // namespace webrtc