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