9cf037b831
R=mallinath@webrtc.org Review URL: https://webrtc-codereview.appspot.com/8139004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5502 4adac7df-926f-26a2-2b94-8c16560cd09d
471 lines
15 KiB
C++
471 lines
15 KiB
C++
/*
|
|
* 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() {}
|
|
|
|
void LocalAudioSinkAdapter::OnData(const void* audio_data,
|
|
int bits_per_sample,
|
|
int sample_rate,
|
|
int number_of_channels,
|
|
int number_of_frames) {
|
|
talk_base::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) {
|
|
talk_base::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()) {
|
|
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) {
|
|
OnEnabledChanged();
|
|
}
|
|
|
|
RemoteAudioTrackHandler::~RemoteAudioTrackHandler() {
|
|
}
|
|
|
|
void RemoteAudioTrackHandler::Stop() {
|
|
provider_->SetAudioPlayout(ssrc(), false, NULL);
|
|
}
|
|
|
|
void RemoteAudioTrackHandler::OnStateChanged() {
|
|
}
|
|
|
|
void RemoteAudioTrackHandler::OnEnabledChanged() {
|
|
provider_->SetAudioPlayout(ssrc(), audio_track_->enabled(),
|
|
audio_track_->GetRenderer());
|
|
}
|
|
|
|
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
|