blob: b9a269a2083150784bf5b13a181e3946fefe9694 [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.scale_framerate_down_by.has_value() ||
45 !encoding_params.dependency_rids.empty()) {
46 return true;
47 }
48 return false;
49}
50
51// Returns true if a "per-sender" encoding parameter contains a value that isn't
52// its default. Currently max_bitrate_bps and bitrate_priority both are
53// implemented "per-sender," meaning that these encoding parameters
54// are used for the RtpSender as a whole, not for a specific encoding layer.
55// This is done by setting these encoding parameters at index 0 of
56// RtpParameters.encodings. This function can be used to check if these
57// parameters are set at any index other than 0 of RtpParameters.encodings,
58// because they are currently unimplemented to be used for a specific encoding
59// layer.
60bool PerSenderRtpEncodingParameterHasValue(
61 const RtpEncodingParameters& encoding_params) {
Tim Haloun648d28a2018-10-18 16:52:22 -070062 if (encoding_params.bitrate_priority != kDefaultBitratePriority ||
63 encoding_params.network_priority != kDefaultBitratePriority) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070064 return true;
65 }
66 return false;
67}
68
Benjamin Wright84583f62018-10-04 14:22:34 -070069// Attempt to attach the frame decryptor to the current media channel on the
70// correct worker thread only if both the media channel exists and a ssrc has
71// been allocated to the stream.
72void MaybeAttachFrameEncryptorToMediaChannel(
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070073 const uint32_t ssrc,
Benjamin Wright84583f62018-10-04 14:22:34 -070074 rtc::Thread* worker_thread,
75 rtc::scoped_refptr<webrtc::FrameEncryptorInterface> frame_encryptor,
Benjamin Wrightc462a6e2018-10-26 13:16:16 -070076 cricket::MediaChannel* media_channel,
77 bool stopped) {
78 if (media_channel && frame_encryptor && ssrc && !stopped) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -070079 worker_thread->Invoke<void>(RTC_FROM_HERE, [&] {
80 media_channel->SetFrameEncryptor(ssrc, frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -070081 });
82 }
83}
84
Florent Castelli892acf02018-10-01 22:47:20 +020085} // namespace
86
Seth Hampson2d2c8882018-05-16 16:02:32 -070087// Returns true if any RtpParameters member that isn't implemented contains a
88// value.
89bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
Florent Castelli87b3c512018-07-18 16:00:28 +020090 if (!parameters.mid.empty()) {
Seth Hampson2d2c8882018-05-16 16:02:32 -070091 return true;
92 }
93 for (size_t i = 0; i < parameters.encodings.size(); ++i) {
94 if (UnimplementedRtpEncodingParameterHasValue(parameters.encodings[i])) {
95 return true;
96 }
97 // Encoding parameters that are per-sender should only contain value at
98 // index 0.
99 if (i != 0 &&
100 PerSenderRtpEncodingParameterHasValue(parameters.encodings[i])) {
101 return true;
102 }
103 }
104 return false;
105}
106
deadbeef70ab1a12015-09-28 16:53:55 -0700107LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
108
109LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
110 rtc::CritScope lock(&lock_);
111 if (sink_)
112 sink_->OnClose();
113}
114
115void LocalAudioSinkAdapter::OnData(const void* audio_data,
116 int bits_per_sample,
117 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800118 size_t number_of_channels,
deadbeef70ab1a12015-09-28 16:53:55 -0700119 size_t number_of_frames) {
120 rtc::CritScope lock(&lock_);
121 if (sink_) {
122 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
123 number_of_frames);
124 }
125}
126
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800127void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
deadbeef70ab1a12015-09-28 16:53:55 -0700128 rtc::CritScope lock(&lock_);
nisseede5da42017-01-12 05:15:36 -0800129 RTC_DCHECK(!sink || !sink_);
deadbeef70ab1a12015-09-28 16:53:55 -0700130 sink_ = sink;
131}
132
Steve Anton47136dd2018-01-12 10:49:35 -0800133AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700134 const std::string& id,
deadbeefe1f9d832016-01-14 15:35:42 -0800135 StatsCollector* stats)
Steve Anton47136dd2018-01-12 10:49:35 -0800136 : worker_thread_(worker_thread),
Steve Anton111fdfd2018-06-25 13:03:36 -0700137 id_(id),
deadbeefe1f9d832016-01-14 15:35:42 -0800138 stats_(stats),
Steve Anton02ee47c2018-01-10 16:26:06 -0800139 dtmf_sender_proxy_(DtmfSenderProxy::Create(
140 rtc::Thread::Current(),
Steve Antonb983bae2018-06-20 11:16:53 -0700141 DtmfSender::Create(rtc::Thread::Current(), this))),
Steve Anton111fdfd2018-06-25 13:03:36 -0700142 sink_adapter_(new LocalAudioSinkAdapter()) {
Steve Anton47136dd2018-01-12 10:49:35 -0800143 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200144 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800145}
deadbeeffac06552015-11-25 11:26:01 -0800146
deadbeef70ab1a12015-09-28 16:53:55 -0700147AudioRtpSender::~AudioRtpSender() {
deadbeef20cb0c12017-02-01 20:27:00 -0800148 // For DtmfSender.
149 SignalDestroyed();
deadbeef70ab1a12015-09-28 16:53:55 -0700150 Stop();
151}
152
deadbeef20cb0c12017-02-01 20:27:00 -0800153bool AudioRtpSender::CanInsertDtmf() {
Steve Anton47136dd2018-01-12 10:49:35 -0800154 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100155 RTC_LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800156 return false;
157 }
158 // Check that this RTP sender is active (description has been applied that
159 // matches an SSRC to its ID).
160 if (!ssrc_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100161 RTC_LOG(LS_ERROR) << "CanInsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800162 return false;
163 }
Steve Anton47136dd2018-01-12 10:49:35 -0800164 return worker_thread_->Invoke<bool>(
165 RTC_FROM_HERE, [&] { return media_channel_->CanInsertDtmf(); });
deadbeef20cb0c12017-02-01 20:27:00 -0800166}
167
168bool AudioRtpSender::InsertDtmf(int code, int duration) {
Steve Anton47136dd2018-01-12 10:49:35 -0800169 if (!media_channel_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100170 RTC_LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
deadbeef20cb0c12017-02-01 20:27:00 -0800171 return false;
172 }
173 if (!ssrc_) {
Jonas Olsson45cc8902018-02-13 10:37:07 +0100174 RTC_LOG(LS_ERROR) << "InsertDtmf: Sender does not have SSRC.";
deadbeef20cb0c12017-02-01 20:27:00 -0800175 return false;
176 }
Steve Anton47136dd2018-01-12 10:49:35 -0800177 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
178 return media_channel_->InsertDtmf(ssrc_, code, duration);
179 });
180 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100181 RTC_LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
deadbeef20cb0c12017-02-01 20:27:00 -0800182 }
Steve Anton47136dd2018-01-12 10:49:35 -0800183 return success;
deadbeef20cb0c12017-02-01 20:27:00 -0800184}
185
186sigslot::signal0<>* AudioRtpSender::GetOnDestroyedSignal() {
187 return &SignalDestroyed;
188}
189
deadbeef70ab1a12015-09-28 16:53:55 -0700190void AudioRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200191 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800192 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700193 if (cached_track_enabled_ != track_->enabled()) {
194 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800195 if (can_send_track()) {
196 SetAudioSend();
197 }
deadbeef70ab1a12015-09-28 16:53:55 -0700198 }
199}
200
201bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200202 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800203 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100204 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800205 return false;
206 }
207 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100208 RTC_LOG(LS_ERROR) << "SetTrack called on audio RtpSender with "
209 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700210 return false;
211 }
212 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
213
214 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800215 if (track_) {
216 track_->RemoveSink(sink_adapter_.get());
217 track_->UnregisterObserver(this);
218 }
219
220 if (can_send_track() && stats_) {
221 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
222 }
deadbeef70ab1a12015-09-28 16:53:55 -0700223
224 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800225 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700226 // Keep a reference to the old track to keep it alive until we call
227 // SetAudioSend.
228 rtc::scoped_refptr<AudioTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700229 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800230 if (track_) {
231 cached_track_enabled_ = track_->enabled();
232 track_->RegisterObserver(this);
233 track_->AddSink(sink_adapter_.get());
234 }
235
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700236 // Update audio channel.
deadbeeffac06552015-11-25 11:26:01 -0800237 if (can_send_track()) {
238 SetAudioSend();
239 if (stats_) {
240 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
241 }
242 } else if (prev_can_send_track) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700243 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800244 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700245 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700246 return true;
247}
248
Florent Castellicebf50f2018-05-03 15:31:53 +0200249RtpParameters AudioRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200250 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700251 return RtpParameters();
252 }
Amit Hilbuchaa584152019-02-06 17:09:52 -0800253 if (!media_channel_ || !ssrc_) {
Florent Castelli892acf02018-10-01 22:47:20 +0200254 RtpParameters result = init_parameters_;
255 last_transaction_id_ = rtc::CreateRandomUuid();
256 result.transaction_id = last_transaction_id_.value();
257 return result;
258 }
Steve Anton47136dd2018-01-12 10:49:35 -0800259 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200260 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
261 last_transaction_id_ = rtc::CreateRandomUuid();
262 result.transaction_id = last_transaction_id_.value();
263 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800264 });
deadbeefa601f5c2016-06-06 14:27:39 -0700265}
266
Zach Steinba37b4b2018-01-23 15:02:36 -0800267RTCError AudioRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700268 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200269 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800270 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700271 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200272 if (!last_transaction_id_) {
273 LOG_AND_RETURN_ERROR(
274 RTCErrorType::INVALID_STATE,
275 "Failed to set parameters since getParameters() has never been called"
276 " on this sender");
277 }
278 if (last_transaction_id_ != parameters.transaction_id) {
279 LOG_AND_RETURN_ERROR(
280 RTCErrorType::INVALID_MODIFICATION,
281 "Failed to set parameters since the transaction_id doesn't match"
282 " the last value returned from getParameters()");
283 }
284
Seth Hampson2d2c8882018-05-16 16:02:32 -0700285 if (UnimplementedRtpParameterHasValue(parameters)) {
286 LOG_AND_RETURN_ERROR(
287 RTCErrorType::UNSUPPORTED_PARAMETER,
288 "Attempted to set an unimplemented parameter of RtpParameters.");
289 }
Amit Hilbuchaa584152019-02-06 17:09:52 -0800290 if (!media_channel_ || !ssrc_) {
Florent Castellic1a0bcb2019-01-29 14:26:48 +0100291 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
292 init_parameters_, parameters);
Florent Castelli892acf02018-10-01 22:47:20 +0200293 if (result.ok()) {
294 init_parameters_ = parameters;
295 }
296 return result;
297 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800298 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200299 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
300 last_transaction_id_.reset();
301 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800302 });
deadbeefa601f5c2016-06-06 14:27:39 -0700303}
304
deadbeef20cb0c12017-02-01 20:27:00 -0800305rtc::scoped_refptr<DtmfSenderInterface> AudioRtpSender::GetDtmfSender() const {
306 return dtmf_sender_proxy_;
307}
308
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700309void AudioRtpSender::SetFrameEncryptor(
310 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
311 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700312 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700313 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700314 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
315 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
316 });
317 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700318}
319
320rtc::scoped_refptr<FrameEncryptorInterface> AudioRtpSender::GetFrameEncryptor()
321 const {
322 return frame_encryptor_;
323}
324
deadbeeffac06552015-11-25 11:26:01 -0800325void AudioRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200326 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800327 if (stopped_ || ssrc == ssrc_) {
328 return;
329 }
330 // If we are already sending with a particular SSRC, stop sending.
331 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700332 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800333 if (stats_) {
334 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
335 }
336 }
337 ssrc_ = ssrc;
338 if (can_send_track()) {
339 SetAudioSend();
340 if (stats_) {
341 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
342 }
343 }
Florent Castelli892acf02018-10-01 22:47:20 +0200344 if (!init_parameters_.encodings.empty()) {
345 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
346 RTC_DCHECK(media_channel_);
347 // Get the current parameters, which are constructed from the SDP.
348 // The number of layers in the SDP is currently authoritative to support
349 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
350 // lines as described in RFC 5576.
351 // All fields should be default constructed and the SSRC field set, which
352 // we need to copy.
353 RtpParameters current_parameters =
354 media_channel_->GetRtpSendParameters(ssrc_);
355 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
356 init_parameters_.encodings[i].ssrc =
357 current_parameters.encodings[i].ssrc;
358 current_parameters.encodings[i] = init_parameters_.encodings[i];
359 }
360 current_parameters.degradation_preference =
361 init_parameters_.degradation_preference;
362 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
363 init_parameters_.encodings.clear();
364 });
365 }
Benjamin Wright84583f62018-10-04 14:22:34 -0700366 // Each time there is an ssrc update.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700367 MaybeAttachFrameEncryptorToMediaChannel(
368 ssrc_, worker_thread_, frame_encryptor_, media_channel_, stopped_);
deadbeeffac06552015-11-25 11:26:01 -0800369}
370
deadbeef70ab1a12015-09-28 16:53:55 -0700371void AudioRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200372 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700373 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800374 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700375 return;
376 }
deadbeeffac06552015-11-25 11:26:01 -0800377 if (track_) {
378 track_->RemoveSink(sink_adapter_.get());
379 track_->UnregisterObserver(this);
380 }
381 if (can_send_track()) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700382 ClearAudioSend();
deadbeeffac06552015-11-25 11:26:01 -0800383 if (stats_) {
384 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
385 }
386 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100387 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800388 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700389}
390
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800391void AudioRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
392 RTC_DCHECK(media_channel == nullptr ||
393 media_channel->media_type() == media_type());
394 media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700395}
396
deadbeeffac06552015-11-25 11:26:01 -0800397void AudioRtpSender::SetAudioSend() {
kwibergee89e782017-08-09 17:22:01 -0700398 RTC_DCHECK(!stopped_);
399 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800400 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100401 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700402 return;
403 }
deadbeef70ab1a12015-09-28 16:53:55 -0700404 cricket::AudioOptions options;
agouaillardb11fb252017-02-03 06:37:05 -0800405#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_WEBKIT_BUILD)
Tommi3c169782016-01-21 16:12:17 +0100406 // TODO(tommi): Remove this hack when we move CreateAudioSource out of
407 // PeerConnection. This is a bit of a strange way to apply local audio
408 // options since it is also applied to all streams/channels, local or remote.
tommi6eca7e32015-12-15 04:27:11 -0800409 if (track_->enabled() && track_->GetSource() &&
410 !track_->GetSource()->remote()) {
Piotr (Peter) Slatala95ca6e12018-11-13 07:57:07 -0800411 options = track_->GetSource()->options();
deadbeef70ab1a12015-09-28 16:53:55 -0700412 }
Tommi3c169782016-01-21 16:12:17 +0100413#endif
deadbeef70ab1a12015-09-28 16:53:55 -0700414
Steve Anton47136dd2018-01-12 10:49:35 -0800415 // |track_->enabled()| hops to the signaling thread, so call it before we hop
416 // to the worker thread or else it will deadlock.
417 bool track_enabled = track_->enabled();
418 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
419 return media_channel_->SetAudioSend(ssrc_, track_enabled, &options,
420 sink_adapter_.get());
421 });
422 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100423 RTC_LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700424 }
425}
426
427void AudioRtpSender::ClearAudioSend() {
428 RTC_DCHECK(ssrc_ != 0);
429 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800430 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100431 RTC_LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700432 return;
433 }
434 cricket::AudioOptions options;
Steve Anton47136dd2018-01-12 10:49:35 -0800435 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
436 return media_channel_->SetAudioSend(ssrc_, false, &options, nullptr);
437 });
438 if (!success) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100439 RTC_LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_;
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700440 }
deadbeef70ab1a12015-09-28 16:53:55 -0700441}
442
Steve Anton47136dd2018-01-12 10:49:35 -0800443VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
Steve Anton111fdfd2018-06-25 13:03:36 -0700444 const std::string& id)
445 : worker_thread_(worker_thread), id_(id) {
Steve Anton47136dd2018-01-12 10:49:35 -0800446 RTC_DCHECK(worker_thread);
Florent Castelli892acf02018-10-01 22:47:20 +0200447 init_parameters_.encodings.emplace_back();
deadbeef20cb0c12017-02-01 20:27:00 -0800448}
449
deadbeef70ab1a12015-09-28 16:53:55 -0700450VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700451 Stop();
452}
453
454void VideoRtpSender::OnChanged() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200455 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged");
deadbeeffac06552015-11-25 11:26:01 -0800456 RTC_DCHECK(!stopped_);
Niels Möllerff40b142018-04-09 08:49:14 +0200457 if (cached_track_content_hint_ != track_->content_hint()) {
pbos5214a0a2016-12-16 15:39:11 -0800458 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800459 if (can_send_track()) {
460 SetVideoSend();
461 }
deadbeef70ab1a12015-09-28 16:53:55 -0700462 }
463}
464
465bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200466 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack");
deadbeeffac06552015-11-25 11:26:01 -0800467 if (stopped_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100468 RTC_LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
deadbeeffac06552015-11-25 11:26:01 -0800469 return false;
470 }
471 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100472 RTC_LOG(LS_ERROR) << "SetTrack called on video RtpSender with "
473 << track->kind() << " track.";
deadbeef70ab1a12015-09-28 16:53:55 -0700474 return false;
475 }
476 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
477
478 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800479 if (track_) {
480 track_->UnregisterObserver(this);
481 }
deadbeef70ab1a12015-09-28 16:53:55 -0700482
483 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800484 bool prev_can_send_track = can_send_track();
deadbeef5dd42fd2016-05-02 16:20:01 -0700485 // Keep a reference to the old track to keep it alive until we call
deadbeef5a4a75a2016-06-02 16:23:38 -0700486 // SetVideoSend.
deadbeef5dd42fd2016-05-02 16:20:01 -0700487 rtc::scoped_refptr<VideoTrackInterface> old_track = track_;
deadbeef70ab1a12015-09-28 16:53:55 -0700488 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800489 if (track_) {
pbos5214a0a2016-12-16 15:39:11 -0800490 cached_track_content_hint_ = track_->content_hint();
deadbeeffac06552015-11-25 11:26:01 -0800491 track_->RegisterObserver(this);
492 }
493
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700494 // Update video channel.
deadbeeffac06552015-11-25 11:26:01 -0800495 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800496 SetVideoSend();
497 } else if (prev_can_send_track) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700498 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800499 }
Steve Anton111fdfd2018-06-25 13:03:36 -0700500 attachment_id_ = (track_ ? GenerateUniqueId() : 0);
deadbeef70ab1a12015-09-28 16:53:55 -0700501 return true;
502}
503
Florent Castellicebf50f2018-05-03 15:31:53 +0200504RtpParameters VideoRtpSender::GetParameters() {
Florent Castelli892acf02018-10-01 22:47:20 +0200505 if (stopped_) {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700506 return RtpParameters();
507 }
Amit Hilbuchaa584152019-02-06 17:09:52 -0800508 if (!media_channel_ || !ssrc_) {
Florent Castelli892acf02018-10-01 22:47:20 +0200509 RtpParameters result = init_parameters_;
510 last_transaction_id_ = rtc::CreateRandomUuid();
511 result.transaction_id = last_transaction_id_.value();
512 return result;
513 }
Steve Anton47136dd2018-01-12 10:49:35 -0800514 return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200515 RtpParameters result = media_channel_->GetRtpSendParameters(ssrc_);
516 last_transaction_id_ = rtc::CreateRandomUuid();
517 result.transaction_id = last_transaction_id_.value();
518 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800519 });
deadbeefa601f5c2016-06-06 14:27:39 -0700520}
521
Zach Steinba37b4b2018-01-23 15:02:36 -0800522RTCError VideoRtpSender::SetParameters(const RtpParameters& parameters) {
deadbeefa601f5c2016-06-06 14:27:39 -0700523 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters");
Florent Castelli892acf02018-10-01 22:47:20 +0200524 if (stopped_) {
Zach Steinba37b4b2018-01-23 15:02:36 -0800525 return RTCError(RTCErrorType::INVALID_STATE);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700526 }
Florent Castellicebf50f2018-05-03 15:31:53 +0200527 if (!last_transaction_id_) {
528 LOG_AND_RETURN_ERROR(
529 RTCErrorType::INVALID_STATE,
530 "Failed to set parameters since getParameters() has never been called"
531 " on this sender");
532 }
533 if (last_transaction_id_ != parameters.transaction_id) {
534 LOG_AND_RETURN_ERROR(
535 RTCErrorType::INVALID_MODIFICATION,
536 "Failed to set parameters since the transaction_id doesn't match"
537 " the last value returned from getParameters()");
538 }
539
Seth Hampson2d2c8882018-05-16 16:02:32 -0700540 if (UnimplementedRtpParameterHasValue(parameters)) {
541 LOG_AND_RETURN_ERROR(
542 RTCErrorType::UNSUPPORTED_PARAMETER,
543 "Attempted to set an unimplemented parameter of RtpParameters.");
544 }
Amit Hilbuchaa584152019-02-06 17:09:52 -0800545 if (!media_channel_ || !ssrc_) {
Florent Castellic1a0bcb2019-01-29 14:26:48 +0100546 auto result = cricket::CheckRtpParametersInvalidModificationAndValues(
547 init_parameters_, parameters);
Florent Castelli892acf02018-10-01 22:47:20 +0200548 if (result.ok()) {
549 init_parameters_ = parameters;
550 }
551 return result;
552 }
Zach Steinba37b4b2018-01-23 15:02:36 -0800553 return worker_thread_->Invoke<RTCError>(RTC_FROM_HERE, [&] {
Florent Castellicebf50f2018-05-03 15:31:53 +0200554 RTCError result = media_channel_->SetRtpSendParameters(ssrc_, parameters);
555 last_transaction_id_.reset();
556 return result;
Steve Anton47136dd2018-01-12 10:49:35 -0800557 });
deadbeefa601f5c2016-06-06 14:27:39 -0700558}
559
deadbeef20cb0c12017-02-01 20:27:00 -0800560rtc::scoped_refptr<DtmfSenderInterface> VideoRtpSender::GetDtmfSender() const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100561 RTC_LOG(LS_ERROR) << "Tried to get DTMF sender from video sender.";
deadbeef20cb0c12017-02-01 20:27:00 -0800562 return nullptr;
563}
564
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700565void VideoRtpSender::SetFrameEncryptor(
566 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
567 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700568 // Special Case: Set the frame encryptor to any value on any existing channel.
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700569 if (media_channel_ && ssrc_ && !stopped_) {
Benjamin Wright6cc9cca2018-10-09 17:29:54 -0700570 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
571 media_channel_->SetFrameEncryptor(ssrc_, frame_encryptor_);
572 });
573 }
Benjamin Wrightd81ac952018-08-29 17:02:10 -0700574}
575
576rtc::scoped_refptr<FrameEncryptorInterface> VideoRtpSender::GetFrameEncryptor()
577 const {
578 return frame_encryptor_;
579}
580
deadbeeffac06552015-11-25 11:26:01 -0800581void VideoRtpSender::SetSsrc(uint32_t ssrc) {
Peter Boströmdabc9442016-04-11 11:45:14 +0200582 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc");
deadbeeffac06552015-11-25 11:26:01 -0800583 if (stopped_ || ssrc == ssrc_) {
584 return;
585 }
586 // If we are already sending with a particular SSRC, stop sending.
587 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700588 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800589 }
590 ssrc_ = ssrc;
591 if (can_send_track()) {
deadbeeffac06552015-11-25 11:26:01 -0800592 SetVideoSend();
593 }
Florent Castelli892acf02018-10-01 22:47:20 +0200594 if (!init_parameters_.encodings.empty()) {
595 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
596 RTC_DCHECK(media_channel_);
597 // Get the current parameters, which are constructed from the SDP.
598 // The number of layers in the SDP is currently authoritative to support
599 // SDP munging for Plan-B simulcast with "a=ssrc-group:SIM <ssrc-id>..."
600 // lines as described in RFC 5576.
601 // All fields should be default constructed and the SSRC field set, which
602 // we need to copy.
603 RtpParameters current_parameters =
604 media_channel_->GetRtpSendParameters(ssrc_);
605 for (size_t i = 0; i < init_parameters_.encodings.size(); ++i) {
606 init_parameters_.encodings[i].ssrc =
607 current_parameters.encodings[i].ssrc;
608 current_parameters.encodings[i] = init_parameters_.encodings[i];
609 }
610 current_parameters.degradation_preference =
611 init_parameters_.degradation_preference;
612 media_channel_->SetRtpSendParameters(ssrc_, current_parameters);
613 init_parameters_.encodings.clear();
614 });
615 }
Benjamin Wrightc462a6e2018-10-26 13:16:16 -0700616 MaybeAttachFrameEncryptorToMediaChannel(
617 ssrc_, worker_thread_, frame_encryptor_, media_channel_, stopped_);
deadbeeffac06552015-11-25 11:26:01 -0800618}
619
deadbeef70ab1a12015-09-28 16:53:55 -0700620void VideoRtpSender::Stop() {
Peter Boströmdabc9442016-04-11 11:45:14 +0200621 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop");
deadbeef70ab1a12015-09-28 16:53:55 -0700622 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800623 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700624 return;
625 }
deadbeeffac06552015-11-25 11:26:01 -0800626 if (track_) {
627 track_->UnregisterObserver(this);
628 }
629 if (can_send_track()) {
deadbeef5a4a75a2016-06-02 16:23:38 -0700630 ClearVideoSend();
deadbeeffac06552015-11-25 11:26:01 -0800631 }
Harald Alvestrand3d976f62018-03-19 19:05:06 +0100632 media_channel_ = nullptr;
deadbeeffac06552015-11-25 11:26:01 -0800633 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700634}
635
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800636void VideoRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
637 RTC_DCHECK(media_channel == nullptr ||
638 media_channel->media_type() == media_type());
639 media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
Benjamin Wrightbfd412e2018-09-10 14:06:02 -0700640}
641
deadbeeffac06552015-11-25 11:26:01 -0800642void VideoRtpSender::SetVideoSend() {
kwibergee89e782017-08-09 17:22:01 -0700643 RTC_DCHECK(!stopped_);
644 RTC_DCHECK(can_send_track());
Steve Anton47136dd2018-01-12 10:49:35 -0800645 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100646 RTC_LOG(LS_ERROR) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700647 return;
648 }
perkj0d3eef22016-03-09 02:39:17 +0100649 cricket::VideoOptions options;
perkja3ede6c2016-03-08 01:27:48 +0100650 VideoTrackSourceInterface* source = track_->GetSource();
perkj0d3eef22016-03-09 02:39:17 +0100651 if (source) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100652 options.is_screencast = source->is_screencast();
Perc0d31e92016-03-31 17:23:39 +0200653 options.video_noise_reduction = source->needs_denoising();
deadbeef70ab1a12015-09-28 16:53:55 -0700654 }
pbos5214a0a2016-12-16 15:39:11 -0800655 switch (cached_track_content_hint_) {
656 case VideoTrackInterface::ContentHint::kNone:
657 break;
658 case VideoTrackInterface::ContentHint::kFluid:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100659 options.is_screencast = false;
pbos5214a0a2016-12-16 15:39:11 -0800660 break;
661 case VideoTrackInterface::ContentHint::kDetailed:
Harald Alvestrandc19ab072018-06-18 08:53:10 +0200662 case VideoTrackInterface::ContentHint::kText:
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +0100663 options.is_screencast = true;
pbos5214a0a2016-12-16 15:39:11 -0800664 break;
665 }
Steve Anton47136dd2018-01-12 10:49:35 -0800666 bool success = worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Yves Gerey665174f2018-06-19 15:03:05 +0200667 return media_channel_->SetVideoSend(ssrc_, &options, track_);
Steve Anton47136dd2018-01-12 10:49:35 -0800668 });
669 RTC_DCHECK(success);
deadbeef5a4a75a2016-06-02 16:23:38 -0700670}
671
672void VideoRtpSender::ClearVideoSend() {
673 RTC_DCHECK(ssrc_ != 0);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700674 RTC_DCHECK(!stopped_);
Steve Anton47136dd2018-01-12 10:49:35 -0800675 if (!media_channel_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100676 RTC_LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700677 return;
678 }
679 // Allow SetVideoSend to fail since |enable| is false and |source| is null.
680 // This the normal case when the underlying media channel has already been
681 // deleted.
Steve Anton47136dd2018-01-12 10:49:35 -0800682 worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllerff40b142018-04-09 08:49:14 +0200683 return media_channel_->SetVideoSend(ssrc_, nullptr, nullptr);
Steve Anton47136dd2018-01-12 10:49:35 -0800684 });
deadbeef70ab1a12015-09-28 16:53:55 -0700685}
686
687} // namespace webrtc