diff options
author | miu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-17 23:09:42 +0000 |
---|---|---|
committer | miu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-17 23:09:42 +0000 |
commit | f59611433c645e16dd9b61413ef1a1da19ee1921 (patch) | |
tree | 36d81dc6de6d8afef96d44a8a8580e73c1346e55 /content/renderer | |
parent | fac11ee05e9b95d043df09627f560fec75411436 (diff) | |
download | chromium_src-f59611433c645e16dd9b61413ef1a1da19ee1921.zip chromium_src-f59611433c645e16dd9b61413ef1a1da19ee1921.tar.gz chromium_src-f59611433c645e16dd9b61413ef1a1da19ee1921.tar.bz2 |
Merge AssociateStreamWithProducer message into CreateStream message for both audio output and input.
Also:
1. Removed RendererAudioOutputDevice class, since it's no longer necessary to manage asynchronously associating a render view with a stream.
2. Clean-ups: Applied several changes/bug fixes to bring the audio input classes/impls up-to-date w.r.t. the audio output classes/impls. Filed bug 179597 for follow-up.
3. Added missing plumbing for associating audio input devices created by WebRtcAudioCapturer to render views.
4. Updated unit tests.
BUG=166779
TEST=media_unittests, content_unittests, TSAN, chrome/test/functional/webrtc_*.py, and manual testing described in http://codereview.chromium.org/11359196/
Review URL: https://codereview.chromium.org/12383016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194711 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
30 files changed, 359 insertions, 404 deletions
diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc index fae521e..927a85f 100644 --- a/content/renderer/media/audio_device_factory.cc +++ b/content/renderer/media/audio_device_factory.cc @@ -7,8 +7,8 @@ #include "base/logging.h" #include "content/renderer/media/audio_input_message_filter.h" #include "content/renderer/media/audio_message_filter.h" -#include "content/renderer/media/renderer_audio_output_device.h" #include "media/audio/audio_input_device.h" +#include "media/audio/audio_output_device.h" namespace content { @@ -16,24 +16,33 @@ namespace content { AudioDeviceFactory* AudioDeviceFactory::factory_ = NULL; // static -scoped_refptr<RendererAudioOutputDevice> AudioDeviceFactory::NewOutputDevice() { - RendererAudioOutputDevice* device = NULL; - if (factory_) - device = factory_->CreateOutputDevice(); - - return device ? device : new RendererAudioOutputDevice( - AudioMessageFilter::Get(), AudioMessageFilter::Get()->io_message_loop()); +scoped_refptr<media::AudioOutputDevice> AudioDeviceFactory::NewOutputDevice( + int render_view_id) { + if (factory_) { + media::AudioOutputDevice* const device = + factory_->CreateOutputDevice(render_view_id); + if (device) + return device; + } + + AudioMessageFilter* const filter = AudioMessageFilter::Get(); + return new media::AudioOutputDevice( + filter->CreateAudioOutputIPC(render_view_id), filter->io_message_loop()); } // static -scoped_refptr<media::AudioInputDevice> AudioDeviceFactory::NewInputDevice() { - media::AudioInputDevice* device = NULL; - if (factory_) - device = factory_->CreateInputDevice(); - - return device ? device : new media::AudioInputDevice( - AudioInputMessageFilter::Get(), - AudioInputMessageFilter::Get()->io_message_loop()); +scoped_refptr<media::AudioInputDevice> AudioDeviceFactory::NewInputDevice( + int render_view_id) { + if (factory_) { + media::AudioInputDevice* const device = + factory_->CreateInputDevice(render_view_id); + if (device) + return device; + } + + AudioInputMessageFilter* const filter = AudioInputMessageFilter::Get(); + return new media::AudioInputDevice( + filter->CreateAudioInputIPC(render_view_id), filter->io_message_loop()); } AudioDeviceFactory::AudioDeviceFactory() { diff --git a/content/renderer/media/audio_device_factory.h b/content/renderer/media/audio_device_factory.h index b06ace7..46bf5f9 100644 --- a/content/renderer/media/audio_device_factory.h +++ b/content/renderer/media/audio_device_factory.h @@ -10,22 +10,27 @@ namespace media { class AudioInputDevice; +class AudioOutputDevice; } namespace content { -class RendererAudioOutputDevice; - -// A factory for creating RendererAudioOutputDevices. There is a global factory -// function that can be installed for the purposes of testing to provide -// a specialized AudioRendererSink class. +// A factory for creating AudioOutputDevices and AudioInputDevices. There is a +// global factory function that can be installed for the purposes of testing to +// provide specialized implementations. class AudioDeviceFactory { public: - // Creates a RendererAudioOutputDevice using the currently registered factory. - static scoped_refptr<RendererAudioOutputDevice> NewOutputDevice(); - - // Creates an AudioInputDevice using the currently registered factory, - static scoped_refptr<media::AudioInputDevice> NewInputDevice(); + // Creates an AudioOutputDevice using the currently registered factory. + // |render_view_id| refers to the render view containing the entity producing + // the audio. + static scoped_refptr<media::AudioOutputDevice> NewOutputDevice( + int render_view_id); + + // Creates an AudioInputDevice using the currently registered factory. + // |render_view_id| refers to the render view containing the entity consuming + // the audio. + static scoped_refptr<media::AudioInputDevice> NewInputDevice( + int render_view_id); protected: AudioDeviceFactory(); @@ -35,8 +40,8 @@ class AudioDeviceFactory { // functions to provide alternate audio device implementations. // If the return value of either of these function is NULL, we fall back // on the default implementation. - virtual RendererAudioOutputDevice* CreateOutputDevice() = 0; - virtual media::AudioInputDevice* CreateInputDevice() = 0; + virtual media::AudioOutputDevice* CreateOutputDevice(int render_view_id) = 0; + virtual media::AudioInputDevice* CreateInputDevice(int render_view_id) = 0; private: // The current globally registered factory. This is NULL when we should diff --git a/content/renderer/media/audio_input_message_filter.cc b/content/renderer/media/audio_input_message_filter.cc index 038edf3..2b78e2c 100644 --- a/content/renderer/media/audio_input_message_filter.cc +++ b/content/renderer/media/audio_input_message_filter.cc @@ -11,24 +11,51 @@ namespace content { -AudioInputMessageFilter* AudioInputMessageFilter::filter_ = NULL; +namespace { +const int kStreamIDNotSet = -1; +} + +class AudioInputMessageFilter::AudioInputIPCImpl + : public NON_EXPORTED_BASE(media::AudioInputIPC) { + public: + AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter>& filter, + int render_view_id); + virtual ~AudioInputIPCImpl(); + + // media::AudioInputIPC implementation. + virtual void CreateStream(media::AudioInputIPCDelegate* delegate, + int session_id, + const media::AudioParameters& params, + bool automatic_gain_control, + uint32 total_segments) OVERRIDE; + virtual void RecordStream() OVERRIDE; + virtual void SetVolume(double volume) OVERRIDE; + virtual void CloseStream() OVERRIDE; + + private: + const scoped_refptr<AudioInputMessageFilter> filter_; + const int render_view_id_; + int stream_id_; +}; + +AudioInputMessageFilter* AudioInputMessageFilter::g_filter = NULL; AudioInputMessageFilter::AudioInputMessageFilter( const scoped_refptr<base::MessageLoopProxy>& io_message_loop) : channel_(NULL), io_message_loop_(io_message_loop) { - DCHECK(!filter_); - filter_ = this; + DCHECK(!g_filter); + g_filter = this; } AudioInputMessageFilter::~AudioInputMessageFilter() { - DCHECK_EQ(filter_, this); - filter_ = NULL; + DCHECK_EQ(g_filter, this); + g_filter = NULL; } -// static. +// static AudioInputMessageFilter* AudioInputMessageFilter::Get() { - return filter_; + return g_filter; } void AudioInputMessageFilter::Send(IPC::Message* message) { @@ -134,43 +161,56 @@ void AudioInputMessageFilter::OnStreamStateChanged( delegate->OnStateChanged(state); } -int AudioInputMessageFilter::AddDelegate( - media::AudioInputIPCDelegate* delegate) { - DCHECK(io_message_loop_->BelongsToCurrentThread()); - return delegates_.Add(delegate); -} +AudioInputMessageFilter::AudioInputIPCImpl::AudioInputIPCImpl( + const scoped_refptr<AudioInputMessageFilter>& filter, int render_view_id) + : filter_(filter), + render_view_id_(render_view_id), + stream_id_(kStreamIDNotSet) {} -void AudioInputMessageFilter::RemoveDelegate(int id) { - DCHECK(io_message_loop_->BelongsToCurrentThread()); - delegates_.Remove(id); +AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {} + +scoped_ptr<media::AudioInputIPC> AudioInputMessageFilter::CreateAudioInputIPC( + int render_view_id) { + DCHECK_GT(render_view_id, 0); + return scoped_ptr<media::AudioInputIPC>( + new AudioInputIPCImpl(this, render_view_id)); } -void AudioInputMessageFilter::CreateStream(int stream_id, - int session_id, - const media::AudioParameters& params, - bool automatic_gain_control, - uint32 total_segments) { - Send(new AudioInputHostMsg_CreateStream( - stream_id, session_id, params, automatic_gain_control, total_segments)); +void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream( + media::AudioInputIPCDelegate* delegate, + int session_id, + const media::AudioParameters& params, + bool automatic_gain_control, + uint32 total_segments) { + DCHECK(filter_->io_message_loop_->BelongsToCurrentThread()); + DCHECK(delegate); -} + stream_id_ = filter_->delegates_.Add(delegate); -void AudioInputMessageFilter::AssociateStreamWithConsumer(int stream_id, - int render_view_id) { - Send(new AudioInputHostMsg_AssociateStreamWithConsumer( - stream_id, render_view_id)); + AudioInputHostMsg_CreateStream_Config config; + config.params = params; + config.automatic_gain_control = automatic_gain_control; + config.shared_memory_count = total_segments; + filter_->Send(new AudioInputHostMsg_CreateStream( + stream_id_, render_view_id_, session_id, config)); } -void AudioInputMessageFilter::RecordStream(int stream_id) { - Send(new AudioInputHostMsg_RecordStream(stream_id)); +void AudioInputMessageFilter::AudioInputIPCImpl::RecordStream() { + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_)); } -void AudioInputMessageFilter::CloseStream(int stream_id) { - Send(new AudioInputHostMsg_CloseStream(stream_id)); +void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) { + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioInputHostMsg_SetVolume(stream_id_, volume)); } -void AudioInputMessageFilter::SetVolume(int stream_id, double volume) { - Send(new AudioInputHostMsg_SetVolume(stream_id, volume)); +void AudioInputMessageFilter::AudioInputIPCImpl::CloseStream() { + DCHECK(filter_->io_message_loop_->BelongsToCurrentThread()); + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_)); + filter_->delegates_.Remove(stream_id_); + stream_id_ = kStreamIDNotSet; } } // namespace content diff --git a/content/renderer/media/audio_input_message_filter.h b/content/renderer/media/audio_input_message_filter.h index bd6a0e12..fcba0a7 100644 --- a/content/renderer/media/audio_input_message_filter.h +++ b/content/renderer/media/audio_input_message_filter.h @@ -6,6 +6,7 @@ #define CONTENT_RENDERER_MEDIA_AUDIO_INPUT_MESSAGE_FILTER_H_ #include "base/id_map.h" +#include "base/memory/scoped_ptr.h" #include "base/shared_memory.h" #include "base/sync_socket.h" #include "content/common/content_export.h" @@ -23,8 +24,7 @@ namespace content { // IO thread (secondary thread of render process), it intercepts audio messages // and process them on IO thread since these messages are time critical. class CONTENT_EXPORT AudioInputMessageFilter - : public IPC::ChannelProxy::MessageFilter, - public NON_EXPORTED_BASE(media::AudioInputIPC) { + : public IPC::ChannelProxy::MessageFilter { public: explicit AudioInputMessageFilter( const scoped_refptr<base::MessageLoopProxy>& io_message_loop); @@ -32,29 +32,22 @@ class CONTENT_EXPORT AudioInputMessageFilter // Getter for the one AudioInputMessageFilter object. static AudioInputMessageFilter* Get(); - // Associates |render_view_id| as the destination of audio for a stream. - void AssociateStreamWithConsumer(int stream_id, int render_view_id); - - // Implementation of AudioInputIPC. All methods must be called on the - // provided |io_message_loop|. - virtual int AddDelegate( - media::AudioInputIPCDelegate* delegate) OVERRIDE; - virtual void RemoveDelegate(int id) OVERRIDE; - virtual void CreateStream( - int stream_id, - int session_id, - const media::AudioParameters& params, - bool automatic_gain_control, - uint32 total_segments) OVERRIDE; - virtual void RecordStream(int stream_id) OVERRIDE; - virtual void CloseStream(int stream_id) OVERRIDE; - virtual void SetVolume(int stream_id, double volume) OVERRIDE; + // Create an AudioInputIPC to be owned by one delegate. |render_view_id| is + // the render view containing the entity consuming the audio. + // + // The returned object is not thread-safe, and must be used on + // |io_message_loop|. + scoped_ptr<media::AudioInputIPC> CreateAudioInputIPC(int render_view_id); scoped_refptr<base::MessageLoopProxy> io_message_loop() const { return io_message_loop_; } private: + // Implementation of media::AudioInputIPC which augments IPC calls with + // stream_id and the destination render_view_id. + class AudioInputIPCImpl; + virtual ~AudioInputMessageFilter(); // Sends an IPC message using |channel_|. @@ -91,12 +84,12 @@ class CONTENT_EXPORT AudioInputMessageFilter // IPC channel for Send(), must only be accesed on |io_message_loop_|. IPC::Channel* channel_; - // The singleton instance for this filter. - static AudioInputMessageFilter* filter_; - // Message loop on which IPC calls are driven. const scoped_refptr<base::MessageLoopProxy> io_message_loop_; + // The singleton instance for this filter. + static AudioInputMessageFilter* g_filter; + DISALLOW_COPY_AND_ASSIGN(AudioInputMessageFilter); }; diff --git a/content/renderer/media/audio_message_filter.cc b/content/renderer/media/audio_message_filter.cc index a3bcf65..1cb5352 100644 --- a/content/renderer/media/audio_message_filter.cc +++ b/content/renderer/media/audio_message_filter.cc @@ -12,56 +12,99 @@ namespace content { -AudioMessageFilter* AudioMessageFilter::filter_ = NULL; - -// static -AudioMessageFilter* AudioMessageFilter::Get() { - return filter_; +namespace { +const int kStreamIDNotSet = -1; } +class AudioMessageFilter::AudioOutputIPCImpl + : public NON_EXPORTED_BASE(media::AudioOutputIPC) { + public: + AudioOutputIPCImpl(const scoped_refptr<AudioMessageFilter>& filter, + int render_view_id); + virtual ~AudioOutputIPCImpl(); + + // media::AudioOutputIPC implementation. + virtual void CreateStream(media::AudioOutputIPCDelegate* delegate, + const media::AudioParameters& params) OVERRIDE; + virtual void PlayStream() OVERRIDE; + virtual void PauseStream() OVERRIDE; + virtual void CloseStream() OVERRIDE; + virtual void SetVolume(double volume) OVERRIDE; + + private: + const scoped_refptr<AudioMessageFilter> filter_; + const int render_view_id_; + int stream_id_; +}; + +AudioMessageFilter* AudioMessageFilter::g_filter = NULL; + AudioMessageFilter::AudioMessageFilter( const scoped_refptr<base::MessageLoopProxy>& io_message_loop) : channel_(NULL), audio_hardware_config_(NULL), io_message_loop_(io_message_loop) { - DCHECK(!filter_); - filter_ = this; + DCHECK(!g_filter); + g_filter = this; } -int AudioMessageFilter::AddDelegate(media::AudioOutputIPCDelegate* delegate) { - DCHECK(io_message_loop_->BelongsToCurrentThread()); - return delegates_.Add(delegate); +AudioMessageFilter::~AudioMessageFilter() { + DCHECK_EQ(g_filter, this); + g_filter = NULL; } -void AudioMessageFilter::RemoveDelegate(int id) { - DCHECK(io_message_loop_->BelongsToCurrentThread()); - delegates_.Remove(id); +// static +AudioMessageFilter* AudioMessageFilter::Get() { + return g_filter; } -void AudioMessageFilter::CreateStream(int stream_id, - const media::AudioParameters& params) { - Send(new AudioHostMsg_CreateStream(stream_id, params)); +AudioMessageFilter::AudioOutputIPCImpl::AudioOutputIPCImpl( + const scoped_refptr<AudioMessageFilter>& filter, int render_view_id) + : filter_(filter), + render_view_id_(render_view_id), + stream_id_(kStreamIDNotSet) {} + +AudioMessageFilter::AudioOutputIPCImpl::~AudioOutputIPCImpl() {} + +scoped_ptr<media::AudioOutputIPC> AudioMessageFilter::CreateAudioOutputIPC( + int render_view_id) { + DCHECK_GT(render_view_id, 0); + return scoped_ptr<media::AudioOutputIPC>( + new AudioOutputIPCImpl(this, render_view_id)); } -void AudioMessageFilter::AssociateStreamWithProducer(int stream_id, - int render_view_id) { - Send(new AudioHostMsg_AssociateStreamWithProducer(stream_id, render_view_id)); +void AudioMessageFilter::AudioOutputIPCImpl::CreateStream( + media::AudioOutputIPCDelegate* delegate, + const media::AudioParameters& params) { + DCHECK(filter_->io_message_loop_->BelongsToCurrentThread()); + DCHECK(delegate); + DCHECK_EQ(stream_id_, kStreamIDNotSet); + stream_id_ = filter_->delegates_.Add(delegate); + filter_->Send(new AudioHostMsg_CreateStream( + stream_id_, render_view_id_, params)); } -void AudioMessageFilter::PlayStream(int stream_id) { - Send(new AudioHostMsg_PlayStream(stream_id)); +void AudioMessageFilter::AudioOutputIPCImpl::PlayStream() { + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioHostMsg_PlayStream(stream_id_)); } -void AudioMessageFilter::PauseStream(int stream_id) { - Send(new AudioHostMsg_PauseStream(stream_id)); +void AudioMessageFilter::AudioOutputIPCImpl::PauseStream() { + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioHostMsg_PauseStream(stream_id_)); } -void AudioMessageFilter::CloseStream(int stream_id) { - Send(new AudioHostMsg_CloseStream(stream_id)); +void AudioMessageFilter::AudioOutputIPCImpl::CloseStream() { + DCHECK(filter_->io_message_loop_->BelongsToCurrentThread()); + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioHostMsg_CloseStream(stream_id_)); + filter_->delegates_.Remove(stream_id_); + stream_id_ = kStreamIDNotSet; } -void AudioMessageFilter::SetVolume(int stream_id, double volume) { - Send(new AudioHostMsg_SetVolume(stream_id, volume)); +void AudioMessageFilter::AudioOutputIPCImpl::SetVolume(double volume) { + DCHECK_NE(stream_id_, kStreamIDNotSet); + filter_->Send(new AudioHostMsg_SetVolume(stream_id_, volume)); } void AudioMessageFilter::Send(IPC::Message* message) { @@ -113,11 +156,6 @@ void AudioMessageFilter::OnChannelClosing() { } } -AudioMessageFilter::~AudioMessageFilter() { - DCHECK_EQ(filter_, this); - filter_ = NULL; -} - void AudioMessageFilter::OnStreamCreated( int stream_id, base::SharedMemoryHandle handle, diff --git a/content/renderer/media/audio_message_filter.h b/content/renderer/media/audio_message_filter.h index d60c80c..38deb80 100644 --- a/content/renderer/media/audio_message_filter.h +++ b/content/renderer/media/audio_message_filter.h @@ -7,6 +7,7 @@ #include "base/gtest_prod_util.h" #include "base/id_map.h" +#include "base/memory/scoped_ptr.h" #include "base/shared_memory.h" #include "base/sync_socket.h" #include "base/synchronization/lock.h" @@ -26,8 +27,7 @@ namespace content { // IO thread (secondary thread of render process) it intercepts audio messages // and process them on IO thread since these messages are time critical. class CONTENT_EXPORT AudioMessageFilter - : public IPC::ChannelProxy::MessageFilter, - public NON_EXPORTED_BASE(media::AudioOutputIPC) { + : public IPC::ChannelProxy::MessageFilter { public: explicit AudioMessageFilter( const scoped_refptr<base::MessageLoopProxy>& io_message_loop); @@ -35,26 +35,12 @@ class CONTENT_EXPORT AudioMessageFilter // Getter for the one AudioMessageFilter object. static AudioMessageFilter* Get(); - // Associates |render_view_id| as the source of audio rendered for a stream. - void AssociateStreamWithProducer(int stream_id, int render_view_id); - - // media::AudioOutputIPC implementation. - virtual int AddDelegate(media::AudioOutputIPCDelegate* delegate) OVERRIDE; - virtual void RemoveDelegate(int id) OVERRIDE; - - // Methods below must be called on the provided |io_message_loop|. - virtual void CreateStream(int stream_id, - const media::AudioParameters& params) OVERRIDE; - virtual void PlayStream(int stream_id) OVERRIDE; - virtual void PauseStream(int stream_id) OVERRIDE; - virtual void CloseStream(int stream_id) OVERRIDE; - virtual void SetVolume(int stream_id, double volume) OVERRIDE; - - // IPC::ChannelProxy::MessageFilter override. Called on |io_message_loop|. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; - virtual void OnFilterRemoved() OVERRIDE; - virtual void OnChannelClosing() OVERRIDE; + // Create an AudioOutputIPC to be owned by one delegate. |render_view_id| is + // the render view containing the entity producing the audio. + // + // The returned object is not thread-safe, and must be used on + // |io_message_loop|. + scoped_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(int render_view_id); // When set, AudioMessageFilter will update the AudioHardwareConfig with new // configuration values as recieved by OnOutputDeviceChanged(). The provided @@ -73,9 +59,19 @@ class CONTENT_EXPORT AudioMessageFilter FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Basic); FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Delegates); + // Implementation of media::AudioOutputIPC which augments IPC calls with + // stream_id and the source render_view_id. + class AudioOutputIPCImpl; + // Sends an IPC message using |channel_|. void Send(IPC::Message* message); + // IPC::ChannelProxy::MessageFilter override. Called on |io_message_loop|. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; + virtual void OnFilterRemoved() OVERRIDE; + virtual void OnChannelClosing() OVERRIDE; + // Received when browser process has created an audio output stream. void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle, #if defined(OS_WIN) @@ -94,9 +90,6 @@ class CONTENT_EXPORT AudioMessageFilter void OnOutputDeviceChanged(int stream_id, int new_buffer_size, int new_sample_rate); - // The singleton instance for this filter. - static AudioMessageFilter* filter_; - // IPC channel for Send(); must only be accesed on |io_message_loop_|. IPC::Channel* channel_; @@ -112,6 +105,9 @@ class CONTENT_EXPORT AudioMessageFilter // Message loop on which IPC calls are driven. const scoped_refptr<base::MessageLoopProxy> io_message_loop_; + // The singleton instance for this filter. + static AudioMessageFilter* g_filter; + DISALLOW_COPY_AND_ASSIGN(AudioMessageFilter); }; diff --git a/content/renderer/media/audio_message_filter_unittest.cc b/content/renderer/media/audio_message_filter_unittest.cc index 4626a64..65ca209 100644 --- a/content/renderer/media/audio_message_filter_unittest.cc +++ b/content/renderer/media/audio_message_filter_unittest.cc @@ -11,6 +11,8 @@ namespace content { namespace { +const int kRenderViewId = 1; + class MockAudioDelegate : public media::AudioOutputIPCDelegate { public: MockAudioDelegate() { @@ -75,7 +77,11 @@ TEST(AudioMessageFilterTest, Basic) { message_loop.message_loop_proxy())); MockAudioDelegate delegate; - int stream_id = filter->AddDelegate(&delegate); + const scoped_ptr<media::AudioOutputIPC> ipc = + filter->CreateAudioOutputIPC(kRenderViewId); + ipc->CreateStream(&delegate, media::AudioParameters()); + static const int kStreamId = 1; + EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId)); // AudioMsg_NotifyStreamCreated #if defined(OS_WIN) @@ -87,7 +93,7 @@ TEST(AudioMessageFilterTest, Basic) { EXPECT_FALSE(delegate.created_received()); filter->OnMessageReceived( AudioMsg_NotifyStreamCreated( - stream_id, base::SharedMemory::NULLHandle(), + kStreamId, base::SharedMemory::NULLHandle(), socket_handle, kLength)); EXPECT_TRUE(delegate.created_received()); EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle())); @@ -98,13 +104,16 @@ TEST(AudioMessageFilterTest, Basic) { EXPECT_FALSE(delegate.state_changed_received()); filter->OnMessageReceived( AudioMsg_NotifyStreamStateChanged( - stream_id, media::AudioOutputIPCDelegate::kPlaying)); + kStreamId, media::AudioOutputIPCDelegate::kPlaying)); EXPECT_TRUE(delegate.state_changed_received()); EXPECT_EQ(media::AudioOutputIPCDelegate::kPlaying, delegate.state()); delegate.Reset(); message_loop.RunUntilIdle(); - filter->RemoveDelegate(stream_id); + + ipc->CloseStream(); + EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(NULL), + filter->delegates_.Lookup(kStreamId)); } TEST(AudioMessageFilterTest, Delegates) { @@ -115,16 +124,23 @@ TEST(AudioMessageFilterTest, Delegates) { MockAudioDelegate delegate1; MockAudioDelegate delegate2; - - int stream_id1 = filter->AddDelegate(&delegate1); - int stream_id2 = filter->AddDelegate(&delegate2); + const scoped_ptr<media::AudioOutputIPC> ipc1 = + filter->CreateAudioOutputIPC(kRenderViewId); + const scoped_ptr<media::AudioOutputIPC> ipc2 = + filter->CreateAudioOutputIPC(kRenderViewId); + ipc1->CreateStream(&delegate1, media::AudioParameters()); + ipc2->CreateStream(&delegate2, media::AudioParameters()); + static const int kStreamId1 = 1; + static const int kStreamId2 = 2; + EXPECT_EQ(&delegate1, filter->delegates_.Lookup(kStreamId1)); + EXPECT_EQ(&delegate2, filter->delegates_.Lookup(kStreamId2)); // Send an IPC message. Make sure the correct delegate gets called. EXPECT_FALSE(delegate1.state_changed_received()); EXPECT_FALSE(delegate2.state_changed_received()); filter->OnMessageReceived( AudioMsg_NotifyStreamStateChanged( - stream_id1, media::AudioOutputIPCDelegate::kPlaying)); + kStreamId1, media::AudioOutputIPCDelegate::kPlaying)); EXPECT_TRUE(delegate1.state_changed_received()); EXPECT_FALSE(delegate2.state_changed_received()); delegate1.Reset(); @@ -133,15 +149,19 @@ TEST(AudioMessageFilterTest, Delegates) { EXPECT_FALSE(delegate2.state_changed_received()); filter->OnMessageReceived( AudioMsg_NotifyStreamStateChanged( - stream_id2, media::AudioOutputIPCDelegate::kPlaying)); + kStreamId2, media::AudioOutputIPCDelegate::kPlaying)); EXPECT_FALSE(delegate1.state_changed_received()); EXPECT_TRUE(delegate2.state_changed_received()); delegate2.Reset(); message_loop.RunUntilIdle(); - filter->RemoveDelegate(stream_id1); - filter->RemoveDelegate(stream_id2); + ipc1->CloseStream(); + ipc2->CloseStream(); + EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(NULL), + filter->delegates_.Lookup(kStreamId1)); + EXPECT_EQ(static_cast<media::AudioOutputIPCDelegate*>(NULL), + filter->delegates_.Lookup(kStreamId2)); } } // namespace content diff --git a/content/renderer/media/audio_renderer_mixer_manager.cc b/content/renderer/media/audio_renderer_mixer_manager.cc index 2f2433f..7db67d1 100644 --- a/content/renderer/media/audio_renderer_mixer_manager.cc +++ b/content/renderer/media/audio_renderer_mixer_manager.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "content/renderer/media/audio_device_factory.h" -#include "content/renderer/media/renderer_audio_output_device.h" +#include "media/audio/audio_output_device.h" #include "media/base/audio_hardware_config.h" #include "media/base/audio_renderer_mixer.h" #include "media/base/audio_renderer_mixer_input.h" @@ -77,10 +77,9 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( mixer = new media::AudioRendererMixer( params, output_params, sink_for_testing_); } else { - scoped_refptr<RendererAudioOutputDevice> device = - AudioDeviceFactory::NewOutputDevice(); - device->SetSourceRenderView(source_render_view_id); - mixer = new media::AudioRendererMixer(params, output_params, device); + mixer = new media::AudioRendererMixer( + params, output_params, AudioDeviceFactory::NewOutputDevice( + source_render_view_id)); } AudioRendererMixerReference mixer_reference = { mixer, 1 }; diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc index aa9b7dc..332c2b7 100644 --- a/content/renderer/media/media_stream_dependency_factory.cc +++ b/content/renderer/media/media_stream_dependency_factory.cc @@ -227,6 +227,7 @@ MediaStreamDependencyFactory::CreateRTCPeerConnectionHandler( } void MediaStreamDependencyFactory::CreateNativeMediaSources( + int render_view_id, const WebKit::WebMediaConstraints& audio_constraints, const WebKit::WebMediaConstraints& video_constraints, WebKit::WebMediaStream* description, @@ -284,7 +285,7 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources( const StreamDeviceInfo device_info = source_data->device_info(); if (IsAudioMediaType(device_info.device.type)) { - if (!InitializeAudioSource(device_info)) { + if (!InitializeAudioSource(render_view_id, device_info)) { DLOG(WARNING) << "Unsupported audio source"; sources_created.Run(description, false); return; @@ -486,7 +487,8 @@ MediaStreamDependencyFactory::CreateLocalVideoSource( } bool MediaStreamDependencyFactory::InitializeAudioSource( - const StreamDeviceInfo& device_info) { + int render_view_id, + const StreamDeviceInfo& device_info) { DVLOG(1) << "MediaStreamDependencyFactory::InitializeAudioSource()"; // TODO(henrika): the current design does not support a unique source @@ -500,6 +502,7 @@ bool MediaStreamDependencyFactory::InitializeAudioSource( // TODO(henrika): refactor \content\public\common\media_stream_request.h // to allow dependency of media::ChannelLayout and avoid static_cast. if (!capturer->Initialize( + render_view_id, static_cast<media::ChannelLayout>(device_info.device.channel_layout), device_info.device.sample_rate, device_info.session_id)) return false; diff --git a/content/renderer/media/media_stream_dependency_factory.h b/content/renderer/media/media_stream_dependency_factory.h index 2bdd8ff..de7c455 100644 --- a/content/renderer/media/media_stream_dependency_factory.h +++ b/content/renderer/media/media_stream_dependency_factory.h @@ -71,6 +71,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory // WebMediaStreamSource. // |audio_constraints| and |video_constraints| set parameters for the sources. void CreateNativeMediaSources( + int render_view_id, const WebKit::WebMediaConstraints& audio_constraints, const WebKit::WebMediaConstraints& video_constraints, WebKit::WebMediaStream* description, @@ -147,7 +148,8 @@ class CONTENT_EXPORT MediaStreamDependencyFactory // Initializes the source using audio parameters for the selected // capture device and specifies which capture device to use as capture // source. - virtual bool InitializeAudioSource(const StreamDeviceInfo& device_info); + virtual bool InitializeAudioSource(int render_view_id, + const StreamDeviceInfo& device_info); // Creates a media::AudioCapturerSource with an implementation that is // specific for a WebAudio source. The created WebAudioCapturerSource diff --git a/content/renderer/media/media_stream_dependency_factory_unittest.cc b/content/renderer/media/media_stream_dependency_factory_unittest.cc index 879c425..948646d 100644 --- a/content/renderer/media/media_stream_dependency_factory_unittest.cc +++ b/content/renderer/media/media_stream_dependency_factory_unittest.cc @@ -86,9 +86,12 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { } void CreateNativeSources(WebKit::WebMediaStream* descriptor) { + static const int kRenderViewId = 1; + MediaSourceCreatedObserver observer; WebKit::WebMediaConstraints audio_constraints; dependency_factory_->CreateNativeMediaSources( + kRenderViewId, WebKit::WebMediaConstraints(), WebKit::WebMediaConstraints(), descriptor, diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc index 85c8fde..d107480 100644 --- a/content/renderer/media/media_stream_impl.cc +++ b/content/renderer/media/media_stream_impl.cc @@ -331,6 +331,7 @@ void MediaStreamImpl::OnStreamGenerated( WebKit::WebMediaConstraints() : request->videoConstraints(); dependency_factory_->CreateNativeMediaSources( + RenderViewObserver::routing_id(), audio_constraints, video_constraints, description, base::Bind(&MediaStreamImpl::OnCreateNativeSourcesComplete, AsWeakPtr())); } diff --git a/content/renderer/media/mock_media_stream_dependency_factory.cc b/content/renderer/media/mock_media_stream_dependency_factory.cc index 3920a71..85a8d18 100644 --- a/content/renderer/media/mock_media_stream_dependency_factory.cc +++ b/content/renderer/media/mock_media_stream_dependency_factory.cc @@ -411,7 +411,8 @@ MockMediaStreamDependencyFactory::CreateLocalVideoSource( } bool MockMediaStreamDependencyFactory::InitializeAudioSource( - const StreamDeviceInfo& device_info) { + int render_view_id, + const StreamDeviceInfo& device_info) { return true; } diff --git a/content/renderer/media/mock_media_stream_dependency_factory.h b/content/renderer/media/mock_media_stream_dependency_factory.h index 9809fab..db7e832 100644 --- a/content/renderer/media/mock_media_stream_dependency_factory.h +++ b/content/renderer/media/mock_media_stream_dependency_factory.h @@ -143,7 +143,7 @@ class MockMediaStreamDependencyFactory : public MediaStreamDependencyFactory { bool is_screencast, const webrtc::MediaConstraintsInterface* constraints) OVERRIDE; virtual bool InitializeAudioSource( - const StreamDeviceInfo& device_info) OVERRIDE; + int render_view_id, const StreamDeviceInfo& device_info) OVERRIDE; virtual bool CreateWebAudioSource( WebKit::WebMediaStreamSource* source) OVERRIDE; virtual scoped_refptr<webrtc::MediaStreamInterface> diff --git a/content/renderer/media/renderer_audio_output_device.cc b/content/renderer/media/renderer_audio_output_device.cc deleted file mode 100644 index 678bbec..0000000 --- a/content/renderer/media/renderer_audio_output_device.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/renderer_audio_output_device.h" - -#include "base/bind.h" -#include "base/message_loop_proxy.h" -#include "content/renderer/media/audio_message_filter.h" - -namespace content { - -RendererAudioOutputDevice::RendererAudioOutputDevice( - AudioMessageFilter* message_filter, - const scoped_refptr<base::MessageLoopProxy>& io_loop) - : AudioOutputDevice(message_filter, io_loop), - source_render_view_id_(MSG_ROUTING_NONE), - is_after_stream_created_(false) { -} - -RendererAudioOutputDevice::~RendererAudioOutputDevice() {} - -void RendererAudioOutputDevice::Start() { - AudioOutputDevice::Start(); - message_loop()->PostTask( - FROM_HERE, - base::Bind(&RendererAudioOutputDevice::OnStart, this)); -} - -void RendererAudioOutputDevice::Stop() { - AudioOutputDevice::Stop(); - message_loop()->PostTask( - FROM_HERE, - base::Bind(&RendererAudioOutputDevice::OnStop, this)); -} - -void RendererAudioOutputDevice::SetSourceRenderView(int render_view_id) { - message_loop()->PostTask( - FROM_HERE, - base::Bind(&RendererAudioOutputDevice::OnSourceChange, this, - render_view_id)); -} - -void RendererAudioOutputDevice::OnStart() { - DCHECK(message_loop()->BelongsToCurrentThread()); - is_after_stream_created_ = true; - OnSourceChange(source_render_view_id_); -} - -void RendererAudioOutputDevice::OnStop() { - DCHECK(message_loop()->BelongsToCurrentThread()); - is_after_stream_created_ = false; -} - -void RendererAudioOutputDevice::OnSourceChange(int render_view_id) { - DCHECK(message_loop()->BelongsToCurrentThread()); - source_render_view_id_ = render_view_id; - if (is_after_stream_created_ && source_render_view_id_ != MSG_ROUTING_NONE) { - AudioMessageFilter* const filter = - static_cast<AudioMessageFilter*>(audio_output_ipc()); - if (filter) - filter->AssociateStreamWithProducer(stream_id(), source_render_view_id_); - } -} - -} // namespace content diff --git a/content/renderer/media/renderer_audio_output_device.h b/content/renderer/media/renderer_audio_output_device.h deleted file mode 100644 index 601cca5..0000000 --- a/content/renderer/media/renderer_audio_output_device.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_RENDERER_AUDIO_OUTPUT_DEVICE_H_ -#define CONTENT_RENDERER_MEDIA_RENDERER_AUDIO_OUTPUT_DEVICE_H_ - -#include "base/memory/ref_counted.h" -#include "media/audio/audio_output_device.h" - -namespace base { -class MessageLoopProxy; -} - -namespace content { - -class AudioDeviceFactory; -class AudioMessageFilter; - -// Subclass of media::AudioOutputDevice to support additional concepts within -// the content component. Use AudioDeviceFactory to instantiate this class. -class RendererAudioOutputDevice - : NON_EXPORTED_BASE(public media::AudioOutputDevice) { - public: - // Set the source of the rendered audio data to the RenderView specified by - // |render_view_id|. Callers should keep in mind that the RenderView which - // caused the instantiation of RendererAudioOutputDevice might not necessarily - // be same as the RenderView which actually renders the audio data. - void SetSourceRenderView(int render_view_id); - - virtual void Start() OVERRIDE; - virtual void Stop() OVERRIDE; - - protected: - friend class AudioDeviceFactory; - - // Creates an uninitialized RendererAudioOutputDevice. Clients must call - // Initialize() before using. - RendererAudioOutputDevice( - AudioMessageFilter* message_filter, - const scoped_refptr<base::MessageLoopProxy>& io_loop); - - private: - virtual ~RendererAudioOutputDevice(); - - void OnStart(); - void OnStop(); - void OnSourceChange(int render_view_id); - - int source_render_view_id_; - bool is_after_stream_created_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(RendererAudioOutputDevice); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_RENDERER_AUDIO_OUTPUT_DEVICE_H_ diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc index ca32103..43a4a61 100644 --- a/content/renderer/media/renderer_webaudiodevice_impl.cc +++ b/content/renderer/media/renderer_webaudiodevice_impl.cc @@ -7,8 +7,8 @@ #include "base/command_line.h" #include "base/logging.h" #include "content/renderer/media/audio_device_factory.h" -#include "content/renderer/media/renderer_audio_output_device.h" #include "content/renderer/render_view_impl.h" +#include "media/audio/audio_output_device.h" #include "media/base/media_switches.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" @@ -38,9 +38,6 @@ void RendererWebAudioDeviceImpl::start() { if (output_device_) return; // Already started. - output_device_ = AudioDeviceFactory::NewOutputDevice(); - output_device_->Initialize(params_, this); - // Assumption: This method is being invoked within a V8 call stack. CHECKs // will fail in the call to frameForCurrentContext() otherwise. // @@ -52,10 +49,9 @@ void RendererWebAudioDeviceImpl::start() { WebView* const web_view = web_frame ? web_frame->view() : NULL; RenderViewImpl* const render_view = web_view ? RenderViewImpl::FromWebView(web_view) : NULL; - if (render_view) { - output_device_->SetSourceRenderView(render_view->routing_id()); - } - + output_device_ = AudioDeviceFactory::NewOutputDevice( + render_view ? render_view->routing_id() : MSG_ROUTING_NONE); + output_device_->Initialize(params_, this); output_device_->Start(); // Note: Default behavior is to auto-play on start. } diff --git a/content/renderer/media/renderer_webaudiodevice_impl.h b/content/renderer/media/renderer_webaudiodevice_impl.h index ca19d074..09c35d8 100644 --- a/content/renderer/media/renderer_webaudiodevice_impl.h +++ b/content/renderer/media/renderer_webaudiodevice_impl.h @@ -12,9 +12,11 @@ #include "third_party/WebKit/Source/Platform/chromium/public/WebAudioDevice.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h" -namespace content { +namespace media { +class AudioOutputDevice; +} -class RendererAudioOutputDevice; +namespace content { class RendererWebAudioDeviceImpl : public WebKit::WebAudioDevice, @@ -50,7 +52,7 @@ class RendererWebAudioDeviceImpl base::ThreadChecker thread_checker_; // When non-NULL, we are started. When NULL, we are stopped. - scoped_refptr<RendererAudioOutputDevice> output_device_; + scoped_refptr<media::AudioOutputDevice> output_device_; DISALLOW_COPY_AND_ASSIGN(RendererWebAudioDeviceImpl); }; diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc index 35f25ee..b07f398 100644 --- a/content/renderer/media/webrtc_audio_capturer.cc +++ b/content/renderer/media/webrtc_audio_capturer.cc @@ -179,7 +179,7 @@ class WebRtcAudioCapturer::ConfiguredBuffer : // static scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { - scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); + scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); return capturer; } @@ -204,7 +204,8 @@ bool WebRtcAudioCapturer::Reconfigure(int sample_rate, return true; } -bool WebRtcAudioCapturer::Initialize(media::ChannelLayout channel_layout, +bool WebRtcAudioCapturer::Initialize(int render_view_id, + media::ChannelLayout channel_layout, int sample_rate, int session_id) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -245,7 +246,7 @@ bool WebRtcAudioCapturer::Initialize(media::ChannelLayout channel_layout, // Create and configure the default audio capturing source. The |source_| // will be overwritten if an external client later calls SetCapturerSource() // providing an alternative media::AudioCapturerSource. - SetCapturerSource(AudioDeviceFactory::NewInputDevice(), + SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), channel_layout, static_cast<float>(sample_rate)); diff --git a/content/renderer/media/webrtc_audio_capturer.h b/content/renderer/media/webrtc_audio_capturer.h index 5d35604..4709b5e 100644 --- a/content/renderer/media/webrtc_audio_capturer.h +++ b/content/renderer/media/webrtc_audio_capturer.h @@ -43,10 +43,11 @@ class CONTENT_EXPORT WebRtcAudioCapturer static scoped_refptr<WebRtcAudioCapturer> CreateCapturer(); // Creates and configures the default audio capturing source using the - // provided audio parameters, |session_id| is passed to the browser to - // decide which device to use. - // Called on the main render thread. - bool Initialize(media::ChannelLayout channel_layout, + // provided audio parameters. |render_view_id| specifies the render view + // consuming audio for capture. |session_id| is passed to the browser to + // decide which device to use. Called on the main render thread. + bool Initialize(int render_view_id, + media::ChannelLayout channel_layout, int sample_rate, int session_id); diff --git a/content/renderer/media/webrtc_audio_device_unittest.cc b/content/renderer/media/webrtc_audio_device_unittest.cc index 4ca0195..5260738 100644 --- a/content/renderer/media/webrtc_audio_device_unittest.cc +++ b/content/renderer/media/webrtc_audio_device_unittest.cc @@ -104,7 +104,7 @@ bool InitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { int sample_rate = hardware_config->GetInputSampleRate(); media::ChannelLayout channel_layout = hardware_config->GetInputChannelLayout(); - if (!capturer->Initialize(channel_layout, sample_rate, 1)) + if (!capturer->Initialize(kRenderViewId, channel_layout, sample_rate, 1)) return false; return true; diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc index d5591d0..f22b9cd 100644 --- a/content/renderer/media/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc_audio_renderer.cc @@ -8,9 +8,9 @@ #include "base/metrics/histogram.h" #include "base/string_util.h" #include "content/renderer/media/audio_device_factory.h" -#include "content/renderer/media/renderer_audio_output_device.h" #include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/render_thread_impl.h" +#include "media/audio/audio_output_device.h" #include "media/audio/audio_parameters.h" #include "media/audio/sample_rates.h" #include "media/base/audio_hardware_config.h" @@ -111,9 +111,6 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { DCHECK(!sink_); DCHECK(!source_); - sink_ = AudioDeviceFactory::NewOutputDevice(); - DCHECK(sink_); - // Use mono on all platforms but Windows for now. // TODO(henrika): Tracking at http://crbug.com/166771. media::ChannelLayout channel_layout = media::CHANNEL_LAYOUT_MONO; @@ -208,8 +205,8 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { source->SetRenderFormat(source_params); // Configure the audio rendering client and start rendering. + sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_); sink_->Initialize(sink_params, this); - sink_->SetSourceRenderView(source_render_view_id_); sink_->Start(); // User must call Play() before any audio can be heard. diff --git a/content/renderer/media/webrtc_audio_renderer.h b/content/renderer/media/webrtc_audio_renderer.h index af4bf38..eb1025684 100644 --- a/content/renderer/media/webrtc_audio_renderer.h +++ b/content/renderer/media/webrtc_audio_renderer.h @@ -14,9 +14,12 @@ #include "media/base/audio_renderer_sink.h" #include "webkit/media/media_stream_audio_renderer.h" +namespace media { +class AudioOutputDevice; +} + namespace content { -class RendererAudioOutputDevice; class WebRtcAudioRendererSource; // This renderer handles calls from the pipeline and WebRtc ADM. It is used @@ -71,7 +74,7 @@ class CONTENT_EXPORT WebRtcAudioRenderer const int source_render_view_id_; // The sink (destination) for rendered audio. - scoped_refptr<RendererAudioOutputDevice> sink_; + scoped_refptr<media::AudioOutputDevice> sink_; // Audio data source from the browser process. WebRtcAudioRendererSource* source_; diff --git a/content/renderer/media/webrtc_local_audio_renderer.cc b/content/renderer/media/webrtc_local_audio_renderer.cc index cc5ba77..da68006 100644 --- a/content/renderer/media/webrtc_local_audio_renderer.cc +++ b/content/renderer/media/webrtc_local_audio_renderer.cc @@ -9,8 +9,8 @@ #include "base/message_loop_proxy.h" #include "base/synchronization/lock.h" #include "content/renderer/media/audio_device_factory.h" -#include "content/renderer/media/renderer_audio_output_device.h" #include "content/renderer/media/webrtc_audio_capturer.h" +#include "media/audio/audio_output_device.h" #include "media/base/audio_bus.h" namespace content { @@ -158,12 +158,11 @@ void WebRtcLocalAudioRenderer::Start() { source_params.sample_rate(), source_params.bits_per_sample(), 2 * source_params.frames_per_buffer()); - sink_ = AudioDeviceFactory::NewOutputDevice(); + sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_); // TODO(henrika): we could utilize the unified audio here instead and do // sink_->InitializeIO(sink_params, 2, callback_.get()); // It would then be possible to avoid using the WebRtcAudioCapturer. sink_->Initialize(sink_params, this); - sink_->SetSourceRenderView(source_render_view_id_); // Start the capturer and local rendering. Note that, the capturer is owned // by the WebRTC ADM and might already bee running. diff --git a/content/renderer/media/webrtc_local_audio_renderer.h b/content/renderer/media/webrtc_local_audio_renderer.h index 0bd310a..0bdb316 100644 --- a/content/renderer/media/webrtc_local_audio_renderer.h +++ b/content/renderer/media/webrtc_local_audio_renderer.h @@ -16,6 +16,7 @@ namespace media { class AudioBus; +class AudioOutputDevice; class AudioParameters; } @@ -25,7 +26,6 @@ class AudioTrackInterface; namespace content { -class RendererAudioOutputDevice; class WebRtcAudioCapturer; // WebRtcLocalAudioRenderer is a webkit_media::MediaStreamAudioRenderer @@ -105,7 +105,7 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer const int source_render_view_id_; // The sink (destination) for rendered audio. - scoped_refptr<RendererAudioOutputDevice> sink_; + scoped_refptr<media::AudioOutputDevice> sink_; // Used to DCHECK that we are called on the correct thread. base::ThreadChecker thread_checker_; diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.cc b/content/renderer/pepper/pepper_platform_audio_input_impl.cc index f71b642..76afa17 100644 --- a/content/renderer/pepper/pepper_platform_audio_input_impl.cc +++ b/content/renderer/pepper/pepper_platform_audio_input_impl.cc @@ -9,7 +9,6 @@ #include "base/message_loop_proxy.h" #include "build/build_config.h" #include "content/common/child_process.h" -#include "content/common/media/audio_messages.h" #include "content/renderer/media/audio_input_message_filter.h" #include "content/renderer/pepper/pepper_plugin_delegate_impl.h" #include "content/renderer/render_thread_impl.h" @@ -55,6 +54,10 @@ void PepperPlatformAudioInputImpl::StopCapture() { void PepperPlatformAudioInputImpl::ShutDown() { DCHECK(main_message_loop_proxy_->BelongsToCurrentThread()); + // Make sure we don't call shutdown more than once. + if (!client_) + return; + // Called on the main thread to stop all audio callbacks. We must only change // the client on the main thread, and the delegates from the I/O thread. client_ = NULL; @@ -80,9 +83,8 @@ void PepperPlatformAudioInputImpl::OnStreamCreated( DCHECK_EQ(1, total_segments); if (base::MessageLoopProxy::current() != main_message_loop_proxy_) { - // No need to check |shutdown_called_| here. If shutdown has occurred, - // |client_| will be NULL and the handles will be cleaned up on the main - // thread. + // If shutdown has occurred, |client_| will be NULL and the handles will be + // cleaned up on the main thread. main_message_loop_proxy_->PostTask( FROM_HERE, base::Bind(&PepperPlatformAudioInputImpl::OnStreamCreated, this, @@ -107,7 +109,7 @@ void PepperPlatformAudioInputImpl::OnStateChanged( } void PepperPlatformAudioInputImpl::OnIPCClosed() { - ipc_ = NULL; + ipc_.reset(); } PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() { @@ -116,19 +118,14 @@ PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() { // Although these members should be accessed on a specific thread (either the // main thread or the I/O thread), it should be fine to examine their value // here. - DCHECK_EQ(0, stream_id_); + DCHECK(!ipc_); DCHECK(!client_); DCHECK(label_.empty()); - DCHECK(shutdown_called_); } PepperPlatformAudioInputImpl::PepperPlatformAudioInputImpl() : client_(NULL), - stream_id_(0), - render_view_id_(MSG_ROUTING_NONE), - main_message_loop_proxy_(base::MessageLoopProxy::current()), - shutdown_called_(false) { - ipc_ = RenderThreadImpl::current()->audio_input_message_filter(); + main_message_loop_proxy_(base::MessageLoopProxy::current()) { } bool PepperPlatformAudioInputImpl::Initialize( @@ -142,8 +139,10 @@ bool PepperPlatformAudioInputImpl::Initialize( if (!plugin_delegate || !client) return false; + ipc_ = RenderThreadImpl::current()->audio_input_message_filter()-> + CreateAudioInputIPC(plugin_delegate->GetRoutingID()); + plugin_delegate_ = plugin_delegate; - render_view_id_ = plugin_delegate_->GetRoutingID(); client_ = client; params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR, @@ -164,26 +163,19 @@ void PepperPlatformAudioInputImpl::InitializeOnIOThread(int session_id) { DCHECK(ChildProcess::current()->io_message_loop_proxy()-> BelongsToCurrentThread()); - if (shutdown_called_) + if (!ipc_) return; - // Make sure we don't call init more than once. - DCHECK_EQ(0, stream_id_); - stream_id_ = ipc_->AddDelegate(this); - DCHECK_NE(0, stream_id_); - // We will be notified by OnStreamCreated(). - ipc_->CreateStream(stream_id_, session_id, params_, false, 1); + ipc_->CreateStream(this, session_id, params_, false, 1); } void PepperPlatformAudioInputImpl::StartCaptureOnIOThread() { DCHECK(ChildProcess::current()->io_message_loop_proxy()-> BelongsToCurrentThread()); - if (stream_id_) { - ipc_->AssociateStreamWithConsumer(stream_id_, render_view_id_); - ipc_->RecordStream(stream_id_); - } + if (ipc_) + ipc_->RecordStream(); } void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() { @@ -191,24 +183,17 @@ void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() { BelongsToCurrentThread()); // TODO(yzshen): We cannot re-start capturing if the stream is closed. - if (stream_id_) - ipc_->CloseStream(stream_id_); + if (ipc_) { + ipc_->CloseStream(); + ipc_.reset(); + } } void PepperPlatformAudioInputImpl::ShutDownOnIOThread() { DCHECK(ChildProcess::current()->io_message_loop_proxy()-> BelongsToCurrentThread()); - // Make sure we don't call shutdown more than once. - if (shutdown_called_) - return; - shutdown_called_ = true; - - if (stream_id_) { - ipc_->CloseStream(stream_id_); - ipc_->RemoveDelegate(stream_id_); - stream_id_ = 0; - } + StopCaptureOnIOThread(); main_message_loop_proxy_->PostTask( FROM_HERE, diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.h b/content/renderer/pepper/pepper_platform_audio_input_impl.h index 7d71347..0cfa92d 100644 --- a/content/renderer/pepper/pepper_platform_audio_input_impl.h +++ b/content/renderer/pepper/pepper_platform_audio_input_impl.h @@ -9,9 +9,9 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "content/renderer/media/audio_input_message_filter.h" +#include "media/audio/audio_input_ipc.h" #include "media/audio/audio_parameters.h" #include "webkit/plugins/ppapi/plugin_delegate.h" @@ -21,7 +21,6 @@ class AudioParameters; namespace content { -class AudioInputMessageFilter; class PepperPluginDelegateImpl; // PepperPlatformAudioInputImpl is operated on two threads: the main thread (the @@ -93,15 +92,8 @@ class PepperPlatformAudioInputImpl webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client_; // Used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE - // I/O thread except to send messages and get the message loop. - scoped_refptr<AudioInputMessageFilter> ipc_; - - // Our ID on the MessageFilter. THIS MUST ONLY BE ACCESSED ON THE I/O THREAD - // or else you could race with the initialize function which sets it. - int32 stream_id_; - - // The render view into which the audio is sent. - int render_view_id_; + // I/O THREAD. + scoped_ptr<media::AudioInputIPC> ipc_; base::MessageLoopProxy* main_message_loop_proxy_; @@ -112,10 +104,6 @@ class PepperPlatformAudioInputImpl // THE MAIN THREAD. std::string label_; - // Whether ShutDownOnIOThread() has been called. THIS MUST ONLY BE ACCESSED ON - // THE I/O THREAD. - bool shutdown_called_; - // Initialized on the main thread and accessed on the I/O thread afterwards. media::AudioParameters params_; diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.cc b/content/renderer/pepper/pepper_platform_audio_output_impl.cc index 90ec7eb..8b8c470 100644 --- a/content/renderer/pepper/pepper_platform_audio_output_impl.cc +++ b/content/renderer/pepper/pepper_platform_audio_output_impl.cc @@ -97,21 +97,19 @@ void PepperPlatformAudioOutputImpl::OnStreamCreated( } void PepperPlatformAudioOutputImpl::OnIPCClosed() { - ipc_ = NULL; + ipc_.reset(); } PepperPlatformAudioOutputImpl::~PepperPlatformAudioOutputImpl() { // Make sure we have been shut down. Warning: this will usually happen on // the I/O thread! - DCHECK_EQ(0, stream_id_); + DCHECK(!ipc_); DCHECK(!client_); } PepperPlatformAudioOutputImpl::PepperPlatformAudioOutputImpl() : client_(NULL), - stream_id_(0), main_message_loop_proxy_(base::MessageLoopProxy::current()) { - ipc_ = RenderThreadImpl::current()->audio_message_filter(); } bool PepperPlatformAudioOutputImpl::Initialize( @@ -122,11 +120,16 @@ bool PepperPlatformAudioOutputImpl::Initialize( DCHECK(client); client_ = client; + RenderThreadImpl* const render_thread = RenderThreadImpl::current(); + ipc_ = render_thread->audio_message_filter()-> + CreateAudioOutputIPC(source_render_view_id); + CHECK(ipc_); + media::AudioParameters::Format format; const int kMaxFramesForLowLatency = 2047; media::AudioHardwareConfig* hardware_config = - RenderThreadImpl::current()->GetAudioHardwareConfig(); + render_thread->GetAudioHardwareConfig(); const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); if (!cmd_line->HasSwitch(switches::kDisableAudioOutputResampler)) { @@ -149,39 +152,42 @@ bool PepperPlatformAudioOutputImpl::Initialize( ChildProcess::current()->io_message_loop()->PostTask( FROM_HERE, base::Bind(&PepperPlatformAudioOutputImpl::InitializeOnIOThread, - this, params, source_render_view_id)); + this, params)); return true; } void PepperPlatformAudioOutputImpl::InitializeOnIOThread( - const media::AudioParameters& params, int source_render_view_id) { - // Make sure we don't call init more than once. - DCHECK_EQ(0, stream_id_); - stream_id_ = ipc_->AddDelegate(this); - DCHECK_NE(0, stream_id_); - - ipc_->CreateStream(stream_id_, params); - ipc_->AssociateStreamWithProducer(stream_id_, source_render_view_id); + const media::AudioParameters& params) { + DCHECK(ChildProcess::current()->io_message_loop_proxy()-> + BelongsToCurrentThread()); + if (ipc_) + ipc_->CreateStream(this, params); } void PepperPlatformAudioOutputImpl::StartPlaybackOnIOThread() { - if (stream_id_) - ipc_->PlayStream(stream_id_); + DCHECK(ChildProcess::current()->io_message_loop_proxy()-> + BelongsToCurrentThread()); + if (ipc_) + ipc_->PlayStream(); } void PepperPlatformAudioOutputImpl::StopPlaybackOnIOThread() { - if (stream_id_) - ipc_->PauseStream(stream_id_); + DCHECK(ChildProcess::current()->io_message_loop_proxy()-> + BelongsToCurrentThread()); + if (ipc_) + ipc_->PauseStream(); } void PepperPlatformAudioOutputImpl::ShutDownOnIOThread() { + DCHECK(ChildProcess::current()->io_message_loop_proxy()-> + BelongsToCurrentThread()); + // Make sure we don't call shutdown more than once. - if (!stream_id_) + if (!ipc_) return; - ipc_->CloseStream(stream_id_); - ipc_->RemoveDelegate(stream_id_); - stream_id_ = 0; + ipc_->CloseStream(); + ipc_.reset(); Release(); // Release for the delegate, balances out the reference taken in // PepperPluginDelegateImpl::CreateAudio. diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.h b/content/renderer/pepper/pepper_platform_audio_output_impl.h index 0be7588..b8eb05d 100644 --- a/content/renderer/pepper/pepper_platform_audio_output_impl.h +++ b/content/renderer/pepper/pepper_platform_audio_output_impl.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "media/audio/audio_output_ipc.h" #include "webkit/plugins/ppapi/plugin_delegate.h" @@ -20,8 +21,6 @@ class MessageLoopProxy; namespace content { -class AudioMessageFilter; - class PepperPlatformAudioOutputImpl : public webkit::ppapi::PluginDelegate::PlatformAudioOutput, public media::AudioOutputIPCDelegate, @@ -63,8 +62,7 @@ class PepperPlatformAudioOutputImpl webkit::ppapi::PluginDelegate::PlatformAudioOutputClient* client); // I/O thread backends to above functions. - void InitializeOnIOThread(const media::AudioParameters& params, - int source_render_view_id); + void InitializeOnIOThread(const media::AudioParameters& params); void StartPlaybackOnIOThread(); void StopPlaybackOnIOThread(); void ShutDownOnIOThread(); @@ -75,11 +73,7 @@ class PepperPlatformAudioOutputImpl // Used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE // I/O thread except to send messages and get the message loop. - scoped_refptr<AudioMessageFilter> ipc_; - - // Our ID on the MessageFilter. THIS MUST ONLY BE ACCESSED ON THE I/O THREAD - // or else you could race with the initialize function which sets it. - int32 stream_id_; + scoped_ptr<media::AudioOutputIPC> ipc_; base::MessageLoopProxy* main_message_loop_proxy_; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 7a3133d..63c3164 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -90,7 +90,6 @@ #include "content/renderer/media/media_stream_dispatcher.h" #include "content/renderer/media/media_stream_impl.h" #include "content/renderer/media/render_media_log.h" -#include "content/renderer/media/renderer_audio_output_device.h" #include "content/renderer/media/renderer_gpu_video_decoder_factories.h" #include "content/renderer/media/rtc_peer_connection_handler.h" #include "content/renderer/media/video_capture_impl_manager.h" @@ -113,6 +112,7 @@ #include "content/renderer/web_ui_extension_data.h" #include "content/renderer/webplugin_delegate_proxy.h" #include "content/renderer/websharedworker_proxy.h" +#include "media/audio/audio_output_device.h" #include "media/base/audio_renderer_mixer_input.h" #include "media/base/filter_collection.h" #include "media/base/media_switches.h" @@ -2723,13 +2723,10 @@ WebMediaPlayer* RenderViewImpl::createMediaPlayer( CreateInput(routing_id_); DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink; } else { - scoped_refptr<RendererAudioOutputDevice> device = - AudioDeviceFactory::NewOutputDevice(); // The RenderView creating AudioRendererSink will be the source of // the audio (WebMediaPlayer is always associated with a document in a // frame at the time RenderAudioSourceProvider is instantiated). - device->SetSourceRenderView(routing_id_); - sink = device; + sink = AudioDeviceFactory::NewOutputDevice(routing_id_); DVLOG(1) << "Using AudioDeviceFactory-provided sink: " << sink; } } |