| 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 |