blob: c56f4a94d9b6fae8f6e07f5743d89c0cbcd93dd5 [file] [log] [blame]
deadbeef6979b022015-09-24 16:47:53 -07001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
deadbeef6979b022015-09-24 16:47:53 -07003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
deadbeef6979b022015-09-24 16:47:53 -07009 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/rtp_sender.h"
deadbeef6979b022015-09-24 16:47:53 -070012
Yves Gereycb11a312019-07-26 18:51:59 +020013#include <atomic>
Benjamin Wrightd81ac952018-08-29 17:02:10 -070014#include <utility>
Steve Anton36b29d12017-10-30 09:57:42 -070015#include <vector>
16
Yves Gerey3e707812018-11-28 16:47:49 +010017#include "api/audio_options.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "api/media_stream_interface.h"
19#include "media/base/media_engine.h"
Guido Urdaneta1ff16c82019-05-20 19:31:53 +020020#include "pc/peer_connection.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "pc/stats_collector.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "rtc_base/checks.h"
23#include "rtc_base/helpers.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "rtc_base/location.h"
25#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/trace_event.h"
deadbeef70ab1a12015-09-28 16:53:55 -070027
28namespace webrtc {
29
Harald Alvestrandc72af932018-01-11 17:18:19 +010030namespace {
31
Yves Gereycb11a312019-07-26 18:51:59 +020032// This function is only expected to be called on the signaling thread.
33// On the other hand, some test or even production setups may use
34// several signaling threads.
Harald Alvestrandc72af932018-01-11 17:18:19 +010035int GenerateUniqueId() {
Yves Gereycb11a312019-07-26 18:51:59 +020036 static std::atomic<int> g_unique_id{0};
Harald Alvestrandc72af932018-01-11 17:18:19 +010037
38 return ++g_unique_id;
39}
40
Seth Hampson2d2c8882018-05-16 16:02:32 -070041// Returns true if a "per-sender" encoding parameter contains a value that isn't
42// its default. Currently max_bitrate_bps and bitrate_priority both are
43// implemented "per-sender," meaning that these encoding parameters
44// are used for the RtpSender as a whole, not for a specific encoding layer.
45// This is done by setting these encoding parameters at index 0 of
46// RtpParameters.encodings. This function can be used to check if these
47// parameters are set at any index other than 0 of RtpParameters.encodings,
48// because they are currently unimplemented to be used for a specific encoding
49// layer.
50bool PerSenderRtpEncodingParameterHasValue(
51 const RtpEncodingParameters& encoding_params) {
Tim Haloun648d28a2018-10-18 16:52:22 -070052 if (encoding_params.bitrate_priority != kDefaultBitratePriority ||
Taylor Brandstetter3f1aee32020-02-27 11:59:23 -080053 encoding_params.network_priority != Priority::kLow) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070054 return true;
55 }
56 return false;
57}
58
Amit Hilbuch2297d332019-02-19 12:49:22 -080059void RemoveEncodingLayers(const std::vector<std::string>& rids,
60 std::vector<RtpEncodingParameters>* encodings) {
61 RTC_DCHECK(encodings);
62 encodings->erase(
63 std::remove_if(encodings->begin(), encodings->end(),
64 [&rids](const RtpEncodingParameters& encoding) {
65 return absl::c_linear_search(rids, encoding.rid);
66 }),
67 encodings->end());
68}
69
70RtpParameters RestoreEncodingLayers(
71 const RtpParameters& parameters,
72 const std::vector<std::string>& removed_rids,
73 const std::vector<RtpEncodingParameters>& all_layers) {
74 RTC_DCHECK_EQ(parameters.encodings.size() + removed_rids.size(),
75 all_layers.size());
76 RtpParameters result(parameters);
77 result.encodings.clear();
78 size_t index = 0;
79 for (const RtpEncodingParameters& encoding : all_layers) {
80 if (absl::c_linear_search(removed_rids, encoding.rid)) {
81 result.encodings.push_back(encoding);
82 continue;
83 }
84 result.encodings.push_back(parameters.encodings[index++]);
85 }
86 return result;
87}
88
Florent Castelli892acf02018-10-01 22:47:20 +020089} // namespace
90
Seth Hampson2d2c8882018-05-16 16:02:32 -070091// Returns true if any RtpParameters member that isn't implemented contains a
92// value.
93bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020094 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070095 return true;
96 }
97 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070098 // Encoding parameters that are per-sender should only contain value at
99 // index 0.
100 if (i != 0 &&
101 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
102 return true;
103 }
104 }
105 return false;
106}
107
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200108RtpSenderBase::RtpSenderBase(rtc::Thread* worker_thread,
109 const std::string& id,
110 SetStreamsObserver* set_streams_observer)
111 : worker_thread_(worker_thread),
112 id_(id),
113 set_streams_observer_(set_streams_observer) {
Steve Anton47136dd2018-01-12 10:49:35 -0800114 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200115 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800116}
deadbeeffac06552015-11-25 11:26:01 -0800117
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800118void RtpSenderBase::SetFrameEncryptor(
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700119 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
120 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700121 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700122 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700123 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
124 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
125 });
126 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700127}
128
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800129void RtpSenderBase::SetMediaChannel(cricket::MediaChannel* media_channel) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800130 RTC_DCHECK(media_channel == nullptr ||
131 media_channel->media_type() == media_type());
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800132 media_channel_ = media_channel;
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700133}
134
Amit Hilbuch619b2942019-02-26 15:55:19 -0800135RtpParameters RtpSenderBase::GetParametersInternal() const {
Florent Castelli892acf02018-10-01 22:47:20 +0200136 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700137 return RtpParameters();
138 }
Amit Hilbuchaa584152019-02-06 17:09:52 -0800139 if (!media_channel_ || !ssrc_) {
Amit Hilbuch619b2942019-02-26 15:55:19 -0800140 return init_parameters_;
Florent Castelli892acf02018-10-01 22:47:20 +0200141 }
Steve Anton47136dd2018-01-12 10:49:35 -0800142 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200143 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
Amit Hilbuch2297d332019-02-19 12:49:22 -0800144 RemoveEncodingLayers(disabled_rids_, &result.encodings);
Florent Castellicebf50f2018-05-03 15:31:53 +0200145 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800146 });
deadbeefa601f5c2016-06-06 14:27:39 -0700147}
148
Amit Hilbuch619b2942019-02-26 15:55:19 -0800149RtpParameters RtpSenderBase::GetParameters() const {
150 RtpParameters result = GetParametersInternal();
151 last_transaction_id_ = rtc::CreateRandomUuid();
152 result.transaction_id = last_transaction_id_.value();
153 return result;
154}
155
156RTCError RtpSenderBase::SetParametersInternal(const RtpParameters& parameters) {
157 RTC_DCHECK(!stopped_);
Florent Castellicebf50f2018-05-03 15:31:53 +0200158
Seth Hampson2d2c8882018-05-16 16:02:32 -0700159 if (UnimplementedRtpParameterHasValue(parameters)) {
160 LOG_AND_RETURN_ERROR(
161 RTCErrorType::UNSUPPORTED_PARAMETER,
162 "Attempted to set an unimplemented parameter of RtpParameters.");
163 }
Amit Hilbuchaa584152019-02-06 17:09:52 -0800164 if (!media_channel_ || !ssrc_) {
Florent Castellic1a0bcb2019-01-29 14:26:48 +0100165 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
166 init_parameters_, parameters);
Florent Castelli892acf02018-10-01 22:47:20 +0200167 if (result.ok()) {
168 init_parameters_ = parameters;
169 }
170 return result;
171 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800172 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Amit Hilbuch2297d332019-02-19 12:49:22 -0800173 RtpParameters rtp_parameters = parameters;
174 if (!disabled_rids_.empty()) {
175 // Need to add the inactive layers.
176 RtpParameters old_parameters =
177 media_channel_->GetRtpSendParameters(ssrc_);
178 rtp_parameters = RestoreEncodingLayers(parameters, disabled_rids_,
179 old_parameters.encodings);
180 }
Amit Hilbuch619b2942019-02-26 15:55:19 -0800181 return media_channel_->SetRtpSendParameters(ssrc_, rtp_parameters);
Steve Anton47136dd2018-01-12 10:49:35 -0800182 });
deadbeefa601f5c2016-06-06 14:27:39 -0700183}
184
Amit Hilbuch619b2942019-02-26 15:55:19 -0800185RTCError RtpSenderBase::SetParameters(const RtpParameters& parameters) {
186 TRACE_EVENT0("webrtc", "RtpSenderBase::SetParameters");
187 if (stopped_) {
188 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
189 "Cannot set parameters on a stopped sender.");
190 }
191 if (!last_transaction_id_) {
192 LOG_AND_RETURN_ERROR(
193 RTCErrorType::INVALID_STATE,
194 "Failed to set parameters since getParameters() has never been called"
195 " on this sender");
196 }
197 if (last_transaction_id_ != parameters.transaction_id) {
198 LOG_AND_RETURN_ERROR(
199 RTCErrorType::INVALID_MODIFICATION,
200 "Failed to set parameters since the transaction_id doesn't match"
201 " the last value returned from getParameters()");
202 }
203
204 RTCError result = SetParametersInternal(parameters);
205 last_transaction_id_.reset();
206 return result;
207}
208
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200209void RtpSenderBase::SetStreams(const std::vector<std::string>& stream_ids) {
210 set_stream_ids(stream_ids);
211 if (set_streams_observer_)
212 set_streams_observer_->OnSetStreams();
213}
214
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800215bool RtpSenderBase::SetTrack(MediaStreamTrackInterface* track) {
216 TRACE_EVENT0("webrtc", "RtpSenderBase::SetTrack");
217 if (stopped_) {
218 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
219 return false;
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700220 }
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800221 if (track && track->kind() != track_kind()) {
222 RTC_LOG(LS_ERROR) << "SetTrack with " << track->kind()
223 << " called on RtpSender with " << track_kind()
224 << " track.";
225 return false;
226 }
227
228 // Detach from old track.
229 if (track_) {
230 DetachTrack();
231 track_->UnregisterObserver(this);
232 RemoveTrackFromStats();
233 }
234
235 // Attach to new track.
236 bool prev_can_send_track = can_send_track();
237 // Keep a reference to the old track to keep it alive until we call SetSend.
238 rtc::scoped_refptr<MediaStreamTrackInterface> old_track = track_;
239 track_ = track;
240 if (track_) {
241 track_->RegisterObserver(this);
242 AttachTrack();
243 }
244
245 // Update channel.
246 if (can_send_track()) {
247 SetSend();
248 AddTrackToStats();
249 } else if (prev_can_send_track) {
250 ClearSend();
251 }
252 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
253 return true;
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700254}
255
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800256void RtpSenderBase::SetSsrc(uint32_t ssrc) {
257 TRACE_EVENT0("webrtc", "RtpSenderBase::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800258 if (stopped_ || ssrc == ssrc_) {
259 return;
260 }
261 // If we are already sending with a particular SSRC, stop sending.
262 if (can_send_track()) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800263 ClearSend();
264 RemoveTrackFromStats();
deadbeeffac06552015-11-25 11:26:01 -0800265 }
266 ssrc_ = ssrc;
267 if (can_send_track()) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800268 SetSend();
269 AddTrackToStats();
deadbeeffac06552015-11-25 11:26:01 -0800270 }
Florent Castelli892acf02018-10-01 22:47:20 +0200271 if (!init_parameters_.encodings.empty()) {
272 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
273 RTC_DCHECK(media_channel_);
274 // Get the current parameters, which are constructed from the SDP.
275 // The number of layers in the SDP is currently authoritative to support
276 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
277 // lines as described in RFC 5576.
278 // All fields should be default constructed and the SSRC field set, which
279 // we need to copy.
280 RtpParameters current_parameters =
281 media_channel_->GetRtpSendParameters(ssrc_);
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800282 RTC_DCHECK_GE(current_parameters.encodings.size(),
283 init_parameters_.encodings.size());
Florent Castelli892acf02018-10-01 22:47:20 +0200284 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
285 init_parameters_.encodings[i].ssrc =
286 current_parameters.encodings[i].ssrc;
Amit Hilbuch2297d332019-02-19 12:49:22 -0800287 init_parameters_.encodings[i].rid = current_parameters.encodings[i].rid;
Florent Castelli892acf02018-10-01 22:47:20 +0200288 current_parameters.encodings[i] = init_parameters_.encodings[i];
289 }
290 current_parameters.degradation_preference =
291 init_parameters_.degradation_preference;
292 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
293 init_parameters_.encodings.clear();
294 });
295 }
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800296 // Attempt to attach the frame decryptor to the current media channel.
297 if (frame_encryptor_) {
298 SetFrameEncryptor(frame_encryptor_);
299 }
Marina Cioceae77912b2020-02-27 16:16:55 +0100300 if (frame_transformer_) {
301 SetEncoderToPacketizerFrameTransformer(frame_transformer_);
302 }
deadbeeffac06552015-11-25 11:26:01 -0800303}
304
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800305void RtpSenderBase::Stop() {
306 TRACE_EVENT0("webrtc", "RtpSenderBase::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700307 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800308 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700309 return;
310 }
deadbeeffac06552015-11-25 11:26:01 -0800311 if (track_) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800312 DetachTrack();
deadbeeffac06552015-11-25 11:26:01 -0800313 track_->UnregisterObserver(this);
314 }
315 if (can_send_track()) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800316 ClearSend();
317 RemoveTrackFromStats();
deadbeeffac06552015-11-25 11:26:01 -0800318 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100319 media_channel_ = nullptr;
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200320 set_streams_observer_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800321 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700322}
323
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800324RTCError RtpSenderBase::DisableEncodingLayers(
Amit Hilbuch2297d332019-02-19 12:49:22 -0800325 const std::vector<std::string>& rids) {
326 if (stopped_) {
Amit Hilbuch619b2942019-02-26 15:55:19 -0800327 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
328 "Cannot disable encodings on a stopped sender.");
Amit Hilbuch2297d332019-02-19 12:49:22 -0800329 }
330
Amit Hilbuch619b2942019-02-26 15:55:19 -0800331 if (rids.empty()) {
Amit Hilbuch2297d332019-02-19 12:49:22 -0800332 return RTCError::OK();
333 }
334
335 // Check that all the specified layers exist and disable them in the channel.
Amit Hilbuch619b2942019-02-26 15:55:19 -0800336 RtpParameters parameters = GetParametersInternal();
Amit Hilbuch2297d332019-02-19 12:49:22 -0800337 for (const std::string& rid : rids) {
Amit Hilbuch619b2942019-02-26 15:55:19 -0800338 if (absl::c_none_of(parameters.encodings,
339 [&rid](const RtpEncodingParameters& encoding) {
340 return encoding.rid == rid;
341 })) {
342 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
343 "RID: " + rid + " does not refer to a valid layer.");
Amit Hilbuch2297d332019-02-19 12:49:22 -0800344 }
Amit Hilbuch2297d332019-02-19 12:49:22 -0800345 }
346
Amit Hilbuch619b2942019-02-26 15:55:19 -0800347 if (!media_channel_ || !ssrc_) {
348 RemoveEncodingLayers(rids, &init_parameters_.encodings);
349 // Invalidate any transaction upon success.
350 last_transaction_id_.reset();
351 return RTCError::OK();
352 }
353
354 for (RtpEncodingParameters& encoding : parameters.encodings) {
355 // Remain active if not in the disable list.
356 encoding.active &= absl::c_none_of(
357 rids,
358 [&encoding](const std::string& rid) { return encoding.rid == rid; });
359 }
360
361 RTCError result = SetParametersInternal(parameters);
Amit Hilbuch2297d332019-02-19 12:49:22 -0800362 if (result.ok()) {
363 disabled_rids_.insert(disabled_rids_.end(), rids.begin(), rids.end());
Amit Hilbuch619b2942019-02-26 15:55:19 -0800364 // Invalidate any transaction upon success.
365 last_transaction_id_.reset();
Amit Hilbuch2297d332019-02-19 12:49:22 -0800366 }
367 return result;
368}
369
Marina Cioceae77912b2020-02-27 16:16:55 +0100370void RtpSenderBase::SetEncoderToPacketizerFrameTransformer(
371 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {
372 frame_transformer_ = std::move(frame_transformer);
373 if (media_channel_ && ssrc_ && !stopped_) {
374 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
375 media_channel_->SetEncoderToPacketizerFrameTransformer(
376 ssrc_, frame_transformer_);
377 });
378 }
379}
380
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800381LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
382
383LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
384 rtc::CritScope lock(&lock_);
385 if (sink_)
386 sink_->OnClose();
387}
388
Minyue Li99d6d812020-01-29 10:25:12 +0100389void LocalAudioSinkAdapter::OnData(
390 const void* audio_data,
391 int bits_per_sample,
392 int sample_rate,
393 size_t number_of_channels,
394 size_t number_of_frames,
395 absl::optional<int64_t> absolute_capture_timestamp_ms) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800396 rtc::CritScope lock(&lock_);
397 if (sink_) {
398 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
Minyue Li99d6d812020-01-29 10:25:12 +0100399 number_of_frames, absolute_capture_timestamp_ms);
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800400 }
401}
402
403void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
404 rtc::CritScope lock(&lock_);
405 RTC_DCHECK(!sink || !sink_);
406 sink_ = sink;
407}
408
409rtc::scoped_refptr<AudioRtpSender> AudioRtpSender::Create(
410 rtc::Thread* worker_thread,
411 const std::string& id,
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200412 StatsCollector* stats,
413 SetStreamsObserver* set_streams_observer) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800414 return rtc::scoped_refptr<AudioRtpSender>(
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200415 new rtc::RefCountedObject<AudioRtpSender>(worker_thread, id, stats,
416 set_streams_observer));
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800417}
418
419AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
420 const std::string& id,
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200421 StatsCollector* stats,
422 SetStreamsObserver* set_streams_observer)
423 : RtpSenderBase(worker_thread, id, set_streams_observer),
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800424 stats_(stats),
425 dtmf_sender_proxy_(DtmfSenderProxy::Create(
426 rtc::Thread::Current(),
427 DtmfSender::Create(rtc::Thread::Current(), this))),
428 sink_adapter_(new LocalAudioSinkAdapter()) {}
429
430AudioRtpSender::~AudioRtpSender() {
431 // For DtmfSender.
432 SignalDestroyed();
433 Stop();
434}
435
436bool AudioRtpSender::CanInsertDtmf() {
437 if (!media_channel_) {
438 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
439 return false;
440 }
441 // Check that this RTP sender is active (description has been applied that
442 // matches an SSRC to its ID).
443 if (!ssrc_) {
444 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
445 return false;
446 }
447 return worker_thread_->Invoke<bool>(
448 RTC_FROM_HERE, [&] { return voice_media_channel()->CanInsertDtmf(); });
449}
450
451bool AudioRtpSender::InsertDtmf(int code, int duration) {
452 if (!media_channel_) {
453 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
454 return false;
455 }
456 if (!ssrc_) {
457 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
458 return false;
459 }
460 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
461 return voice_media_channel()->InsertDtmf(ssrc_, code, duration);
462 });
463 if (!success) {
464 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
465 }
466 return success;
467}
468
469sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
470 return &SignalDestroyed;
471}
472
473void AudioRtpSender::OnChanged() {
474 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
475 RTC_DCHECK(!stopped_);
476 if (cached_track_enabled_ != track_->enabled()) {
477 cached_track_enabled_ = track_->enabled();
478 if (can_send_track()) {
479 SetSend();
480 }
481 }
482}
483
484void AudioRtpSender::DetachTrack() {
485 RTC_DCHECK(track_);
486 audio_track()->RemoveSink(sink_adapter_.get());
487}
488
489void AudioRtpSender::AttachTrack() {
490 RTC_DCHECK(track_);
491 cached_track_enabled_ = track_->enabled();
492 audio_track()->AddSink(sink_adapter_.get());
493}
494
495void AudioRtpSender::AddTrackToStats() {
496 if (can_send_track() && stats_) {
497 stats_->AddLocalAudioTrack(audio_track().get(), ssrc_);
498 }
499}
500
501void AudioRtpSender::RemoveTrackFromStats() {
502 if (can_send_track() && stats_) {
503 stats_->RemoveLocalAudioTrack(audio_track().get(), ssrc_);
504 }
505}
506
507rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
508 return dtmf_sender_proxy_;
509}
510
511void AudioRtpSender::SetSend() {
512 RTC_DCHECK(!stopped_);
513 RTC_DCHECK(can_send_track());
514 if (!media_channel_) {
515 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
516 return;
517 }
518 cricket::AudioOptions options;
519#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
520 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
521 // PeerConnection. This is a bit of a strange way to apply local audio
522 // options since it is also applied to all streams/channels, local or remote.
523 if (track_->enabled() && audio_track()->GetSource() &&
524 !audio_track()->GetSource()->remote()) {
525 options = audio_track()->GetSource()->options();
526 }
527#endif
528
529 // |track_->enabled()| hops to the signaling thread, so call it before we hop
530 // to the worker thread or else it will deadlock.
531 bool track_enabled = track_->enabled();
532 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
533 return voice_media_channel()->SetAudioSend(ssrc_, track_enabled, &options,
534 sink_adapter_.get());
535 });
536 if (!success) {
537 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
538 }
539}
540
541void AudioRtpSender::ClearSend() {
542 RTC_DCHECK(ssrc_ != 0);
543 RTC_DCHECK(!stopped_);
544 if (!media_channel_) {
545 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
546 return;
547 }
548 cricket::AudioOptions options;
549 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
550 return voice_media_channel()->SetAudioSend(ssrc_, false, &options, nullptr);
551 });
552 if (!success) {
553 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
554 }
555}
556
557rtc::scoped_refptr<VideoRtpSender> VideoRtpSender::Create(
558 rtc::Thread* worker_thread,
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200559 const std::string& id,
560 SetStreamsObserver* set_streams_observer) {
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800561 return rtc::scoped_refptr<VideoRtpSender>(
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200562 new rtc::RefCountedObject<VideoRtpSender>(worker_thread, id,
563 set_streams_observer));
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800564}
565
566VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Guido Urdaneta1ff16c82019-05-20 19:31:53 +0200567 const std::string& id,
568 SetStreamsObserver* set_streams_observer)
569 : RtpSenderBase(worker_thread, id, set_streams_observer) {}
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800570
571VideoRtpSender::~VideoRtpSender() {
572 Stop();
573}
574
575void VideoRtpSender::OnChanged() {
576 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
577 RTC_DCHECK(!stopped_);
578 if (cached_track_content_hint_ != video_track()->content_hint()) {
579 cached_track_content_hint_ = video_track()->content_hint();
580 if (can_send_track()) {
581 SetSend();
582 }
583 }
584}
585
586void VideoRtpSender::AttachTrack() {
587 RTC_DCHECK(track_);
588 cached_track_content_hint_ = video_track()->content_hint();
589}
590
591rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
592 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
593 return nullptr;
594}
595
596void VideoRtpSender::SetSend() {
597 RTC_DCHECK(!stopped_);
598 RTC_DCHECK(can_send_track());
599 if (!media_channel_) {
600 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
601 return;
602 }
603 cricket::VideoOptions options;
604 VideoTrackSourceInterface* source = video_track()->GetSource();
605 if (source) {
606 options.is_screencast = source->is_screencast();
607 options.video_noise_reduction = source->needs_denoising();
608 }
Florent Castellib05ca4b2020-03-05 13:39:55 +0100609 options.content_hint = cached_track_content_hint_;
Amit Hilbuchea7ef2a2019-02-19 15:20:21 -0800610 switch (cached_track_content_hint_) {
611 case VideoTrackInterface::ContentHint::kNone:
612 break;
613 case VideoTrackInterface::ContentHint::kFluid:
614 options.is_screencast = false;
615 break;
616 case VideoTrackInterface::ContentHint::kDetailed:
617 case VideoTrackInterface::ContentHint::kText:
618 options.is_screencast = true;
619 break;
620 }
621 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
622 return video_media_channel()->SetVideoSend(ssrc_, &options, video_track());
623 });
624 RTC_DCHECK(success);
625}
626
627void VideoRtpSender::ClearSend() {
628 RTC_DCHECK(ssrc_ != 0);
629 RTC_DCHECK(!stopped_);
630 if (!media_channel_) {
631 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
632 return;
633 }
634 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
635 // This the normal case when the underlying media channel has already been
636 // deleted.
637 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
638 return video_media_channel()->SetVideoSend(ssrc_, nullptr, nullptr);
639 });
640}
641
deadbeef70ab1a12015-09-28 16:53:55 -0700642} // namespace webrtc