|  | /* | 
|  | *  Copyright 2015 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "webrtc/pc/rtpreceiver.h" | 
|  |  | 
|  | #include "webrtc/api/mediastreamtrackproxy.h" | 
|  | #include "webrtc/api/videosourceproxy.h" | 
|  | #include "webrtc/base/trace_event.h" | 
|  | #include "webrtc/pc/audiotrack.h" | 
|  | #include "webrtc/pc/videotrack.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | AudioRtpReceiver::AudioRtpReceiver(const std::string& track_id, | 
|  | uint32_t ssrc, | 
|  | cricket::VoiceChannel* channel) | 
|  | : id_(track_id), | 
|  | ssrc_(ssrc), | 
|  | channel_(channel), | 
|  | track_(AudioTrackProxy::Create( | 
|  | rtc::Thread::Current(), | 
|  | AudioTrack::Create(track_id, | 
|  | RemoteAudioSource::Create(ssrc, channel)))), | 
|  | cached_track_enabled_(track_->enabled()) { | 
|  | RTC_DCHECK(track_->GetSource()->remote()); | 
|  | track_->RegisterObserver(this); | 
|  | track_->GetSource()->RegisterAudioObserver(this); | 
|  | Reconfigure(); | 
|  | if (channel_) { | 
|  | channel_->SignalFirstPacketReceived.connect( | 
|  | this, &AudioRtpReceiver::OnFirstPacketReceived); | 
|  | } | 
|  | } | 
|  |  | 
|  | AudioRtpReceiver::~AudioRtpReceiver() { | 
|  | track_->GetSource()->UnregisterAudioObserver(this); | 
|  | track_->UnregisterObserver(this); | 
|  | Stop(); | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::OnChanged() { | 
|  | if (cached_track_enabled_ != track_->enabled()) { | 
|  | cached_track_enabled_ = track_->enabled(); | 
|  | Reconfigure(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::OnSetVolume(double volume) { | 
|  | RTC_DCHECK(volume >= 0 && volume <= 10); | 
|  | cached_volume_ = volume; | 
|  | if (!channel_) { | 
|  | LOG(LS_ERROR) << "AudioRtpReceiver::OnSetVolume: No audio channel exists."; | 
|  | return; | 
|  | } | 
|  | // When the track is disabled, the volume of the source, which is the | 
|  | // corresponding WebRtc Voice Engine channel will be 0. So we do not allow | 
|  | // setting the volume to the source when the track is disabled. | 
|  | if (!stopped_ && track_->enabled()) { | 
|  | if (!channel_->SetOutputVolume(ssrc_, cached_volume_)) { | 
|  | RTC_NOTREACHED(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | RtpParameters AudioRtpReceiver::GetParameters() const { | 
|  | if (!channel_ || stopped_) { | 
|  | return RtpParameters(); | 
|  | } | 
|  | return channel_->GetRtpReceiveParameters(ssrc_); | 
|  | } | 
|  |  | 
|  | bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) { | 
|  | TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters"); | 
|  | if (!channel_ || stopped_) { | 
|  | return false; | 
|  | } | 
|  | return channel_->SetRtpReceiveParameters(ssrc_, parameters); | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::Stop() { | 
|  | // TODO(deadbeef): Need to do more here to fully stop receiving packets. | 
|  | if (stopped_) { | 
|  | return; | 
|  | } | 
|  | if (channel_) { | 
|  | // Allow that SetOutputVolume fail. This is the normal case when the | 
|  | // underlying media channel has already been deleted. | 
|  | channel_->SetOutputVolume(ssrc_, 0); | 
|  | } | 
|  | stopped_ = true; | 
|  | } | 
|  |  | 
|  | std::vector<RtpSource> AudioRtpReceiver::GetSources() const { | 
|  | return channel_->GetSources(ssrc_); | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::Reconfigure() { | 
|  | RTC_DCHECK(!stopped_); | 
|  | if (!channel_) { | 
|  | LOG(LS_ERROR) << "AudioRtpReceiver::Reconfigure: No audio channel exists."; | 
|  | return; | 
|  | } | 
|  | if (!channel_->SetOutputVolume(ssrc_, | 
|  | track_->enabled() ? cached_volume_ : 0)) { | 
|  | RTC_NOTREACHED(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) { | 
|  | observer_ = observer; | 
|  | // Deliver any notifications the observer may have missed by being set late. | 
|  | if (received_first_packet_ && observer_) { | 
|  | observer_->OnFirstPacketReceived(media_type()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::SetChannel(cricket::VoiceChannel* channel) { | 
|  | if (channel_) { | 
|  | channel_->SignalFirstPacketReceived.disconnect(this); | 
|  | } | 
|  | channel_ = channel; | 
|  | if (channel_) { | 
|  | channel_->SignalFirstPacketReceived.connect( | 
|  | this, &AudioRtpReceiver::OnFirstPacketReceived); | 
|  | } | 
|  | } | 
|  |  | 
|  | void AudioRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) { | 
|  | if (observer_) { | 
|  | observer_->OnFirstPacketReceived(media_type()); | 
|  | } | 
|  | received_first_packet_ = true; | 
|  | } | 
|  |  | 
|  | VideoRtpReceiver::VideoRtpReceiver(const std::string& track_id, | 
|  | rtc::Thread* worker_thread, | 
|  | uint32_t ssrc, | 
|  | cricket::VideoChannel* channel) | 
|  | : id_(track_id), | 
|  | ssrc_(ssrc), | 
|  | channel_(channel), | 
|  | source_(new RefCountedObject<VideoTrackSource>(&broadcaster_, | 
|  | true /* remote */)), | 
|  | track_(VideoTrackProxy::Create( | 
|  | rtc::Thread::Current(), | 
|  | worker_thread, | 
|  | VideoTrack::Create( | 
|  | track_id, | 
|  | VideoTrackSourceProxy::Create(rtc::Thread::Current(), | 
|  | worker_thread, | 
|  | source_)))) { | 
|  | source_->SetState(MediaSourceInterface::kLive); | 
|  | if (!channel_) { | 
|  | LOG(LS_ERROR) | 
|  | << "VideoRtpReceiver::VideoRtpReceiver: No video channel exists."; | 
|  | } else { | 
|  | if (!channel_->SetSink(ssrc_, &broadcaster_)) { | 
|  | RTC_NOTREACHED(); | 
|  | } | 
|  | } | 
|  | if (channel_) { | 
|  | channel_->SignalFirstPacketReceived.connect( | 
|  | this, &VideoRtpReceiver::OnFirstPacketReceived); | 
|  | } | 
|  | } | 
|  |  | 
|  | VideoRtpReceiver::~VideoRtpReceiver() { | 
|  | // Since cricket::VideoRenderer is not reference counted, | 
|  | // we need to remove it from the channel before we are deleted. | 
|  | Stop(); | 
|  | } | 
|  |  | 
|  | RtpParameters VideoRtpReceiver::GetParameters() const { | 
|  | if (!channel_ || stopped_) { | 
|  | return RtpParameters(); | 
|  | } | 
|  | return channel_->GetRtpReceiveParameters(ssrc_); | 
|  | } | 
|  |  | 
|  | bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) { | 
|  | TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters"); | 
|  | if (!channel_ || stopped_) { | 
|  | return false; | 
|  | } | 
|  | return channel_->SetRtpReceiveParameters(ssrc_, parameters); | 
|  | } | 
|  |  | 
|  | void VideoRtpReceiver::Stop() { | 
|  | // TODO(deadbeef): Need to do more here to fully stop receiving packets. | 
|  | if (stopped_) { | 
|  | return; | 
|  | } | 
|  | source_->SetState(MediaSourceInterface::kEnded); | 
|  | source_->OnSourceDestroyed(); | 
|  | if (!channel_) { | 
|  | LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists."; | 
|  | } else { | 
|  | // Allow that SetSink fail. This is the normal case when the underlying | 
|  | // media channel has already been deleted. | 
|  | channel_->SetSink(ssrc_, nullptr); | 
|  | } | 
|  | stopped_ = true; | 
|  | } | 
|  |  | 
|  | void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) { | 
|  | observer_ = observer; | 
|  | // Deliver any notifications the observer may have missed by being set late. | 
|  | if (received_first_packet_ && observer_) { | 
|  | observer_->OnFirstPacketReceived(media_type()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void VideoRtpReceiver::SetChannel(cricket::VideoChannel* channel) { | 
|  | if (channel_) { | 
|  | channel_->SignalFirstPacketReceived.disconnect(this); | 
|  | channel_->SetSink(ssrc_, nullptr); | 
|  | } | 
|  | channel_ = channel; | 
|  | if (channel_) { | 
|  | if (!channel_->SetSink(ssrc_, &broadcaster_)) { | 
|  | RTC_NOTREACHED(); | 
|  | } | 
|  | channel_->SignalFirstPacketReceived.connect( | 
|  | this, &VideoRtpReceiver::OnFirstPacketReceived); | 
|  | } | 
|  | } | 
|  |  | 
|  | void VideoRtpReceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) { | 
|  | if (observer_) { | 
|  | observer_->OnFirstPacketReceived(media_type()); | 
|  | } | 
|  | received_first_packet_ = true; | 
|  | } | 
|  |  | 
|  | }  // namespace webrtc |