1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "pc/rtp_sender.h"
12
13 #include <algorithm>
14 #include <atomic>
15 #include <string>
16 #include <utility>
17 #include <vector>
18
19 #include "absl/algorithm/container.h"
20 #include "api/audio_options.h"
21 #include "api/media_stream_interface.h"
22 #include "api/priority.h"
23 #include "media/base/media_engine.h"
24 #include "pc/legacy_stats_collector_interface.h"
25 #include "rtc_base/checks.h"
26 #include "rtc_base/helpers.h"
27 #include "rtc_base/logging.h"
28 #include "rtc_base/trace_event.h"
29
30 namespace webrtc {
31
32 namespace {
33
34 // This function is only expected to be called on the signaling thread.
35 // On the other hand, some test or even production setups may use
36 // several signaling threads.
GenerateUniqueId()37 int GenerateUniqueId() {
38 static std::atomic<int> g_unique_id{0};
39
40 return ++g_unique_id;
41 }
42
43 // Returns true if a "per-sender" encoding parameter contains a value that isn't
44 // its default. Currently max_bitrate_bps and bitrate_priority both are
45 // implemented "per-sender," meaning that these encoding parameters
46 // are used for the RtpSender as a whole, not for a specific encoding layer.
47 // This is done by setting these encoding parameters at index 0 of
48 // RtpParameters.encodings. This function can be used to check if these
49 // parameters are set at any index other than 0 of RtpParameters.encodings,
50 // because they are currently unimplemented to be used for a specific encoding
51 // layer.
PerSenderRtpEncodingParameterHasValue(const RtpEncodingParameters & encoding_params)52 bool PerSenderRtpEncodingParameterHasValue(
53 const RtpEncodingParameters& encoding_params) {
54 if (encoding_params.bitrate_priority != kDefaultBitratePriority ||
55 encoding_params.network_priority != Priority::kLow) {
56 return true;
57 }
58 return false;
59 }
60
RemoveEncodingLayers(const std::vector<std::string> & rids,std::vector<RtpEncodingParameters> * encodings)61 void RemoveEncodingLayers(const std::vector<std::string>& rids,
62 std::vector<RtpEncodingParameters>* encodings) {
63 RTC_DCHECK(encodings);
64 encodings->erase(
65 std::remove_if(encodings->begin(), encodings->end(),
66 [&rids](const RtpEncodingParameters& encoding) {
67 return absl::c_linear_search(rids, encoding.rid);
68 }),
69 encodings->end());
70 }
71
RestoreEncodingLayers(const RtpParameters & parameters,const std::vector<std::string> & removed_rids,const std::vector<RtpEncodingParameters> & all_layers)72 RtpParameters RestoreEncodingLayers(
73 const RtpParameters& parameters,
74 const std::vector<std::string>& removed_rids,
75 const std::vector<RtpEncodingParameters>& all_layers) {
76 RTC_CHECK_EQ(parameters.encodings.size() + removed_rids.size(),
77 all_layers.size());
78 RtpParameters result(parameters);
79 result.encodings.clear();
80 size_t index = 0;
81 for (const RtpEncodingParameters& encoding : all_layers) {
82 if (absl::c_linear_search(removed_rids, encoding.rid)) {
83 result.encodings.push_back(encoding);
84 continue;
85 }
86 result.encodings.push_back(parameters.encodings[index++]);
87 }
88 return result;
89 }
90
91 class SignalingThreadCallback {
92 public:
SignalingThreadCallback(rtc::Thread * signaling_thread,SetParametersCallback callback)93 SignalingThreadCallback(rtc::Thread* signaling_thread,
94 SetParametersCallback callback)
95 : signaling_thread_(signaling_thread), callback_(std::move(callback)) {}
SignalingThreadCallback(SignalingThreadCallback && other)96 SignalingThreadCallback(SignalingThreadCallback&& other)
97 : signaling_thread_(other.signaling_thread_),
98 callback_(std::move(other.callback_)) {
99 other.callback_ = nullptr;
100 }
101
~SignalingThreadCallback()102 ~SignalingThreadCallback() {
103 if (callback_) {
104 Resolve(RTCError(RTCErrorType::INTERNAL_ERROR));
105
106 RTC_CHECK_NOTREACHED();
107 }
108 }
109
operator ()(const RTCError & error)110 void operator()(const RTCError& error) { Resolve(error); }
111
112 private:
Resolve(const RTCError & error)113 void Resolve(const RTCError& error) {
114 if (!signaling_thread_->IsCurrent()) {
115 signaling_thread_->PostTask(
116 [callback = std::move(callback_), error]() mutable {
117 webrtc::InvokeSetParametersCallback(callback, error);
118 });
119 callback_ = nullptr;
120 return;
121 }
122
123 webrtc::InvokeSetParametersCallback(callback_, error);
124 callback_ = nullptr;
125 }
126
127 rtc::Thread* signaling_thread_;
128 SetParametersCallback callback_;
129 };
130
131 } // namespace
132
133 // Returns true if any RtpParameters member that isn't implemented contains a
134 // value.
UnimplementedRtpParameterHasValue(const RtpParameters & parameters)135 bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
136 if (!parameters.mid.empty()) {
137 return true;
138 }
139 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
140 // Encoding parameters that are per-sender should only contain value at
141 // index 0.
142 if (i != 0 &&
143 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
144 return true;
145 }
146 }
147 return false;
148 }
149
RtpSenderBase(rtc::Thread * worker_thread,const std::string & id,SetStreamsObserver * set_streams_observer)150 RtpSenderBase::RtpSenderBase(rtc::Thread* worker_thread,
151 const std::string& id,
152 SetStreamsObserver* set_streams_observer)
153 : signaling_thread_(rtc::Thread::Current()),
154 worker_thread_(worker_thread),
155 id_(id),
156 set_streams_observer_(set_streams_observer) {
157 RTC_DCHECK(worker_thread);
158 init_parameters_.encodings.emplace_back();
159 }
160
SetFrameEncryptor(rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor)161 void RtpSenderBase::SetFrameEncryptor(
162 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
163 RTC_DCHECK_RUN_ON(signaling_thread_);
164 frame_encryptor_ = std::move(frame_encryptor);
165 // Special Case: Set the frame encryptor to any value on any existing channel.
166 if (media_channel_ && ssrc_ && !stopped_) {
167 worker_thread_->BlockingCall(
168 [&] { media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_); });
169 }
170 }
171
SetEncoderSelector(std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> encoder_selector)172 void RtpSenderBase::SetEncoderSelector(
173 std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface>
174 encoder_selector) {
175 RTC_DCHECK_RUN_ON(signaling_thread_);
176 encoder_selector_ = std::move(encoder_selector);
177 SetEncoderSelectorOnChannel();
178 }
179
SetEncoderSelectorOnChannel()180 void RtpSenderBase::SetEncoderSelectorOnChannel() {
181 RTC_DCHECK_RUN_ON(signaling_thread_);
182 if (media_channel_ && ssrc_ && !stopped_) {
183 worker_thread_->BlockingCall([&] {
184 media_channel_->SetEncoderSelector(ssrc_, encoder_selector_.get());
185 });
186 }
187 }
188
SetMediaChannel(cricket::MediaChannel * media_channel)189 void RtpSenderBase::SetMediaChannel(cricket::MediaChannel* media_channel) {
190 RTC_DCHECK(media_channel == nullptr ||
191 media_channel->media_type() == media_type());
192 media_channel_ = media_channel;
193 }
194
GetParametersInternal() const195 RtpParameters RtpSenderBase::GetParametersInternal() const {
196 RTC_DCHECK_RUN_ON(signaling_thread_);
197 if (stopped_) {
198 return RtpParameters();
199 }
200 if (!media_channel_ || !ssrc_) {
201 return init_parameters_;
202 }
203 return worker_thread_->BlockingCall([&] {
204 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
205 RemoveEncodingLayers(disabled_rids_, &result.encodings);
206 return result;
207 });
208 }
209
GetParametersInternalWithAllLayers() const210 RtpParameters RtpSenderBase::GetParametersInternalWithAllLayers() const {
211 RTC_DCHECK_RUN_ON(signaling_thread_);
212 if (stopped_) {
213 return RtpParameters();
214 }
215 if (!media_channel_ || !ssrc_) {
216 return init_parameters_;
217 }
218 return worker_thread_->BlockingCall([&] {
219 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
220 return result;
221 });
222 }
223
GetParameters() const224 RtpParameters RtpSenderBase::GetParameters() const {
225 RTC_DCHECK_RUN_ON(signaling_thread_);
226 RtpParameters result = GetParametersInternal();
227 last_transaction_id_ = rtc::CreateRandomUuid();
228 result.transaction_id = last_transaction_id_.value();
229 return result;
230 }
231
SetParametersInternal(const RtpParameters & parameters,SetParametersCallback callback,bool blocking)232 void RtpSenderBase::SetParametersInternal(const RtpParameters& parameters,
233 SetParametersCallback callback,
234 bool blocking) {
235 RTC_DCHECK_RUN_ON(signaling_thread_);
236 RTC_DCHECK(!stopped_);
237
238 if (UnimplementedRtpParameterHasValue(parameters)) {
239 RTCError error(
240 RTCErrorType::UNSUPPORTED_PARAMETER,
241 "Attempted to set an unimplemented parameter of RtpParameters.");
242 RTC_LOG(LS_ERROR) << error.message() << " ("
243 << ::webrtc::ToString(error.type()) << ")";
244 webrtc::InvokeSetParametersCallback(callback, error);
245 return;
246 }
247 if (!media_channel_ || !ssrc_) {
248 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
249 init_parameters_, parameters, video_codec_preferences_);
250 if (result.ok()) {
251 init_parameters_ = parameters;
252 }
253 webrtc::InvokeSetParametersCallback(callback, result);
254 return;
255 }
256 auto task = [&, callback = std::move(callback),
257 parameters = std::move(parameters)]() mutable {
258 RtpParameters rtp_parameters = parameters;
259 RtpParameters old_parameters = media_channel_->GetRtpSendParameters(ssrc_);
260 if (!disabled_rids_.empty()) {
261 // Need to add the inactive layers.
262 rtp_parameters = RestoreEncodingLayers(parameters, disabled_rids_,
263 old_parameters.encodings);
264 }
265
266 RTCError result = cricket::CheckRtpParametersInvalidModificationAndValues(
267 old_parameters, rtp_parameters);
268 if (!result.ok()) {
269 webrtc::InvokeSetParametersCallback(callback, result);
270 return;
271 }
272
273 result = CheckSVCParameters(rtp_parameters);
274 if (!result.ok()) {
275 webrtc::InvokeSetParametersCallback(callback, result);
276 return;
277 }
278
279 media_channel_->SetRtpSendParameters(ssrc_, rtp_parameters,
280 std::move(callback));
281 };
282 if (blocking)
283 worker_thread_->BlockingCall(task);
284 else
285 worker_thread_->PostTask(std::move(task));
286 }
287
SetParametersInternalWithAllLayers(const RtpParameters & parameters)288 RTCError RtpSenderBase::SetParametersInternalWithAllLayers(
289 const RtpParameters& parameters) {
290 RTC_DCHECK_RUN_ON(signaling_thread_);
291 RTC_DCHECK(!stopped_);
292
293 if (UnimplementedRtpParameterHasValue(parameters)) {
294 LOG_AND_RETURN_ERROR(
295 RTCErrorType::UNSUPPORTED_PARAMETER,
296 "Attempted to set an unimplemented parameter of RtpParameters.");
297 }
298 if (!media_channel_ || !ssrc_) {
299 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
300 init_parameters_, parameters, video_codec_preferences_);
301 if (result.ok()) {
302 init_parameters_ = parameters;
303 }
304 return result;
305 }
306 return worker_thread_->BlockingCall([&] {
307 RtpParameters rtp_parameters = parameters;
308 return media_channel_->SetRtpSendParameters(ssrc_, rtp_parameters, nullptr);
309 });
310 }
311
CheckSetParameters(const RtpParameters & parameters)312 RTCError RtpSenderBase::CheckSetParameters(const RtpParameters& parameters) {
313 RTC_DCHECK_RUN_ON(signaling_thread_);
314 if (is_transceiver_stopped_) {
315 LOG_AND_RETURN_ERROR(
316 RTCErrorType::INVALID_STATE,
317 "Cannot set parameters on sender of a stopped transceiver.");
318 }
319 if (stopped_) {
320 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
321 "Cannot set parameters on a stopped sender.");
322 }
323 if (!last_transaction_id_) {
324 LOG_AND_RETURN_ERROR(
325 RTCErrorType::INVALID_STATE,
326 "Failed to set parameters since getParameters() has never been called"
327 " on this sender");
328 }
329 if (last_transaction_id_ != parameters.transaction_id) {
330 LOG_AND_RETURN_ERROR(
331 RTCErrorType::INVALID_MODIFICATION,
332 "Failed to set parameters since the transaction_id doesn't match"
333 " the last value returned from getParameters()");
334 }
335
336 return RTCError::OK();
337 }
338
SetParameters(const RtpParameters & parameters)339 RTCError RtpSenderBase::SetParameters(const RtpParameters& parameters) {
340 RTC_DCHECK_RUN_ON(signaling_thread_);
341 TRACE_EVENT0("webrtc", "RtpSenderBase::SetParameters");
342 RTCError result = CheckSetParameters(parameters);
343 if (!result.ok())
344 return result;
345
346 // Some tests rely on working in single thread mode without a run loop and a
347 // blocking call is required to keep them working. The encoder configuration
348 // also involves another thread with an asynchronous task, thus we still do
349 // need to wait for the callback to be resolved this way.
350 std::unique_ptr<rtc::Event> done_event = std::make_unique<rtc::Event>();
351 SetParametersInternal(
352 parameters,
353 [done = done_event.get(), &result](RTCError error) {
354 result = error;
355 done->Set();
356 },
357 true);
358 done_event->Wait(rtc::Event::kForever);
359 last_transaction_id_.reset();
360 return result;
361 }
362
SetParametersAsync(const RtpParameters & parameters,SetParametersCallback callback)363 void RtpSenderBase::SetParametersAsync(const RtpParameters& parameters,
364 SetParametersCallback callback) {
365 RTC_DCHECK_RUN_ON(signaling_thread_);
366 RTC_DCHECK(callback);
367 TRACE_EVENT0("webrtc", "RtpSenderBase::SetParametersAsync");
368 RTCError result = CheckSetParameters(parameters);
369 if (!result.ok()) {
370 webrtc::InvokeSetParametersCallback(callback, result);
371 return;
372 }
373
374 SetParametersInternal(
375 parameters,
376 SignalingThreadCallback(
377 signaling_thread_,
378 [this, callback = std::move(callback)](RTCError error) mutable {
379 last_transaction_id_.reset();
380 webrtc::InvokeSetParametersCallback(callback, error);
381 }),
382 false);
383 }
384
SetStreams(const std::vector<std::string> & stream_ids)385 void RtpSenderBase::SetStreams(const std::vector<std::string>& stream_ids) {
386 set_stream_ids(stream_ids);
387 if (set_streams_observer_)
388 set_streams_observer_->OnSetStreams();
389 }
390
SetTrack(MediaStreamTrackInterface * track)391 bool RtpSenderBase::SetTrack(MediaStreamTrackInterface* track) {
392 RTC_DCHECK_RUN_ON(signaling_thread_);
393 TRACE_EVENT0("webrtc", "RtpSenderBase::SetTrack");
394 if (stopped_) {
395 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
396 return false;
397 }
398 if (track && track->kind() != track_kind()) {
399 RTC_LOG(LS_ERROR) << "SetTrack with " << track->kind()
400 << " called on RtpSender with " << track_kind()
401 << " track.";
402 return false;
403 }
404
405 // Detach from old track.
406 if (track_) {
407 DetachTrack();
408 track_->UnregisterObserver(this);
409 RemoveTrackFromStats();
410 }
411
412 // Attach to new track.
413 bool prev_can_send_track = can_send_track();
414 // Keep a reference to the old track to keep it alive until we call SetSend.
415 rtc::scoped_refptr<MediaStreamTrackInterface> old_track = track_;
416 track_ = track;
417 if (track_) {
418 track_->RegisterObserver(this);
419 AttachTrack();
420 }
421
422 // Update channel.
423 if (can_send_track()) {
424 SetSend();
425 AddTrackToStats();
426 } else if (prev_can_send_track) {
427 ClearSend();
428 }
429 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
430 return true;
431 }
432
SetSsrc(uint32_t ssrc)433 void RtpSenderBase::SetSsrc(uint32_t ssrc) {
434 RTC_DCHECK_RUN_ON(signaling_thread_);
435 TRACE_EVENT0("webrtc", "RtpSenderBase::SetSsrc");
436 if (stopped_ || ssrc == ssrc_) {
437 return;
438 }
439 // If we are already sending with a particular SSRC, stop sending.
440 if (can_send_track()) {
441 ClearSend();
442 RemoveTrackFromStats();
443 }
444 ssrc_ = ssrc;
445 if (can_send_track()) {
446 SetSend();
447 AddTrackToStats();
448 }
449 if (!init_parameters_.encodings.empty() ||
450 init_parameters_.degradation_preference.has_value()) {
451 worker_thread_->BlockingCall([&] {
452 RTC_DCHECK(media_channel_);
453 // Get the current parameters, which are constructed from the SDP.
454 // The number of layers in the SDP is currently authoritative to support
455 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
456 // lines as described in RFC 5576.
457 // All fields should be default constructed and the SSRC field set, which
458 // we need to copy.
459 RtpParameters current_parameters =
460 media_channel_->GetRtpSendParameters(ssrc_);
461 RTC_CHECK_GE(current_parameters.encodings.size(),
462 init_parameters_.encodings.size());
463 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
464 init_parameters_.encodings[i].ssrc =
465 current_parameters.encodings[i].ssrc;
466 init_parameters_.encodings[i].rid = current_parameters.encodings[i].rid;
467 current_parameters.encodings[i] = init_parameters_.encodings[i];
468 }
469 current_parameters.degradation_preference =
470 init_parameters_.degradation_preference;
471 media_channel_->SetRtpSendParameters(ssrc_, current_parameters, nullptr);
472 init_parameters_.encodings.clear();
473 init_parameters_.degradation_preference = absl::nullopt;
474 });
475 }
476 // Attempt to attach the frame decryptor to the current media channel.
477 if (frame_encryptor_) {
478 SetFrameEncryptor(frame_encryptor_);
479 }
480 if (frame_transformer_) {
481 SetEncoderToPacketizerFrameTransformer(frame_transformer_);
482 }
483 if (encoder_selector_) {
484 SetEncoderSelectorOnChannel();
485 }
486 }
487
Stop()488 void RtpSenderBase::Stop() {
489 RTC_DCHECK_RUN_ON(signaling_thread_);
490 TRACE_EVENT0("webrtc", "RtpSenderBase::Stop");
491 // TODO(deadbeef): Need to do more here to fully stop sending packets.
492 if (stopped_) {
493 return;
494 }
495 if (track_) {
496 DetachTrack();
497 track_->UnregisterObserver(this);
498 }
499 if (can_send_track()) {
500 ClearSend();
501 RemoveTrackFromStats();
502 }
503 media_channel_ = nullptr;
504 set_streams_observer_ = nullptr;
505 stopped_ = true;
506 }
507
DisableEncodingLayers(const std::vector<std::string> & rids)508 RTCError RtpSenderBase::DisableEncodingLayers(
509 const std::vector<std::string>& rids) {
510 RTC_DCHECK_RUN_ON(signaling_thread_);
511 if (stopped_) {
512 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
513 "Cannot disable encodings on a stopped sender.");
514 }
515
516 if (rids.empty()) {
517 return RTCError::OK();
518 }
519
520 // Check that all the specified layers exist and disable them in the channel.
521 RtpParameters parameters = GetParametersInternalWithAllLayers();
522 for (const std::string& rid : rids) {
523 if (absl::c_none_of(parameters.encodings,
524 [&rid](const RtpEncodingParameters& encoding) {
525 return encoding.rid == rid;
526 })) {
527 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
528 "RID: " + rid + " does not refer to a valid layer.");
529 }
530 }
531
532 if (!media_channel_ || !ssrc_) {
533 RemoveEncodingLayers(rids, &init_parameters_.encodings);
534 // Invalidate any transaction upon success.
535 last_transaction_id_.reset();
536 return RTCError::OK();
537 }
538
539 for (RtpEncodingParameters& encoding : parameters.encodings) {
540 // Remain active if not in the disable list.
541 encoding.active &= absl::c_none_of(
542 rids,
543 [&encoding](const std::string& rid) { return encoding.rid == rid; });
544 }
545
546 RTCError result = SetParametersInternalWithAllLayers(parameters);
547 if (result.ok()) {
548 disabled_rids_.insert(disabled_rids_.end(), rids.begin(), rids.end());
549 // Invalidate any transaction upon success.
550 last_transaction_id_.reset();
551 }
552 return result;
553 }
554
SetEncoderToPacketizerFrameTransformer(rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)555 void RtpSenderBase::SetEncoderToPacketizerFrameTransformer(
556 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
557 RTC_DCHECK_RUN_ON(signaling_thread_);
558 frame_transformer_ = std::move(frame_transformer);
559 if (media_channel_ && ssrc_ && !stopped_) {
560 worker_thread_->BlockingCall([&] {
561 media_channel_->SetEncoderToPacketizerFrameTransformer(
562 ssrc_, frame_transformer_);
563 });
564 }
565 }
566
LocalAudioSinkAdapter()567 LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
568
~LocalAudioSinkAdapter()569 LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
570 MutexLock lock(&lock_);
571 if (sink_)
572 sink_->OnClose();
573 }
574
OnData(const void * audio_data,int bits_per_sample,int sample_rate,size_t number_of_channels,size_t number_of_frames,absl::optional<int64_t> absolute_capture_timestamp_ms)575 void LocalAudioSinkAdapter::OnData(
576 const void* audio_data,
577 int bits_per_sample,
578 int sample_rate,
579 size_t number_of_channels,
580 size_t number_of_frames,
581 absl::optional<int64_t> absolute_capture_timestamp_ms) {
582 TRACE_EVENT2("webrtc", "LocalAudioSinkAdapter::OnData", "sample_rate",
583 sample_rate, "number_of_frames", number_of_frames);
584 MutexLock lock(&lock_);
585 if (sink_) {
586 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
587 number_of_frames, absolute_capture_timestamp_ms);
588 num_preferred_channels_ = sink_->NumPreferredChannels();
589 }
590 }
591
SetSink(cricket::AudioSource::Sink * sink)592 void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
593 MutexLock lock(&lock_);
594 RTC_DCHECK(!sink || !sink_);
595 sink_ = sink;
596 }
597
Create(rtc::Thread * worker_thread,const std::string & id,LegacyStatsCollectorInterface * stats,SetStreamsObserver * set_streams_observer)598 rtc::scoped_refptr<AudioRtpSender> AudioRtpSender::Create(
599 rtc::Thread* worker_thread,
600 const std::string& id,
601 LegacyStatsCollectorInterface* stats,
602 SetStreamsObserver* set_streams_observer) {
603 return rtc::make_ref_counted<AudioRtpSender>(worker_thread, id, stats,
604 set_streams_observer);
605 }
606
AudioRtpSender(rtc::Thread * worker_thread,const std::string & id,LegacyStatsCollectorInterface * legacy_stats,SetStreamsObserver * set_streams_observer)607 AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
608 const std::string& id,
609 LegacyStatsCollectorInterface* legacy_stats,
610 SetStreamsObserver* set_streams_observer)
611 : RtpSenderBase(worker_thread, id, set_streams_observer),
612 legacy_stats_(legacy_stats),
613 dtmf_sender_(DtmfSender::Create(rtc::Thread::Current(), this)),
614 dtmf_sender_proxy_(
615 DtmfSenderProxy::Create(rtc::Thread::Current(), dtmf_sender_)),
616 sink_adapter_(new LocalAudioSinkAdapter()) {}
617
~AudioRtpSender()618 AudioRtpSender::~AudioRtpSender() {
619 dtmf_sender_->OnDtmfProviderDestroyed();
620 Stop();
621 }
622
CanInsertDtmf()623 bool AudioRtpSender::CanInsertDtmf() {
624 if (!media_channel_) {
625 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
626 return false;
627 }
628 // Check that this RTP sender is active (description has been applied that
629 // matches an SSRC to its ID).
630 if (!ssrc_) {
631 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
632 return false;
633 }
634 return worker_thread_->BlockingCall(
635 [&] { return voice_media_channel()->CanInsertDtmf(); });
636 }
637
InsertDtmf(int code,int duration)638 bool AudioRtpSender::InsertDtmf(int code, int duration) {
639 if (!media_channel_) {
640 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
641 return false;
642 }
643 if (!ssrc_) {
644 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
645 return false;
646 }
647 bool success = worker_thread_->BlockingCall(
648 [&] { return voice_media_channel()->InsertDtmf(ssrc_, code, duration); });
649 if (!success) {
650 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
651 }
652 return success;
653 }
654
OnChanged()655 void AudioRtpSender::OnChanged() {
656 RTC_DCHECK_RUN_ON(signaling_thread_);
657 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
658 RTC_DCHECK(!stopped_);
659 if (cached_track_enabled_ != track_->enabled()) {
660 cached_track_enabled_ = track_->enabled();
661 if (can_send_track()) {
662 SetSend();
663 }
664 }
665 }
666
DetachTrack()667 void AudioRtpSender::DetachTrack() {
668 RTC_DCHECK(track_);
669 audio_track()->RemoveSink(sink_adapter_.get());
670 }
671
AttachTrack()672 void AudioRtpSender::AttachTrack() {
673 RTC_DCHECK(track_);
674 cached_track_enabled_ = track_->enabled();
675 audio_track()->AddSink(sink_adapter_.get());
676 }
677
AddTrackToStats()678 void AudioRtpSender::AddTrackToStats() {
679 if (can_send_track() && legacy_stats_) {
680 legacy_stats_->AddLocalAudioTrack(audio_track().get(), ssrc_);
681 }
682 }
683
RemoveTrackFromStats()684 void AudioRtpSender::RemoveTrackFromStats() {
685 if (can_send_track() && legacy_stats_) {
686 legacy_stats_->RemoveLocalAudioTrack(audio_track().get(), ssrc_);
687 }
688 }
689
GetDtmfSender() const690 rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
691 RTC_DCHECK_RUN_ON(signaling_thread_);
692 return dtmf_sender_proxy_;
693 }
694
GenerateKeyFrame(const std::vector<std::string> & rids)695 RTCError AudioRtpSender::GenerateKeyFrame(
696 const std::vector<std::string>& rids) {
697 RTC_DCHECK_RUN_ON(signaling_thread_);
698 RTC_DLOG(LS_ERROR) << "Tried to get generate a key frame for audio.";
699 return RTCError(RTCErrorType::UNSUPPORTED_OPERATION,
700 "Generating key frames for audio is not supported.");
701 }
702
SetSend()703 void AudioRtpSender::SetSend() {
704 RTC_DCHECK_RUN_ON(signaling_thread_);
705 RTC_DCHECK(!stopped_);
706 RTC_DCHECK(can_send_track());
707 if (!media_channel_) {
708 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
709 return;
710 }
711 cricket::AudioOptions options;
712 #if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
713 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
714 // PeerConnection. This is a bit of a strange way to apply local audio
715 // options since it is also applied to all streams/channels, local or remote.
716 if (track_->enabled() && audio_track()->GetSource() &&
717 !audio_track()->GetSource()->remote()) {
718 options = audio_track()->GetSource()->options();
719 }
720 #endif
721
722 // `track_->enabled()` hops to the signaling thread, so call it before we hop
723 // to the worker thread or else it will deadlock.
724 bool track_enabled = track_->enabled();
725 bool success = worker_thread_->BlockingCall([&] {
726 return voice_media_channel()->SetAudioSend(ssrc_, track_enabled, &options,
727 sink_adapter_.get());
728 });
729 if (!success) {
730 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
731 }
732 }
733
ClearSend()734 void AudioRtpSender::ClearSend() {
735 RTC_DCHECK_RUN_ON(signaling_thread_);
736 RTC_DCHECK(ssrc_ != 0);
737 RTC_DCHECK(!stopped_);
738 if (!media_channel_) {
739 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
740 return;
741 }
742 cricket::AudioOptions options;
743 bool success = worker_thread_->BlockingCall([&] {
744 return voice_media_channel()->SetAudioSend(ssrc_, false, &options, nullptr);
745 });
746 if (!success) {
747 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
748 }
749 }
750
Create(rtc::Thread * worker_thread,const std::string & id,SetStreamsObserver * set_streams_observer)751 rtc::scoped_refptr<VideoRtpSender> VideoRtpSender::Create(
752 rtc::Thread* worker_thread,
753 const std::string& id,
754 SetStreamsObserver* set_streams_observer) {
755 return rtc::make_ref_counted<VideoRtpSender>(worker_thread, id,
756 set_streams_observer);
757 }
758
VideoRtpSender(rtc::Thread * worker_thread,const std::string & id,SetStreamsObserver * set_streams_observer)759 VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
760 const std::string& id,
761 SetStreamsObserver* set_streams_observer)
762 : RtpSenderBase(worker_thread, id, set_streams_observer) {}
763
~VideoRtpSender()764 VideoRtpSender::~VideoRtpSender() {
765 Stop();
766 }
767
OnChanged()768 void VideoRtpSender::OnChanged() {
769 RTC_DCHECK_RUN_ON(signaling_thread_);
770 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
771 RTC_DCHECK(!stopped_);
772
773 auto content_hint = video_track()->content_hint();
774 if (cached_track_content_hint_ != content_hint) {
775 cached_track_content_hint_ = content_hint;
776 if (can_send_track()) {
777 SetSend();
778 }
779 }
780 }
781
AttachTrack()782 void VideoRtpSender::AttachTrack() {
783 RTC_DCHECK(track_);
784 cached_track_content_hint_ = video_track()->content_hint();
785 }
786
GetDtmfSender() const787 rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
788 RTC_DCHECK_RUN_ON(signaling_thread_);
789 RTC_DLOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
790 return nullptr;
791 }
792
GenerateKeyFrame(const std::vector<std::string> & rids)793 RTCError VideoRtpSender::GenerateKeyFrame(
794 const std::vector<std::string>& rids) {
795 RTC_DCHECK_RUN_ON(signaling_thread_);
796 if (video_media_channel() && ssrc_ && !stopped_) {
797 auto parameters = GetParameters();
798 for (const auto& rid : rids) {
799 if (rid.empty()) {
800 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
801 "Attempted to specify an empty rid.");
802 }
803 if (!absl::c_any_of(parameters.encodings,
804 [&rid](const RtpEncodingParameters& parameters) {
805 return parameters.rid == rid;
806 })) {
807 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
808 "Attempted to specify a rid not configured.");
809 }
810 }
811 worker_thread_->PostTask([&, rids] {
812 video_media_channel()->GenerateSendKeyFrame(ssrc_, rids);
813 });
814 } else {
815 RTC_LOG(LS_WARNING) << "Tried to generate key frame for sender that is "
816 "stopped or has no media channel.";
817 }
818 return RTCError::OK();
819 }
820
SetSend()821 void VideoRtpSender::SetSend() {
822 RTC_DCHECK_RUN_ON(signaling_thread_);
823 RTC_DCHECK(!stopped_);
824 RTC_DCHECK(can_send_track());
825 if (!media_channel_) {
826 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
827 return;
828 }
829 cricket::VideoOptions options;
830 VideoTrackSourceInterface* source = video_track()->GetSource();
831 if (source) {
832 options.is_screencast = source->is_screencast();
833 options.video_noise_reduction = source->needs_denoising();
834 }
835 options.content_hint = cached_track_content_hint_;
836 switch (cached_track_content_hint_) {
837 case VideoTrackInterface::ContentHint::kNone:
838 break;
839 case VideoTrackInterface::ContentHint::kFluid:
840 options.is_screencast = false;
841 break;
842 case VideoTrackInterface::ContentHint::kDetailed:
843 case VideoTrackInterface::ContentHint::kText:
844 options.is_screencast = true;
845 break;
846 }
847 bool success = worker_thread_->BlockingCall([&] {
848 return video_media_channel()->SetVideoSend(ssrc_, &options,
849 video_track().get());
850 });
851 RTC_DCHECK(success);
852 }
853
ClearSend()854 void VideoRtpSender::ClearSend() {
855 RTC_DCHECK_RUN_ON(signaling_thread_);
856 RTC_DCHECK(ssrc_ != 0);
857 RTC_DCHECK(!stopped_);
858 if (!media_channel_) {
859 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
860 return;
861 }
862 // Allow SetVideoSend to fail since `enable` is false and `source` is null.
863 // This the normal case when the underlying media channel has already been
864 // deleted.
865 worker_thread_->BlockingCall(
866 [&] { video_media_channel()->SetVideoSend(ssrc_, nullptr, nullptr); });
867 }
868
CheckSVCParameters(const RtpParameters & parameters)869 RTCError VideoRtpSender::CheckSVCParameters(const RtpParameters& parameters) {
870 cricket::VideoCodec codec;
871 video_media_channel()->GetSendCodec(&codec);
872
873 // Match the currently used codec against the codec preferences to gather
874 // the SVC capabilities.
875 std::vector<cricket::VideoCodec> codecs;
876 for (const auto& codec_preference : video_codec_preferences_) {
877 if (codec.Matches(codec_preference)) {
878 codecs.push_back(codec_preference);
879 }
880 }
881
882 return cricket::CheckScalabilityModeValues(parameters, codecs);
883 }
884
885 } // namespace webrtc
886