OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * 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. | |
9 */ | |
10 | |
11 #include "webrtc/api/rtpsender.h" | |
12 | |
13 #include "webrtc/api/localaudiosource.h" | |
14 #include "webrtc/api/mediastreaminterface.h" | |
15 #include "webrtc/base/helpers.h" | |
16 #include "webrtc/base/trace_event.h" | |
17 | |
18 namespace webrtc { | |
19 | |
20 LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {} | |
21 | |
22 LocalAudioSinkAdapter::~LocalAudioSinkAdapter() { | |
23 rtc::CritScope lock(&lock_); | |
24 if (sink_) | |
25 sink_->OnClose(); | |
26 } | |
27 | |
28 void LocalAudioSinkAdapter::OnData(const void* audio_data, | |
29 int bits_per_sample, | |
30 int sample_rate, | |
31 size_t number_of_channels, | |
32 size_t number_of_frames) { | |
33 rtc::CritScope lock(&lock_); | |
34 if (sink_) { | |
35 sink_->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels, | |
36 number_of_frames); | |
37 } | |
38 } | |
39 | |
40 void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) { | |
41 rtc::CritScope lock(&lock_); | |
42 ASSERT(!sink || !sink_); | |
43 sink_ = sink; | |
44 } | |
45 | |
46 AudioRtpSender::AudioRtpSender(AudioTrackInterface* track, | |
47 const std::string& stream_id, | |
48 cricket::VoiceChannel* channel, | |
49 StatsCollector* stats) | |
50 : id_(track->id()), | |
51 stream_id_(stream_id), | |
52 channel_(channel), | |
53 stats_(stats), | |
54 track_(track), | |
55 cached_track_enabled_(track->enabled()), | |
56 sink_adapter_(new LocalAudioSinkAdapter()) { | |
57 track_->RegisterObserver(this); | |
58 track_->AddSink(sink_adapter_.get()); | |
59 } | |
60 | |
61 AudioRtpSender::AudioRtpSender(AudioTrackInterface* track, | |
62 cricket::VoiceChannel* channel, | |
63 StatsCollector* stats) | |
64 : id_(track->id()), | |
65 stream_id_(rtc::CreateRandomUuid()), | |
66 channel_(channel), | |
67 stats_(stats), | |
68 track_(track), | |
69 cached_track_enabled_(track->enabled()), | |
70 sink_adapter_(new LocalAudioSinkAdapter()) { | |
71 track_->RegisterObserver(this); | |
72 track_->AddSink(sink_adapter_.get()); | |
73 } | |
74 | |
75 AudioRtpSender::AudioRtpSender(cricket::VoiceChannel* channel, | |
76 StatsCollector* stats) | |
77 : id_(rtc::CreateRandomUuid()), | |
78 stream_id_(rtc::CreateRandomUuid()), | |
79 channel_(channel), | |
80 stats_(stats), | |
81 sink_adapter_(new LocalAudioSinkAdapter()) {} | |
82 | |
83 AudioRtpSender::~AudioRtpSender() { | |
84 Stop(); | |
85 } | |
86 | |
87 void AudioRtpSender::OnChanged() { | |
88 TRACE_EVENT0("webrtc", "AudioRtpSender::OnChanged"); | |
89 RTC_DCHECK(!stopped_); | |
90 if (cached_track_enabled_ != track_->enabled()) { | |
91 cached_track_enabled_ = track_->enabled(); | |
92 if (can_send_track()) { | |
93 SetAudioSend(); | |
94 } | |
95 } | |
96 } | |
97 | |
98 bool AudioRtpSender::SetTrack(MediaStreamTrackInterface* track) { | |
99 TRACE_EVENT0("webrtc", "AudioRtpSender::SetTrack"); | |
100 if (stopped_) { | |
101 LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender."; | |
102 return false; | |
103 } | |
104 if (track && track->kind() != MediaStreamTrackInterface::kAudioKind) { | |
105 LOG(LS_ERROR) << "SetTrack called on audio RtpSender with " << track->kind() | |
106 << " track."; | |
107 return false; | |
108 } | |
109 AudioTrackInterface* audio_track = static_cast<AudioTrackInterface*>(track); | |
110 | |
111 // Detach from old track. | |
112 if (track_) { | |
113 track_->RemoveSink(sink_adapter_.get()); | |
114 track_->UnregisterObserver(this); | |
115 } | |
116 | |
117 if (can_send_track() && stats_) { | |
118 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_); | |
119 } | |
120 | |
121 // Attach to new track. | |
122 bool prev_can_send_track = can_send_track(); | |
123 // Keep a reference to the old track to keep it alive until we call | |
124 // SetAudioSend. | |
125 rtc::scoped_refptr<AudioTrackInterface> old_track = track_; | |
126 track_ = audio_track; | |
127 if (track_) { | |
128 cached_track_enabled_ = track_->enabled(); | |
129 track_->RegisterObserver(this); | |
130 track_->AddSink(sink_adapter_.get()); | |
131 } | |
132 | |
133 // Update audio channel. | |
134 if (can_send_track()) { | |
135 SetAudioSend(); | |
136 if (stats_) { | |
137 stats_->AddLocalAudioTrack(track_.get(), ssrc_); | |
138 } | |
139 } else if (prev_can_send_track) { | |
140 ClearAudioSend(); | |
141 } | |
142 return true; | |
143 } | |
144 | |
145 RtpParameters AudioRtpSender::GetParameters() const { | |
146 if (!channel_ || stopped_) { | |
147 return RtpParameters(); | |
148 } | |
149 return channel_->GetRtpSendParameters(ssrc_); | |
150 } | |
151 | |
152 bool AudioRtpSender::SetParameters(const RtpParameters& parameters) { | |
153 TRACE_EVENT0("webrtc", "AudioRtpSender::SetParameters"); | |
154 if (!channel_ || stopped_) { | |
155 return false; | |
156 } | |
157 return channel_->SetRtpSendParameters(ssrc_, parameters); | |
158 } | |
159 | |
160 void AudioRtpSender::SetSsrc(uint32_t ssrc) { | |
161 TRACE_EVENT0("webrtc", "AudioRtpSender::SetSsrc"); | |
162 if (stopped_ || ssrc == ssrc_) { | |
163 return; | |
164 } | |
165 // If we are already sending with a particular SSRC, stop sending. | |
166 if (can_send_track()) { | |
167 ClearAudioSend(); | |
168 if (stats_) { | |
169 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_); | |
170 } | |
171 } | |
172 ssrc_ = ssrc; | |
173 if (can_send_track()) { | |
174 SetAudioSend(); | |
175 if (stats_) { | |
176 stats_->AddLocalAudioTrack(track_.get(), ssrc_); | |
177 } | |
178 } | |
179 } | |
180 | |
181 void AudioRtpSender::Stop() { | |
182 TRACE_EVENT0("webrtc", "AudioRtpSender::Stop"); | |
183 // TODO(deadbeef): Need to do more here to fully stop sending packets. | |
184 if (stopped_) { | |
185 return; | |
186 } | |
187 if (track_) { | |
188 track_->RemoveSink(sink_adapter_.get()); | |
189 track_->UnregisterObserver(this); | |
190 } | |
191 if (can_send_track()) { | |
192 ClearAudioSend(); | |
193 if (stats_) { | |
194 stats_->RemoveLocalAudioTrack(track_.get(), ssrc_); | |
195 } | |
196 } | |
197 stopped_ = true; | |
198 } | |
199 | |
200 void AudioRtpSender::SetAudioSend() { | |
201 RTC_DCHECK(!stopped_ && can_send_track()); | |
202 if (!channel_) { | |
203 LOG(LS_ERROR) << "SetAudioSend: No audio channel exists."; | |
204 return; | |
205 } | |
206 cricket::AudioOptions options; | |
207 #if !defined(WEBRTC_CHROMIUM_BUILD) | |
208 // TODO(tommi): Remove this hack when we move CreateAudioSource out of | |
209 // PeerConnection. This is a bit of a strange way to apply local audio | |
210 // options since it is also applied to all streams/channels, local or remote. | |
211 if (track_->enabled() && track_->GetSource() && | |
212 !track_->GetSource()->remote()) { | |
213 // TODO(xians): Remove this static_cast since we should be able to connect | |
214 // a remote audio track to a peer connection. | |
215 options = static_cast<LocalAudioSource*>(track_->GetSource())->options(); | |
216 } | |
217 #endif | |
218 | |
219 cricket::AudioSource* source = sink_adapter_.get(); | |
220 RTC_DCHECK(source != nullptr); | |
221 if (!channel_->SetAudioSend(ssrc_, track_->enabled(), &options, source)) { | |
222 LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc_; | |
223 } | |
224 } | |
225 | |
226 void AudioRtpSender::ClearAudioSend() { | |
227 RTC_DCHECK(ssrc_ != 0); | |
228 RTC_DCHECK(!stopped_); | |
229 if (!channel_) { | |
230 LOG(LS_WARNING) << "ClearAudioSend: No audio channel exists."; | |
231 return; | |
232 } | |
233 cricket::AudioOptions options; | |
234 if (!channel_->SetAudioSend(ssrc_, false, &options, nullptr)) { | |
235 LOG(LS_WARNING) << "ClearAudioSend: ssrc is incorrect: " << ssrc_; | |
236 } | |
237 } | |
238 | |
239 VideoRtpSender::VideoRtpSender(VideoTrackInterface* track, | |
240 const std::string& stream_id, | |
241 cricket::VideoChannel* channel) | |
242 : id_(track->id()), | |
243 stream_id_(stream_id), | |
244 channel_(channel), | |
245 track_(track), | |
246 cached_track_enabled_(track->enabled()) { | |
247 track_->RegisterObserver(this); | |
248 } | |
249 | |
250 VideoRtpSender::VideoRtpSender(VideoTrackInterface* track, | |
251 cricket::VideoChannel* channel) | |
252 : id_(track->id()), | |
253 stream_id_(rtc::CreateRandomUuid()), | |
254 channel_(channel), | |
255 track_(track), | |
256 cached_track_enabled_(track->enabled()) { | |
257 track_->RegisterObserver(this); | |
258 } | |
259 | |
260 VideoRtpSender::VideoRtpSender(cricket::VideoChannel* channel) | |
261 : id_(rtc::CreateRandomUuid()), | |
262 stream_id_(rtc::CreateRandomUuid()), | |
263 channel_(channel) {} | |
264 | |
265 VideoRtpSender::~VideoRtpSender() { | |
266 Stop(); | |
267 } | |
268 | |
269 void VideoRtpSender::OnChanged() { | |
270 TRACE_EVENT0("webrtc", "VideoRtpSender::OnChanged"); | |
271 RTC_DCHECK(!stopped_); | |
272 if (cached_track_enabled_ != track_->enabled()) { | |
273 cached_track_enabled_ = track_->enabled(); | |
274 if (can_send_track()) { | |
275 SetVideoSend(); | |
276 } | |
277 } | |
278 } | |
279 | |
280 bool VideoRtpSender::SetTrack(MediaStreamTrackInterface* track) { | |
281 TRACE_EVENT0("webrtc", "VideoRtpSender::SetTrack"); | |
282 if (stopped_) { | |
283 LOG(LS_ERROR) << "SetTrack can't be called on a stopped RtpSender."; | |
284 return false; | |
285 } | |
286 if (track && track->kind() != MediaStreamTrackInterface::kVideoKind) { | |
287 LOG(LS_ERROR) << "SetTrack called on video RtpSender with " << track->kind() | |
288 << " track."; | |
289 return false; | |
290 } | |
291 VideoTrackInterface* video_track = static_cast<VideoTrackInterface*>(track); | |
292 | |
293 // Detach from old track. | |
294 if (track_) { | |
295 track_->UnregisterObserver(this); | |
296 } | |
297 | |
298 // Attach to new track. | |
299 bool prev_can_send_track = can_send_track(); | |
300 // Keep a reference to the old track to keep it alive until we call | |
301 // SetVideoSend. | |
302 rtc::scoped_refptr<VideoTrackInterface> old_track = track_; | |
303 track_ = video_track; | |
304 if (track_) { | |
305 cached_track_enabled_ = track_->enabled(); | |
306 track_->RegisterObserver(this); | |
307 } | |
308 | |
309 // Update video channel. | |
310 if (can_send_track()) { | |
311 SetVideoSend(); | |
312 } else if (prev_can_send_track) { | |
313 ClearVideoSend(); | |
314 } | |
315 return true; | |
316 } | |
317 | |
318 RtpParameters VideoRtpSender::GetParameters() const { | |
319 if (!channel_ || stopped_) { | |
320 return RtpParameters(); | |
321 } | |
322 return channel_->GetRtpSendParameters(ssrc_); | |
323 } | |
324 | |
325 bool VideoRtpSender::SetParameters(const RtpParameters& parameters) { | |
326 TRACE_EVENT0("webrtc", "VideoRtpSender::SetParameters"); | |
327 if (!channel_ || stopped_) { | |
328 return false; | |
329 } | |
330 return channel_->SetRtpSendParameters(ssrc_, parameters); | |
331 } | |
332 | |
333 void VideoRtpSender::SetSsrc(uint32_t ssrc) { | |
334 TRACE_EVENT0("webrtc", "VideoRtpSender::SetSsrc"); | |
335 if (stopped_ || ssrc == ssrc_) { | |
336 return; | |
337 } | |
338 // If we are already sending with a particular SSRC, stop sending. | |
339 if (can_send_track()) { | |
340 ClearVideoSend(); | |
341 } | |
342 ssrc_ = ssrc; | |
343 if (can_send_track()) { | |
344 SetVideoSend(); | |
345 } | |
346 } | |
347 | |
348 void VideoRtpSender::Stop() { | |
349 TRACE_EVENT0("webrtc", "VideoRtpSender::Stop"); | |
350 // TODO(deadbeef): Need to do more here to fully stop sending packets. | |
351 if (stopped_) { | |
352 return; | |
353 } | |
354 if (track_) { | |
355 track_->UnregisterObserver(this); | |
356 } | |
357 if (can_send_track()) { | |
358 ClearVideoSend(); | |
359 } | |
360 stopped_ = true; | |
361 } | |
362 | |
363 void VideoRtpSender::SetVideoSend() { | |
364 RTC_DCHECK(!stopped_ && can_send_track()); | |
365 if (!channel_) { | |
366 LOG(LS_ERROR) << "SetVideoSend: No video channel exists."; | |
367 return; | |
368 } | |
369 cricket::VideoOptions options; | |
370 VideoTrackSourceInterface* source = track_->GetSource(); | |
371 if (source) { | |
372 options.is_screencast = rtc::Optional<bool>(source->is_screencast()); | |
373 options.video_noise_reduction = source->needs_denoising(); | |
374 } | |
375 if (!channel_->SetVideoSend(ssrc_, track_->enabled(), &options, track_)) { | |
376 RTC_DCHECK(false); | |
377 } | |
378 } | |
379 | |
380 void VideoRtpSender::ClearVideoSend() { | |
381 RTC_DCHECK(ssrc_ != 0); | |
382 RTC_DCHECK(!stopped_); | |
383 if (!channel_) { | |
384 LOG(LS_WARNING) << "SetVideoSend: No video channel exists."; | |
385 return; | |
386 } | |
387 // Allow SetVideoSend to fail since |enable| is false and |source| is null. | |
388 // This the normal case when the underlying media channel has already been | |
389 // deleted. | |
390 channel_->SetVideoSend(ssrc_, false, nullptr, nullptr); | |
391 } | |
392 | |
393 } // namespace webrtc | |
OLD | NEW |