blob: ea10b7b33f9b4e6ef3f92c8e5eab6124b2ac816b [file] [log] [blame]
deadbeef6979b022015-09-24 16:47:53 -07001/*
2 * libjingle
3 * Copyright 2015 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/app/webrtc/rtpsender.h"
29
deadbeef70ab1a12015-09-28 16:53:55 -070030#include "talk/app/webrtc/localaudiosource.h"
31#include "talk/app/webrtc/videosourceinterface.h"
deadbeeffac06552015-11-25 11:26:01 -080032#include "webrtc/base/helpers.h"
deadbeef70ab1a12015-09-28 16:53:55 -070033
34namespace webrtc {
35
36LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
37
38LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
39 rtc::CritScope lock(&lock_);
40 if (sink_)
41 sink_->OnClose();
42}
43
44void LocalAudioSinkAdapter::OnData(const void* audio_data,
45 int bits_per_sample,
46 int sample_rate,
47 int number_of_channels,
48 size_t number_of_frames) {
49 rtc::CritScope lock(&lock_);
50 if (sink_) {
51 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels,
52 number_of_frames);
53 }
54}
55
56void LocalAudioSinkAdapter::SetSink(cricket::AudioRenderer::Sink* sink) {
57 rtc::CritScope lock(&lock_);
58 ASSERT(!sink || !sink_);
59 sink_ = sink;
60}
61
62AudioRtpSender::AudioRtpSender(AudioTrackInterface* track,
deadbeeffac06552015-11-25 11:26:01 -080063 const std::string& stream_id,
64 AudioProviderInterface* provider,
65 StatsCollector* stats)
deadbeef70ab1a12015-09-28 16:53:55 -070066 : id_(track->id()),
deadbeeffac06552015-11-25 11:26:01 -080067 stream_id_(stream_id),
deadbeef5def7b92015-11-20 11:43:22 -080068 provider_(provider),
deadbeeffac06552015-11-25 11:26:01 -080069 stats_(stats),
70 track_(track),
deadbeef70ab1a12015-09-28 16:53:55 -070071 cached_track_enabled_(track->enabled()),
72 sink_adapter_(new LocalAudioSinkAdapter()) {
deadbeeffac06552015-11-25 11:26:01 -080073 RTC_DCHECK(provider != nullptr);
deadbeef70ab1a12015-09-28 16:53:55 -070074 track_->RegisterObserver(this);
75 track_->AddSink(sink_adapter_.get());
deadbeef70ab1a12015-09-28 16:53:55 -070076}
77
deadbeeffac06552015-11-25 11:26:01 -080078AudioRtpSender::AudioRtpSender(AudioProviderInterface* provider,
79 StatsCollector* stats)
80 : id_(rtc::CreateRandomUuid()),
81 stream_id_(rtc::CreateRandomUuid()),
82 provider_(provider),
83 stats_(stats),
84 sink_adapter_(new LocalAudioSinkAdapter()) {}
85
deadbeef70ab1a12015-09-28 16:53:55 -070086AudioRtpSender::~AudioRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -070087 Stop();
88}
89
90void AudioRtpSender::OnChanged() {
deadbeeffac06552015-11-25 11:26:01 -080091 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -070092 if (cached_track_enabled_ != track_->enabled()) {
93 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -080094 if (can_send_track()) {
95 SetAudioSend();
96 }
deadbeef70ab1a12015-09-28 16:53:55 -070097 }
98}
99
100bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) {
deadbeeffac06552015-11-25 11:26:01 -0800101 if (stopped_) {
102 LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
103 return false;
104 }
105 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) {
deadbeef70ab1a12015-09-28 16:53:55 -0700106 LOG(LS_ERROR) << "SetTrack called on audio RtpSender with " << track->kind()
107 << " track.";
108 return false;
109 }
110 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track);
111
112 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800113 if (track_) {
114 track_->RemoveSink(sink_adapter_.get());
115 track_->UnregisterObserver(this);
116 }
117
118 if (can_send_track() && stats_) {
119 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
120 }
deadbeef70ab1a12015-09-28 16:53:55 -0700121
122 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800123 bool prev_can_send_track = can_send_track();
deadbeef70ab1a12015-09-28 16:53:55 -0700124 track_ = audio_track;
deadbeeffac06552015-11-25 11:26:01 -0800125 if (track_) {
126 cached_track_enabled_ = track_->enabled();
127 track_->RegisterObserver(this);
128 track_->AddSink(sink_adapter_.get());
129 }
130
131 // Update audio provider.
132 if (can_send_track()) {
133 SetAudioSend();
134 if (stats_) {
135 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
136 }
137 } else if (prev_can_send_track) {
138 cricket::AudioOptions options;
139 provider_->SetAudioSend(ssrc_, false, options, nullptr);
140 }
deadbeef70ab1a12015-09-28 16:53:55 -0700141 return true;
142}
143
deadbeeffac06552015-11-25 11:26:01 -0800144void AudioRtpSender::SetSsrc(uint32_t ssrc) {
145 if (stopped_ || ssrc == ssrc_) {
146 return;
147 }
148 // If we are already sending with a particular SSRC, stop sending.
149 if (can_send_track()) {
150 cricket::AudioOptions options;
151 provider_->SetAudioSend(ssrc_, false, options, nullptr);
152 if (stats_) {
153 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
154 }
155 }
156 ssrc_ = ssrc;
157 if (can_send_track()) {
158 SetAudioSend();
159 if (stats_) {
160 stats_->AddLocalAudioTrack(track_.get(), ssrc_);
161 }
162 }
163}
164
deadbeef70ab1a12015-09-28 16:53:55 -0700165void AudioRtpSender::Stop() {
166 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800167 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700168 return;
169 }
deadbeeffac06552015-11-25 11:26:01 -0800170 if (track_) {
171 track_->RemoveSink(sink_adapter_.get());
172 track_->UnregisterObserver(this);
173 }
174 if (can_send_track()) {
175 cricket::AudioOptions options;
176 provider_->SetAudioSend(ssrc_, false, options, nullptr);
177 if (stats_) {
178 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_);
179 }
180 }
181 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700182}
183
deadbeeffac06552015-11-25 11:26:01 -0800184void AudioRtpSender::SetAudioSend() {
185 RTC_DCHECK(!stopped_ && can_send_track());
deadbeef70ab1a12015-09-28 16:53:55 -0700186 cricket::AudioOptions options;
187 if (track_->enabled() && track_->GetSource()) {
188 // TODO(xians): Remove this static_cast since we should be able to connect
deadbeeffac06552015-11-25 11:26:01 -0800189 // a remote audio track to a peer connection.
deadbeef70ab1a12015-09-28 16:53:55 -0700190 options = static_cast<LocalAudioSource*>(track_->GetSource())->options();
191 }
192
193 // Use the renderer if the audio track has one, otherwise use the sink
194 // adapter owned by this class.
195 cricket::AudioRenderer* renderer =
196 track_->GetRenderer() ? track_->GetRenderer() : sink_adapter_.get();
197 ASSERT(renderer != nullptr);
198 provider_->SetAudioSend(ssrc_, track_->enabled(), options, renderer);
199}
200
201VideoRtpSender::VideoRtpSender(VideoTrackInterface* track,
deadbeeffac06552015-11-25 11:26:01 -0800202 const std::string& stream_id,
deadbeef70ab1a12015-09-28 16:53:55 -0700203 VideoProviderInterface* provider)
204 : id_(track->id()),
deadbeeffac06552015-11-25 11:26:01 -0800205 stream_id_(stream_id),
deadbeef5def7b92015-11-20 11:43:22 -0800206 provider_(provider),
deadbeeffac06552015-11-25 11:26:01 -0800207 track_(track),
deadbeef70ab1a12015-09-28 16:53:55 -0700208 cached_track_enabled_(track->enabled()) {
deadbeeffac06552015-11-25 11:26:01 -0800209 RTC_DCHECK(provider != nullptr);
deadbeef70ab1a12015-09-28 16:53:55 -0700210 track_->RegisterObserver(this);
deadbeef70ab1a12015-09-28 16:53:55 -0700211}
212
deadbeeffac06552015-11-25 11:26:01 -0800213VideoRtpSender::VideoRtpSender(VideoProviderInterface* provider)
214 : id_(rtc::CreateRandomUuid()),
215 stream_id_(rtc::CreateRandomUuid()),
216 provider_(provider) {}
217
deadbeef70ab1a12015-09-28 16:53:55 -0700218VideoRtpSender::~VideoRtpSender() {
deadbeef70ab1a12015-09-28 16:53:55 -0700219 Stop();
220}
221
222void VideoRtpSender::OnChanged() {
deadbeeffac06552015-11-25 11:26:01 -0800223 RTC_DCHECK(!stopped_);
deadbeef70ab1a12015-09-28 16:53:55 -0700224 if (cached_track_enabled_ != track_->enabled()) {
225 cached_track_enabled_ = track_->enabled();
deadbeeffac06552015-11-25 11:26:01 -0800226 if (can_send_track()) {
227 SetVideoSend();
228 }
deadbeef70ab1a12015-09-28 16:53:55 -0700229 }
230}
231
232bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) {
deadbeeffac06552015-11-25 11:26:01 -0800233 if (stopped_) {
234 LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender.";
235 return false;
236 }
237 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) {
deadbeef70ab1a12015-09-28 16:53:55 -0700238 LOG(LS_ERROR) << "SetTrack called on video RtpSender with " << track->kind()
239 << " track.";
240 return false;
241 }
242 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track);
243
244 // Detach from old track.
deadbeeffac06552015-11-25 11:26:01 -0800245 if (track_) {
246 track_->UnregisterObserver(this);
247 }
deadbeef70ab1a12015-09-28 16:53:55 -0700248
249 // Attach to new track.
deadbeeffac06552015-11-25 11:26:01 -0800250 bool prev_can_send_track = can_send_track();
deadbeef70ab1a12015-09-28 16:53:55 -0700251 track_ = video_track;
deadbeeffac06552015-11-25 11:26:01 -0800252 if (track_) {
253 cached_track_enabled_ = track_->enabled();
254 track_->RegisterObserver(this);
255 }
256
257 // Update video provider.
258 if (can_send_track()) {
259 VideoSourceInterface* source = track_->GetSource();
260 // TODO(deadbeef): If SetTrack is called with a disabled track, and the
261 // previous track was enabled, this could cause a frame from the new track
262 // to slip out. Really, what we need is for SetCaptureDevice and
263 // SetVideoSend
264 // to be combined into one atomic operation, all the way down to
265 // WebRtcVideoSendStream.
266 provider_->SetCaptureDevice(ssrc_,
267 source ? source->GetVideoCapturer() : nullptr);
268 SetVideoSend();
269 } else if (prev_can_send_track) {
270 provider_->SetCaptureDevice(ssrc_, nullptr);
271 provider_->SetVideoSend(ssrc_, false, nullptr);
272 }
deadbeef70ab1a12015-09-28 16:53:55 -0700273 return true;
274}
275
deadbeeffac06552015-11-25 11:26:01 -0800276void VideoRtpSender::SetSsrc(uint32_t ssrc) {
277 if (stopped_ || ssrc == ssrc_) {
278 return;
279 }
280 // If we are already sending with a particular SSRC, stop sending.
281 if (can_send_track()) {
282 provider_->SetCaptureDevice(ssrc_, nullptr);
283 provider_->SetVideoSend(ssrc_, false, nullptr);
284 }
285 ssrc_ = ssrc;
286 if (can_send_track()) {
287 VideoSourceInterface* source = track_->GetSource();
288 provider_->SetCaptureDevice(ssrc_,
289 source ? source->GetVideoCapturer() : nullptr);
290 SetVideoSend();
291 }
292}
293
deadbeef70ab1a12015-09-28 16:53:55 -0700294void VideoRtpSender::Stop() {
295 // TODO(deadbeef): Need to do more here to fully stop sending packets.
deadbeeffac06552015-11-25 11:26:01 -0800296 if (stopped_) {
deadbeef70ab1a12015-09-28 16:53:55 -0700297 return;
298 }
deadbeeffac06552015-11-25 11:26:01 -0800299 if (track_) {
300 track_->UnregisterObserver(this);
301 }
302 if (can_send_track()) {
303 provider_->SetCaptureDevice(ssrc_, nullptr);
304 provider_->SetVideoSend(ssrc_, false, nullptr);
305 }
306 stopped_ = true;
deadbeef70ab1a12015-09-28 16:53:55 -0700307}
308
deadbeeffac06552015-11-25 11:26:01 -0800309void VideoRtpSender::SetVideoSend() {
310 RTC_DCHECK(!stopped_ && can_send_track());
deadbeef70ab1a12015-09-28 16:53:55 -0700311 const cricket::VideoOptions* options = nullptr;
312 VideoSourceInterface* source = track_->GetSource();
313 if (track_->enabled() && source) {
314 options = source->options();
315 }
316 provider_->SetVideoSend(ssrc_, track_->enabled(), options);
317}
318
319} // namespace webrtc