xref: /aosp_15_r20/external/webrtc/pc/rtp_sender.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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