| /* |
| * libjingle |
| * Copyright 2012 Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "talk/app/webrtc/mediastreamhandler.h" |
| |
| #include "talk/app/webrtc/localaudiosource.h" |
| #include "talk/app/webrtc/videosource.h" |
| #include "talk/app/webrtc/videosourceinterface.h" |
| |
| namespace webrtc { |
| |
| TrackHandler::TrackHandler(MediaStreamTrackInterface* track, uint32 ssrc) |
| : track_(track), |
| ssrc_(ssrc), |
| state_(track->state()), |
| enabled_(track->enabled()) { |
| track_->RegisterObserver(this); |
| } |
| |
| TrackHandler::~TrackHandler() { |
| track_->UnregisterObserver(this); |
| } |
| |
| void TrackHandler::OnChanged() { |
| if (state_ != track_->state()) { |
| state_ = track_->state(); |
| OnStateChanged(); |
| } |
| if (enabled_ != track_->enabled()) { |
| enabled_ = track_->enabled(); |
| OnEnabledChanged(); |
| } |
| } |
| |
| LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(NULL) {} |
| |
| LocalAudioSinkAdapter::~LocalAudioSinkAdapter() { |
| rtc::CritScope lock(&lock_); |
| if (sink_) |
| sink_->OnClose(); |
| } |
| |
| void LocalAudioSinkAdapter::OnData(const void* audio_data, |
| int bits_per_sample, |
| int sample_rate, |
| int number_of_channels, |
| size_t number_of_frames) { |
| rtc::CritScope lock(&lock_); |
| if (sink_) { |
| sink_->OnData(audio_data, bits_per_sample, sample_rate, |
| number_of_channels, number_of_frames); |
| } |
| } |
| |
| void LocalAudioSinkAdapter::SetSink(cricket::AudioRenderer::Sink* sink) { |
| rtc::CritScope lock(&lock_); |
| ASSERT(!sink || !sink_); |
| sink_ = sink; |
| } |
| |
| LocalAudioTrackHandler::LocalAudioTrackHandler( |
| AudioTrackInterface* track, |
| uint32 ssrc, |
| AudioProviderInterface* provider) |
| : TrackHandler(track, ssrc), |
| audio_track_(track), |
| provider_(provider), |
| sink_adapter_(new LocalAudioSinkAdapter()) { |
| OnEnabledChanged(); |
| track->AddSink(sink_adapter_.get()); |
| } |
| |
| LocalAudioTrackHandler::~LocalAudioTrackHandler() { |
| } |
| |
| void LocalAudioTrackHandler::OnStateChanged() { |
| // TODO(perkj): What should happen when the state change? |
| } |
| |
| void LocalAudioTrackHandler::Stop() { |
| audio_track_->RemoveSink(sink_adapter_.get()); |
| cricket::AudioOptions options; |
| provider_->SetAudioSend(ssrc(), false, options, NULL); |
| } |
| |
| void LocalAudioTrackHandler::OnEnabledChanged() { |
| cricket::AudioOptions options; |
| if (audio_track_->enabled() && audio_track_->GetSource()) { |
| // TODO(xians): Remove this static_cast since we should be able to connect |
| // a remote audio track to peer connection. |
| options = static_cast<LocalAudioSource*>( |
| audio_track_->GetSource())->options(); |
| } |
| |
| // Use the renderer if the audio track has one, otherwise use the sink |
| // adapter owned by this class. |
| cricket::AudioRenderer* renderer = audio_track_->GetRenderer() ? |
| audio_track_->GetRenderer() : sink_adapter_.get(); |
| ASSERT(renderer != NULL); |
| provider_->SetAudioSend(ssrc(), audio_track_->enabled(), options, renderer); |
| } |
| |
| RemoteAudioTrackHandler::RemoteAudioTrackHandler( |
| AudioTrackInterface* track, |
| uint32 ssrc, |
| AudioProviderInterface* provider) |
| : TrackHandler(track, ssrc), |
| audio_track_(track), |
| provider_(provider) { |
| track->GetSource()->RegisterAudioObserver(this); |
| OnEnabledChanged(); |
| } |
| |
| RemoteAudioTrackHandler::~RemoteAudioTrackHandler() { |
| audio_track_->GetSource()->UnregisterAudioObserver(this); |
| } |
| |
| void RemoteAudioTrackHandler::Stop() { |
| provider_->SetAudioPlayout(ssrc(), false, NULL); |
| } |
| |
| void RemoteAudioTrackHandler::OnStateChanged() { |
| } |
| |
| void RemoteAudioTrackHandler::OnEnabledChanged() { |
| provider_->SetAudioPlayout(ssrc(), audio_track_->enabled(), |
| audio_track_->GetRenderer()); |
| } |
| |
| void RemoteAudioTrackHandler::OnSetVolume(double volume) { |
| // 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 (audio_track_->enabled()) |
| provider_->SetAudioPlayoutVolume(ssrc(), volume); |
| } |
| |
| LocalVideoTrackHandler::LocalVideoTrackHandler( |
| VideoTrackInterface* track, |
| uint32 ssrc, |
| VideoProviderInterface* provider) |
| : TrackHandler(track, ssrc), |
| local_video_track_(track), |
| provider_(provider) { |
| VideoSourceInterface* source = local_video_track_->GetSource(); |
| if (source) |
| provider_->SetCaptureDevice(ssrc, source->GetVideoCapturer()); |
| OnEnabledChanged(); |
| } |
| |
| LocalVideoTrackHandler::~LocalVideoTrackHandler() { |
| } |
| |
| void LocalVideoTrackHandler::OnStateChanged() { |
| } |
| |
| void LocalVideoTrackHandler::Stop() { |
| provider_->SetCaptureDevice(ssrc(), NULL); |
| provider_->SetVideoSend(ssrc(), false, NULL); |
| } |
| |
| void LocalVideoTrackHandler::OnEnabledChanged() { |
| const cricket::VideoOptions* options = NULL; |
| VideoSourceInterface* source = local_video_track_->GetSource(); |
| if (local_video_track_->enabled() && source) { |
| options = source->options(); |
| } |
| provider_->SetVideoSend(ssrc(), local_video_track_->enabled(), options); |
| } |
| |
| RemoteVideoTrackHandler::RemoteVideoTrackHandler( |
| VideoTrackInterface* track, |
| uint32 ssrc, |
| VideoProviderInterface* provider) |
| : TrackHandler(track, ssrc), |
| remote_video_track_(track), |
| provider_(provider) { |
| OnEnabledChanged(); |
| provider_->SetVideoPlayout(ssrc, true, |
| remote_video_track_->GetSource()->FrameInput()); |
| } |
| |
| RemoteVideoTrackHandler::~RemoteVideoTrackHandler() { |
| } |
| |
| void RemoteVideoTrackHandler::Stop() { |
| // Since cricket::VideoRenderer is not reference counted |
| // we need to remove the renderer before we are deleted. |
| provider_->SetVideoPlayout(ssrc(), false, NULL); |
| } |
| |
| void RemoteVideoTrackHandler::OnStateChanged() { |
| } |
| |
| void RemoteVideoTrackHandler::OnEnabledChanged() { |
| } |
| |
| MediaStreamHandler::MediaStreamHandler(MediaStreamInterface* stream, |
| AudioProviderInterface* audio_provider, |
| VideoProviderInterface* video_provider) |
| : stream_(stream), |
| audio_provider_(audio_provider), |
| video_provider_(video_provider) { |
| } |
| |
| MediaStreamHandler::~MediaStreamHandler() { |
| for (TrackHandlers::iterator it = track_handlers_.begin(); |
| it != track_handlers_.end(); ++it) { |
| delete *it; |
| } |
| } |
| |
| void MediaStreamHandler::RemoveTrack(MediaStreamTrackInterface* track) { |
| for (TrackHandlers::iterator it = track_handlers_.begin(); |
| it != track_handlers_.end(); ++it) { |
| if ((*it)->track() == track) { |
| TrackHandler* track = *it; |
| track->Stop(); |
| delete track; |
| track_handlers_.erase(it); |
| break; |
| } |
| } |
| } |
| |
| TrackHandler* MediaStreamHandler::FindTrackHandler( |
| MediaStreamTrackInterface* track) { |
| TrackHandlers::iterator it = track_handlers_.begin(); |
| for (; it != track_handlers_.end(); ++it) { |
| if ((*it)->track() == track) { |
| return *it; |
| break; |
| } |
| } |
| return NULL; |
| } |
| |
| MediaStreamInterface* MediaStreamHandler::stream() { |
| return stream_.get(); |
| } |
| |
| void MediaStreamHandler::OnChanged() { |
| } |
| |
| void MediaStreamHandler::Stop() { |
| for (TrackHandlers::const_iterator it = track_handlers_.begin(); |
| it != track_handlers_.end(); ++it) { |
| (*it)->Stop(); |
| } |
| } |
| |
| LocalMediaStreamHandler::LocalMediaStreamHandler( |
| MediaStreamInterface* stream, |
| AudioProviderInterface* audio_provider, |
| VideoProviderInterface* video_provider) |
| : MediaStreamHandler(stream, audio_provider, video_provider) { |
| } |
| |
| LocalMediaStreamHandler::~LocalMediaStreamHandler() { |
| } |
| |
| void LocalMediaStreamHandler::AddAudioTrack(AudioTrackInterface* audio_track, |
| uint32 ssrc) { |
| ASSERT(!FindTrackHandler(audio_track)); |
| |
| TrackHandler* handler(new LocalAudioTrackHandler(audio_track, ssrc, |
| audio_provider_)); |
| track_handlers_.push_back(handler); |
| } |
| |
| void LocalMediaStreamHandler::AddVideoTrack(VideoTrackInterface* video_track, |
| uint32 ssrc) { |
| ASSERT(!FindTrackHandler(video_track)); |
| |
| TrackHandler* handler(new LocalVideoTrackHandler(video_track, ssrc, |
| video_provider_)); |
| track_handlers_.push_back(handler); |
| } |
| |
| RemoteMediaStreamHandler::RemoteMediaStreamHandler( |
| MediaStreamInterface* stream, |
| AudioProviderInterface* audio_provider, |
| VideoProviderInterface* video_provider) |
| : MediaStreamHandler(stream, audio_provider, video_provider) { |
| } |
| |
| RemoteMediaStreamHandler::~RemoteMediaStreamHandler() { |
| } |
| |
| void RemoteMediaStreamHandler::AddAudioTrack(AudioTrackInterface* audio_track, |
| uint32 ssrc) { |
| ASSERT(!FindTrackHandler(audio_track)); |
| TrackHandler* handler( |
| new RemoteAudioTrackHandler(audio_track, ssrc, audio_provider_)); |
| track_handlers_.push_back(handler); |
| } |
| |
| void RemoteMediaStreamHandler::AddVideoTrack(VideoTrackInterface* video_track, |
| uint32 ssrc) { |
| ASSERT(!FindTrackHandler(video_track)); |
| TrackHandler* handler( |
| new RemoteVideoTrackHandler(video_track, ssrc, video_provider_)); |
| track_handlers_.push_back(handler); |
| } |
| |
| MediaStreamHandlerContainer::MediaStreamHandlerContainer( |
| AudioProviderInterface* audio_provider, |
| VideoProviderInterface* video_provider) |
| : audio_provider_(audio_provider), |
| video_provider_(video_provider) { |
| } |
| |
| MediaStreamHandlerContainer::~MediaStreamHandlerContainer() { |
| ASSERT(remote_streams_handlers_.empty()); |
| ASSERT(local_streams_handlers_.empty()); |
| } |
| |
| void MediaStreamHandlerContainer::TearDown() { |
| for (StreamHandlerList::iterator it = remote_streams_handlers_.begin(); |
| it != remote_streams_handlers_.end(); ++it) { |
| (*it)->Stop(); |
| delete *it; |
| } |
| remote_streams_handlers_.clear(); |
| for (StreamHandlerList::iterator it = local_streams_handlers_.begin(); |
| it != local_streams_handlers_.end(); ++it) { |
| (*it)->Stop(); |
| delete *it; |
| } |
| local_streams_handlers_.clear(); |
| } |
| |
| void MediaStreamHandlerContainer::RemoveRemoteStream( |
| MediaStreamInterface* stream) { |
| DeleteStreamHandler(&remote_streams_handlers_, stream); |
| } |
| |
| void MediaStreamHandlerContainer::AddRemoteAudioTrack( |
| MediaStreamInterface* stream, |
| AudioTrackInterface* audio_track, |
| uint32 ssrc) { |
| MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_, |
| stream); |
| if (handler == NULL) { |
| handler = CreateRemoteStreamHandler(stream); |
| } |
| handler->AddAudioTrack(audio_track, ssrc); |
| } |
| |
| void MediaStreamHandlerContainer::AddRemoteVideoTrack( |
| MediaStreamInterface* stream, |
| VideoTrackInterface* video_track, |
| uint32 ssrc) { |
| MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_, |
| stream); |
| if (handler == NULL) { |
| handler = CreateRemoteStreamHandler(stream); |
| } |
| handler->AddVideoTrack(video_track, ssrc); |
| } |
| |
| void MediaStreamHandlerContainer::RemoveRemoteTrack( |
| MediaStreamInterface* stream, |
| MediaStreamTrackInterface* track) { |
| MediaStreamHandler* handler = FindStreamHandler(remote_streams_handlers_, |
| stream); |
| if (!VERIFY(handler != NULL)) { |
| LOG(LS_WARNING) << "Local MediaStreamHandler for stream with id " |
| << stream->label() << "doesnt't exist."; |
| return; |
| } |
| handler->RemoveTrack(track); |
| } |
| |
| void MediaStreamHandlerContainer::RemoveLocalStream( |
| MediaStreamInterface* stream) { |
| DeleteStreamHandler(&local_streams_handlers_, stream); |
| } |
| |
| void MediaStreamHandlerContainer::AddLocalAudioTrack( |
| MediaStreamInterface* stream, |
| AudioTrackInterface* audio_track, |
| uint32 ssrc) { |
| MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_, |
| stream); |
| if (handler == NULL) { |
| handler = CreateLocalStreamHandler(stream); |
| } |
| handler->AddAudioTrack(audio_track, ssrc); |
| } |
| |
| void MediaStreamHandlerContainer::AddLocalVideoTrack( |
| MediaStreamInterface* stream, |
| VideoTrackInterface* video_track, |
| uint32 ssrc) { |
| MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_, |
| stream); |
| if (handler == NULL) { |
| handler = CreateLocalStreamHandler(stream); |
| } |
| handler->AddVideoTrack(video_track, ssrc); |
| } |
| |
| void MediaStreamHandlerContainer::RemoveLocalTrack( |
| MediaStreamInterface* stream, |
| MediaStreamTrackInterface* track) { |
| MediaStreamHandler* handler = FindStreamHandler(local_streams_handlers_, |
| stream); |
| if (!VERIFY(handler != NULL)) { |
| LOG(LS_WARNING) << "Remote MediaStreamHandler for stream with id " |
| << stream->label() << "doesnt't exist."; |
| return; |
| } |
| handler->RemoveTrack(track); |
| } |
| |
| MediaStreamHandler* MediaStreamHandlerContainer::CreateRemoteStreamHandler( |
| MediaStreamInterface* stream) { |
| ASSERT(!FindStreamHandler(remote_streams_handlers_, stream)); |
| |
| RemoteMediaStreamHandler* handler = |
| new RemoteMediaStreamHandler(stream, audio_provider_, video_provider_); |
| remote_streams_handlers_.push_back(handler); |
| return handler; |
| } |
| |
| MediaStreamHandler* MediaStreamHandlerContainer::CreateLocalStreamHandler( |
| MediaStreamInterface* stream) { |
| ASSERT(!FindStreamHandler(local_streams_handlers_, stream)); |
| |
| LocalMediaStreamHandler* handler = |
| new LocalMediaStreamHandler(stream, audio_provider_, video_provider_); |
| local_streams_handlers_.push_back(handler); |
| return handler; |
| } |
| |
| MediaStreamHandler* MediaStreamHandlerContainer::FindStreamHandler( |
| const StreamHandlerList& handlers, |
| MediaStreamInterface* stream) { |
| StreamHandlerList::const_iterator it = handlers.begin(); |
| for (; it != handlers.end(); ++it) { |
| if ((*it)->stream() == stream) { |
| return *it; |
| } |
| } |
| return NULL; |
| } |
| |
| void MediaStreamHandlerContainer::DeleteStreamHandler( |
| StreamHandlerList* streamhandlers, MediaStreamInterface* stream) { |
| StreamHandlerList::iterator it = streamhandlers->begin(); |
| for (; it != streamhandlers->end(); ++it) { |
| if ((*it)->stream() == stream) { |
| (*it)->Stop(); |
| delete *it; |
| streamhandlers->erase(it); |
| break; |
| } |
| } |
| } |
| |
| } // namespace webrtc |