blob: 76fdca6e94209483ea7673251dda42d5e9c6f88f [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,
Benjamin Wrightc462a6e2018-10-26 13:16:16 -070075 cricket::MediaChannel* media_channel,
76 bool stopped) {
77 if (media_channel && frame_encryptor && ssrc && !stopped) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070078 worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
79 media_channel->SetFrameEncryptor(ssrc, frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -070080 });
81 }
82}
83
Florent Castelli892acf02018-10-01 22:47:20 +020084} // namespace
85
Seth Hampson2d2c8882018-05-16 16:02:32 -070086// Returns true if any RtpParameters member that isn't implemented contains a
87// value.
88bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020089 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070090 return true;
91 }
92 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
93 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
94 return true;
95 }
96 // Encoding parameters that are per-sender should only contain value at
97 // index 0.
98 if (i != 0 &&
99 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
100 return true;
101 }
102 }
103 return false;
104}
105
deadbeef70ab1a12015-09-28 16:53:55 -0700106LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
107
108LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
109 rtc::CritScope lock(&lock_);
110 if (sink_)
111 sink_->OnClose();
112}
113
114void LocalAudioSinkAdapter::OnData(const void* audio_data,
115 int bits_per_sample,
116 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800117 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700118 size_t number_of_frames) {
119 rtc::CritScope lock(&lock_);
120 if (sink_) {
121 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
122 number_of_frames);
123 }
124}
125
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800126void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700127 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800128 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700129 sink_ = sink;
130}
131
Steve Anton47136dd2018-01-12 10:49:35 -0800132AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700133 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800134 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800135 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700136 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800137 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800138 dtmf_sender_proxy_(DtmfSenderProxy::Create(
139 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700140 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700141 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800142 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200143 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800144}
deadbeeffac06552015-11-25 11:26:01 -0800145
deadbeef70ab1a12015-09-28 16:53:55 -0700146AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800147 // For DtmfSender.
148 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700149 Stop();
150}
151
deadbeef20cb0c12017-02-01 20:27:00 -0800152bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800153 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100154 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800155 return false;
156 }
157 // Check that this RTP sender is active (description has been applied that
158 // matches an SSRC to its ID).
159 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100160 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800161 return false;
162 }
Steve Anton47136dd2018-01-12 10:49:35 -0800163 return worker_thread_->Invoke<bool>(
164 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800165}
166
167bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800168 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100169 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800170 return false;
171 }
172 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100173 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800174 return false;
175 }
Steve Anton47136dd2018-01-12 10:49:35 -0800176 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
177 return media_channel_->InsertDtmf(ssrc_, code, duration);
178 });
179 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100180 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800181 }
Steve Anton47136dd2018-01-12 10:49:35 -0800182 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800183}
184
185sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
186 return &SignalDestroyed;
187}
188
deadbeef70ab1a12015-09-28 16:53:55 -0700189void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200190 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800191 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700192 if (cached_track_enabled_ != track_->enabled()) {
193 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800194 if (can_send_track()) {
195 SetAudioSend();
196 }
deadbeef70ab1a12015-09-28 16:53:55 -0700197 }
198}
199
200bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200201 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800202 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100203 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800204 return false;
205 }
206 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100207 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
208 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700209 return false;
210 }
211 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
212
213 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800214 if (track_) {
215 track_->RemoveSink(sink_adapter_.get());
216 track_->UnregisterObserver(this);
217 }
218
219 if (can_send_track() && stats_) {
220 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
221 }
deadbeef70ab1a12015-09-28 16:53:55 -0700222
223 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800224 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700225 // Keep a reference to the old track to keep it alive until we call
226 // SetAudioSend.
227 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700228 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800229 if (track_) {
230 cached_track_enabled_ = track_->enabled();
231 track_->RegisterObserver(this);
232 track_->AddSink(sink_adapter_.get());
233 }
234
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700235 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800236 if (can_send_track()) {
237 SetAudioSend();
238 if (stats_) {
239 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
240 }
241 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700242 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800243 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700244 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700245 return true;
246}
247
Florent Castellicebf50f2018-05-03 15:31:53 +0200248RtpParameters AudioRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200249 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700250 return RtpParameters();
251 }
Florent Castelli892acf02018-10-01 22:47:20 +0200252 if (!media_channel_) {
253 RtpParameters result = init_parameters_;
254 last_transaction_id_ = rtc::CreateRandomUuid();
255 result.transaction_id = last_transaction_id_.value();
256 return result;
257 }
Steve Anton47136dd2018-01-12 10:49:35 -0800258 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200259 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
260 last_transaction_id_ = rtc::CreateRandomUuid();
261 result.transaction_id = last_transaction_id_.value();
262 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800263 });
deadbeefa601f5c2016-06-06 14:27:39 -0700264}
265
Zach Steinba37b4b2018-01-23 15:02:36 -0800266RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700267 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200268 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800269 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700270 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200271 if (!last_transaction_id_) {
272 LOG_AND_RETURN_ERROR(
273 RTCErrorType::INVALID_STATE,
274 "Failed to set parameters since getParameters() has never been called"
275 " on this sender");
276 }
277 if (last_transaction_id_ != parameters.transaction_id) {
278 LOG_AND_RETURN_ERROR(
279 RTCErrorType::INVALID_MODIFICATION,
280 "Failed to set parameters since the transaction_id doesn't match"
281 " the last value returned from getParameters()");
282 }
283
Seth Hampson2d2c8882018-05-16 16:02:32 -0700284 if (UnimplementedRtpParameterHasValue(parameters)) {
285 LOG_AND_RETURN_ERROR(
286 RTCErrorType::UNSUPPORTED_PARAMETER,
287 "Attempted to set an unimplemented parameter of RtpParameters.");
288 }
Florent Castelli892acf02018-10-01 22:47:20 +0200289 if (!media_channel_) {
290 auto result = cricket::ValidateRtpParameters(init_parameters_, parameters);
291 if (result.ok()) {
292 init_parameters_ = parameters;
293 }
294 return result;
295 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800296 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200297 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
298 last_transaction_id_.reset();
299 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800300 });
deadbeefa601f5c2016-06-06 14:27:39 -0700301}
302
deadbeef20cb0c12017-02-01 20:27:00 -0800303rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
304 return dtmf_sender_proxy_;
305}
306
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700307void AudioRtpSender::SetFrameEncryptor(
308 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
309 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700310 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700311 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700312 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
313 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
314 });
315 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700316}
317
318rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
319 const {
320 return frame_encryptor_;
321}
322
deadbeeffac06552015-11-25 11:26:01 -0800323void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200324 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800325 if (stopped_ || ssrc == ssrc_) {
326 return;
327 }
328 // If we are already sending with a particular SSRC, stop sending.
329 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700330 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800331 if (stats_) {
332 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
333 }
334 }
335 ssrc_ = ssrc;
336 if (can_send_track()) {
337 SetAudioSend();
338 if (stats_) {
339 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
340 }
341 }
Florent Castelli892acf02018-10-01 22:47:20 +0200342 if (!init_parameters_.encodings.empty()) {
343 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
344 RTC_DCHECK(media_channel_);
345 // Get the current parameters, which are constructed from the SDP.
346 // The number of layers in the SDP is currently authoritative to support
347 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
348 // lines as described in RFC 5576.
349 // All fields should be default constructed and the SSRC field set, which
350 // we need to copy.
351 RtpParameters current_parameters =
352 media_channel_->GetRtpSendParameters(ssrc_);
353 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
354 init_parameters_.encodings[i].ssrc =
355 current_parameters.encodings[i].ssrc;
356 current_parameters.encodings[i] = init_parameters_.encodings[i];
357 }
358 current_parameters.degradation_preference =
359 init_parameters_.degradation_preference;
360 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
361 init_parameters_.encodings.clear();
362 });
363 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700364 // Each time there is an ssrc update.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700365 MaybeAttachFrameEncryptorToMediaChannel(
366 ssrc_, worker_thread_, frame_encryptor_, media_channel_, stopped_);
deadbeeffac06552015-11-25 11:26:01 -0800367}
368
deadbeef70ab1a12015-09-28 16:53:55 -0700369void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200370 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700371 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800372 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700373 return;
374 }
deadbeeffac06552015-11-25 11:26:01 -0800375 if (track_) {
376 track_->RemoveSink(sink_adapter_.get());
377 track_->UnregisterObserver(this);
378 }
379 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700380 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800381 if (stats_) {
382 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
383 }
384 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100385 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800386 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700387}
388
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800389void AudioRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
390 RTC_DCHECK(media_channel == nullptr ||
391 media_channel->media_type() == media_type());
392 media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700393}
394
deadbeeffac06552015-11-25 11:26:01 -0800395void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700396 RTC_DCHECK(!stopped_);
397 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800398 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100399 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700400 return;
401 }
deadbeef70ab1a12015-09-28 16:53:55 -0700402 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800403#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100404 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
405 // PeerConnection. This is a bit of a strange way to apply local audio
406 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800407 if (track_->enabled() && track_->GetSource() &&
408 !track_->GetSource()->remote()) {
Piotr (Peter) Slatala95ca6e12018-11-13 07:57:07 -0800409 options = track_->GetSource()->options();
deadbeef70ab1a12015-09-28 16:53:55 -0700410 }
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.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700566 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700567 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 Wrightc462a6e2018-10-26 13:16:16 -0700613 MaybeAttachFrameEncryptorToMediaChannel(
614 ssrc_, worker_thread_, frame_encryptor_, media_channel_, stopped_);
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
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800633void VideoRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
634 RTC_DCHECK(media_channel == nullptr ||
635 media_channel->media_type() == media_type());
636 media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700637}
638
deadbeeffac06552015-11-25 11:26:01 -0800639void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700640 RTC_DCHECK(!stopped_);
641 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800642 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100643 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700644 return;
645 }
perkj0d3eef22016-03-09 02:39:17 +0100646 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100647 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100648 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100649 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200650 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700651 }
pbos5214a0a2016-12-16 15:39:11 -0800652 switch (cached_track_content_hint_) {
653 case VideoTrackInterface::ContentHint::kNone:
654 break;
655 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100656 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800657 break;
658 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200659 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100660 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800661 break;
662 }
Steve Anton47136dd2018-01-12 10:49:35 -0800663 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200664 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800665 });
666 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700667}
668
669void VideoRtpSender::ClearVideoSend() {
670 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700671 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800672 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100673 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700674 return;
675 }
676 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
677 // This the normal case when the underlying media channel has already been
678 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800679 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200680 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800681 });
deadbeef70ab1a12015-09-28 16:53:55 -0700682}
683
684} // namespace webrtc