blob: 20130a187c01d2af0187e0d7826343a05a340823 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "pc/rtpsender.h"
deadbeef6979b022015-09-24 16:47:53 -070012
Benjamin Wrightd81ac952018-08-29 17:02:10 -070013#include <utility>
Steve Anton36b29d12017-10-30 09:57:42 -070014#include <vector>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "api/mediastreaminterface.h"
17#include "pc/localaudiosource.h"
Steve Anton2d8609c2018-01-23 16:38:46 -080018#include "pc/statscollector.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/checks.h"
20#include "rtc_base/helpers.h"
21#include "rtc_base/trace_event.h"
deadbeef70ab1a12015-09-28 16:53:55 -070022
23namespace webrtc {
24
Harald Alvestrandc72af932018-01-11 17:18:19 +010025namespace {
26
27// This function is only expected to be called on the signalling thread.
28int GenerateUniqueId() {
29 static int g_unique_id = 0;
30
31 return ++g_unique_id;
32}
33
Florent Castelli892acf02018-10-01 22:47:20 +020034// Attaches the frame encryptor to the media channel through an invoke on a
35// worker thread. This set must be done on the corresponding worker thread that
36// the media channel was created on.
37void AttachFrameEncryptorToMediaChannel(
38 rtc::Thread* worker_thread,
39 webrtc::FrameEncryptorInterface* frame_encryptor,
40 cricket::MediaChannel* media_channel) {
41 if (media_channel) {
42 return worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
43 media_channel->SetFrameEncryptor(frame_encryptor);
44 });
45 }
46}
47
Seth Hampson2d2c8882018-05-16 16:02:32 -070048// Returns an true if any RtpEncodingParameters member that isn't implemented
49// contains a value.
50bool UnimplementedRtpEncodingParameterHasValue(
51 const RtpEncodingParameters& encoding_params) {
52 if (encoding_params.codec_payload_type.has_value() ||
53 encoding_params.fec.has_value() || encoding_params.rtx.has_value() ||
54 encoding_params.dtx.has_value() || encoding_params.ptime.has_value() ||
Seth Hampson2d2c8882018-05-16 16:02:32 -070055 !encoding_params.rid.empty() ||
56 encoding_params.scale_resolution_down_by.has_value() ||
57 encoding_params.scale_framerate_down_by.has_value() ||
58 !encoding_params.dependency_rids.empty()) {
59 return true;
60 }
61 return false;
62}
63
64// Returns true if a "per-sender" encoding parameter contains a value that isn't
65// its default. Currently max_bitrate_bps and bitrate_priority both are
66// implemented "per-sender," meaning that these encoding parameters
67// are used for the RtpSender as a whole, not for a specific encoding layer.
68// This is done by setting these encoding parameters at index 0 of
69// RtpParameters.encodings. This function can be used to check if these
70// parameters are set at any index other than 0 of RtpParameters.encodings,
71// because they are currently unimplemented to be used for a specific encoding
72// layer.
73bool PerSenderRtpEncodingParameterHasValue(
74 const RtpEncodingParameters& encoding_params) {
Åsa Persson55659812018-06-18 17:51:32 +020075 if (encoding_params.bitrate_priority != kDefaultBitratePriority) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070076 return true;
77 }
78 return false;
79}
80
Florent Castelli892acf02018-10-01 22:47:20 +020081} // namespace
82
Seth Hampson2d2c8882018-05-16 16:02:32 -070083// Returns true if any RtpParameters member that isn't implemented contains a
84// value.
85bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020086 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070087 return true;
88 }
89 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
90 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
91 return true;
92 }
93 // Encoding parameters that are per-sender should only contain value at
94 // index 0.
95 if (i != 0 &&
96 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
97 return true;
98 }
99 }
100 return false;
101}
102
deadbeef70ab1a12015-09-28 16:53:55 -0700103LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
104
105LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
106 rtc::CritScope lock(&lock_);
107 if (sink_)
108 sink_->OnClose();
109}
110
111void LocalAudioSinkAdapter::OnData(const void* audio_data,
112 int bits_per_sample,
113 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800114 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700115 size_t number_of_frames) {
116 rtc::CritScope lock(&lock_);
117 if (sink_) {
118 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
119 number_of_frames);
120 }
121}
122
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800123void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700124 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800125 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700126 sink_ = sink;
127}
128
Steve Anton47136dd2018-01-12 10:49:35 -0800129AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700130 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800131 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800132 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700133 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800134 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800135 dtmf_sender_proxy_(DtmfSenderProxy::Create(
136 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700137 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700138 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800139 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200140 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800141}
deadbeeffac06552015-11-25 11:26:01 -0800142
deadbeef70ab1a12015-09-28 16:53:55 -0700143AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800144 // For DtmfSender.
145 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700146 Stop();
147}
148
deadbeef20cb0c12017-02-01 20:27:00 -0800149bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800150 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100151 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800152 return false;
153 }
154 // Check that this RTP sender is active (description has been applied that
155 // matches an SSRC to its ID).
156 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100157 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800158 return false;
159 }
Steve Anton47136dd2018-01-12 10:49:35 -0800160 return worker_thread_->Invoke<bool>(
161 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800162}
163
164bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800165 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100166 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800167 return false;
168 }
169 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100170 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800171 return false;
172 }
Steve Anton47136dd2018-01-12 10:49:35 -0800173 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
174 return media_channel_->InsertDtmf(ssrc_, code, duration);
175 });
176 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100177 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800178 }
Steve Anton47136dd2018-01-12 10:49:35 -0800179 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800180}
181
182sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
183 return &SignalDestroyed;
184}
185
deadbeef70ab1a12015-09-28 16:53:55 -0700186void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200187 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800188 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700189 if (cached_track_enabled_ != track_->enabled()) {
190 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800191 if (can_send_track()) {
192 SetAudioSend();
193 }
deadbeef70ab1a12015-09-28 16:53:55 -0700194 }
195}
196
197bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200198 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800199 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100200 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800201 return false;
202 }
203 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100204 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
205 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700206 return false;
207 }
208 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
209
210 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800211 if (track_) {
212 track_->RemoveSink(sink_adapter_.get());
213 track_->UnregisterObserver(this);
214 }
215
216 if (can_send_track() && stats_) {
217 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
218 }
deadbeef70ab1a12015-09-28 16:53:55 -0700219
220 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800221 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700222 // Keep a reference to the old track to keep it alive until we call
223 // SetAudioSend.
224 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700225 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800226 if (track_) {
227 cached_track_enabled_ = track_->enabled();
228 track_->RegisterObserver(this);
229 track_->AddSink(sink_adapter_.get());
230 }
231
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700232 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800233 if (can_send_track()) {
234 SetAudioSend();
235 if (stats_) {
236 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
237 }
238 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700239 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800240 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700241 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700242 return true;
243}
244
Florent Castellicebf50f2018-05-03 15:31:53 +0200245RtpParameters AudioRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200246 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700247 return RtpParameters();
248 }
Florent Castelli892acf02018-10-01 22:47:20 +0200249 if (!media_channel_) {
250 RtpParameters result = init_parameters_;
251 last_transaction_id_ = rtc::CreateRandomUuid();
252 result.transaction_id = last_transaction_id_.value();
253 return result;
254 }
Steve Anton47136dd2018-01-12 10:49:35 -0800255 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200256 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
257 last_transaction_id_ = rtc::CreateRandomUuid();
258 result.transaction_id = last_transaction_id_.value();
259 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800260 });
deadbeefa601f5c2016-06-06 14:27:39 -0700261}
262
Zach Steinba37b4b2018-01-23 15:02:36 -0800263RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700264 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200265 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800266 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700267 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200268 if (!last_transaction_id_) {
269 LOG_AND_RETURN_ERROR(
270 RTCErrorType::INVALID_STATE,
271 "Failed to set parameters since getParameters() has never been called"
272 " on this sender");
273 }
274 if (last_transaction_id_ != parameters.transaction_id) {
275 LOG_AND_RETURN_ERROR(
276 RTCErrorType::INVALID_MODIFICATION,
277 "Failed to set parameters since the transaction_id doesn't match"
278 " the last value returned from getParameters()");
279 }
280
Seth Hampson2d2c8882018-05-16 16:02:32 -0700281 if (UnimplementedRtpParameterHasValue(parameters)) {
282 LOG_AND_RETURN_ERROR(
283 RTCErrorType::UNSUPPORTED_PARAMETER,
284 "Attempted to set an unimplemented parameter of RtpParameters.");
285 }
Florent Castelli892acf02018-10-01 22:47:20 +0200286 if (!media_channel_) {
287 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
288 if (result.ok()) {
289 init_parameters_ = parameters;
290 }
291 return result;
292 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800293 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200294 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
295 last_transaction_id_.reset();
296 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800297 });
deadbeefa601f5c2016-06-06 14:27:39 -0700298}
299
deadbeef20cb0c12017-02-01 20:27:00 -0800300rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
301 return dtmf_sender_proxy_;
302}
303
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700304void AudioRtpSender::SetFrameEncryptor(
305 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
306 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700307 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
308 media_channel_);
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700309}
310
311rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
312 const {
313 return frame_encryptor_;
314}
315
deadbeeffac06552015-11-25 11:26:01 -0800316void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200317 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800318 if (stopped_ || ssrc == ssrc_) {
319 return;
320 }
321 // If we are already sending with a particular SSRC, stop sending.
322 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700323 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800324 if (stats_) {
325 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
326 }
327 }
328 ssrc_ = ssrc;
329 if (can_send_track()) {
330 SetAudioSend();
331 if (stats_) {
332 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
333 }
334 }
Florent Castelli892acf02018-10-01 22:47:20 +0200335 if (!init_parameters_.encodings.empty()) {
336 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
337 RTC_DCHECK(media_channel_);
338 // Get the current parameters, which are constructed from the SDP.
339 // The number of layers in the SDP is currently authoritative to support
340 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
341 // lines as described in RFC 5576.
342 // All fields should be default constructed and the SSRC field set, which
343 // we need to copy.
344 RtpParameters current_parameters =
345 media_channel_->GetRtpSendParameters(ssrc_);
346 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
347 init_parameters_.encodings[i].ssrc =
348 current_parameters.encodings[i].ssrc;
349 current_parameters.encodings[i] = init_parameters_.encodings[i];
350 }
351 current_parameters.degradation_preference =
352 init_parameters_.degradation_preference;
353 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
354 init_parameters_.encodings.clear();
355 });
356 }
deadbeeffac06552015-11-25 11:26:01 -0800357}
358
deadbeef70ab1a12015-09-28 16:53:55 -0700359void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200360 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700361 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800362 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700363 return;
364 }
deadbeeffac06552015-11-25 11:26:01 -0800365 if (track_) {
366 track_->RemoveSink(sink_adapter_.get());
367 track_->UnregisterObserver(this);
368 }
369 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700370 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800371 if (stats_) {
372 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
373 }
374 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100375 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800376 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700377}
378
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700379void AudioRtpSender::SetVoiceMediaChannel(
380 cricket::VoiceMediaChannel* voice_media_channel) {
381 media_channel_ = voice_media_channel;
382 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
383 media_channel_);
384}
385
deadbeeffac06552015-11-25 11:26:01 -0800386void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700387 RTC_DCHECK(!stopped_);
388 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800389 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100390 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700391 return;
392 }
deadbeef70ab1a12015-09-28 16:53:55 -0700393 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800394#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100395 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
396 // PeerConnection. This is a bit of a strange way to apply local audio
397 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800398 if (track_->enabled() && track_->GetSource() &&
399 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700400 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800401 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700402 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
403 }
Tommi3c169782016-01-21 16:12:17 +0100404#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700405
Steve Anton47136dd2018-01-12 10:49:35 -0800406 // |track_->enabled()| hops to the signaling thread, so call it before we hop
407 // to the worker thread or else it will deadlock.
408 bool track_enabled = track_->enabled();
409 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
410 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
411 sink_adapter_.get());
412 });
413 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100414 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700415 }
416}
417
418void AudioRtpSender::ClearAudioSend() {
419 RTC_DCHECK(ssrc_ != 0);
420 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800421 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100422 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700423 return;
424 }
425 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800426 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
427 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
428 });
429 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100430 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700431 }
deadbeef70ab1a12015-09-28 16:53:55 -0700432}
433
Steve Anton47136dd2018-01-12 10:49:35 -0800434VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700435 const std::string& id)
436 : worker_thread_(worker_thread), id_(id) {
Steve Anton47136dd2018-01-12 10:49:35 -0800437 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200438 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800439}
440
deadbeef70ab1a12015-09-28 16:53:55 -0700441VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700442 Stop();
443}
444
445void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200446 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800447 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200448 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800449 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800450 if (can_send_track()) {
451 SetVideoSend();
452 }
deadbeef70ab1a12015-09-28 16:53:55 -0700453 }
454}
455
456bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200457 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800458 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100459 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800460 return false;
461 }
462 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100463 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
464 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700465 return false;
466 }
467 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
468
469 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800470 if (track_) {
471 track_->UnregisterObserver(this);
472 }
deadbeef70ab1a12015-09-28 16:53:55 -0700473
474 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800475 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700476 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700477 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700478 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700479 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800480 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800481 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800482 track_->RegisterObserver(this);
483 }
484
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700485 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800486 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800487 SetVideoSend();
488 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700489 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800490 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700491 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700492 return true;
493}
494
Florent Castellicebf50f2018-05-03 15:31:53 +0200495RtpParameters VideoRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200496 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700497 return RtpParameters();
498 }
Florent Castelli892acf02018-10-01 22:47:20 +0200499 if (!media_channel_) {
500 RtpParameters result = init_parameters_;
501 last_transaction_id_ = rtc::CreateRandomUuid();
502 result.transaction_id = last_transaction_id_.value();
503 return result;
504 }
Steve Anton47136dd2018-01-12 10:49:35 -0800505 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200506 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
507 last_transaction_id_ = rtc::CreateRandomUuid();
508 result.transaction_id = last_transaction_id_.value();
509 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800510 });
deadbeefa601f5c2016-06-06 14:27:39 -0700511}
512
Zach Steinba37b4b2018-01-23 15:02:36 -0800513RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700514 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200515 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800516 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700517 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200518 if (!last_transaction_id_) {
519 LOG_AND_RETURN_ERROR(
520 RTCErrorType::INVALID_STATE,
521 "Failed to set parameters since getParameters() has never been called"
522 " on this sender");
523 }
524 if (last_transaction_id_ != parameters.transaction_id) {
525 LOG_AND_RETURN_ERROR(
526 RTCErrorType::INVALID_MODIFICATION,
527 "Failed to set parameters since the transaction_id doesn't match"
528 " the last value returned from getParameters()");
529 }
530
Seth Hampson2d2c8882018-05-16 16:02:32 -0700531 if (UnimplementedRtpParameterHasValue(parameters)) {
532 LOG_AND_RETURN_ERROR(
533 RTCErrorType::UNSUPPORTED_PARAMETER,
534 "Attempted to set an unimplemented parameter of RtpParameters.");
535 }
Florent Castelli892acf02018-10-01 22:47:20 +0200536 if (!media_channel_) {
537 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
538 if (result.ok()) {
539 init_parameters_ = parameters;
540 }
541 return result;
542 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800543 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200544 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
545 last_transaction_id_.reset();
546 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800547 });
deadbeefa601f5c2016-06-06 14:27:39 -0700548}
549
deadbeef20cb0c12017-02-01 20:27:00 -0800550rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100551 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800552 return nullptr;
553}
554
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700555void VideoRtpSender::SetFrameEncryptor(
556 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
557 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700558 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
559 media_channel_);
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700560}
561
562rtc::scoped_refptr<FrameEncryptorInterface> VideoRtpSender::GetFrameEncryptor()
563 const {
564 return frame_encryptor_;
565}
566
deadbeeffac06552015-11-25 11:26:01 -0800567void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200568 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800569 if (stopped_ || ssrc == ssrc_) {
570 return;
571 }
572 // If we are already sending with a particular SSRC, stop sending.
573 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700574 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800575 }
576 ssrc_ = ssrc;
577 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800578 SetVideoSend();
579 }
Florent Castelli892acf02018-10-01 22:47:20 +0200580 if (!init_parameters_.encodings.empty()) {
581 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
582 RTC_DCHECK(media_channel_);
583 // Get the current parameters, which are constructed from the SDP.
584 // The number of layers in the SDP is currently authoritative to support
585 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
586 // lines as described in RFC 5576.
587 // All fields should be default constructed and the SSRC field set, which
588 // we need to copy.
589 RtpParameters current_parameters =
590 media_channel_->GetRtpSendParameters(ssrc_);
591 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
592 init_parameters_.encodings[i].ssrc =
593 current_parameters.encodings[i].ssrc;
594 current_parameters.encodings[i] = init_parameters_.encodings[i];
595 }
596 current_parameters.degradation_preference =
597 init_parameters_.degradation_preference;
598 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
599 init_parameters_.encodings.clear();
600 });
601 }
deadbeeffac06552015-11-25 11:26:01 -0800602}
603
deadbeef70ab1a12015-09-28 16:53:55 -0700604void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200605 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700606 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800607 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700608 return;
609 }
deadbeeffac06552015-11-25 11:26:01 -0800610 if (track_) {
611 track_->UnregisterObserver(this);
612 }
613 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700614 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800615 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100616 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800617 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700618}
619
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700620void VideoRtpSender::SetVideoMediaChannel(
621 cricket::VideoMediaChannel* video_media_channel) {
622 media_channel_ = video_media_channel;
623 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
624 media_channel_);
625}
626
deadbeeffac06552015-11-25 11:26:01 -0800627void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700628 RTC_DCHECK(!stopped_);
629 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800630 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100631 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700632 return;
633 }
perkj0d3eef22016-03-09 02:39:17 +0100634 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100635 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100636 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100637 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200638 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700639 }
pbos5214a0a2016-12-16 15:39:11 -0800640 switch (cached_track_content_hint_) {
641 case VideoTrackInterface::ContentHint::kNone:
642 break;
643 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100644 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800645 break;
646 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200647 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100648 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800649 break;
650 }
Steve Anton47136dd2018-01-12 10:49:35 -0800651 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200652 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800653 });
654 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700655}
656
657void VideoRtpSender::ClearVideoSend() {
658 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700659 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800660 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100661 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700662 return;
663 }
664 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
665 // This the normal case when the underlying media channel has already been
666 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800667 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200668 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800669 });
deadbeef70ab1a12015-09-28 16:53:55 -0700670}
671
672} // namespace webrtc