blob: 626c850505aa9e5514ec1af6e3b8d9d09d6307d6 [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
deadbeefa601f5c2016-06-06 14:27:39 -0700190RtpParameters AudioRtpSender::GetParameters() const {
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, [&] {
195 return media_channel_->GetRtpSendParameters(ssrc_);
196 });
deadbeefa601f5c2016-06-06 14:27:39 -0700197}
198
Zach Steinba37b4b2018-01-23 15:02:36 -0800199RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700200 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800201 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800202 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700203 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800204 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Steve Anton47136dd2018-01-12 10:49:35 -0800205 return media_channel_->SetRtpSendParameters(ssrc_, parameters);
206 });
deadbeefa601f5c2016-06-06 14:27:39 -0700207}
208
deadbeef20cb0c12017-02-01 20:27:00 -0800209rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
210 return dtmf_sender_proxy_;
211}
212
deadbeeffac06552015-11-25 11:26:01 -0800213void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200214 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800215 if (stopped_ || ssrc == ssrc_) {
216 return;
217 }
218 // If we are already sending with a particular SSRC, stop sending.
219 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700220 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800221 if (stats_) {
222 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
223 }
224 }
225 ssrc_ = ssrc;
226 if (can_send_track()) {
227 SetAudioSend();
228 if (stats_) {
229 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
230 }
231 }
232}
233
deadbeef70ab1a12015-09-28 16:53:55 -0700234void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200235 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700236 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800237 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700238 return;
239 }
deadbeeffac06552015-11-25 11:26:01 -0800240 if (track_) {
241 track_->RemoveSink(sink_adapter_.get());
242 track_->UnregisterObserver(this);
243 }
244 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700245 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800246 if (stats_) {
247 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
248 }
249 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100250 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800251 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700252}
253
deadbeeffac06552015-11-25 11:26:01 -0800254void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700255 RTC_DCHECK(!stopped_);
256 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800257 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100258 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700259 return;
260 }
deadbeef70ab1a12015-09-28 16:53:55 -0700261 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800262#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100263 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
264 // PeerConnection. This is a bit of a strange way to apply local audio
265 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800266 if (track_->enabled() && track_->GetSource() &&
267 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700268 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800269 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700270 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
271 }
Tommi3c169782016-01-21 16:12:17 +0100272#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700273
Steve Anton47136dd2018-01-12 10:49:35 -0800274 // |track_->enabled()| hops to the signaling thread, so call it before we hop
275 // to the worker thread or else it will deadlock.
276 bool track_enabled = track_->enabled();
277 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
278 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
279 sink_adapter_.get());
280 });
281 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100282 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700283 }
284}
285
286void AudioRtpSender::ClearAudioSend() {
287 RTC_DCHECK(ssrc_ != 0);
288 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800289 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100290 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700291 return;
292 }
293 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800294 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
295 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
296 });
297 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100298 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700299 }
deadbeef70ab1a12015-09-28 16:53:55 -0700300}
301
Steve Anton47136dd2018-01-12 10:49:35 -0800302VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread)
303 : VideoRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}) {}
Steve Anton02ee47c2018-01-10 16:26:06 -0800304
Steve Anton47136dd2018-01-12 10:49:35 -0800305VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
306 rtc::scoped_refptr<VideoTrackInterface> track,
Seth Hampson845e8782018-03-02 11:34:10 -0800307 const std::vector<std::string>& stream_ids)
Steve Anton47136dd2018-01-12 10:49:35 -0800308 : worker_thread_(worker_thread),
309 id_(track ? track->id() : rtc::CreateRandomUuid()),
Seth Hampson845e8782018-03-02 11:34:10 -0800310 stream_ids_(stream_ids),
Steve Anton02ee47c2018-01-10 16:26:06 -0800311 track_(track),
312 cached_track_enabled_(track ? track->enabled() : false),
Seth Hampson845e8782018-03-02 11:34:10 -0800313 cached_track_content_hint_(track
314 ? track->content_hint()
315 : VideoTrackInterface::ContentHint::kNone),
Harald Alvestrandc72af932018-01-11 17:18:19 +0100316 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -0800317 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -0800318 if (track_) {
319 track_->RegisterObserver(this);
deadbeef20cb0c12017-02-01 20:27:00 -0800320 }
deadbeef20cb0c12017-02-01 20:27:00 -0800321}
322
deadbeef70ab1a12015-09-28 16:53:55 -0700323VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700324 Stop();
325}
326
327void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200328 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800329 RTC_DCHECK(!stopped_);
pbos5214a0a2016-12-16 15:39:11 -0800330 if (cached_track_enabled_ != track_->enabled() ||
331 cached_track_content_hint_ != track_->content_hint()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700332 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800333 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800334 if (can_send_track()) {
335 SetVideoSend();
336 }
deadbeef70ab1a12015-09-28 16:53:55 -0700337 }
338}
339
340bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200341 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800342 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100343 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800344 return false;
345 }
346 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100347 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
348 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700349 return false;
350 }
351 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
352
353 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800354 if (track_) {
355 track_->UnregisterObserver(this);
356 }
deadbeef70ab1a12015-09-28 16:53:55 -0700357
358 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800359 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700360 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700361 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700362 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700363 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800364 if (track_) {
365 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800366 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800367 track_->RegisterObserver(this);
368 }
369
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700370 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800371 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800372 SetVideoSend();
373 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700374 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800375 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100376 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700377 return true;
378}
379
deadbeefa601f5c2016-06-06 14:27:39 -0700380RtpParameters VideoRtpSender::GetParameters() const {
Steve Anton47136dd2018-01-12 10:49:35 -0800381 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700382 return RtpParameters();
383 }
Steve Anton47136dd2018-01-12 10:49:35 -0800384 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
385 return media_channel_->GetRtpSendParameters(ssrc_);
386 });
deadbeefa601f5c2016-06-06 14:27:39 -0700387}
388
Zach Steinba37b4b2018-01-23 15:02:36 -0800389RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700390 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800391 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800392 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700393 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800394 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Steve Anton47136dd2018-01-12 10:49:35 -0800395 return media_channel_->SetRtpSendParameters(ssrc_, parameters);
396 });
deadbeefa601f5c2016-06-06 14:27:39 -0700397}
398
deadbeef20cb0c12017-02-01 20:27:00 -0800399rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100400 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800401 return nullptr;
402}
403
deadbeeffac06552015-11-25 11:26:01 -0800404void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200405 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800406 if (stopped_ || ssrc == ssrc_) {
407 return;
408 }
409 // If we are already sending with a particular SSRC, stop sending.
410 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700411 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800412 }
413 ssrc_ = ssrc;
414 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800415 SetVideoSend();
416 }
417}
418
deadbeef70ab1a12015-09-28 16:53:55 -0700419void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200420 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700421 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800422 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700423 return;
424 }
deadbeeffac06552015-11-25 11:26:01 -0800425 if (track_) {
426 track_->UnregisterObserver(this);
427 }
428 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700429 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800430 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100431 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800432 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700433}
434
deadbeeffac06552015-11-25 11:26:01 -0800435void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700436 RTC_DCHECK(!stopped_);
437 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800438 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100439 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700440 return;
441 }
perkj0d3eef22016-03-09 02:39:17 +0100442 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100443 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100444 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100445 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200446 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700447 }
pbos5214a0a2016-12-16 15:39:11 -0800448 switch (cached_track_content_hint_) {
449 case VideoTrackInterface::ContentHint::kNone:
450 break;
451 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100452 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800453 break;
454 case VideoTrackInterface::ContentHint::kDetailed:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100455 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800456 break;
457 }
Steve Anton47136dd2018-01-12 10:49:35 -0800458 // |track_->enabled()| hops to the signaling thread, so call it before we hop
459 // to the worker thread or else it will deadlock.
460 bool track_enabled = track_->enabled();
461 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
462 return media_channel_->SetVideoSend(ssrc_, track_enabled, &options, track_);
463 });
464 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700465}
466
467void VideoRtpSender::ClearVideoSend() {
468 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700469 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800470 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100471 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700472 return;
473 }
474 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
475 // This the normal case when the underlying media channel has already been
476 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800477 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
478 return media_channel_->SetVideoSend(ssrc_, false, nullptr, nullptr);
479 });
deadbeef70ab1a12015-09-28 16:53:55 -0700480}
481
482} // namespace webrtc