blob: 3b0bbf886aab618d8fa568b830f872e4f0d99ac2 [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
33} // namespace
34
deadbeef70ab1a12015-09-28 16:53:55 -070035LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
36
37LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
38 rtc::CritScope lock(&lock_);
39 if (sink_)
40 sink_->OnClose();
41}
42
43void LocalAudioSinkAdapter::OnData(const void* audio_data,
44 int bits_per_sample,
45 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -080046 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -070047 size_t number_of_frames) {
48 rtc::CritScope lock(&lock_);
49 if (sink_) {
50 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
51 number_of_frames);
52 }
53}
54
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080055void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -070056 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -080057 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -070058 sink_ = sink;
59}
60
Steve Anton47136dd2018-01-12 10:49:35 -080061AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
62 StatsCollector* stats)
63 : AudioRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}, stats) {
64}
deadbeef70ab1a12015-09-28 16:53:55 -070065
Steve Anton47136dd2018-01-12 10:49:35 -080066AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
67 rtc::scoped_refptr<AudioTrackInterface> track,
Seth Hampson845e8782018-03-02 11:34:10 -080068 const std::vector<std::string>& stream_ids,
deadbeefe1f9d832016-01-14 15:35:42 -080069 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -080070 : worker_thread_(worker_thread),
71 id_(track ? track->id() : rtc::CreateRandomUuid()),
Seth Hampson845e8782018-03-02 11:34:10 -080072 stream_ids_(stream_ids),
deadbeefe1f9d832016-01-14 15:35:42 -080073 stats_(stats),
74 track_(track),
Steve Anton02ee47c2018-01-10 16:26:06 -080075 dtmf_sender_proxy_(DtmfSenderProxy::Create(
76 rtc::Thread::Current(),
77 DtmfSender::Create(track_, rtc::Thread::Current(), this))),
78 cached_track_enabled_(track ? track->enabled() : false),
Harald Alvestrandc72af932018-01-11 17:18:19 +010079 sink_adapter_(new LocalAudioSinkAdapter()),
80 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -080081 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -080082 if (track_) {
83 track_->RegisterObserver(this);
84 track_->AddSink(sink_adapter_.get());
85 }
deadbeef20cb0c12017-02-01 20:27:00 -080086}
deadbeeffac06552015-11-25 11:26:01 -080087
deadbeef70ab1a12015-09-28 16:53:55 -070088AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -080089 // For DtmfSender.
90 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -070091 Stop();
92}
93
deadbeef20cb0c12017-02-01 20:27:00 -080094bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -080095 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010096 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -080097 return false;
98 }
99 // Check that this RTP sender is active (description has been applied that
100 // matches an SSRC to its ID).
101 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100102 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800103 return false;
104 }
Steve Anton47136dd2018-01-12 10:49:35 -0800105 return worker_thread_->Invoke<bool>(
106 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800107}
108
109bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800110 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100111 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800112 return false;
113 }
114 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100115 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800116 return false;
117 }
Steve Anton47136dd2018-01-12 10:49:35 -0800118 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
119 return media_channel_->InsertDtmf(ssrc_, code, duration);
120 });
121 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100122 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800123 }
Steve Anton47136dd2018-01-12 10:49:35 -0800124 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800125}
126
127sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
128 return &SignalDestroyed;
129}
130
deadbeef70ab1a12015-09-28 16:53:55 -0700131void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200132 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800133 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700134 if (cached_track_enabled_ != track_->enabled()) {
135 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800136 if (can_send_track()) {
137 SetAudioSend();
138 }
deadbeef70ab1a12015-09-28 16:53:55 -0700139 }
140}
141
142bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200143 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800144 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100145 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800146 return false;
147 }
148 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100149 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
150 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700151 return false;
152 }
153 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
154
155 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800156 if (track_) {
157 track_->RemoveSink(sink_adapter_.get());
158 track_->UnregisterObserver(this);
159 }
160
161 if (can_send_track() && stats_) {
162 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
163 }
deadbeef70ab1a12015-09-28 16:53:55 -0700164
165 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800166 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700167 // Keep a reference to the old track to keep it alive until we call
168 // SetAudioSend.
169 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700170 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800171 if (track_) {
172 cached_track_enabled_ = track_->enabled();
173 track_->RegisterObserver(this);
174 track_->AddSink(sink_adapter_.get());
175 }
176
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700177 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800178 if (can_send_track()) {
179 SetAudioSend();
180 if (stats_) {
181 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
182 }
183 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700184 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800185 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100186 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700187 return true;
188}
189
Florent Castellicebf50f2018-05-03 15:31:53 +0200190RtpParameters AudioRtpSender::GetParameters() {
Steve Anton47136dd2018-01-12 10:49:35 -0800191 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700192 return RtpParameters();
193 }
Steve Anton47136dd2018-01-12 10:49:35 -0800194 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200195 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
196 last_transaction_id_ = rtc::CreateRandomUuid();
197 result.transaction_id = last_transaction_id_.value();
198 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800199 });
deadbeefa601f5c2016-06-06 14:27:39 -0700200}
201
Zach Steinba37b4b2018-01-23 15:02:36 -0800202RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700203 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800204 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800205 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700206 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200207 if (!last_transaction_id_) {
208 LOG_AND_RETURN_ERROR(
209 RTCErrorType::INVALID_STATE,
210 "Failed to set parameters since getParameters() has never been called"
211 " on this sender");
212 }
213 if (last_transaction_id_ != parameters.transaction_id) {
214 LOG_AND_RETURN_ERROR(
215 RTCErrorType::INVALID_MODIFICATION,
216 "Failed to set parameters since the transaction_id doesn't match"
217 " the last value returned from getParameters()");
218 }
219
Zach Steinba37b4b2018-01-23 15:02:36 -0800220 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200221 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
222 last_transaction_id_.reset();
223 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800224 });
deadbeefa601f5c2016-06-06 14:27:39 -0700225}
226
deadbeef20cb0c12017-02-01 20:27:00 -0800227rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
228 return dtmf_sender_proxy_;
229}
230
deadbeeffac06552015-11-25 11:26:01 -0800231void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200232 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800233 if (stopped_ || ssrc == ssrc_) {
234 return;
235 }
236 // If we are already sending with a particular SSRC, stop sending.
237 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700238 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800239 if (stats_) {
240 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
241 }
242 }
243 ssrc_ = ssrc;
244 if (can_send_track()) {
245 SetAudioSend();
246 if (stats_) {
247 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
248 }
249 }
250}
251
deadbeef70ab1a12015-09-28 16:53:55 -0700252void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200253 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700254 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800255 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700256 return;
257 }
deadbeeffac06552015-11-25 11:26:01 -0800258 if (track_) {
259 track_->RemoveSink(sink_adapter_.get());
260 track_->UnregisterObserver(this);
261 }
262 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700263 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800264 if (stats_) {
265 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
266 }
267 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100268 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800269 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700270}
271
deadbeeffac06552015-11-25 11:26:01 -0800272void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700273 RTC_DCHECK(!stopped_);
274 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800275 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100276 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700277 return;
278 }
deadbeef70ab1a12015-09-28 16:53:55 -0700279 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800280#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100281 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
282 // PeerConnection. This is a bit of a strange way to apply local audio
283 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800284 if (track_->enabled() && track_->GetSource() &&
285 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700286 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800287 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700288 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
289 }
Tommi3c169782016-01-21 16:12:17 +0100290#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700291
Steve Anton47136dd2018-01-12 10:49:35 -0800292 // |track_->enabled()| hops to the signaling thread, so call it before we hop
293 // to the worker thread or else it will deadlock.
294 bool track_enabled = track_->enabled();
295 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
296 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
297 sink_adapter_.get());
298 });
299 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100300 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700301 }
302}
303
304void AudioRtpSender::ClearAudioSend() {
305 RTC_DCHECK(ssrc_ != 0);
306 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800307 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100308 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700309 return;
310 }
311 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800312 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
313 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
314 });
315 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100316 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700317 }
deadbeef70ab1a12015-09-28 16:53:55 -0700318}
319
Steve Anton47136dd2018-01-12 10:49:35 -0800320VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread)
321 : VideoRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}) {}
Steve Anton02ee47c2018-01-10 16:26:06 -0800322
Steve Anton47136dd2018-01-12 10:49:35 -0800323VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
324 rtc::scoped_refptr<VideoTrackInterface> track,
Seth Hampson845e8782018-03-02 11:34:10 -0800325 const std::vector<std::string>& stream_ids)
Steve Anton47136dd2018-01-12 10:49:35 -0800326 : worker_thread_(worker_thread),
327 id_(track ? track->id() : rtc::CreateRandomUuid()),
Seth Hampson845e8782018-03-02 11:34:10 -0800328 stream_ids_(stream_ids),
Steve Anton02ee47c2018-01-10 16:26:06 -0800329 track_(track),
Seth Hampson845e8782018-03-02 11:34:10 -0800330 cached_track_content_hint_(track
331 ? track->content_hint()
332 : VideoTrackInterface::ContentHint::kNone),
Harald Alvestrandc72af932018-01-11 17:18:19 +0100333 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -0800334 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -0800335 if (track_) {
336 track_->RegisterObserver(this);
deadbeef20cb0c12017-02-01 20:27:00 -0800337 }
deadbeef20cb0c12017-02-01 20:27:00 -0800338}
339
deadbeef70ab1a12015-09-28 16:53:55 -0700340VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700341 Stop();
342}
343
344void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200345 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800346 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200347 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800348 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800349 if (can_send_track()) {
350 SetVideoSend();
351 }
deadbeef70ab1a12015-09-28 16:53:55 -0700352 }
353}
354
355bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200356 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800357 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100358 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800359 return false;
360 }
361 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100362 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
363 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700364 return false;
365 }
366 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
367
368 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800369 if (track_) {
370 track_->UnregisterObserver(this);
371 }
deadbeef70ab1a12015-09-28 16:53:55 -0700372
373 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800374 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700375 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700376 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700377 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700378 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800379 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800380 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800381 track_->RegisterObserver(this);
382 }
383
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700384 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800385 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800386 SetVideoSend();
387 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700388 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800389 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100390 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700391 return true;
392}
393
Florent Castellicebf50f2018-05-03 15:31:53 +0200394RtpParameters VideoRtpSender::GetParameters() {
Steve Anton47136dd2018-01-12 10:49:35 -0800395 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700396 return RtpParameters();
397 }
Steve Anton47136dd2018-01-12 10:49:35 -0800398 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200399 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
400 last_transaction_id_ = rtc::CreateRandomUuid();
401 result.transaction_id = last_transaction_id_.value();
402 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800403 });
deadbeefa601f5c2016-06-06 14:27:39 -0700404}
405
Zach Steinba37b4b2018-01-23 15:02:36 -0800406RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700407 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800408 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800409 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700410 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200411 if (!last_transaction_id_) {
412 LOG_AND_RETURN_ERROR(
413 RTCErrorType::INVALID_STATE,
414 "Failed to set parameters since getParameters() has never been called"
415 " on this sender");
416 }
417 if (last_transaction_id_ != parameters.transaction_id) {
418 LOG_AND_RETURN_ERROR(
419 RTCErrorType::INVALID_MODIFICATION,
420 "Failed to set parameters since the transaction_id doesn't match"
421 " the last value returned from getParameters()");
422 }
423
Zach Steinba37b4b2018-01-23 15:02:36 -0800424 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200425 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
426 last_transaction_id_.reset();
427 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800428 });
deadbeefa601f5c2016-06-06 14:27:39 -0700429}
430
deadbeef20cb0c12017-02-01 20:27:00 -0800431rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100432 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800433 return nullptr;
434}
435
deadbeeffac06552015-11-25 11:26:01 -0800436void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200437 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800438 if (stopped_ || ssrc == ssrc_) {
439 return;
440 }
441 // If we are already sending with a particular SSRC, stop sending.
442 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700443 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800444 }
445 ssrc_ = ssrc;
446 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800447 SetVideoSend();
448 }
449}
450
deadbeef70ab1a12015-09-28 16:53:55 -0700451void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200452 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700453 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800454 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700455 return;
456 }
deadbeeffac06552015-11-25 11:26:01 -0800457 if (track_) {
458 track_->UnregisterObserver(this);
459 }
460 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700461 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800462 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100463 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800464 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700465}
466
deadbeeffac06552015-11-25 11:26:01 -0800467void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700468 RTC_DCHECK(!stopped_);
469 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800470 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100471 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700472 return;
473 }
perkj0d3eef22016-03-09 02:39:17 +0100474 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100475 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100476 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100477 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200478 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700479 }
pbos5214a0a2016-12-16 15:39:11 -0800480 switch (cached_track_content_hint_) {
481 case VideoTrackInterface::ContentHint::kNone:
482 break;
483 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100484 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800485 break;
486 case VideoTrackInterface::ContentHint::kDetailed:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100487 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800488 break;
489 }
Steve Anton47136dd2018-01-12 10:49:35 -0800490 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200491 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800492 });
493 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700494}
495
496void VideoRtpSender::ClearVideoSend() {
497 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700498 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800499 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100500 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700501 return;
502 }
503 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
504 // This the normal case when the underlying media channel has already been
505 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800506 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200507 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800508 });
deadbeef70ab1a12015-09-28 16:53:55 -0700509}
510
511} // namespace webrtc