blob: dadd13d91b2169e02934ba5e45c1e80f5d9907d1 [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
Seth Hampson2d2c8882018-05-16 16:02:32 -070034// Returns an true if any RtpEncodingParameters member that isn't implemented
35// contains a value.
36bool UnimplementedRtpEncodingParameterHasValue(
37 const RtpEncodingParameters& encoding_params) {
38 if (encoding_params.codec_payload_type.has_value() ||
39 encoding_params.fec.has_value() || encoding_params.rtx.has_value() ||
40 encoding_params.dtx.has_value() || encoding_params.ptime.has_value() ||
Seth Hampson2d2c8882018-05-16 16:02:32 -070041 !encoding_params.rid.empty() ||
42 encoding_params.scale_resolution_down_by.has_value() ||
43 encoding_params.scale_framerate_down_by.has_value() ||
44 !encoding_params.dependency_rids.empty()) {
45 return true;
46 }
47 return false;
48}
49
50// Returns true if a "per-sender" encoding parameter contains a value that isn't
51// its default. Currently max_bitrate_bps and bitrate_priority both are
52// implemented "per-sender," meaning that these encoding parameters
53// are used for the RtpSender as a whole, not for a specific encoding layer.
54// This is done by setting these encoding parameters at index 0 of
55// RtpParameters.encodings. This function can be used to check if these
56// parameters are set at any index other than 0 of RtpParameters.encodings,
57// because they are currently unimplemented to be used for a specific encoding
58// layer.
59bool PerSenderRtpEncodingParameterHasValue(
60 const RtpEncodingParameters& encoding_params) {
Tim Haloun648d28a2018-10-18 16:52:22 -070061 if (encoding_params.bitrate_priority != kDefaultBitratePriority ||
62 encoding_params.network_priority != kDefaultBitratePriority) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070063 return true;
64 }
65 return false;
66}
67
Benjamin Wright84583f62018-10-04 14:22:34 -070068// Attempt to attach the frame decryptor to the current media channel on the
69// correct worker thread only if both the media channel exists and a ssrc has
70// been allocated to the stream.
71void MaybeAttachFrameEncryptorToMediaChannel(
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070072 const uint32_t ssrc,
Benjamin Wright84583f62018-10-04 14:22:34 -070073 rtc::Thread* worker_thread,
74 rtc::scoped_refptr<webrtc::FrameEncryptorInterface> frame_encryptor,
75 cricket::MediaChannel* media_channel) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070076 if (media_channel && frame_encryptor && ssrc) {
77 worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
78 media_channel->SetFrameEncryptor(ssrc, frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -070079 });
80 }
81}
82
Florent Castelli892acf02018-10-01 22:47:20 +020083} // namespace
84
Seth Hampson2d2c8882018-05-16 16:02:32 -070085// Returns true if any RtpParameters member that isn't implemented contains a
86// value.
87bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020088 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070089 return true;
90 }
91 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
92 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
93 return true;
94 }
95 // Encoding parameters that are per-sender should only contain value at
96 // index 0.
97 if (i != 0 &&
98 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
99 return true;
100 }
101 }
102 return false;
103}
104
deadbeef70ab1a12015-09-28 16:53:55 -0700105LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
106
107LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
108 rtc::CritScope lock(&lock_);
109 if (sink_)
110 sink_->OnClose();
111}
112
113void LocalAudioSinkAdapter::OnData(const void* audio_data,
114 int bits_per_sample,
115 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800116 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700117 size_t number_of_frames) {
118 rtc::CritScope lock(&lock_);
119 if (sink_) {
120 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
121 number_of_frames);
122 }
123}
124
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800125void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700126 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800127 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700128 sink_ = sink;
129}
130
Steve Anton47136dd2018-01-12 10:49:35 -0800131AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700132 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800133 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800134 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700135 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800136 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800137 dtmf_sender_proxy_(DtmfSenderProxy::Create(
138 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700139 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700140 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800141 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200142 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800143}
deadbeeffac06552015-11-25 11:26:01 -0800144
deadbeef70ab1a12015-09-28 16:53:55 -0700145AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800146 // For DtmfSender.
147 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700148 Stop();
149}
150
deadbeef20cb0c12017-02-01 20:27:00 -0800151bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800152 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100153 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800154 return false;
155 }
156 // Check that this RTP sender is active (description has been applied that
157 // matches an SSRC to its ID).
158 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100159 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800160 return false;
161 }
Steve Anton47136dd2018-01-12 10:49:35 -0800162 return worker_thread_->Invoke<bool>(
163 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800164}
165
166bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800167 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100168 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800169 return false;
170 }
171 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100172 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800173 return false;
174 }
Steve Anton47136dd2018-01-12 10:49:35 -0800175 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
176 return media_channel_->InsertDtmf(ssrc_, code, duration);
177 });
178 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100179 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800180 }
Steve Anton47136dd2018-01-12 10:49:35 -0800181 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800182}
183
184sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
185 return &SignalDestroyed;
186}
187
deadbeef70ab1a12015-09-28 16:53:55 -0700188void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200189 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800190 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700191 if (cached_track_enabled_ != track_->enabled()) {
192 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800193 if (can_send_track()) {
194 SetAudioSend();
195 }
deadbeef70ab1a12015-09-28 16:53:55 -0700196 }
197}
198
199bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200200 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800201 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100202 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800203 return false;
204 }
205 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100206 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
207 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700208 return false;
209 }
210 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
211
212 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800213 if (track_) {
214 track_->RemoveSink(sink_adapter_.get());
215 track_->UnregisterObserver(this);
216 }
217
218 if (can_send_track() && stats_) {
219 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
220 }
deadbeef70ab1a12015-09-28 16:53:55 -0700221
222 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800223 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700224 // Keep a reference to the old track to keep it alive until we call
225 // SetAudioSend.
226 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700227 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800228 if (track_) {
229 cached_track_enabled_ = track_->enabled();
230 track_->RegisterObserver(this);
231 track_->AddSink(sink_adapter_.get());
232 }
233
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700234 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800235 if (can_send_track()) {
236 SetAudioSend();
237 if (stats_) {
238 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
239 }
240 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700241 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800242 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700243 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700244 return true;
245}
246
Florent Castellicebf50f2018-05-03 15:31:53 +0200247RtpParameters AudioRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200248 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700249 return RtpParameters();
250 }
Florent Castelli892acf02018-10-01 22:47:20 +0200251 if (!media_channel_) {
252 RtpParameters result = init_parameters_;
253 last_transaction_id_ = rtc::CreateRandomUuid();
254 result.transaction_id = last_transaction_id_.value();
255 return result;
256 }
Steve Anton47136dd2018-01-12 10:49:35 -0800257 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200258 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
259 last_transaction_id_ = rtc::CreateRandomUuid();
260 result.transaction_id = last_transaction_id_.value();
261 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800262 });
deadbeefa601f5c2016-06-06 14:27:39 -0700263}
264
Zach Steinba37b4b2018-01-23 15:02:36 -0800265RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700266 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200267 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800268 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700269 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200270 if (!last_transaction_id_) {
271 LOG_AND_RETURN_ERROR(
272 RTCErrorType::INVALID_STATE,
273 "Failed to set parameters since getParameters() has never been called"
274 " on this sender");
275 }
276 if (last_transaction_id_ != parameters.transaction_id) {
277 LOG_AND_RETURN_ERROR(
278 RTCErrorType::INVALID_MODIFICATION,
279 "Failed to set parameters since the transaction_id doesn't match"
280 " the last value returned from getParameters()");
281 }
282
Seth Hampson2d2c8882018-05-16 16:02:32 -0700283 if (UnimplementedRtpParameterHasValue(parameters)) {
284 LOG_AND_RETURN_ERROR(
285 RTCErrorType::UNSUPPORTED_PARAMETER,
286 "Attempted to set an unimplemented parameter of RtpParameters.");
287 }
Florent Castelli892acf02018-10-01 22:47:20 +0200288 if (!media_channel_) {
289 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
290 if (result.ok()) {
291 init_parameters_ = parameters;
292 }
293 return result;
294 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800295 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200296 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
297 last_transaction_id_.reset();
298 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800299 });
deadbeefa601f5c2016-06-06 14:27:39 -0700300}
301
deadbeef20cb0c12017-02-01 20:27:00 -0800302rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
303 return dtmf_sender_proxy_;
304}
305
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700306void AudioRtpSender::SetFrameEncryptor(
307 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
308 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700309 // Special Case: Set the frame encryptor to any value on any existing channel.
310 if (media_channel_ && ssrc_) {
311 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
312 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
313 });
314 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700315}
316
317rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
318 const {
319 return frame_encryptor_;
320}
321
deadbeeffac06552015-11-25 11:26:01 -0800322void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200323 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800324 if (stopped_ || ssrc == ssrc_) {
325 return;
326 }
327 // If we are already sending with a particular SSRC, stop sending.
328 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700329 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800330 if (stats_) {
331 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
332 }
333 }
334 ssrc_ = ssrc;
335 if (can_send_track()) {
336 SetAudioSend();
337 if (stats_) {
338 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
339 }
340 }
Florent Castelli892acf02018-10-01 22:47:20 +0200341 if (!init_parameters_.encodings.empty()) {
342 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
343 RTC_DCHECK(media_channel_);
344 // Get the current parameters, which are constructed from the SDP.
345 // The number of layers in the SDP is currently authoritative to support
346 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
347 // lines as described in RFC 5576.
348 // All fields should be default constructed and the SSRC field set, which
349 // we need to copy.
350 RtpParameters current_parameters =
351 media_channel_->GetRtpSendParameters(ssrc_);
352 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
353 init_parameters_.encodings[i].ssrc =
354 current_parameters.encodings[i].ssrc;
355 current_parameters.encodings[i] = init_parameters_.encodings[i];
356 }
357 current_parameters.degradation_preference =
358 init_parameters_.degradation_preference;
359 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
360 init_parameters_.encodings.clear();
361 });
362 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700363 // Each time there is an ssrc update.
364 MaybeAttachFrameEncryptorToMediaChannel(ssrc_, worker_thread_,
365 frame_encryptor_, media_channel_);
deadbeeffac06552015-11-25 11:26:01 -0800366}
367
deadbeef70ab1a12015-09-28 16:53:55 -0700368void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200369 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700370 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800371 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700372 return;
373 }
deadbeeffac06552015-11-25 11:26:01 -0800374 if (track_) {
375 track_->RemoveSink(sink_adapter_.get());
376 track_->UnregisterObserver(this);
377 }
378 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700379 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800380 if (stats_) {
381 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
382 }
383 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100384 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800385 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700386}
387
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700388void AudioRtpSender::SetVoiceMediaChannel(
389 cricket::VoiceMediaChannel* voice_media_channel) {
390 media_channel_ = voice_media_channel;
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700391}
392
deadbeeffac06552015-11-25 11:26:01 -0800393void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700394 RTC_DCHECK(!stopped_);
395 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800396 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100397 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700398 return;
399 }
deadbeef70ab1a12015-09-28 16:53:55 -0700400 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800401#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100402 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
403 // PeerConnection. This is a bit of a strange way to apply local audio
404 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800405 if (track_->enabled() && track_->GetSource() &&
406 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700407 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800408 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700409 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
410 }
Tommi3c169782016-01-21 16:12:17 +0100411#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700412
Steve Anton47136dd2018-01-12 10:49:35 -0800413 // |track_->enabled()| hops to the signaling thread, so call it before we hop
414 // to the worker thread or else it will deadlock.
415 bool track_enabled = track_->enabled();
416 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
417 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
418 sink_adapter_.get());
419 });
420 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100421 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700422 }
423}
424
425void AudioRtpSender::ClearAudioSend() {
426 RTC_DCHECK(ssrc_ != 0);
427 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800428 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100429 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700430 return;
431 }
432 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800433 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
434 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
435 });
436 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100437 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700438 }
deadbeef70ab1a12015-09-28 16:53:55 -0700439}
440
Steve Anton47136dd2018-01-12 10:49:35 -0800441VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700442 const std::string& id)
443 : worker_thread_(worker_thread), id_(id) {
Steve Anton47136dd2018-01-12 10:49:35 -0800444 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200445 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800446}
447
deadbeef70ab1a12015-09-28 16:53:55 -0700448VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700449 Stop();
450}
451
452void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200453 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800454 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200455 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800456 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800457 if (can_send_track()) {
458 SetVideoSend();
459 }
deadbeef70ab1a12015-09-28 16:53:55 -0700460 }
461}
462
463bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200464 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800465 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100466 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800467 return false;
468 }
469 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100470 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
471 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700472 return false;
473 }
474 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
475
476 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800477 if (track_) {
478 track_->UnregisterObserver(this);
479 }
deadbeef70ab1a12015-09-28 16:53:55 -0700480
481 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800482 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700483 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700484 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700485 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700486 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800487 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800488 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800489 track_->RegisterObserver(this);
490 }
491
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700492 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800493 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800494 SetVideoSend();
495 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700496 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800497 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700498 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700499 return true;
500}
501
Florent Castellicebf50f2018-05-03 15:31:53 +0200502RtpParameters VideoRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200503 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700504 return RtpParameters();
505 }
Florent Castelli892acf02018-10-01 22:47:20 +0200506 if (!media_channel_) {
507 RtpParameters result = init_parameters_;
508 last_transaction_id_ = rtc::CreateRandomUuid();
509 result.transaction_id = last_transaction_id_.value();
510 return result;
511 }
Steve Anton47136dd2018-01-12 10:49:35 -0800512 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200513 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
514 last_transaction_id_ = rtc::CreateRandomUuid();
515 result.transaction_id = last_transaction_id_.value();
516 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800517 });
deadbeefa601f5c2016-06-06 14:27:39 -0700518}
519
Zach Steinba37b4b2018-01-23 15:02:36 -0800520RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700521 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200522 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800523 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700524 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200525 if (!last_transaction_id_) {
526 LOG_AND_RETURN_ERROR(
527 RTCErrorType::INVALID_STATE,
528 "Failed to set parameters since getParameters() has never been called"
529 " on this sender");
530 }
531 if (last_transaction_id_ != parameters.transaction_id) {
532 LOG_AND_RETURN_ERROR(
533 RTCErrorType::INVALID_MODIFICATION,
534 "Failed to set parameters since the transaction_id doesn't match"
535 " the last value returned from getParameters()");
536 }
537
Seth Hampson2d2c8882018-05-16 16:02:32 -0700538 if (UnimplementedRtpParameterHasValue(parameters)) {
539 LOG_AND_RETURN_ERROR(
540 RTCErrorType::UNSUPPORTED_PARAMETER,
541 "Attempted to set an unimplemented parameter of RtpParameters.");
542 }
Florent Castelli892acf02018-10-01 22:47:20 +0200543 if (!media_channel_) {
544 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
545 if (result.ok()) {
546 init_parameters_ = parameters;
547 }
548 return result;
549 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800550 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200551 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
552 last_transaction_id_.reset();
553 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800554 });
deadbeefa601f5c2016-06-06 14:27:39 -0700555}
556
deadbeef20cb0c12017-02-01 20:27:00 -0800557rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100558 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800559 return nullptr;
560}
561
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700562void VideoRtpSender::SetFrameEncryptor(
563 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
564 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700565 // Special Case: Set the frame encryptor to any value on any existing channel.
566 if (media_channel_ && ssrc_) {
567 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
568 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
569 });
570 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700571}
572
573rtc::scoped_refptr<FrameEncryptorInterface> VideoRtpSender::GetFrameEncryptor()
574 const {
575 return frame_encryptor_;
576}
577
deadbeeffac06552015-11-25 11:26:01 -0800578void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200579 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800580 if (stopped_ || ssrc == ssrc_) {
581 return;
582 }
583 // If we are already sending with a particular SSRC, stop sending.
584 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700585 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800586 }
587 ssrc_ = ssrc;
588 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800589 SetVideoSend();
590 }
Florent Castelli892acf02018-10-01 22:47:20 +0200591 if (!init_parameters_.encodings.empty()) {
592 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
593 RTC_DCHECK(media_channel_);
594 // Get the current parameters, which are constructed from the SDP.
595 // The number of layers in the SDP is currently authoritative to support
596 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
597 // lines as described in RFC 5576.
598 // All fields should be default constructed and the SSRC field set, which
599 // we need to copy.
600 RtpParameters current_parameters =
601 media_channel_->GetRtpSendParameters(ssrc_);
602 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
603 init_parameters_.encodings[i].ssrc =
604 current_parameters.encodings[i].ssrc;
605 current_parameters.encodings[i] = init_parameters_.encodings[i];
606 }
607 current_parameters.degradation_preference =
608 init_parameters_.degradation_preference;
609 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
610 init_parameters_.encodings.clear();
611 });
612 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700613 MaybeAttachFrameEncryptorToMediaChannel(ssrc_, worker_thread_,
614 frame_encryptor_, media_channel_);
deadbeeffac06552015-11-25 11:26:01 -0800615}
616
deadbeef70ab1a12015-09-28 16:53:55 -0700617void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200618 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700619 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800620 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700621 return;
622 }
deadbeeffac06552015-11-25 11:26:01 -0800623 if (track_) {
624 track_->UnregisterObserver(this);
625 }
626 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700627 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800628 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100629 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800630 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700631}
632
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700633void VideoRtpSender::SetVideoMediaChannel(
634 cricket::VideoMediaChannel* video_media_channel) {
635 media_channel_ = video_media_channel;
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700636}
637
deadbeeffac06552015-11-25 11:26:01 -0800638void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700639 RTC_DCHECK(!stopped_);
640 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800641 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100642 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700643 return;
644 }
perkj0d3eef22016-03-09 02:39:17 +0100645 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100646 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100647 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100648 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200649 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700650 }
pbos5214a0a2016-12-16 15:39:11 -0800651 switch (cached_track_content_hint_) {
652 case VideoTrackInterface::ContentHint::kNone:
653 break;
654 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100655 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800656 break;
657 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200658 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100659 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800660 break;
661 }
Steve Anton47136dd2018-01-12 10:49:35 -0800662 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200663 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800664 });
665 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700666}
667
668void VideoRtpSender::ClearVideoSend() {
669 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700670 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800671 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100672 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700673 return;
674 }
675 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
676 // This the normal case when the underlying media channel has already been
677 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800678 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200679 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800680 });
deadbeef70ab1a12015-09-28 16:53:55 -0700681}
682
683} // namespace webrtc