blob: f5f8a71bc962fdb2c1ba6e5866875fe630659b1b [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"
17#include "rtc_base/checks.h"
18#include "rtc_base/helpers.h"
19#include "rtc_base/trace_event.h"
deadbeef70ab1a12015-09-28 16:53:55 -070020
21namespace webrtc {
22
23LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
24
25LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
26 rtc::CritScope lock(&lock_);
27 if (sink_)
28 sink_->OnClose();
29}
30
31void LocalAudioSinkAdapter::OnData(const void* audio_data,
32 int bits_per_sample,
33 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -080034 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -070035 size_t number_of_frames) {
36 rtc::CritScope lock(&lock_);
37 if (sink_) {
38 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
39 number_of_frames);
40 }
41}
42
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080043void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -070044 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -080045 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -070046 sink_ = sink;
47}
48
49AudioRtpSender::AudioRtpSender(AudioTrackInterface* track,
Steve Anton8ffb9c32017-08-31 15:45:38 -070050 const std::vector<std::string>& stream_ids,
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -070051 cricket::VoiceChannel* channel,
deadbeeffac06552015-11-25 11:26:01 -080052 StatsCollector* stats)
deadbeef70ab1a12015-09-28 16:53:55 -070053 : id_(track->id()),
Steve Anton8ffb9c32017-08-31 15:45:38 -070054 stream_ids_(stream_ids),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -070055 channel_(channel),
deadbeeffac06552015-11-25 11:26:01 -080056 stats_(stats),
57 track_(track),
deadbeef70ab1a12015-09-28 16:53:55 -070058 cached_track_enabled_(track->enabled()),
59 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton8ffb9c32017-08-31 15:45:38 -070060 // TODO(steveanton): Relax this constraint once more Unified Plan work is
61 // done.
62 RTC_CHECK(stream_ids_.size() == 1U);
deadbeef70ab1a12015-09-28 16:53:55 -070063 track_->RegisterObserver(this);
64 track_->AddSink(sink_adapter_.get());
deadbeef20cb0c12017-02-01 20:27:00 -080065 CreateDtmfSender();
deadbeef70ab1a12015-09-28 16:53:55 -070066}
67
deadbeefe1f9d832016-01-14 15:35:42 -080068AudioRtpSender::AudioRtpSender(AudioTrackInterface* track,
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -070069 cricket::VoiceChannel* channel,
deadbeefe1f9d832016-01-14 15:35:42 -080070 StatsCollector* stats)
71 : id_(track->id()),
Steve Anton8ffb9c32017-08-31 15:45:38 -070072 // TODO(steveanton): With Unified Plan this should be empty.
73 stream_ids_({rtc::CreateRandomUuid()}),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -070074 channel_(channel),
deadbeefe1f9d832016-01-14 15:35:42 -080075 stats_(stats),
76 track_(track),
77 cached_track_enabled_(track->enabled()),
78 sink_adapter_(new LocalAudioSinkAdapter()) {
deadbeefe1f9d832016-01-14 15:35:42 -080079 track_->RegisterObserver(this);
80 track_->AddSink(sink_adapter_.get());
deadbeef20cb0c12017-02-01 20:27:00 -080081 CreateDtmfSender();
deadbeefe1f9d832016-01-14 15:35:42 -080082}
83
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -070084AudioRtpSender::AudioRtpSender(cricket::VoiceChannel* channel,
deadbeeffac06552015-11-25 11:26:01 -080085 StatsCollector* stats)
86 : id_(rtc::CreateRandomUuid()),
Steve Anton8ffb9c32017-08-31 15:45:38 -070087 // TODO(steveanton): With Unified Plan this should be empty.
88 stream_ids_({rtc::CreateRandomUuid()}),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -070089 channel_(channel),
deadbeeffac06552015-11-25 11:26:01 -080090 stats_(stats),
deadbeef20cb0c12017-02-01 20:27:00 -080091 sink_adapter_(new LocalAudioSinkAdapter()) {
92 CreateDtmfSender();
93}
deadbeeffac06552015-11-25 11:26:01 -080094
deadbeef70ab1a12015-09-28 16:53:55 -070095AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -080096 // For DtmfSender.
97 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -070098 Stop();
99}
100
deadbeef20cb0c12017-02-01 20:27:00 -0800101bool AudioRtpSender::CanInsertDtmf() {
102 if (!channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100103 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800104 return false;
105 }
106 // Check that this RTP sender is active (description has been applied that
107 // matches an SSRC to its ID).
108 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100109 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800110 return false;
111 }
112 return channel_->CanInsertDtmf();
113}
114
115bool AudioRtpSender::InsertDtmf(int code, int duration) {
116 if (!channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100117 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800118 return false;
119 }
120 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100121 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800122 return false;
123 }
124 if (!channel_->InsertDtmf(ssrc_, code, duration)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100125 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800126 return false;
127 }
128 return true;
129}
130
131sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
132 return &SignalDestroyed;
133}
134
deadbeef70ab1a12015-09-28 16:53:55 -0700135void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200136 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800137 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700138 if (cached_track_enabled_ != track_->enabled()) {
139 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800140 if (can_send_track()) {
141 SetAudioSend();
142 }
deadbeef70ab1a12015-09-28 16:53:55 -0700143 }
144}
145
146bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200147 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800148 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100149 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800150 return false;
151 }
152 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100153 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
154 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700155 return false;
156 }
157 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
158
159 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800160 if (track_) {
161 track_->RemoveSink(sink_adapter_.get());
162 track_->UnregisterObserver(this);
163 }
164
165 if (can_send_track() && stats_) {
166 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
167 }
deadbeef70ab1a12015-09-28 16:53:55 -0700168
169 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800170 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700171 // Keep a reference to the old track to keep it alive until we call
172 // SetAudioSend.
173 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700174 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800175 if (track_) {
176 cached_track_enabled_ = track_->enabled();
177 track_->RegisterObserver(this);
178 track_->AddSink(sink_adapter_.get());
179 }
180
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700181 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800182 if (can_send_track()) {
183 SetAudioSend();
184 if (stats_) {
185 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
186 }
187 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700188 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800189 }
deadbeef70ab1a12015-09-28 16:53:55 -0700190 return true;
191}
192
deadbeefa601f5c2016-06-06 14:27:39 -0700193RtpParameters AudioRtpSender::GetParameters() const {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700194 if (!channel_ || stopped_) {
195 return RtpParameters();
196 }
197 return channel_->GetRtpSendParameters(ssrc_);
deadbeefa601f5c2016-06-06 14:27:39 -0700198}
199
200bool AudioRtpSender::SetParameters(const RtpParameters& parameters) {
201 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700202 if (!channel_ || stopped_) {
203 return false;
204 }
205 return channel_->SetRtpSendParameters(ssrc_, parameters);
deadbeefa601f5c2016-06-06 14:27:39 -0700206}
207
deadbeef20cb0c12017-02-01 20:27:00 -0800208rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
209 return dtmf_sender_proxy_;
210}
211
deadbeeffac06552015-11-25 11:26:01 -0800212void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200213 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800214 if (stopped_ || ssrc == ssrc_) {
215 return;
216 }
217 // If we are already sending with a particular SSRC, stop sending.
218 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700219 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800220 if (stats_) {
221 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
222 }
223 }
224 ssrc_ = ssrc;
225 if (can_send_track()) {
226 SetAudioSend();
227 if (stats_) {
228 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
229 }
230 }
231}
232
deadbeef70ab1a12015-09-28 16:53:55 -0700233void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200234 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700235 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800236 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700237 return;
238 }
deadbeeffac06552015-11-25 11:26:01 -0800239 if (track_) {
240 track_->RemoveSink(sink_adapter_.get());
241 track_->UnregisterObserver(this);
242 }
243 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700244 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800245 if (stats_) {
246 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
247 }
248 }
249 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700250}
251
deadbeeffac06552015-11-25 11:26:01 -0800252void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700253 RTC_DCHECK(!stopped_);
254 RTC_DCHECK(can_send_track());
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700255 if (!channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100256 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700257 return;
258 }
deadbeef70ab1a12015-09-28 16:53:55 -0700259 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800260#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100261 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
262 // PeerConnection. This is a bit of a strange way to apply local audio
263 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800264 if (track_->enabled() && track_->GetSource() &&
265 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700266 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800267 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700268 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
269 }
Tommi3c169782016-01-21 16:12:17 +0100270#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700271
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800272 cricket::AudioSource* source = sink_adapter_.get();
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700273 RTC_DCHECK(source != nullptr);
274 if (!channel_->SetAudioSend(ssrc_, track_->enabled(), &options, source)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100275 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700276 }
277}
278
279void AudioRtpSender::ClearAudioSend() {
280 RTC_DCHECK(ssrc_ != 0);
281 RTC_DCHECK(!stopped_);
282 if (!channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100283 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700284 return;
285 }
286 cricket::AudioOptions options;
287 if (!channel_->SetAudioSend(ssrc_, false, &options, nullptr)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100288 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700289 }
deadbeef70ab1a12015-09-28 16:53:55 -0700290}
291
deadbeef20cb0c12017-02-01 20:27:00 -0800292void AudioRtpSender::CreateDtmfSender() {
293 // Should be on signaling thread.
294 // TODO(deadbeef): Add thread checking to RtpSender/RtpReceiver
295 // implementations.
296 rtc::scoped_refptr<DtmfSenderInterface> sender(
297 DtmfSender::Create(track_, rtc::Thread::Current(), this));
298 if (!sender.get()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100299 RTC_LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create.";
deadbeef20cb0c12017-02-01 20:27:00 -0800300 RTC_NOTREACHED();
301 }
302 dtmf_sender_proxy_ =
303 DtmfSenderProxy::Create(rtc::Thread::Current(), sender.get());
304}
305
deadbeef70ab1a12015-09-28 16:53:55 -0700306VideoRtpSender::VideoRtpSender(VideoTrackInterface* track,
Steve Anton8ffb9c32017-08-31 15:45:38 -0700307 const std::vector<std::string>& stream_ids,
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700308 cricket::VideoChannel* channel)
deadbeef70ab1a12015-09-28 16:53:55 -0700309 : id_(track->id()),
Steve Anton8ffb9c32017-08-31 15:45:38 -0700310 stream_ids_({stream_ids}),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700311 channel_(channel),
deadbeeffac06552015-11-25 11:26:01 -0800312 track_(track),
pbos5214a0a2016-12-16 15:39:11 -0800313 cached_track_enabled_(track->enabled()),
314 cached_track_content_hint_(track->content_hint()) {
Steve Anton8ffb9c32017-08-31 15:45:38 -0700315 // TODO(steveanton): Relax this constraint once more Unified Plan work is
316 // done.
317 RTC_CHECK(stream_ids_.size() == 1U);
deadbeef70ab1a12015-09-28 16:53:55 -0700318 track_->RegisterObserver(this);
deadbeef70ab1a12015-09-28 16:53:55 -0700319}
320
deadbeefe1f9d832016-01-14 15:35:42 -0800321VideoRtpSender::VideoRtpSender(VideoTrackInterface* track,
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700322 cricket::VideoChannel* channel)
deadbeefe1f9d832016-01-14 15:35:42 -0800323 : id_(track->id()),
Steve Anton8ffb9c32017-08-31 15:45:38 -0700324 // TODO(steveanton): With Unified Plan this should be empty.
325 stream_ids_({rtc::CreateRandomUuid()}),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700326 channel_(channel),
deadbeefe1f9d832016-01-14 15:35:42 -0800327 track_(track),
pbos5214a0a2016-12-16 15:39:11 -0800328 cached_track_enabled_(track->enabled()),
329 cached_track_content_hint_(track->content_hint()) {
deadbeefe1f9d832016-01-14 15:35:42 -0800330 track_->RegisterObserver(this);
331}
332
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700333VideoRtpSender::VideoRtpSender(cricket::VideoChannel* channel)
deadbeeffac06552015-11-25 11:26:01 -0800334 : id_(rtc::CreateRandomUuid()),
Steve Anton8ffb9c32017-08-31 15:45:38 -0700335 // TODO(steveanton): With Unified Plan this should be empty.
336 stream_ids_({rtc::CreateRandomUuid()}),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700337 channel_(channel) {}
deadbeeffac06552015-11-25 11:26:01 -0800338
deadbeef70ab1a12015-09-28 16:53:55 -0700339VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700340 Stop();
341}
342
343void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200344 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800345 RTC_DCHECK(!stopped_);
pbos5214a0a2016-12-16 15:39:11 -0800346 if (cached_track_enabled_ != track_->enabled() ||
347 cached_track_content_hint_ != track_->content_hint()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700348 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800349 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800350 if (can_send_track()) {
351 SetVideoSend();
352 }
deadbeef70ab1a12015-09-28 16:53:55 -0700353 }
354}
355
356bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200357 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800358 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100359 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800360 return false;
361 }
362 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100363 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
364 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700365 return false;
366 }
367 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
368
369 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800370 if (track_) {
371 track_->UnregisterObserver(this);
372 }
deadbeef70ab1a12015-09-28 16:53:55 -0700373
374 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800375 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700376 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700377 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700378 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700379 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800380 if (track_) {
381 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800382 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800383 track_->RegisterObserver(this);
384 }
385
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700386 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800387 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800388 SetVideoSend();
389 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700390 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800391 }
deadbeef70ab1a12015-09-28 16:53:55 -0700392 return true;
393}
394
deadbeefa601f5c2016-06-06 14:27:39 -0700395RtpParameters VideoRtpSender::GetParameters() const {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700396 if (!channel_ || stopped_) {
397 return RtpParameters();
398 }
399 return channel_->GetRtpSendParameters(ssrc_);
deadbeefa601f5c2016-06-06 14:27:39 -0700400}
401
402bool VideoRtpSender::SetParameters(const RtpParameters& parameters) {
403 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700404 if (!channel_ || stopped_) {
405 return false;
406 }
407 return channel_->SetRtpSendParameters(ssrc_, parameters);
deadbeefa601f5c2016-06-06 14:27:39 -0700408}
409
deadbeef20cb0c12017-02-01 20:27:00 -0800410rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100411 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800412 return nullptr;
413}
414
deadbeeffac06552015-11-25 11:26:01 -0800415void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200416 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800417 if (stopped_ || ssrc == ssrc_) {
418 return;
419 }
420 // If we are already sending with a particular SSRC, stop sending.
421 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700422 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800423 }
424 ssrc_ = ssrc;
425 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800426 SetVideoSend();
427 }
428}
429
deadbeef70ab1a12015-09-28 16:53:55 -0700430void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200431 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700432 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800433 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700434 return;
435 }
deadbeeffac06552015-11-25 11:26:01 -0800436 if (track_) {
437 track_->UnregisterObserver(this);
438 }
439 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700440 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800441 }
442 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700443}
444
deadbeeffac06552015-11-25 11:26:01 -0800445void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700446 RTC_DCHECK(!stopped_);
447 RTC_DCHECK(can_send_track());
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700448 if (!channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100449 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700450 return;
451 }
perkj0d3eef22016-03-09 02:39:17 +0100452 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100453 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100454 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100455 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200456 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700457 }
pbos5214a0a2016-12-16 15:39:11 -0800458 switch (cached_track_content_hint_) {
459 case VideoTrackInterface::ContentHint::kNone:
460 break;
461 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100462 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800463 break;
464 case VideoTrackInterface::ContentHint::kDetailed:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100465 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800466 break;
467 }
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700468 if (!channel_->SetVideoSend(ssrc_, track_->enabled(), &options, track_)) {
nisseeb4ca4e2017-01-12 02:24:27 -0800469 RTC_NOTREACHED();
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700470 }
deadbeef5a4a75a2016-06-02 16:23:38 -0700471}
472
473void VideoRtpSender::ClearVideoSend() {
474 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700475 RTC_DCHECK(!stopped_);
476 if (!channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100477 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700478 return;
479 }
480 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
481 // This the normal case when the underlying media channel has already been
482 // deleted.
483 channel_->SetVideoSend(ssrc_, false, nullptr, nullptr);
deadbeef70ab1a12015-09-28 16:53:55 -0700484}
485
486} // namespace webrtc