blob: 170aa9c5075d91a2baec69ef1bae20da1a1b5206 [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 // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are
83 // supported.
Seth Hampson845e8782018-03-02 11:34:10 -080084 RTC_DCHECK_EQ(stream_ids.size(), 1u);
Steve Anton02ee47c2018-01-10 16:26:06 -080085 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_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100114 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800115 return false;
116 }
117 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100118 RTC_LOG(LS_ERROR) << "InsertDtmf: 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 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100253 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800254 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700255}
256
deadbeeffac06552015-11-25 11:26:01 -0800257void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700258 RTC_DCHECK(!stopped_);
259 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800260 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100261 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700262 return;
263 }
deadbeef70ab1a12015-09-28 16:53:55 -0700264 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800265#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100266 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
267 // PeerConnection. This is a bit of a strange way to apply local audio
268 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800269 if (track_->enabled() && track_->GetSource() &&
270 !track_->GetSource()->remote()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700271 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800272 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700273 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
274 }
Tommi3c169782016-01-21 16:12:17 +0100275#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700276
Steve Anton47136dd2018-01-12 10:49:35 -0800277 // |track_->enabled()| hops to the signaling thread, so call it before we hop
278 // to the worker thread or else it will deadlock.
279 bool track_enabled = track_->enabled();
280 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
281 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
282 sink_adapter_.get());
283 });
284 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100285 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700286 }
287}
288
289void AudioRtpSender::ClearAudioSend() {
290 RTC_DCHECK(ssrc_ != 0);
291 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800292 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100293 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700294 return;
295 }
296 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800297 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
298 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
299 });
300 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100301 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700302 }
deadbeef70ab1a12015-09-28 16:53:55 -0700303}
304
Steve Anton47136dd2018-01-12 10:49:35 -0800305VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread)
306 : VideoRtpSender(worker_thread, nullptr, {rtc::CreateRandomUuid()}) {}
Steve Anton02ee47c2018-01-10 16:26:06 -0800307
Steve Anton47136dd2018-01-12 10:49:35 -0800308VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
309 rtc::scoped_refptr<VideoTrackInterface> track,
Seth Hampson845e8782018-03-02 11:34:10 -0800310 const std::vector<std::string>& stream_ids)
Steve Anton47136dd2018-01-12 10:49:35 -0800311 : worker_thread_(worker_thread),
312 id_(track ? track->id() : rtc::CreateRandomUuid()),
Seth Hampson845e8782018-03-02 11:34:10 -0800313 stream_ids_(stream_ids),
Steve Anton02ee47c2018-01-10 16:26:06 -0800314 track_(track),
315 cached_track_enabled_(track ? track->enabled() : false),
Seth Hampson845e8782018-03-02 11:34:10 -0800316 cached_track_content_hint_(track
317 ? track->content_hint()
318 : VideoTrackInterface::ContentHint::kNone),
Harald Alvestrandc72af932018-01-11 17:18:19 +0100319 attachment_id_(track ? GenerateUniqueId() : 0) {
Steve Anton47136dd2018-01-12 10:49:35 -0800320 RTC_DCHECK(worker_thread);
Steve Anton02ee47c2018-01-10 16:26:06 -0800321 // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are
322 // supported.
Seth Hampson845e8782018-03-02 11:34:10 -0800323 RTC_DCHECK_EQ(stream_ids.size(), 1u);
Steve Anton02ee47c2018-01-10 16:26:06 -0800324 if (track_) {
325 track_->RegisterObserver(this);
deadbeef20cb0c12017-02-01 20:27:00 -0800326 }
deadbeef20cb0c12017-02-01 20:27:00 -0800327}
328
deadbeef70ab1a12015-09-28 16:53:55 -0700329VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700330 Stop();
331}
332
333void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200334 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800335 RTC_DCHECK(!stopped_);
pbos5214a0a2016-12-16 15:39:11 -0800336 if (cached_track_enabled_ != track_->enabled() ||
337 cached_track_content_hint_ != track_->content_hint()) {
deadbeef70ab1a12015-09-28 16:53:55 -0700338 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800339 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800340 if (can_send_track()) {
341 SetVideoSend();
342 }
deadbeef70ab1a12015-09-28 16:53:55 -0700343 }
344}
345
346bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200347 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800348 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100349 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800350 return false;
351 }
352 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100353 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
354 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700355 return false;
356 }
357 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
358
359 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800360 if (track_) {
361 track_->UnregisterObserver(this);
362 }
deadbeef70ab1a12015-09-28 16:53:55 -0700363
364 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800365 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700366 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700367 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700368 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700369 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800370 if (track_) {
371 cached_track_enabled_ = track_->enabled();
pbos5214a0a2016-12-16 15:39:11 -0800372 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800373 track_->RegisterObserver(this);
374 }
375
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700376 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800377 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800378 SetVideoSend();
379 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700380 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800381 }
Harald Alvestrandc72af932018-01-11 17:18:19 +0100382 attachment_id_ = GenerateUniqueId();
deadbeef70ab1a12015-09-28 16:53:55 -0700383 return true;
384}
385
deadbeefa601f5c2016-06-06 14:27:39 -0700386RtpParameters VideoRtpSender::GetParameters() const {
Steve Anton47136dd2018-01-12 10:49:35 -0800387 if (!media_channel_ || stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700388 return RtpParameters();
389 }
Steve Anton47136dd2018-01-12 10:49:35 -0800390 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
391 return media_channel_->GetRtpSendParameters(ssrc_);
392 });
deadbeefa601f5c2016-06-06 14:27:39 -0700393}
394
Zach Steinba37b4b2018-01-23 15:02:36 -0800395RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700396 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Steve Anton47136dd2018-01-12 10:49:35 -0800397 if (!media_channel_ || stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800398 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700399 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800400 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Steve Anton47136dd2018-01-12 10:49:35 -0800401 return media_channel_->SetRtpSendParameters(ssrc_, parameters);
402 });
deadbeefa601f5c2016-06-06 14:27:39 -0700403}
404
deadbeef20cb0c12017-02-01 20:27:00 -0800405rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100406 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800407 return nullptr;
408}
409
deadbeeffac06552015-11-25 11:26:01 -0800410void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200411 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800412 if (stopped_ || ssrc == ssrc_) {
413 return;
414 }
415 // If we are already sending with a particular SSRC, stop sending.
416 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700417 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800418 }
419 ssrc_ = ssrc;
420 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800421 SetVideoSend();
422 }
423}
424
deadbeef70ab1a12015-09-28 16:53:55 -0700425void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200426 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700427 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800428 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700429 return;
430 }
deadbeeffac06552015-11-25 11:26:01 -0800431 if (track_) {
432 track_->UnregisterObserver(this);
433 }
434 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700435 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800436 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100437 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800438 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700439}
440
deadbeeffac06552015-11-25 11:26:01 -0800441void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700442 RTC_DCHECK(!stopped_);
443 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800444 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100445 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700446 return;
447 }
perkj0d3eef22016-03-09 02:39:17 +0100448 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100449 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100450 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100451 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200452 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700453 }
pbos5214a0a2016-12-16 15:39:11 -0800454 switch (cached_track_content_hint_) {
455 case VideoTrackInterface::ContentHint::kNone:
456 break;
457 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100458 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800459 break;
460 case VideoTrackInterface::ContentHint::kDetailed:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100461 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800462 break;
463 }
Steve Anton47136dd2018-01-12 10:49:35 -0800464 // |track_->enabled()| hops to the signaling thread, so call it before we hop
465 // to the worker thread or else it will deadlock.
466 bool track_enabled = track_->enabled();
467 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
468 return media_channel_->SetVideoSend(ssrc_, track_enabled, &options, track_);
469 });
470 RTC_DCHECK(success);
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_);
Steve Anton47136dd2018-01-12 10:49:35 -0800476 if (!media_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.
Steve Anton47136dd2018-01-12 10:49:35 -0800483 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
484 return media_channel_->SetVideoSend(ssrc_, false, nullptr, nullptr);
485 });
deadbeef70ab1a12015-09-28 16:53:55 -0700486}
487
488} // namespace webrtc