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