blob: d88b1fc5a006660e2586ca3df928ebe44bc6eca6 [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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/rtp_sender.h"
deadbeef6979b022015-09-24 16:47:53 -070012
Benjamin Wrightd81ac952018-08-29 17:02:10 -070013#include <utility>
Steve Anton36b29d12017-10-30 09:57:42 -070014#include <vector>
15
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "api/audio_options.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "api/media_stream_interface.h"
18#include "media/base/media_engine.h"
19#include "pc/stats_collector.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "rtc_base/checks.h"
21#include "rtc_base/helpers.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "rtc_base/location.h"
23#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/trace_event.h"
deadbeef70ab1a12015-09-28 16:53:55 -070025
26namespace webrtc {
27
Harald Alvestrandc72af932018-01-11 17:18:19 +010028namespace {
29
30// This function is only expected to be called on the signalling thread.
31int GenerateUniqueId() {
32 static int g_unique_id = 0;
33
34 return ++g_unique_id;
35}
36
Seth Hampson2d2c8882018-05-16 16:02:32 -070037// Returns an true if any RtpEncodingParameters member that isn't implemented
38// contains a value.
39bool UnimplementedRtpEncodingParameterHasValue(
40 const RtpEncodingParameters& encoding_params) {
Henrik Grunelle1301a82018-12-13 12:13:22 +000041 if (encoding_params.codec_payload_type.has_value() ||
42 encoding_params.fec.has_value() || encoding_params.rtx.has_value() ||
Seth Hampson2d2c8882018-05-16 16:02:32 -070043 encoding_params.dtx.has_value() || encoding_params.ptime.has_value() ||
Seth Hampson2d2c8882018-05-16 16:02:32 -070044 !encoding_params.rid.empty() ||
Seth Hampson2d2c8882018-05-16 16:02:32 -070045 encoding_params.scale_framerate_down_by.has_value() ||
46 !encoding_params.dependency_rids.empty()) {
47 return true;
48 }
49 return false;
50}
51
52// Returns true if a "per-sender" encoding parameter contains a value that isn't
53// its default. Currently max_bitrate_bps and bitrate_priority both are
54// implemented "per-sender," meaning that these encoding parameters
55// are used for the RtpSender as a whole, not for a specific encoding layer.
56// This is done by setting these encoding parameters at index 0 of
57// RtpParameters.encodings. This function can be used to check if these
58// parameters are set at any index other than 0 of RtpParameters.encodings,
59// because they are currently unimplemented to be used for a specific encoding
60// layer.
61bool PerSenderRtpEncodingParameterHasValue(
62 const RtpEncodingParameters& encoding_params) {
Tim Haloun648d28a2018-10-18 16:52:22 -070063 if (encoding_params.bitrate_priority != kDefaultBitratePriority ||
64 encoding_params.network_priority != kDefaultBitratePriority) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070065 return true;
66 }
67 return false;
68}
69
Benjamin Wright84583f62018-10-04 14:22:34 -070070// Attempt to attach the frame decryptor to the current media channel on the
71// correct worker thread only if both the media channel exists and a ssrc has
72// been allocated to the stream.
73void MaybeAttachFrameEncryptorToMediaChannel(
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070074 const uint32_t ssrc,
Benjamin Wright84583f62018-10-04 14:22:34 -070075 rtc::Thread* worker_thread,
76 rtc::scoped_refptr<webrtc::FrameEncryptorInterface> frame_encryptor,
Benjamin Wrightc462a6e2018-10-26 13:16:16 -070077 cricket::MediaChannel* media_channel,
78 bool stopped) {
79 if (media_channel && frame_encryptor && ssrc && !stopped) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070080 worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
81 media_channel->SetFrameEncryptor(ssrc, frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -070082 });
83 }
84}
85
Florent Castelli892acf02018-10-01 22:47:20 +020086} // namespace
87
Seth Hampson2d2c8882018-05-16 16:02:32 -070088// Returns true if any RtpParameters member that isn't implemented contains a
89// value.
90bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020091 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070092 return true;
93 }
94 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
95 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
96 return true;
97 }
98 // Encoding parameters that are per-sender should only contain value at
99 // index 0.
100 if (i != 0 &&
101 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
102 return true;
103 }
104 }
105 return false;
106}
107
deadbeef70ab1a12015-09-28 16:53:55 -0700108LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
109
110LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
111 rtc::CritScope lock(&lock_);
112 if (sink_)
113 sink_->OnClose();
114}
115
116void LocalAudioSinkAdapter::OnData(const void* audio_data,
117 int bits_per_sample,
118 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800119 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700120 size_t number_of_frames) {
121 rtc::CritScope lock(&lock_);
122 if (sink_) {
123 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
124 number_of_frames);
125 }
126}
127
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800128void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700129 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800130 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700131 sink_ = sink;
132}
133
Steve Anton47136dd2018-01-12 10:49:35 -0800134AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700135 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800136 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800137 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700138 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800139 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800140 dtmf_sender_proxy_(DtmfSenderProxy::Create(
141 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700142 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700143 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800144 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200145 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800146}
deadbeeffac06552015-11-25 11:26:01 -0800147
deadbeef70ab1a12015-09-28 16:53:55 -0700148AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800149 // For DtmfSender.
150 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700151 Stop();
152}
153
deadbeef20cb0c12017-02-01 20:27:00 -0800154bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800155 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100156 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800157 return false;
158 }
159 // Check that this RTP sender is active (description has been applied that
160 // matches an SSRC to its ID).
161 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100162 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800163 return false;
164 }
Steve Anton47136dd2018-01-12 10:49:35 -0800165 return worker_thread_->Invoke<bool>(
166 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800167}
168
169bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800170 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100171 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800172 return false;
173 }
174 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100175 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800176 return false;
177 }
Steve Anton47136dd2018-01-12 10:49:35 -0800178 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
179 return media_channel_->InsertDtmf(ssrc_, code, duration);
180 });
181 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100182 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800183 }
Steve Anton47136dd2018-01-12 10:49:35 -0800184 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800185}
186
187sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
188 return &SignalDestroyed;
189}
190
deadbeef70ab1a12015-09-28 16:53:55 -0700191void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200192 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800193 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700194 if (cached_track_enabled_ != track_->enabled()) {
195 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800196 if (can_send_track()) {
197 SetAudioSend();
198 }
deadbeef70ab1a12015-09-28 16:53:55 -0700199 }
200}
201
202bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200203 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800204 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100205 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800206 return false;
207 }
208 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100209 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
210 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700211 return false;
212 }
213 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
214
215 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800216 if (track_) {
217 track_->RemoveSink(sink_adapter_.get());
218 track_->UnregisterObserver(this);
219 }
220
221 if (can_send_track() && stats_) {
222 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
223 }
deadbeef70ab1a12015-09-28 16:53:55 -0700224
225 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800226 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700227 // Keep a reference to the old track to keep it alive until we call
228 // SetAudioSend.
229 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700230 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800231 if (track_) {
232 cached_track_enabled_ = track_->enabled();
233 track_->RegisterObserver(this);
234 track_->AddSink(sink_adapter_.get());
235 }
236
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700237 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800238 if (can_send_track()) {
239 SetAudioSend();
240 if (stats_) {
241 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
242 }
243 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700244 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800245 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700246 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700247 return true;
248}
249
Florent Castellicebf50f2018-05-03 15:31:53 +0200250RtpParameters AudioRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200251 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700252 return RtpParameters();
253 }
Florent Castelli892acf02018-10-01 22:47:20 +0200254 if (!media_channel_) {
255 RtpParameters result = init_parameters_;
256 last_transaction_id_ = rtc::CreateRandomUuid();
257 result.transaction_id = last_transaction_id_.value();
258 return result;
259 }
Steve Anton47136dd2018-01-12 10:49:35 -0800260 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200261 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
262 last_transaction_id_ = rtc::CreateRandomUuid();
263 result.transaction_id = last_transaction_id_.value();
264 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800265 });
deadbeefa601f5c2016-06-06 14:27:39 -0700266}
267
Zach Steinba37b4b2018-01-23 15:02:36 -0800268RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700269 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200270 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800271 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700272 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200273 if (!last_transaction_id_) {
274 LOG_AND_RETURN_ERROR(
275 RTCErrorType::INVALID_STATE,
276 "Failed to set parameters since getParameters() has never been called"
277 " on this sender");
278 }
279 if (last_transaction_id_ != parameters.transaction_id) {
280 LOG_AND_RETURN_ERROR(
281 RTCErrorType::INVALID_MODIFICATION,
282 "Failed to set parameters since the transaction_id doesn't match"
283 " the last value returned from getParameters()");
284 }
285
Seth Hampson2d2c8882018-05-16 16:02:32 -0700286 if (UnimplementedRtpParameterHasValue(parameters)) {
287 LOG_AND_RETURN_ERROR(
288 RTCErrorType::UNSUPPORTED_PARAMETER,
289 "Attempted to set an unimplemented parameter of RtpParameters.");
290 }
Florent Castelli892acf02018-10-01 22:47:20 +0200291 if (!media_channel_) {
Florent Castellic1a0bcb2019-01-29 14:26:48 +0100292 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
293 init_parameters_, parameters);
Florent Castelli892acf02018-10-01 22:47:20 +0200294 if (result.ok()) {
295 init_parameters_ = parameters;
296 }
297 return result;
298 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800299 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200300 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
301 last_transaction_id_.reset();
302 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800303 });
deadbeefa601f5c2016-06-06 14:27:39 -0700304}
305
deadbeef20cb0c12017-02-01 20:27:00 -0800306rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
307 return dtmf_sender_proxy_;
308}
309
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700310void AudioRtpSender::SetFrameEncryptor(
311 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
312 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700313 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700314 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700315 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
316 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
317 });
318 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700319}
320
321rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
322 const {
323 return frame_encryptor_;
324}
325
deadbeeffac06552015-11-25 11:26:01 -0800326void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200327 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800328 if (stopped_ || ssrc == ssrc_) {
329 return;
330 }
331 // If we are already sending with a particular SSRC, stop sending.
332 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700333 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800334 if (stats_) {
335 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
336 }
337 }
338 ssrc_ = ssrc;
339 if (can_send_track()) {
340 SetAudioSend();
341 if (stats_) {
342 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
343 }
344 }
Florent Castelli892acf02018-10-01 22:47:20 +0200345 if (!init_parameters_.encodings.empty()) {
346 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
347 RTC_DCHECK(media_channel_);
348 // Get the current parameters, which are constructed from the SDP.
349 // The number of layers in the SDP is currently authoritative to support
350 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
351 // lines as described in RFC 5576.
352 // All fields should be default constructed and the SSRC field set, which
353 // we need to copy.
354 RtpParameters current_parameters =
355 media_channel_->GetRtpSendParameters(ssrc_);
356 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
357 init_parameters_.encodings[i].ssrc =
358 current_parameters.encodings[i].ssrc;
359 current_parameters.encodings[i] = init_parameters_.encodings[i];
360 }
361 current_parameters.degradation_preference =
362 init_parameters_.degradation_preference;
363 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
364 init_parameters_.encodings.clear();
365 });
366 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700367 // Each time there is an ssrc update.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700368 MaybeAttachFrameEncryptorToMediaChannel(
369 ssrc_, worker_thread_, frame_encryptor_, media_channel_, stopped_);
deadbeeffac06552015-11-25 11:26:01 -0800370}
371
deadbeef70ab1a12015-09-28 16:53:55 -0700372void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200373 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700374 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800375 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700376 return;
377 }
deadbeeffac06552015-11-25 11:26:01 -0800378 if (track_) {
379 track_->RemoveSink(sink_adapter_.get());
380 track_->UnregisterObserver(this);
381 }
382 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700383 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800384 if (stats_) {
385 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
386 }
387 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100388 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800389 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700390}
391
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800392void AudioRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
393 RTC_DCHECK(media_channel == nullptr ||
394 media_channel->media_type() == media_type());
395 media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700396}
397
deadbeeffac06552015-11-25 11:26:01 -0800398void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700399 RTC_DCHECK(!stopped_);
400 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800401 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100402 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700403 return;
404 }
deadbeef70ab1a12015-09-28 16:53:55 -0700405 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800406#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100407 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
408 // PeerConnection. This is a bit of a strange way to apply local audio
409 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800410 if (track_->enabled() && track_->GetSource() &&
411 !track_->GetSource()->remote()) {
Piotr (Peter) Slatala95ca6e12018-11-13 07:57:07 -0800412 options = track_->GetSource()->options();
deadbeef70ab1a12015-09-28 16:53:55 -0700413 }
Tommi3c169782016-01-21 16:12:17 +0100414#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700415
Steve Anton47136dd2018-01-12 10:49:35 -0800416 // |track_->enabled()| hops to the signaling thread, so call it before we hop
417 // to the worker thread or else it will deadlock.
418 bool track_enabled = track_->enabled();
419 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
420 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
421 sink_adapter_.get());
422 });
423 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100424 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700425 }
426}
427
428void AudioRtpSender::ClearAudioSend() {
429 RTC_DCHECK(ssrc_ != 0);
430 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800431 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100432 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700433 return;
434 }
435 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800436 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
437 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
438 });
439 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100440 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700441 }
deadbeef70ab1a12015-09-28 16:53:55 -0700442}
443
Steve Anton47136dd2018-01-12 10:49:35 -0800444VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700445 const std::string& id)
446 : worker_thread_(worker_thread), id_(id) {
Steve Anton47136dd2018-01-12 10:49:35 -0800447 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200448 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800449}
450
deadbeef70ab1a12015-09-28 16:53:55 -0700451VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700452 Stop();
453}
454
455void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200456 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800457 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200458 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800459 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800460 if (can_send_track()) {
461 SetVideoSend();
462 }
deadbeef70ab1a12015-09-28 16:53:55 -0700463 }
464}
465
466bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200467 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800468 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100469 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800470 return false;
471 }
472 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100473 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
474 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700475 return false;
476 }
477 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
478
479 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800480 if (track_) {
481 track_->UnregisterObserver(this);
482 }
deadbeef70ab1a12015-09-28 16:53:55 -0700483
484 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800485 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700486 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700487 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700488 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700489 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800490 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800491 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800492 track_->RegisterObserver(this);
493 }
494
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700495 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800496 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800497 SetVideoSend();
498 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700499 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800500 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700501 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700502 return true;
503}
504
Florent Castellicebf50f2018-05-03 15:31:53 +0200505RtpParameters VideoRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200506 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700507 return RtpParameters();
508 }
Florent Castelli892acf02018-10-01 22:47:20 +0200509 if (!media_channel_) {
510 RtpParameters result = init_parameters_;
511 last_transaction_id_ = rtc::CreateRandomUuid();
512 result.transaction_id = last_transaction_id_.value();
513 return result;
514 }
Steve Anton47136dd2018-01-12 10:49:35 -0800515 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200516 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
517 last_transaction_id_ = rtc::CreateRandomUuid();
518 result.transaction_id = last_transaction_id_.value();
519 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800520 });
deadbeefa601f5c2016-06-06 14:27:39 -0700521}
522
Zach Steinba37b4b2018-01-23 15:02:36 -0800523RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700524 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200525 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800526 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700527 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200528 if (!last_transaction_id_) {
529 LOG_AND_RETURN_ERROR(
530 RTCErrorType::INVALID_STATE,
531 "Failed to set parameters since getParameters() has never been called"
532 " on this sender");
533 }
534 if (last_transaction_id_ != parameters.transaction_id) {
535 LOG_AND_RETURN_ERROR(
536 RTCErrorType::INVALID_MODIFICATION,
537 "Failed to set parameters since the transaction_id doesn't match"
538 " the last value returned from getParameters()");
539 }
540
Seth Hampson2d2c8882018-05-16 16:02:32 -0700541 if (UnimplementedRtpParameterHasValue(parameters)) {
542 LOG_AND_RETURN_ERROR(
543 RTCErrorType::UNSUPPORTED_PARAMETER,
544 "Attempted to set an unimplemented parameter of RtpParameters.");
545 }
Florent Castelli892acf02018-10-01 22:47:20 +0200546 if (!media_channel_) {
Florent Castellic1a0bcb2019-01-29 14:26:48 +0100547 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
548 init_parameters_, parameters);
Florent Castelli892acf02018-10-01 22:47:20 +0200549 if (result.ok()) {
550 init_parameters_ = parameters;
551 }
552 return result;
553 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800554 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200555 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
556 last_transaction_id_.reset();
557 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800558 });
deadbeefa601f5c2016-06-06 14:27:39 -0700559}
560
deadbeef20cb0c12017-02-01 20:27:00 -0800561rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100562 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800563 return nullptr;
564}
565
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700566void VideoRtpSender::SetFrameEncryptor(
567 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
568 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700569 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700570 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700571 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
572 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
573 });
574 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700575}
576
577rtc::scoped_refptr<FrameEncryptorInterface> VideoRtpSender::GetFrameEncryptor()
578 const {
579 return frame_encryptor_;
580}
581
deadbeeffac06552015-11-25 11:26:01 -0800582void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200583 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800584 if (stopped_ || ssrc == ssrc_) {
585 return;
586 }
587 // If we are already sending with a particular SSRC, stop sending.
588 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700589 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800590 }
591 ssrc_ = ssrc;
592 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800593 SetVideoSend();
594 }
Florent Castelli892acf02018-10-01 22:47:20 +0200595 if (!init_parameters_.encodings.empty()) {
596 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
597 RTC_DCHECK(media_channel_);
598 // Get the current parameters, which are constructed from the SDP.
599 // The number of layers in the SDP is currently authoritative to support
600 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
601 // lines as described in RFC 5576.
602 // All fields should be default constructed and the SSRC field set, which
603 // we need to copy.
604 RtpParameters current_parameters =
605 media_channel_->GetRtpSendParameters(ssrc_);
606 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
607 init_parameters_.encodings[i].ssrc =
608 current_parameters.encodings[i].ssrc;
609 current_parameters.encodings[i] = init_parameters_.encodings[i];
610 }
611 current_parameters.degradation_preference =
612 init_parameters_.degradation_preference;
613 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
614 init_parameters_.encodings.clear();
615 });
616 }
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700617 MaybeAttachFrameEncryptorToMediaChannel(
618 ssrc_, worker_thread_, frame_encryptor_, media_channel_, stopped_);
deadbeeffac06552015-11-25 11:26:01 -0800619}
620
deadbeef70ab1a12015-09-28 16:53:55 -0700621void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200622 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700623 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800624 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700625 return;
626 }
deadbeeffac06552015-11-25 11:26:01 -0800627 if (track_) {
628 track_->UnregisterObserver(this);
629 }
630 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700631 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800632 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100633 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800634 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700635}
636
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800637void VideoRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
638 RTC_DCHECK(media_channel == nullptr ||
639 media_channel->media_type() == media_type());
640 media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700641}
642
deadbeeffac06552015-11-25 11:26:01 -0800643void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700644 RTC_DCHECK(!stopped_);
645 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800646 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100647 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700648 return;
649 }
perkj0d3eef22016-03-09 02:39:17 +0100650 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100651 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100652 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100653 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200654 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700655 }
pbos5214a0a2016-12-16 15:39:11 -0800656 switch (cached_track_content_hint_) {
657 case VideoTrackInterface::ContentHint::kNone:
658 break;
659 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100660 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800661 break;
662 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200663 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100664 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800665 break;
666 }
Steve Anton47136dd2018-01-12 10:49:35 -0800667 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200668 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800669 });
670 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700671}
672
673void VideoRtpSender::ClearVideoSend() {
674 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700675 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800676 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100677 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700678 return;
679 }
680 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
681 // This the normal case when the underlying media channel has already been
682 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800683 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200684 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800685 });
deadbeef70ab1a12015-09-28 16:53:55 -0700686}
687
688} // namespace webrtc