blob: 3bb90f24da14b914d303f5ba8ec3c637cd4b52bd [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) {
Åsa Persson55659812018-06-18 17:51:32 +020061 if (encoding_params.bitrate_priority != kDefaultBitratePriority) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070062 return true;
63 }
64 return false;
65}
66
Benjamin Wright84583f62018-10-04 14:22:34 -070067// Attempt to attach the frame decryptor to the current media channel on the
68// correct worker thread only if both the media channel exists and a ssrc has
69// been allocated to the stream.
70void MaybeAttachFrameEncryptorToMediaChannel(
71 const absl::optional<uint32_t> ssrc,
72 rtc::Thread* worker_thread,
73 rtc::scoped_refptr<webrtc::FrameEncryptorInterface> frame_encryptor,
74 cricket::MediaChannel* media_channel) {
75 if (media_channel && ssrc.has_value()) {
76 return worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
77 media_channel->SetFrameEncryptor(*ssrc, frame_encryptor);
78 });
79 }
80}
81
Florent Castelli892acf02018-10-01 22:47:20 +020082} // namespace
83
Seth Hampson2d2c8882018-05-16 16:02:32 -070084// Returns true if any RtpParameters member that isn't implemented contains a
85// value.
86bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020087 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070088 return true;
89 }
90 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
91 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
92 return true;
93 }
94 // Encoding parameters that are per-sender should only contain value at
95 // index 0.
96 if (i != 0 &&
97 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
98 return true;
99 }
100 }
101 return false;
102}
103
deadbeef70ab1a12015-09-28 16:53:55 -0700104LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
105
106LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
107 rtc::CritScope lock(&lock_);
108 if (sink_)
109 sink_->OnClose();
110}
111
112void LocalAudioSinkAdapter::OnData(const void* audio_data,
113 int bits_per_sample,
114 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800115 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700116 size_t number_of_frames) {
117 rtc::CritScope lock(&lock_);
118 if (sink_) {
119 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
120 number_of_frames);
121 }
122}
123
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800124void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700125 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800126 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700127 sink_ = sink;
128}
129
Steve Anton47136dd2018-01-12 10:49:35 -0800130AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700131 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800132 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800133 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700134 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800135 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800136 dtmf_sender_proxy_(DtmfSenderProxy::Create(
137 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700138 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700139 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800140 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200141 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800142}
deadbeeffac06552015-11-25 11:26:01 -0800143
deadbeef70ab1a12015-09-28 16:53:55 -0700144AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800145 // For DtmfSender.
146 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700147 Stop();
148}
149
deadbeef20cb0c12017-02-01 20:27:00 -0800150bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800151 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800153 return false;
154 }
155 // Check that this RTP sender is active (description has been applied that
156 // matches an SSRC to its ID).
157 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100158 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800159 return false;
160 }
Steve Anton47136dd2018-01-12 10:49:35 -0800161 return worker_thread_->Invoke<bool>(
162 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800163}
164
165bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800166 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100167 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800168 return false;
169 }
170 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100171 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800172 return false;
173 }
Steve Anton47136dd2018-01-12 10:49:35 -0800174 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
175 return media_channel_->InsertDtmf(ssrc_, code, duration);
176 });
177 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100178 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800179 }
Steve Anton47136dd2018-01-12 10:49:35 -0800180 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800181}
182
183sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
184 return &SignalDestroyed;
185}
186
deadbeef70ab1a12015-09-28 16:53:55 -0700187void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200188 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800189 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700190 if (cached_track_enabled_ != track_->enabled()) {
191 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800192 if (can_send_track()) {
193 SetAudioSend();
194 }
deadbeef70ab1a12015-09-28 16:53:55 -0700195 }
196}
197
198bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200199 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800200 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100201 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800202 return false;
203 }
204 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100205 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
206 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700207 return false;
208 }
209 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
210
211 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800212 if (track_) {
213 track_->RemoveSink(sink_adapter_.get());
214 track_->UnregisterObserver(this);
215 }
216
217 if (can_send_track() && stats_) {
218 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
219 }
deadbeef70ab1a12015-09-28 16:53:55 -0700220
221 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800222 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700223 // Keep a reference to the old track to keep it alive until we call
224 // SetAudioSend.
225 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700226 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800227 if (track_) {
228 cached_track_enabled_ = track_->enabled();
229 track_->RegisterObserver(this);
230 track_->AddSink(sink_adapter_.get());
231 }
232
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700233 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800234 if (can_send_track()) {
235 SetAudioSend();
236 if (stats_) {
237 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
238 }
239 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700240 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800241 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700242 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700243 return true;
244}
245
Florent Castellicebf50f2018-05-03 15:31:53 +0200246RtpParameters AudioRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200247 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700248 return RtpParameters();
249 }
Florent Castelli892acf02018-10-01 22:47:20 +0200250 if (!media_channel_) {
251 RtpParameters result = init_parameters_;
252 last_transaction_id_ = rtc::CreateRandomUuid();
253 result.transaction_id = last_transaction_id_.value();
254 return result;
255 }
Steve Anton47136dd2018-01-12 10:49:35 -0800256 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200257 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
258 last_transaction_id_ = rtc::CreateRandomUuid();
259 result.transaction_id = last_transaction_id_.value();
260 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800261 });
deadbeefa601f5c2016-06-06 14:27:39 -0700262}
263
Zach Steinba37b4b2018-01-23 15:02:36 -0800264RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700265 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200266 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800267 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700268 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200269 if (!last_transaction_id_) {
270 LOG_AND_RETURN_ERROR(
271 RTCErrorType::INVALID_STATE,
272 "Failed to set parameters since getParameters() has never been called"
273 " on this sender");
274 }
275 if (last_transaction_id_ != parameters.transaction_id) {
276 LOG_AND_RETURN_ERROR(
277 RTCErrorType::INVALID_MODIFICATION,
278 "Failed to set parameters since the transaction_id doesn't match"
279 " the last value returned from getParameters()");
280 }
281
Seth Hampson2d2c8882018-05-16 16:02:32 -0700282 if (UnimplementedRtpParameterHasValue(parameters)) {
283 LOG_AND_RETURN_ERROR(
284 RTCErrorType::UNSUPPORTED_PARAMETER,
285 "Attempted to set an unimplemented parameter of RtpParameters.");
286 }
Florent Castelli892acf02018-10-01 22:47:20 +0200287 if (!media_channel_) {
288 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
289 if (result.ok()) {
290 init_parameters_ = parameters;
291 }
292 return result;
293 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800294 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200295 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
296 last_transaction_id_.reset();
297 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800298 });
deadbeefa601f5c2016-06-06 14:27:39 -0700299}
300
deadbeef20cb0c12017-02-01 20:27:00 -0800301rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
302 return dtmf_sender_proxy_;
303}
304
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700305void AudioRtpSender::SetFrameEncryptor(
306 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
307 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -0700308 MaybeAttachFrameEncryptorToMediaChannel(ssrc_, worker_thread_,
309 frame_encryptor_, media_channel_);
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700310}
311
312rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
313 const {
314 return frame_encryptor_;
315}
316
deadbeeffac06552015-11-25 11:26:01 -0800317void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200318 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800319 if (stopped_ || ssrc == ssrc_) {
320 return;
321 }
322 // If we are already sending with a particular SSRC, stop sending.
323 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700324 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800325 if (stats_) {
326 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
327 }
328 }
329 ssrc_ = ssrc;
330 if (can_send_track()) {
331 SetAudioSend();
332 if (stats_) {
333 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
334 }
335 }
Florent Castelli892acf02018-10-01 22:47:20 +0200336 if (!init_parameters_.encodings.empty()) {
337 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
338 RTC_DCHECK(media_channel_);
339 // Get the current parameters, which are constructed from the SDP.
340 // The number of layers in the SDP is currently authoritative to support
341 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
342 // lines as described in RFC 5576.
343 // All fields should be default constructed and the SSRC field set, which
344 // we need to copy.
345 RtpParameters current_parameters =
346 media_channel_->GetRtpSendParameters(ssrc_);
347 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
348 init_parameters_.encodings[i].ssrc =
349 current_parameters.encodings[i].ssrc;
350 current_parameters.encodings[i] = init_parameters_.encodings[i];
351 }
352 current_parameters.degradation_preference =
353 init_parameters_.degradation_preference;
354 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
355 init_parameters_.encodings.clear();
356 });
357 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700358 // Each time there is an ssrc update.
359 MaybeAttachFrameEncryptorToMediaChannel(ssrc_, worker_thread_,
360 frame_encryptor_, media_channel_);
deadbeeffac06552015-11-25 11:26:01 -0800361}
362
deadbeef70ab1a12015-09-28 16:53:55 -0700363void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200364 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700365 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800366 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700367 return;
368 }
deadbeeffac06552015-11-25 11:26:01 -0800369 if (track_) {
370 track_->RemoveSink(sink_adapter_.get());
371 track_->UnregisterObserver(this);
372 }
373 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700374 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800375 if (stats_) {
376 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
377 }
378 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100379 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800380 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700381}
382
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700383void AudioRtpSender::SetVoiceMediaChannel(
384 cricket::VoiceMediaChannel* voice_media_channel) {
385 media_channel_ = voice_media_channel;
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700386}
387
deadbeeffac06552015-11-25 11:26:01 -0800388void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700389 RTC_DCHECK(!stopped_);
390 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800391 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100392 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700393 return;
394 }
deadbeef70ab1a12015-09-28 16:53:55 -0700395 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800396#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100397 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
398 // PeerConnection. This is a bit of a strange way to apply local audio
399 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800400 if (track_->enabled() && track_->GetSource() &&
401 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700402 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800403 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700404 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
405 }
Tommi3c169782016-01-21 16:12:17 +0100406#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700407
Steve Anton47136dd2018-01-12 10:49:35 -0800408 // |track_->enabled()| hops to the signaling thread, so call it before we hop
409 // to the worker thread or else it will deadlock.
410 bool track_enabled = track_->enabled();
411 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
412 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
413 sink_adapter_.get());
414 });
415 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100416 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700417 }
418}
419
420void AudioRtpSender::ClearAudioSend() {
421 RTC_DCHECK(ssrc_ != 0);
422 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800423 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100424 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700425 return;
426 }
427 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800428 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
429 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
430 });
431 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100432 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700433 }
deadbeef70ab1a12015-09-28 16:53:55 -0700434}
435
Steve Anton47136dd2018-01-12 10:49:35 -0800436VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700437 const std::string& id)
438 : worker_thread_(worker_thread), id_(id) {
Steve Anton47136dd2018-01-12 10:49:35 -0800439 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200440 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800441}
442
deadbeef70ab1a12015-09-28 16:53:55 -0700443VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700444 Stop();
445}
446
447void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200448 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800449 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200450 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800451 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800452 if (can_send_track()) {
453 SetVideoSend();
454 }
deadbeef70ab1a12015-09-28 16:53:55 -0700455 }
456}
457
458bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200459 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800460 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100461 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800462 return false;
463 }
464 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100465 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
466 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700467 return false;
468 }
469 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
470
471 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800472 if (track_) {
473 track_->UnregisterObserver(this);
474 }
deadbeef70ab1a12015-09-28 16:53:55 -0700475
476 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800477 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700478 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700479 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700480 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700481 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800482 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800483 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800484 track_->RegisterObserver(this);
485 }
486
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700487 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800488 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800489 SetVideoSend();
490 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700491 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800492 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700493 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700494 return true;
495}
496
Florent Castellicebf50f2018-05-03 15:31:53 +0200497RtpParameters VideoRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200498 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700499 return RtpParameters();
500 }
Florent Castelli892acf02018-10-01 22:47:20 +0200501 if (!media_channel_) {
502 RtpParameters result = init_parameters_;
503 last_transaction_id_ = rtc::CreateRandomUuid();
504 result.transaction_id = last_transaction_id_.value();
505 return result;
506 }
Steve Anton47136dd2018-01-12 10:49:35 -0800507 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200508 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
509 last_transaction_id_ = rtc::CreateRandomUuid();
510 result.transaction_id = last_transaction_id_.value();
511 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800512 });
deadbeefa601f5c2016-06-06 14:27:39 -0700513}
514
Zach Steinba37b4b2018-01-23 15:02:36 -0800515RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700516 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200517 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800518 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700519 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200520 if (!last_transaction_id_) {
521 LOG_AND_RETURN_ERROR(
522 RTCErrorType::INVALID_STATE,
523 "Failed to set parameters since getParameters() has never been called"
524 " on this sender");
525 }
526 if (last_transaction_id_ != parameters.transaction_id) {
527 LOG_AND_RETURN_ERROR(
528 RTCErrorType::INVALID_MODIFICATION,
529 "Failed to set parameters since the transaction_id doesn't match"
530 " the last value returned from getParameters()");
531 }
532
Seth Hampson2d2c8882018-05-16 16:02:32 -0700533 if (UnimplementedRtpParameterHasValue(parameters)) {
534 LOG_AND_RETURN_ERROR(
535 RTCErrorType::UNSUPPORTED_PARAMETER,
536 "Attempted to set an unimplemented parameter of RtpParameters.");
537 }
Florent Castelli892acf02018-10-01 22:47:20 +0200538 if (!media_channel_) {
539 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
540 if (result.ok()) {
541 init_parameters_ = parameters;
542 }
543 return result;
544 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800545 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200546 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
547 last_transaction_id_.reset();
548 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800549 });
deadbeefa601f5c2016-06-06 14:27:39 -0700550}
551
deadbeef20cb0c12017-02-01 20:27:00 -0800552rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100553 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800554 return nullptr;
555}
556
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700557void VideoRtpSender::SetFrameEncryptor(
558 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
559 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -0700560 MaybeAttachFrameEncryptorToMediaChannel(ssrc_, worker_thread_,
561 frame_encryptor_, media_channel_);
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700562}
563
564rtc::scoped_refptr<FrameEncryptorInterface> VideoRtpSender::GetFrameEncryptor()
565 const {
566 return frame_encryptor_;
567}
568
deadbeeffac06552015-11-25 11:26:01 -0800569void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200570 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800571 if (stopped_ || ssrc == ssrc_) {
572 return;
573 }
574 // If we are already sending with a particular SSRC, stop sending.
575 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700576 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800577 }
578 ssrc_ = ssrc;
579 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800580 SetVideoSend();
581 }
Florent Castelli892acf02018-10-01 22:47:20 +0200582 if (!init_parameters_.encodings.empty()) {
583 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
584 RTC_DCHECK(media_channel_);
585 // Get the current parameters, which are constructed from the SDP.
586 // The number of layers in the SDP is currently authoritative to support
587 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
588 // lines as described in RFC 5576.
589 // All fields should be default constructed and the SSRC field set, which
590 // we need to copy.
591 RtpParameters current_parameters =
592 media_channel_->GetRtpSendParameters(ssrc_);
593 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
594 init_parameters_.encodings[i].ssrc =
595 current_parameters.encodings[i].ssrc;
596 current_parameters.encodings[i] = init_parameters_.encodings[i];
597 }
598 current_parameters.degradation_preference =
599 init_parameters_.degradation_preference;
600 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
601 init_parameters_.encodings.clear();
602 });
603 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700604 MaybeAttachFrameEncryptorToMediaChannel(ssrc_, worker_thread_,
605 frame_encryptor_, media_channel_);
deadbeeffac06552015-11-25 11:26:01 -0800606}
607
deadbeef70ab1a12015-09-28 16:53:55 -0700608void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200609 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700610 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800611 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700612 return;
613 }
deadbeeffac06552015-11-25 11:26:01 -0800614 if (track_) {
615 track_->UnregisterObserver(this);
616 }
617 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700618 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800619 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100620 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800621 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700622}
623
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700624void VideoRtpSender::SetVideoMediaChannel(
625 cricket::VideoMediaChannel* video_media_channel) {
626 media_channel_ = video_media_channel;
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700627}
628
deadbeeffac06552015-11-25 11:26:01 -0800629void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700630 RTC_DCHECK(!stopped_);
631 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800632 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100633 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700634 return;
635 }
perkj0d3eef22016-03-09 02:39:17 +0100636 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100637 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100638 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100639 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200640 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700641 }
pbos5214a0a2016-12-16 15:39:11 -0800642 switch (cached_track_content_hint_) {
643 case VideoTrackInterface::ContentHint::kNone:
644 break;
645 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100646 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800647 break;
648 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200649 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100650 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800651 break;
652 }
Steve Anton47136dd2018-01-12 10:49:35 -0800653 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200654 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800655 });
656 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700657}
658
659void VideoRtpSender::ClearVideoSend() {
660 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700661 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800662 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100663 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700664 return;
665 }
666 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
667 // This the normal case when the underlying media channel has already been
668 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800669 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200670 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800671 });
deadbeef70ab1a12015-09-28 16:53:55 -0700672}
673
674} // namespace webrtc