Chromium Code Reviews| Index: talk/app/webrtc/remoteaudiosource.cc | 
| diff --git a/talk/app/webrtc/remoteaudiosource.cc b/talk/app/webrtc/remoteaudiosource.cc | 
| index 41f3d8798a912bb24e897f54c250ab3ed38494c6..a71f26926ee3c57d6950eff3e32710966bb1e25f 100644 | 
| --- a/talk/app/webrtc/remoteaudiosource.cc | 
| +++ b/talk/app/webrtc/remoteaudiosource.cc | 
| @@ -30,43 +30,125 @@ | 
| #include <algorithm> | 
| #include <functional> | 
| +#include "talk/app/webrtc/mediastreamprovider.h" | 
| +#include "webrtc/base/checks.h" | 
| #include "webrtc/base/logging.h" | 
| +#include "webrtc/base/thread.h" | 
| namespace webrtc { | 
| -rtc::scoped_refptr<RemoteAudioSource> RemoteAudioSource::Create() { | 
| - return new rtc::RefCountedObject<RemoteAudioSource>(); | 
| +class RemoteAudioSource::MessageHandler : public rtc::MessageHandler { | 
| + public: | 
| + MessageHandler(RemoteAudioSource* source) : source_(source) {} | 
| + | 
| + private: | 
| + ~MessageHandler() override {} | 
| + | 
| + void OnMessage(rtc::Message* msg) override { | 
| + source_->OnMessage(msg); | 
| + delete this; | 
| + } | 
| + | 
| + const rtc::scoped_refptr<RemoteAudioSource> source_; | 
| + RTC_DISALLOW_COPY_AND_ASSIGN(MessageHandler); | 
| +}; | 
| + | 
| +rtc::scoped_refptr<RemoteAudioSource> RemoteAudioSource::Create( | 
| + uint32_t ssrc, | 
| + AudioProviderInterface* provider) { | 
| + return new rtc::RefCountedObject<RemoteAudioSource>(ssrc, provider); | 
| } | 
| -RemoteAudioSource::RemoteAudioSource() { | 
| +RemoteAudioSource::RemoteAudioSource(uint32_t ssrc, | 
| + AudioProviderInterface* provider) | 
| + : ssrc_(ssrc), provider_(provider), main_thread_(rtc::Thread::Current()), | 
| + state_(MediaSourceInterface::kLive) { | 
| + RTC_DCHECK(provider_); | 
| + RTC_DCHECK(main_thread_); | 
| } | 
| RemoteAudioSource::~RemoteAudioSource() { | 
| - ASSERT(audio_observers_.empty()); | 
| + RTC_DCHECK(main_thread_->IsCurrent()); | 
| + RTC_DCHECK(audio_observers_.empty()); | 
| + RTC_DCHECK(sinks_.empty()); | 
| } | 
| MediaSourceInterface::SourceState RemoteAudioSource::state() const { | 
| - return MediaSourceInterface::kLive; | 
| + return state_; | 
| } | 
| void RemoteAudioSource::SetVolume(double volume) { | 
| - ASSERT(volume >= 0 && volume <= 10); | 
| - for (AudioObserverList::iterator it = audio_observers_.begin(); | 
| - it != audio_observers_.end(); ++it) { | 
| - (*it)->OnSetVolume(volume); | 
| + RTC_DCHECK(volume >= 0 && volume <= 10); | 
| + for (auto* observer : audio_observers_) { | 
| + observer->OnSetVolume(volume); | 
| } | 
| } | 
| void RemoteAudioSource::RegisterAudioObserver(AudioObserver* observer) { | 
| - ASSERT(observer != NULL); | 
| - ASSERT(std::find(audio_observers_.begin(), audio_observers_.end(), | 
| + RTC_DCHECK(observer != NULL); | 
| + RTC_DCHECK(std::find(audio_observers_.begin(), audio_observers_.end(), | 
| observer) == audio_observers_.end()); | 
| audio_observers_.push_back(observer); | 
| } | 
| void RemoteAudioSource::UnregisterAudioObserver(AudioObserver* observer) { | 
| - ASSERT(observer != NULL); | 
| + RTC_DCHECK(observer != NULL); | 
| audio_observers_.remove(observer); | 
| } | 
| +void RemoteAudioSource::AddSink(AudioTrackSinkInterface* sink) { | 
| + RTC_DCHECK(main_thread_->IsCurrent()); | 
| + RTC_DCHECK(sink); | 
| + RTC_DCHECK(state_ == MediaSourceInterface::kLive); | 
| + | 
| + if (!provider_) { | 
| + LOG(LS_ERROR) << "No audio provider, so can't set an audio sink."; | 
| + return; | 
| + } | 
| + | 
| + if (sinks_.empty()) | 
| + provider_->SetRawAudioSink(ssrc_, this); | 
| + | 
| + rtc::CritScope lock(&sink_lock_); | 
| + RTC_DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()); | 
| + sinks_.push_back(sink); | 
| +} | 
| + | 
| +void RemoteAudioSource::RemoveSink(AudioTrackSinkInterface* sink) { | 
| + RTC_DCHECK(main_thread_->IsCurrent()); | 
| + RTC_DCHECK(sink); | 
| + { | 
| + rtc::CritScope lock(&sink_lock_); | 
| + sinks_.remove(sink); | 
| + } | 
| + | 
| + if (sinks_.empty() && provider_) | 
| + provider_->SetRawAudioSink(ssrc_, nullptr); | 
| +} | 
| + | 
| +void RemoteAudioSource::OnData(const void* audio_data, | 
| + int bits_per_sample, | 
| + int sample_rate, | 
| + int number_of_channels, | 
| + size_t number_of_frames) { | 
| + // Called on the externally-owned audio callback thread, via/from webrtc. | 
| + rtc::CritScope lock(&sink_lock_); | 
| + for (auto* sink : sinks_) { | 
| + sink->OnData(audio_data, bits_per_sample, sample_rate, number_of_channels, | 
| + number_of_frames); | 
| + } | 
| +} | 
| + | 
| +void RemoteAudioSource::OnClose() { | 
| 
 
perkj_webrtc
2015/12/10 12:24:05
What triggers this?
 
tommi
2015/12/10 22:37:25
Deletion of the session.  It tears down the voice
 
 | 
| + main_thread_->Post(new MessageHandler(this)); | 
| 
 
perkj_webrtc
2015/12/10 12:24:05
use async_invoker instead. You don't need the Mess
 
tommi
2015/12/10 22:37:25
I started doing that but I'm hesitating.  Have you
 
 | 
| +} | 
| + | 
| +void RemoteAudioSource::OnMessage(rtc::Message* msg) { | 
| + RTC_DCHECK(main_thread_->IsCurrent()); | 
| + provider_ = nullptr; | 
| + sinks_.clear(); | 
| + state_ = MediaSourceInterface::kEnded; | 
| + FireOnChanged(); | 
| +} | 
| + | 
| } // namespace webrtc |