blob: 52710d92043de50ca873e8a123a8fa7329aea468 [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
67// Returns true if any RtpParameters member that isn't implemented contains a
68// value.
69bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020070 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070071 return true;
72 }
73 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
74 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
75 return true;
76 }
77 // Encoding parameters that are per-sender should only contain value at
78 // index 0.
79 if (i != 0 &&
80 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
81 return true;
82 }
83 }
84 return false;
85}
86
Benjamin Wrightbfd412e2018-09-10 14:06:02 -070087// Attaches the frame encryptor to the media channel through an invoke on a
88// worker thread. This set must be done on the corresponding worker thread that
89// the media channel was created on.
90void AttachFrameEncryptorToMediaChannel(
91 rtc::Thread* worker_thread,
92 webrtc::FrameEncryptorInterface* frame_encryptor,
93 cricket::MediaChannel* media_channel) {
94 if (media_channel) {
95 return worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
96 media_channel->SetFrameEncryptor(frame_encryptor);
97 });
98 }
99}
100
Harald Alvestrandc72af932018-01-11 17:18:19 +0100101} // namespace
102
deadbeef70ab1a12015-09-28 16:53:55 -0700103LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
104
105LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
106 rtc::CritScope lock(&lock_);
107 if (sink_)
108 sink_->OnClose();
109}
110
111void LocalAudioSinkAdapter::OnData(const void* audio_data,
112 int bits_per_sample,
113 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800114 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700115 size_t number_of_frames) {
116 rtc::CritScope lock(&lock_);
117 if (sink_) {
118 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
119 number_of_frames);
120 }
121}
122
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800123void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700124 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800125 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700126 sink_ = sink;
127}
128
Steve Anton47136dd2018-01-12 10:49:35 -0800129AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700130 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800131 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800132 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700133 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800134 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800135 dtmf_sender_proxy_(DtmfSenderProxy::Create(
136 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700137 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700138 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800139 RTC_DCHECK(worker_thread);
deadbeef20cb0c12017-02-01 20:27:00 -0800140}
deadbeeffac06552015-11-25 11:26:01 -0800141
deadbeef70ab1a12015-09-28 16:53:55 -0700142AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800143 // For DtmfSender.
144 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700145 Stop();
146}
147
deadbeef20cb0c12017-02-01 20:27:00 -0800148bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800149 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100150 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800151 return false;
152 }
153 // Check that this RTP sender is active (description has been applied that
154 // matches an SSRC to its ID).
155 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100156 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800157 return false;
158 }
Steve Anton47136dd2018-01-12 10:49:35 -0800159 return worker_thread_->Invoke<bool>(
160 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800161}
162
163bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800164 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100165 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800166 return false;
167 }
168 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100169 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800170 return false;
171 }
Steve Anton47136dd2018-01-12 10:49:35 -0800172 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
173 return media_channel_->InsertDtmf(ssrc_, code, duration);
174 });
175 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100176 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800177 }
Steve Anton47136dd2018-01-12 10:49:35 -0800178 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800179}
180
181sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
182 return &SignalDestroyed;
183}
184
deadbeef70ab1a12015-09-28 16:53:55 -0700185void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200186 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800187 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700188 if (cached_track_enabled_ != track_->enabled()) {
189 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800190 if (can_send_track()) {
191 SetAudioSend();
192 }
deadbeef70ab1a12015-09-28 16:53:55 -0700193 }
194}
195
196bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200197 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800198 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100199 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800200 return false;
201 }
202 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100203 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
204 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700205 return false;
206 }
207 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
208
209 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800210 if (track_) {
211 track_->RemoveSink(sink_adapter_.get());
212 track_->UnregisterObserver(this);
213 }
214
215 if (can_send_track() && stats_) {
216 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
217 }
deadbeef70ab1a12015-09-28 16:53:55 -0700218
219 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800220 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700221 // Keep a reference to the old track to keep it alive until we call
222 // SetAudioSend.
223 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700224 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800225 if (track_) {
226 cached_track_enabled_ = track_->enabled();
227 track_->RegisterObserver(this);
228 track_->AddSink(sink_adapter_.get());
229 }
230
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700231 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800232 if (can_send_track()) {
233 SetAudioSend();
234 if (stats_) {
235 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
236 }
237 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700238 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800239 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700240 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700241 return true;
242}
243
Florent Castellicebf50f2018-05-03 15:31:53 +0200244RtpParameters AudioRtpSender::GetParameters() {
Steve Anton47136dd2018-01-12 10:49:35 -0800245 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700246 return RtpParameters();
247 }
Steve Anton47136dd2018-01-12 10:49:35 -0800248 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200249 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
250 last_transaction_id_ = rtc::CreateRandomUuid();
251 result.transaction_id = last_transaction_id_.value();
252 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800253 });
deadbeefa601f5c2016-06-06 14:27:39 -0700254}
255
Zach Steinba37b4b2018-01-23 15:02:36 -0800256RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700257 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800258 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800259 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700260 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200261 if (!last_transaction_id_) {
262 LOG_AND_RETURN_ERROR(
263 RTCErrorType::INVALID_STATE,
264 "Failed to set parameters since getParameters() has never been called"
265 " on this sender");
266 }
267 if (last_transaction_id_ != parameters.transaction_id) {
268 LOG_AND_RETURN_ERROR(
269 RTCErrorType::INVALID_MODIFICATION,
270 "Failed to set parameters since the transaction_id doesn't match"
271 " the last value returned from getParameters()");
272 }
273
Seth Hampson2d2c8882018-05-16 16:02:32 -0700274 if (UnimplementedRtpParameterHasValue(parameters)) {
275 LOG_AND_RETURN_ERROR(
276 RTCErrorType::UNSUPPORTED_PARAMETER,
277 "Attempted to set an unimplemented parameter of RtpParameters.");
278 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800279 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200280 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
281 last_transaction_id_.reset();
282 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800283 });
deadbeefa601f5c2016-06-06 14:27:39 -0700284}
285
deadbeef20cb0c12017-02-01 20:27:00 -0800286rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
287 return dtmf_sender_proxy_;
288}
289
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700290void AudioRtpSender::SetFrameEncryptor(
291 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
292 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700293 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
294 media_channel_);
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700295}
296
297rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
298 const {
299 return frame_encryptor_;
300}
301
deadbeeffac06552015-11-25 11:26:01 -0800302void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200303 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800304 if (stopped_ || ssrc == ssrc_) {
305 return;
306 }
307 // If we are already sending with a particular SSRC, stop sending.
308 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700309 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800310 if (stats_) {
311 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
312 }
313 }
314 ssrc_ = ssrc;
315 if (can_send_track()) {
316 SetAudioSend();
317 if (stats_) {
318 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
319 }
320 }
321}
322
deadbeef70ab1a12015-09-28 16:53:55 -0700323void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200324 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700325 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800326 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700327 return;
328 }
deadbeeffac06552015-11-25 11:26:01 -0800329 if (track_) {
330 track_->RemoveSink(sink_adapter_.get());
331 track_->UnregisterObserver(this);
332 }
333 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700334 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800335 if (stats_) {
336 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
337 }
338 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100339 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800340 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700341}
342
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700343void AudioRtpSender::SetVoiceMediaChannel(
344 cricket::VoiceMediaChannel* voice_media_channel) {
345 media_channel_ = voice_media_channel;
346 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
347 media_channel_);
348}
349
deadbeeffac06552015-11-25 11:26:01 -0800350void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700351 RTC_DCHECK(!stopped_);
352 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800353 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100354 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700355 return;
356 }
deadbeef70ab1a12015-09-28 16:53:55 -0700357 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800358#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100359 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
360 // PeerConnection. This is a bit of a strange way to apply local audio
361 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800362 if (track_->enabled() && track_->GetSource() &&
363 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700364 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800365 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700366 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
367 }
Tommi3c169782016-01-21 16:12:17 +0100368#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700369
Steve Anton47136dd2018-01-12 10:49:35 -0800370 // |track_->enabled()| hops to the signaling thread, so call it before we hop
371 // to the worker thread or else it will deadlock.
372 bool track_enabled = track_->enabled();
373 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
374 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
375 sink_adapter_.get());
376 });
377 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100378 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700379 }
380}
381
382void AudioRtpSender::ClearAudioSend() {
383 RTC_DCHECK(ssrc_ != 0);
384 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800385 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100386 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700387 return;
388 }
389 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800390 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
391 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
392 });
393 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100394 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700395 }
deadbeef70ab1a12015-09-28 16:53:55 -0700396}
397
Steve Anton47136dd2018-01-12 10:49:35 -0800398VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700399 const std::string& id)
400 : worker_thread_(worker_thread), id_(id) {
Steve Anton47136dd2018-01-12 10:49:35 -0800401 RTC_DCHECK(worker_thread);
deadbeef20cb0c12017-02-01 20:27:00 -0800402}
403
deadbeef70ab1a12015-09-28 16:53:55 -0700404VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700405 Stop();
406}
407
408void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200409 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800410 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200411 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800412 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800413 if (can_send_track()) {
414 SetVideoSend();
415 }
deadbeef70ab1a12015-09-28 16:53:55 -0700416 }
417}
418
419bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200420 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800421 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100422 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800423 return false;
424 }
425 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100426 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
427 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700428 return false;
429 }
430 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
431
432 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800433 if (track_) {
434 track_->UnregisterObserver(this);
435 }
deadbeef70ab1a12015-09-28 16:53:55 -0700436
437 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800438 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700439 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700440 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700441 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700442 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800443 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800444 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800445 track_->RegisterObserver(this);
446 }
447
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700448 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800449 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800450 SetVideoSend();
451 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700452 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800453 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700454 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700455 return true;
456}
457
Florent Castellicebf50f2018-05-03 15:31:53 +0200458RtpParameters VideoRtpSender::GetParameters() {
Steve Anton47136dd2018-01-12 10:49:35 -0800459 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700460 return RtpParameters();
461 }
Steve Anton47136dd2018-01-12 10:49:35 -0800462 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200463 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
464 last_transaction_id_ = rtc::CreateRandomUuid();
465 result.transaction_id = last_transaction_id_.value();
466 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800467 });
deadbeefa601f5c2016-06-06 14:27:39 -0700468}
469
Zach Steinba37b4b2018-01-23 15:02:36 -0800470RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700471 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800472 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800473 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700474 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200475 if (!last_transaction_id_) {
476 LOG_AND_RETURN_ERROR(
477 RTCErrorType::INVALID_STATE,
478 "Failed to set parameters since getParameters() has never been called"
479 " on this sender");
480 }
481 if (last_transaction_id_ != parameters.transaction_id) {
482 LOG_AND_RETURN_ERROR(
483 RTCErrorType::INVALID_MODIFICATION,
484 "Failed to set parameters since the transaction_id doesn't match"
485 " the last value returned from getParameters()");
486 }
487
Seth Hampson2d2c8882018-05-16 16:02:32 -0700488 if (UnimplementedRtpParameterHasValue(parameters)) {
489 LOG_AND_RETURN_ERROR(
490 RTCErrorType::UNSUPPORTED_PARAMETER,
491 "Attempted to set an unimplemented parameter of RtpParameters.");
492 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800493 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200494 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
495 last_transaction_id_.reset();
496 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800497 });
deadbeefa601f5c2016-06-06 14:27:39 -0700498}
499
deadbeef20cb0c12017-02-01 20:27:00 -0800500rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100501 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800502 return nullptr;
503}
504
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700505void VideoRtpSender::SetFrameEncryptor(
506 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
507 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700508 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
509 media_channel_);
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700510}
511
512rtc::scoped_refptr<FrameEncryptorInterface> VideoRtpSender::GetFrameEncryptor()
513 const {
514 return frame_encryptor_;
515}
516
deadbeeffac06552015-11-25 11:26:01 -0800517void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200518 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800519 if (stopped_ || ssrc == ssrc_) {
520 return;
521 }
522 // If we are already sending with a particular SSRC, stop sending.
523 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700524 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800525 }
526 ssrc_ = ssrc;
527 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800528 SetVideoSend();
529 }
530}
531
deadbeef70ab1a12015-09-28 16:53:55 -0700532void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200533 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700534 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800535 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700536 return;
537 }
deadbeeffac06552015-11-25 11:26:01 -0800538 if (track_) {
539 track_->UnregisterObserver(this);
540 }
541 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700542 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800543 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100544 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800545 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700546}
547
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700548void VideoRtpSender::SetVideoMediaChannel(
549 cricket::VideoMediaChannel* video_media_channel) {
550 media_channel_ = video_media_channel;
551 AttachFrameEncryptorToMediaChannel(worker_thread_, frame_encryptor_.get(),
552 media_channel_);
553}
554
deadbeeffac06552015-11-25 11:26:01 -0800555void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700556 RTC_DCHECK(!stopped_);
557 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800558 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100559 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700560 return;
561 }
perkj0d3eef22016-03-09 02:39:17 +0100562 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100563 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100564 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100565 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200566 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700567 }
pbos5214a0a2016-12-16 15:39:11 -0800568 switch (cached_track_content_hint_) {
569 case VideoTrackInterface::ContentHint::kNone:
570 break;
571 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100572 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800573 break;
574 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200575 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100576 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800577 break;
578 }
Steve Anton47136dd2018-01-12 10:49:35 -0800579 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200580 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800581 });
582 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700583}
584
585void VideoRtpSender::ClearVideoSend() {
586 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700587 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800588 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100589 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700590 return;
591 }
592 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
593 // This the normal case when the underlying media channel has already been
594 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800595 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200596 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800597 });
deadbeef70ab1a12015-09-28 16:53:55 -0700598}
599
600} // namespace webrtc