blob: 6095418788c2147a4d6294c47cc3e7645417404e [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,
Steve Anton02ee47c2018-01-10 16:26:06 -080068 const std::vector<std::string>& stream_labels,
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()),
Steve Anton02ee47c2018-01-10 16:26:06 -080072 stream_ids_(stream_labels),
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 // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are
83 // supported.
84 RTC_DCHECK_EQ(stream_labels.size(), 1u);
85 if (track_) {
86 track_->RegisterObserver(this);
87 track_->AddSink(sink_adapter_.get());
88 }
deadbeef20cb0c12017-02-01 20:27:00 -080089}
deadbeeffac06552015-11-25 11:26:01 -080090
deadbeef70ab1a12015-09-28 16:53:55 -070091AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -080092 // For DtmfSender.
93 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -070094 Stop();
95}
96
deadbeef20cb0c12017-02-01 20:27:00 -080097bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -080098 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010099 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800100 return false;
101 }
102 // Check that this RTP sender is active (description has been applied that
103 // matches an SSRC to its ID).
104 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100105 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800106 return false;
107 }
Steve Anton47136dd2018-01-12 10:49:35 -0800108 return worker_thread_->Invoke<bool>(
109 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800110}
111
112bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800113 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100114 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800115 return false;
116 }
117 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100118 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800119 return false;
120 }
Steve Anton47136dd2018-01-12 10:49:35 -0800121 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
122 return media_channel_->InsertDtmf(ssrc_, code, duration);
123 });
124 if (!success) {
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 }
Steve Anton47136dd2018-01-12 10:49:35 -0800127 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800128}
129
130sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
131 return &SignalDestroyed;
132}
133
deadbeef70ab1a12015-09-28 16:53:55 -0700134void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200135 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800136 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700137 if (cached_track_enabled_ != track_->enabled()) {
138 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800139 if (can_send_track()) {
140 SetAudioSend();
141 }
deadbeef70ab1a12015-09-28 16:53:55 -0700142 }
143}
144
145bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200146 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800147 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100148 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800149 return false;
150 }
151 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
153 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700154 return false;
155 }
156 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
157
158 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800159 if (track_) {
160 track_->RemoveSink(sink_adapter_.get());
161 track_->UnregisterObserver(this);
162 }
163
164 if (can_send_track() && stats_) {
165 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
166 }
deadbeef70ab1a12015-09-28 16:53:55 -0700167
168 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800169 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700170 // Keep a reference to the old track to keep it alive until we call
171 // SetAudioSend.
172 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700173 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800174 if (track_) {
175 cached_track_enabled_ = track_->enabled();
176 track_->RegisterObserver(this);
177 track_->AddSink(sink_adapter_.get());
178 }
179
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700180 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800181 if (can_send_track()) {
182 SetAudioSend();
183 if (stats_) {
184 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
185 }
186 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700187 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800188 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100189 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700190 return true;
191}
192
deadbeefa601f5c2016-06-06 14:27:39 -0700193RtpParameters AudioRtpSender::GetParameters() const {
Steve Anton47136dd2018-01-12 10:49:35 -0800194 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700195 return RtpParameters();
196 }
Steve Anton47136dd2018-01-12 10:49:35 -0800197 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
198 return media_channel_->GetRtpSendParameters(ssrc_);
199 });
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 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800207 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Steve Anton47136dd2018-01-12 10:49:35 -0800208 return media_channel_->SetRtpSendParameters(ssrc_, parameters);
209 });
deadbeefa601f5c2016-06-06 14:27:39 -0700210}
211
deadbeef20cb0c12017-02-01 20:27:00 -0800212rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
213 return dtmf_sender_proxy_;
214}
215
deadbeeffac06552015-11-25 11:26:01 -0800216void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200217 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800218 if (stopped_ || ssrc == ssrc_) {
219 return;
220 }
221 // If we are already sending with a particular SSRC, stop sending.
222 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700223 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800224 if (stats_) {
225 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
226 }
227 }
228 ssrc_ = ssrc;
229 if (can_send_track()) {
230 SetAudioSend();
231 if (stats_) {
232 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
233 }
234 }
235}
236
deadbeef70ab1a12015-09-28 16:53:55 -0700237void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200238 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700239 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800240 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700241 return;
242 }
deadbeeffac06552015-11-25 11:26:01 -0800243 if (track_) {
244 track_->RemoveSink(sink_adapter_.get());
245 track_->UnregisterObserver(this);
246 }
247 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700248 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800249 if (stats_) {
250 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
251 }
252 }
253 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700254}
255
deadbeeffac06552015-11-25 11:26:01 -0800256void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700257 RTC_DCHECK(!stopped_);
258 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800259 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100260 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700261 return;
262 }
deadbeef70ab1a12015-09-28 16:53:55 -0700263 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800264#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100265 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
266 // PeerConnection. This is a bit of a strange way to apply local audio
267 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800268 if (track_->enabled() && track_->GetSource() &&
269 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700270 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800271 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700272 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
273 }
Tommi3c169782016-01-21 16:12:17 +0100274#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700275
Steve Anton47136dd2018-01-12 10:49:35 -0800276 // |track_->enabled()| hops to the signaling thread, so call it before we hop
277 // to the worker thread or else it will deadlock.
278 bool track_enabled = track_->enabled();
279 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
280 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
281 sink_adapter_.get());
282 });
283 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100284 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700285 }
286}
287
288void AudioRtpSender::ClearAudioSend() {
289 RTC_DCHECK(ssrc_ != 0);
290 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800291 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100292 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700293 return;
294 }
295 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800296 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
297 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
298 });
299 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100300 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700301 }
deadbeef70ab1a12015-09-28 16:53:55 -0700302}
303
Steve Anton47136dd2018-01-12 10:49:35 -0800304VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread)
305 : VideoRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}) {}
Steve Anton02ee47c2018-01-10 16:26:06 -0800306
Steve Anton47136dd2018-01-12 10:49:35 -0800307VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
308 rtc::scoped_refptr<VideoTrackInterface> track,
Steve Anton02ee47c2018-01-10 16:26:06 -0800309 const std::vector<std::string>& stream_labels)
Steve Anton47136dd2018-01-12 10:49:35 -0800310 : worker_thread_(worker_thread),
311 id_(track ? track->id() : rtc::CreateRandomUuid()),
Steve Anton02ee47c2018-01-10 16:26:06 -0800312 stream_ids_(stream_labels),
313 track_(track),
314 cached_track_enabled_(track ? track->enabled() : false),
Steve Anton47136dd2018-01-12 10:49:35 -0800315 cached_track_content_hint_(
316 track ? track->content_hint()
317 : VideoTrackInterface::ContentHint::kNone),
Harald Alvestrandc72af932018-01-11 17:18:19 +0100318 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -0800319 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -0800320 // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are
321 // supported.
322 RTC_DCHECK_EQ(stream_labels.size(), 1u);
323 if (track_) {
324 track_->RegisterObserver(this);
deadbeef20cb0c12017-02-01 20:27:00 -0800325 }
deadbeef20cb0c12017-02-01 20:27:00 -0800326}
327
deadbeef70ab1a12015-09-28 16:53:55 -0700328VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700329 Stop();
330}
331
332void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200333 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800334 RTC_DCHECK(!stopped_);
pbos5214a0a2016-12-16 15:39:11 -0800335 if (cached_track_enabled_ != track_->enabled() ||
336 cached_track_content_hint_ != track_->content_hint()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700337 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800338 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800339 if (can_send_track()) {
340 SetVideoSend();
341 }
deadbeef70ab1a12015-09-28 16:53:55 -0700342 }
343}
344
345bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200346 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800347 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100348 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800349 return false;
350 }
351 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100352 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
353 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700354 return false;
355 }
356 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
357
358 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800359 if (track_) {
360 track_->UnregisterObserver(this);
361 }
deadbeef70ab1a12015-09-28 16:53:55 -0700362
363 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800364 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700365 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700366 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700367 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700368 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800369 if (track_) {
370 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800371 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800372 track_->RegisterObserver(this);
373 }
374
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700375 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800376 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800377 SetVideoSend();
378 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700379 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800380 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100381 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700382 return true;
383}
384
deadbeefa601f5c2016-06-06 14:27:39 -0700385RtpParameters VideoRtpSender::GetParameters() const {
Steve Anton47136dd2018-01-12 10:49:35 -0800386 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700387 return RtpParameters();
388 }
Steve Anton47136dd2018-01-12 10:49:35 -0800389 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
390 return media_channel_->GetRtpSendParameters(ssrc_);
391 });
deadbeefa601f5c2016-06-06 14:27:39 -0700392}
393
Zach Steinba37b4b2018-01-23 15:02:36 -0800394RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700395 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800396 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800397 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700398 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800399 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Steve Anton47136dd2018-01-12 10:49:35 -0800400 return media_channel_->SetRtpSendParameters(ssrc_, parameters);
401 });
deadbeefa601f5c2016-06-06 14:27:39 -0700402}
403
deadbeef20cb0c12017-02-01 20:27:00 -0800404rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100405 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800406 return nullptr;
407}
408
deadbeeffac06552015-11-25 11:26:01 -0800409void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200410 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800411 if (stopped_ || ssrc == ssrc_) {
412 return;
413 }
414 // If we are already sending with a particular SSRC, stop sending.
415 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700416 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800417 }
418 ssrc_ = ssrc;
419 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800420 SetVideoSend();
421 }
422}
423
deadbeef70ab1a12015-09-28 16:53:55 -0700424void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200425 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700426 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800427 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700428 return;
429 }
deadbeeffac06552015-11-25 11:26:01 -0800430 if (track_) {
431 track_->UnregisterObserver(this);
432 }
433 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700434 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800435 }
436 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700437}
438
deadbeeffac06552015-11-25 11:26:01 -0800439void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700440 RTC_DCHECK(!stopped_);
441 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800442 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100443 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700444 return;
445 }
perkj0d3eef22016-03-09 02:39:17 +0100446 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100447 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100448 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100449 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200450 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700451 }
pbos5214a0a2016-12-16 15:39:11 -0800452 switch (cached_track_content_hint_) {
453 case VideoTrackInterface::ContentHint::kNone:
454 break;
455 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100456 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800457 break;
458 case VideoTrackInterface::ContentHint::kDetailed:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100459 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800460 break;
461 }
Steve Anton47136dd2018-01-12 10:49:35 -0800462 // |track_->enabled()| hops to the signaling thread, so call it before we hop
463 // to the worker thread or else it will deadlock.
464 bool track_enabled = track_->enabled();
465 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
466 return media_channel_->SetVideoSend(ssrc_, track_enabled, &options, track_);
467 });
468 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700469}
470
471void VideoRtpSender::ClearVideoSend() {
472 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700473 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800474 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100475 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700476 return;
477 }
478 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
479 // This the normal case when the underlying media channel has already been
480 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800481 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
482 return media_channel_->SetVideoSend(ssrc_, false, nullptr, nullptr);
483 });
deadbeef70ab1a12015-09-28 16:53:55 -0700484}
485
486} // namespace webrtc