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