blob: e8105a835c36b8e4ea8e43f49a8a7133f763db5d [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
Steve Anton36b29d12017-10-30 09:57:42 -070013#include <vector>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/mediastreaminterface.h"
16#include "pc/localaudiosource.h"
Steve Anton2d8609c2018-01-23 16:38:46 -080017#include "pc/statscollector.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/checks.h"
19#include "rtc_base/helpers.h"
20#include "rtc_base/trace_event.h"
deadbeef70ab1a12015-09-28 16:53:55 -070021
22namespace webrtc {
23
Harald Alvestrandc72af932018-01-11 17:18:19 +010024namespace {
25
26// This function is only expected to be called on the signalling thread.
27int GenerateUniqueId() {
28 static int g_unique_id = 0;
29
30 return ++g_unique_id;
31}
32
Seth Hampson2d2c8882018-05-16 16:02:32 -070033// Returns an true if any RtpEncodingParameters member that isn't implemented
34// contains a value.
35bool UnimplementedRtpEncodingParameterHasValue(
36 const RtpEncodingParameters& encoding_params) {
37 if (encoding_params.codec_payload_type.has_value() ||
38 encoding_params.fec.has_value() || encoding_params.rtx.has_value() ||
39 encoding_params.dtx.has_value() || encoding_params.ptime.has_value() ||
40 encoding_params.max_framerate.has_value() ||
41 !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 Castelliabe301f2018-06-12 18:33:49 +020070 if (!parameters.mid.empty() ||
Seth Hampson2d2c8882018-05-16 16:02:32 -070071 parameters.degradation_preference != DegradationPreference::BALANCED) {
72 return true;
73 }
74 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
75 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
76 return true;
77 }
78 // Encoding parameters that are per-sender should only contain value at
79 // index 0.
80 if (i != 0 &&
81 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
82 return true;
83 }
84 }
85 return false;
86}
87
Harald Alvestrandc72af932018-01-11 17:18:19 +010088} // namespace
89
deadbeef70ab1a12015-09-28 16:53:55 -070090LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
91
92LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
93 rtc::CritScope lock(&lock_);
94 if (sink_)
95 sink_->OnClose();
96}
97
98void LocalAudioSinkAdapter::OnData(const void* audio_data,
99 int bits_per_sample,
100 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800101 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700102 size_t number_of_frames) {
103 rtc::CritScope lock(&lock_);
104 if (sink_) {
105 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
106 number_of_frames);
107 }
108}
109
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800110void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700111 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800112 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700113 sink_ = sink;
114}
115
Steve Anton47136dd2018-01-12 10:49:35 -0800116AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
117 StatsCollector* stats)
118 : AudioRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}, stats) {
119}
deadbeef70ab1a12015-09-28 16:53:55 -0700120
Steve Anton47136dd2018-01-12 10:49:35 -0800121AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
122 rtc::scoped_refptr<AudioTrackInterface> track,
Seth Hampson845e8782018-03-02 11:34:10 -0800123 const std::vector<std::string>& stream_ids,
deadbeefe1f9d832016-01-14 15:35:42 -0800124 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800125 : worker_thread_(worker_thread),
126 id_(track ? track->id() : rtc::CreateRandomUuid()),
Seth Hampson845e8782018-03-02 11:34:10 -0800127 stream_ids_(stream_ids),
deadbeefe1f9d832016-01-14 15:35:42 -0800128 stats_(stats),
129 track_(track),
Steve Anton02ee47c2018-01-10 16:26:06 -0800130 dtmf_sender_proxy_(DtmfSenderProxy::Create(
131 rtc::Thread::Current(),
132 DtmfSender::Create(track_, rtc::Thread::Current(), this))),
133 cached_track_enabled_(track ? track->enabled() : false),
Harald Alvestrandc72af932018-01-11 17:18:19 +0100134 sink_adapter_(new LocalAudioSinkAdapter()),
135 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -0800136 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -0800137 if (track_) {
138 track_->RegisterObserver(this);
139 track_->AddSink(sink_adapter_.get());
140 }
deadbeef20cb0c12017-02-01 20:27:00 -0800141}
deadbeeffac06552015-11-25 11:26:01 -0800142
deadbeef70ab1a12015-09-28 16:53:55 -0700143AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800144 // For DtmfSender.
145 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700146 Stop();
147}
148
deadbeef20cb0c12017-02-01 20:27:00 -0800149bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800150 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100151 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800152 return false;
153 }
154 // Check that this RTP sender is active (description has been applied that
155 // matches an SSRC to its ID).
156 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100157 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800158 return false;
159 }
Steve Anton47136dd2018-01-12 10:49:35 -0800160 return worker_thread_->Invoke<bool>(
161 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800162}
163
164bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800165 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100166 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800167 return false;
168 }
169 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100170 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800171 return false;
172 }
Steve Anton47136dd2018-01-12 10:49:35 -0800173 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
174 return media_channel_->InsertDtmf(ssrc_, code, duration);
175 });
176 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100177 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800178 }
Steve Anton47136dd2018-01-12 10:49:35 -0800179 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800180}
181
182sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
183 return &SignalDestroyed;
184}
185
deadbeef70ab1a12015-09-28 16:53:55 -0700186void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200187 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800188 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700189 if (cached_track_enabled_ != track_->enabled()) {
190 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800191 if (can_send_track()) {
192 SetAudioSend();
193 }
deadbeef70ab1a12015-09-28 16:53:55 -0700194 }
195}
196
197bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200198 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800199 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100200 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800201 return false;
202 }
203 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100204 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
205 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700206 return false;
207 }
208 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
209
210 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800211 if (track_) {
212 track_->RemoveSink(sink_adapter_.get());
213 track_->UnregisterObserver(this);
214 }
215
216 if (can_send_track() && stats_) {
217 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
218 }
deadbeef70ab1a12015-09-28 16:53:55 -0700219
220 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800221 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700222 // Keep a reference to the old track to keep it alive until we call
223 // SetAudioSend.
224 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700225 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800226 if (track_) {
227 cached_track_enabled_ = track_->enabled();
228 track_->RegisterObserver(this);
229 track_->AddSink(sink_adapter_.get());
230 }
231
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700232 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800233 if (can_send_track()) {
234 SetAudioSend();
235 if (stats_) {
236 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
237 }
238 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700239 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800240 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100241 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700242 return true;
243}
244
Florent Castellicebf50f2018-05-03 15:31:53 +0200245RtpParameters AudioRtpSender::GetParameters() {
Steve Anton47136dd2018-01-12 10:49:35 -0800246 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700247 return RtpParameters();
248 }
Steve Anton47136dd2018-01-12 10:49:35 -0800249 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200250 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
251 last_transaction_id_ = rtc::CreateRandomUuid();
252 result.transaction_id = last_transaction_id_.value();
253 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800254 });
deadbeefa601f5c2016-06-06 14:27:39 -0700255}
256
Zach Steinba37b4b2018-01-23 15:02:36 -0800257RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700258 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800259 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800260 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700261 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200262 if (!last_transaction_id_) {
263 LOG_AND_RETURN_ERROR(
264 RTCErrorType::INVALID_STATE,
265 "Failed to set parameters since getParameters() has never been called"
266 " on this sender");
267 }
268 if (last_transaction_id_ != parameters.transaction_id) {
269 LOG_AND_RETURN_ERROR(
270 RTCErrorType::INVALID_MODIFICATION,
271 "Failed to set parameters since the transaction_id doesn't match"
272 " the last value returned from getParameters()");
273 }
274
Seth Hampson2d2c8882018-05-16 16:02:32 -0700275 if (UnimplementedRtpParameterHasValue(parameters)) {
276 LOG_AND_RETURN_ERROR(
277 RTCErrorType::UNSUPPORTED_PARAMETER,
278 "Attempted to set an unimplemented parameter of RtpParameters.");
279 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800280 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200281 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
282 last_transaction_id_.reset();
283 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800284 });
deadbeefa601f5c2016-06-06 14:27:39 -0700285}
286
deadbeef20cb0c12017-02-01 20:27:00 -0800287rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
288 return dtmf_sender_proxy_;
289}
290
deadbeeffac06552015-11-25 11:26:01 -0800291void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200292 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800293 if (stopped_ || ssrc == ssrc_) {
294 return;
295 }
296 // If we are already sending with a particular SSRC, stop sending.
297 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700298 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800299 if (stats_) {
300 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
301 }
302 }
303 ssrc_ = ssrc;
304 if (can_send_track()) {
305 SetAudioSend();
306 if (stats_) {
307 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
308 }
309 }
310}
311
deadbeef70ab1a12015-09-28 16:53:55 -0700312void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200313 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700314 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800315 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700316 return;
317 }
deadbeeffac06552015-11-25 11:26:01 -0800318 if (track_) {
319 track_->RemoveSink(sink_adapter_.get());
320 track_->UnregisterObserver(this);
321 }
322 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700323 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800324 if (stats_) {
325 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
326 }
327 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100328 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800329 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700330}
331
deadbeeffac06552015-11-25 11:26:01 -0800332void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700333 RTC_DCHECK(!stopped_);
334 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800335 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100336 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700337 return;
338 }
deadbeef70ab1a12015-09-28 16:53:55 -0700339 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800340#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100341 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
342 // PeerConnection. This is a bit of a strange way to apply local audio
343 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800344 if (track_->enabled() && track_->GetSource() &&
345 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700346 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800347 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700348 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
349 }
Tommi3c169782016-01-21 16:12:17 +0100350#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700351
Steve Anton47136dd2018-01-12 10:49:35 -0800352 // |track_->enabled()| hops to the signaling thread, so call it before we hop
353 // to the worker thread or else it will deadlock.
354 bool track_enabled = track_->enabled();
355 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
356 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
357 sink_adapter_.get());
358 });
359 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100360 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700361 }
362}
363
364void AudioRtpSender::ClearAudioSend() {
365 RTC_DCHECK(ssrc_ != 0);
366 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800367 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100368 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700369 return;
370 }
371 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800372 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
373 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
374 });
375 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100376 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700377 }
deadbeef70ab1a12015-09-28 16:53:55 -0700378}
379
Steve Anton47136dd2018-01-12 10:49:35 -0800380VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread)
381 : VideoRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}) {}
Steve Anton02ee47c2018-01-10 16:26:06 -0800382
Steve Anton47136dd2018-01-12 10:49:35 -0800383VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
384 rtc::scoped_refptr<VideoTrackInterface> track,
Seth Hampson845e8782018-03-02 11:34:10 -0800385 const std::vector<std::string>& stream_ids)
Steve Anton47136dd2018-01-12 10:49:35 -0800386 : worker_thread_(worker_thread),
387 id_(track ? track->id() : rtc::CreateRandomUuid()),
Seth Hampson845e8782018-03-02 11:34:10 -0800388 stream_ids_(stream_ids),
Steve Anton02ee47c2018-01-10 16:26:06 -0800389 track_(track),
Seth Hampson845e8782018-03-02 11:34:10 -0800390 cached_track_content_hint_(track
391 ? track->content_hint()
392 : VideoTrackInterface::ContentHint::kNone),
Harald Alvestrandc72af932018-01-11 17:18:19 +0100393 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -0800394 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -0800395 if (track_) {
396 track_->RegisterObserver(this);
deadbeef20cb0c12017-02-01 20:27:00 -0800397 }
deadbeef20cb0c12017-02-01 20:27:00 -0800398}
399
deadbeef70ab1a12015-09-28 16:53:55 -0700400VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700401 Stop();
402}
403
404void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200405 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800406 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200407 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800408 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800409 if (can_send_track()) {
410 SetVideoSend();
411 }
deadbeef70ab1a12015-09-28 16:53:55 -0700412 }
413}
414
415bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200416 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800417 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100418 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800419 return false;
420 }
421 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100422 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
423 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700424 return false;
425 }
426 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
427
428 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800429 if (track_) {
430 track_->UnregisterObserver(this);
431 }
deadbeef70ab1a12015-09-28 16:53:55 -0700432
433 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800434 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700435 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700436 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700437 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700438 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800439 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800440 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800441 track_->RegisterObserver(this);
442 }
443
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700444 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800445 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800446 SetVideoSend();
447 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700448 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800449 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100450 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700451 return true;
452}
453
Florent Castellicebf50f2018-05-03 15:31:53 +0200454RtpParameters VideoRtpSender::GetParameters() {
Steve Anton47136dd2018-01-12 10:49:35 -0800455 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700456 return RtpParameters();
457 }
Steve Anton47136dd2018-01-12 10:49:35 -0800458 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200459 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
460 last_transaction_id_ = rtc::CreateRandomUuid();
461 result.transaction_id = last_transaction_id_.value();
462 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800463 });
deadbeefa601f5c2016-06-06 14:27:39 -0700464}
465
Zach Steinba37b4b2018-01-23 15:02:36 -0800466RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700467 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800468 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800469 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700470 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200471 if (!last_transaction_id_) {
472 LOG_AND_RETURN_ERROR(
473 RTCErrorType::INVALID_STATE,
474 "Failed to set parameters since getParameters() has never been called"
475 " on this sender");
476 }
477 if (last_transaction_id_ != parameters.transaction_id) {
478 LOG_AND_RETURN_ERROR(
479 RTCErrorType::INVALID_MODIFICATION,
480 "Failed to set parameters since the transaction_id doesn't match"
481 " the last value returned from getParameters()");
482 }
483
Seth Hampson2d2c8882018-05-16 16:02:32 -0700484 if (UnimplementedRtpParameterHasValue(parameters)) {
485 LOG_AND_RETURN_ERROR(
486 RTCErrorType::UNSUPPORTED_PARAMETER,
487 "Attempted to set an unimplemented parameter of RtpParameters.");
488 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800489 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200490 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
491 last_transaction_id_.reset();
492 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800493 });
deadbeefa601f5c2016-06-06 14:27:39 -0700494}
495
deadbeef20cb0c12017-02-01 20:27:00 -0800496rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100497 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800498 return nullptr;
499}
500
deadbeeffac06552015-11-25 11:26:01 -0800501void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200502 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800503 if (stopped_ || ssrc == ssrc_) {
504 return;
505 }
506 // If we are already sending with a particular SSRC, stop sending.
507 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700508 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800509 }
510 ssrc_ = ssrc;
511 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800512 SetVideoSend();
513 }
514}
515
deadbeef70ab1a12015-09-28 16:53:55 -0700516void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200517 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700518 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800519 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700520 return;
521 }
deadbeeffac06552015-11-25 11:26:01 -0800522 if (track_) {
523 track_->UnregisterObserver(this);
524 }
525 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700526 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800527 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100528 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800529 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700530}
531
deadbeeffac06552015-11-25 11:26:01 -0800532void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700533 RTC_DCHECK(!stopped_);
534 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800535 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100536 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700537 return;
538 }
perkj0d3eef22016-03-09 02:39:17 +0100539 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100540 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100541 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100542 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200543 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700544 }
pbos5214a0a2016-12-16 15:39:11 -0800545 switch (cached_track_content_hint_) {
546 case VideoTrackInterface::ContentHint::kNone:
547 break;
548 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100549 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800550 break;
551 case VideoTrackInterface::ContentHint::kDetailed:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100552 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800553 break;
554 }
Steve Anton47136dd2018-01-12 10:49:35 -0800555 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200556 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800557 });
558 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700559}
560
561void VideoRtpSender::ClearVideoSend() {
562 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700563 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800564 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100565 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700566 return;
567 }
568 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
569 // This the normal case when the underlying media channel has already been
570 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800571 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200572 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800573 });
deadbeef70ab1a12015-09-28 16:53:55 -0700574}
575
576} // namespace webrtc