diff options
35 files changed, 701 insertions, 444 deletions
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc index 0935090..42728f7 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager.cc @@ -8,6 +8,7 @@ #include "base/memory/scoped_ptr.h" #include "content/browser/renderer_host/media/audio_input_device_manager_event_handler.h" #include "content/public/browser/browser_thread.h" +#include "media/audio/audio_input_ipc.h" #include "media/audio/audio_manager_base.h" using content::BrowserThread; @@ -15,8 +16,6 @@ using content::BrowserThread; namespace media_stream { const int AudioInputDeviceManager::kFakeOpenSessionId = 1; -const int AudioInputDeviceManager::kInvalidSessionId = 0; -const char AudioInputDeviceManager::kInvalidDeviceId[] = ""; // Starting id for the first capture session. const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; @@ -158,15 +157,15 @@ void AudioInputDeviceManager::Start( } // Checks if the device has been opened or not. - std::string device_id = (devices_.find(session_id) == devices_.end()) ? - kInvalidDeviceId : devices_[session_id].unique_id; + std::string device_id; // Adds the event handler to the session if the session has not been started, - // otherwise post a |kInvalidDeviceId| to indicate that Start() fails. - if (event_handlers_.find(session_id) == event_handlers_.end()) + // otherwise post an empty |device_id| to indicate that Start() fails. + if (event_handlers_.find(session_id) == event_handlers_.end()) { event_handlers_.insert(std::make_pair(session_id, event_handler)); - else - device_id = kInvalidDeviceId; + if (devices_.find(session_id) != devices_.end()) + device_id = devices_[session_id].unique_id; + } // Posts a callback through the AudioInputRendererHost to notify the renderer // that the device has started. diff --git a/content/browser/renderer_host/media/audio_input_device_manager.h b/content/browser/renderer_host/media/audio_input_device_manager.h index 3d79dc9..f035fb2 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager.h +++ b/content/browser/renderer_host/media/audio_input_device_manager.h @@ -38,9 +38,6 @@ class CONTENT_EXPORT AudioInputDeviceManager // AudioInputDeviceManager before MediaStream is implemented. static const int kFakeOpenSessionId; - static const int kInvalidSessionId; - static const char kInvalidDeviceId[]; - explicit AudioInputDeviceManager(media::AudioManager* audio_manager); // MediaStreamProvider implementation, called on IO thread. diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc index 257cec7..475109a 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc @@ -459,8 +459,7 @@ TEST_F(AudioInputDeviceManagerTest, StartInvalidSession) { int invalid_session_id = session_id + 1; manager_->Start(invalid_session_id, audio_input_event_handler.get()); EXPECT_CALL(*audio_input_event_handler, - DeviceStarted(invalid_session_id, - AudioInputDeviceManager::kInvalidDeviceId)) + DeviceStarted(invalid_session_id, std::string())) .Times(1); message_loop_->RunAllPending(); @@ -505,8 +504,7 @@ TEST_F(AudioInputDeviceManagerTest, StartSessionTwice) { // Starts the session for the second time, it should fail. manager_->Start(session_id, audio_input_event_handler.get()); EXPECT_CALL(*audio_input_event_handler, - DeviceStarted(session_id, - AudioInputDeviceManager::kInvalidDeviceId)) + DeviceStarted(session_id, std::string())) .Times(1); manager_->Stop(session_id); diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc index 4af7b61..af893e0 100644 --- a/content/browser/renderer_host/media/audio_input_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc @@ -291,8 +291,8 @@ void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) { } void AudioInputRendererHost::SendErrorMessage(int stream_id) { - Send(new AudioInputMsg_NotifyStreamStateChanged(stream_id, - kAudioStreamError)); + Send(new AudioInputMsg_NotifyStreamStateChanged( + stream_id, media::AudioInputIPCDelegate::kError)); } void AudioInputRendererHost::DeleteEntries() { @@ -333,8 +333,8 @@ void AudioInputRendererHost::OnDeviceStopped(int session_id) { // Device has been stopped, close the input stream. CloseAndDeleteStream(entry); // Notify the renderer that the state of the input stream has changed. - Send(new AudioInputMsg_NotifyStreamStateChanged(stream_id, - kAudioStreamPaused)); + Send(new AudioInputMsg_NotifyStreamStateChanged( + stream_id, media::AudioInputIPCDelegate::kStopped)); } // Delete the session entry. diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index c59ef44..27b8825 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc @@ -147,7 +147,7 @@ void AudioRendererHost::DoSendPlayingMessage( return; Send(new AudioMsg_NotifyStreamStateChanged( - entry->stream_id, kAudioStreamPlaying)); + entry->stream_id, media::AudioOutputIPCDelegate::kPlaying)); } void AudioRendererHost::DoSendPausedMessage( @@ -159,7 +159,7 @@ void AudioRendererHost::DoSendPausedMessage( return; Send(new AudioMsg_NotifyStreamStateChanged( - entry->stream_id, kAudioStreamPaused)); + entry->stream_id, media::AudioOutputIPCDelegate::kPaused)); } void AudioRendererHost::DoHandleError(media::AudioOutputController* controller, @@ -312,7 +312,8 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) { } void AudioRendererHost::SendErrorMessage(int32 stream_id) { - Send(new AudioMsg_NotifyStreamStateChanged(stream_id, kAudioStreamError)); + Send(new AudioMsg_NotifyStreamStateChanged( + stream_id, media::AudioOutputIPCDelegate::kError)); } void AudioRendererHost::DeleteEntries() { diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc index 786cf79..62c09bf 100644 --- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc +++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc @@ -118,15 +118,20 @@ class MockAudioRendererHost : public AudioRendererHost { } void OnStreamStateChanged(const IPC::Message& msg, int stream_id, - AudioStreamState state) { - if (state == kAudioStreamPlaying) { - OnStreamPlaying(stream_id); - } else if (state == kAudioStreamPaused) { - OnStreamPaused(stream_id); - } else if (state == kAudioStreamError) { - OnStreamError(stream_id); - } else { - FAIL() << "Unknown stream state"; + media::AudioOutputIPCDelegate::State state) { + switch (state) { + case media::AudioOutputIPCDelegate::kPlaying: + OnStreamPlaying(stream_id); + break; + case media::AudioOutputIPCDelegate::kPaused: + OnStreamPaused(stream_id); + break; + case media::AudioOutputIPCDelegate::kError: + OnStreamError(stream_id); + break; + default: + FAIL() << "Unknown stream state"; + break; } } diff --git a/content/common/media/audio_messages.h b/content/common/media/audio_messages.h index ce0d4bd..fd7f1f3 100644 --- a/content/common/media/audio_messages.h +++ b/content/common/media/audio_messages.h @@ -12,16 +12,18 @@ #include "base/sync_socket.h" #include "content/common/content_export.h" #include "content/common/media/audio_param_traits.h" -#include "content/common/media/audio_stream_state.h" #include "ipc/ipc_message_macros.h" #include "media/audio/audio_buffers_state.h" +#include "media/audio/audio_input_ipc.h" +#include "media/audio/audio_output_ipc.h" #include "media/audio/audio_parameters.h" #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT CONTENT_EXPORT #define IPC_MESSAGE_START AudioMsgStart -IPC_ENUM_TRAITS(AudioStreamState) +IPC_ENUM_TRAITS(media::AudioInputIPCDelegate::State) +IPC_ENUM_TRAITS(media::AudioOutputIPCDelegate::State) IPC_STRUCT_TRAITS_BEGIN(media::AudioBuffersState) IPC_STRUCT_TRAITS_MEMBER(pending_bytes) @@ -70,12 +72,12 @@ IPC_MESSAGE_CONTROL4(AudioInputMsg_NotifyStreamCreated, // update after the renderer has requested a Create/Start/Close. IPC_MESSAGE_CONTROL2(AudioMsg_NotifyStreamStateChanged, int /* stream id */, - AudioStreamState /* new state */) + media::AudioOutputIPCDelegate::State /* new state */) // Notification message sent from browser to renderer for state update. IPC_MESSAGE_CONTROL2(AudioInputMsg_NotifyStreamStateChanged, int /* stream id */, - AudioStreamState /* new state */) + media::AudioInputIPCDelegate::State /* new state */) IPC_MESSAGE_CONTROL2(AudioInputMsg_NotifyStreamVolume, int /* stream id */, diff --git a/content/common/media/audio_stream_state.h b/content/common/media/audio_stream_state.h deleted file mode 100644 index 3c8cc0e..0000000 --- a/content/common/media/audio_stream_state.h +++ /dev/null @@ -1,17 +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_COMMON_MEDIA_AUDIO_STREAM_STATE_H_ -#define CONTENT_COMMON_MEDIA_AUDIO_STREAM_STATE_H_ - -// Current status of the audio output stream in the browser process. Browser -// sends information about the current playback state and error to the -// renderer process using this type. -enum AudioStreamState { - kAudioStreamPlaying, - kAudioStreamPaused, - kAudioStreamError -}; - -#endif // CONTENT_COMMON_MEDIA_AUDIO_STREAM_STATE_H_ diff --git a/content/content_common.gypi b/content/content_common.gypi index 98a1eb5..18770e8 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -269,7 +269,6 @@ 'common/media/audio_messages.h', 'common/media/audio_param_traits.cc', 'common/media/audio_param_traits.h', - 'common/media/audio_stream_state.h', 'common/media/media_stream_messages.h', 'common/media/media_stream_options.cc', 'common/media/media_stream_options.h', diff --git a/content/renderer/media/audio_device.cc b/content/renderer/media/audio_device.cc index 9936ebd..db1e592 100644 --- a/content/renderer/media/audio_device.cc +++ b/content/renderer/media/audio_device.cc @@ -8,8 +8,6 @@ #include "base/message_loop.h" #include "base/threading/thread_restrictions.h" #include "base/time.h" -#include "content/common/media/audio_messages.h" -#include "content/common/view_messages.h" #include "media/audio/audio_output_controller.h" #include "media/audio/audio_util.h" @@ -38,15 +36,15 @@ class AudioDevice::AudioThreadCallback }; AudioDevice::AudioDevice( + media::AudioOutputIPC* ipc, const scoped_refptr<base::MessageLoopProxy>& io_loop) : ScopedLoopObserver(io_loop), callback_(NULL), + ipc_(ipc), stream_id_(0), play_on_start_(true), is_started_(false) { - // Use the filter instance already created on the main render thread. - CHECK(AudioMessageFilter::Get()) << "Invalid audio message filter."; - filter_ = AudioMessageFilter::Get(); + CHECK(ipc_); } void AudioDevice::Initialize(const media::AudioParameters& params, @@ -112,14 +110,14 @@ void AudioDevice::CreateStreamOnIOThread(const media::AudioParameters& params) { if (stream_id_) return; - stream_id_ = filter_->AddDelegate(this); - Send(new AudioHostMsg_CreateStream(stream_id_, params)); + stream_id_ = ipc_->AddDelegate(this); + ipc_->CreateStream(stream_id_, params); } void AudioDevice::PlayOnIOThread() { DCHECK(message_loop()->BelongsToCurrentThread()); if (stream_id_ && is_started_) - Send(new AudioHostMsg_PlayStream(stream_id_)); + ipc_->PlayStream(stream_id_); else play_on_start_ = true; } @@ -127,9 +125,9 @@ void AudioDevice::PlayOnIOThread() { void AudioDevice::PauseOnIOThread(bool flush) { DCHECK(message_loop()->BelongsToCurrentThread()); if (stream_id_ && is_started_) { - Send(new AudioHostMsg_PauseStream(stream_id_)); + ipc_->PauseStream(stream_id_); if (flush) - Send(new AudioHostMsg_FlushStream(stream_id_)); + ipc_->FlushStream(stream_id_); } else { // Note that |flush| isn't relevant here since this is the case where // the stream is first starting. @@ -144,8 +142,8 @@ void AudioDevice::ShutDownOnIOThread() { if (stream_id_) { is_started_ = false; - filter_->RemoveDelegate(stream_id_); - Send(new AudioHostMsg_CloseStream(stream_id_)); + ipc_->CloseStream(stream_id_); + ipc_->RemoveDelegate(stream_id_); stream_id_ = 0; } @@ -164,17 +162,17 @@ void AudioDevice::ShutDownOnIOThread() { void AudioDevice::SetVolumeOnIOThread(double volume) { DCHECK(message_loop()->BelongsToCurrentThread()); if (stream_id_) - Send(new AudioHostMsg_SetVolume(stream_id_, volume)); + ipc_->SetVolume(stream_id_, volume); } -void AudioDevice::OnStateChanged(AudioStreamState state) { +void AudioDevice::OnStateChanged(media::AudioOutputIPCDelegate::State state) { DCHECK(message_loop()->BelongsToCurrentThread()); // Do nothing if the stream has been closed. if (!stream_id_) return; - if (state == kAudioStreamError) { + if (state == media::AudioOutputIPCDelegate::kError) { DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)"; // Don't dereference the callback object if the audio thread // is stopped or stopping. That could mean that the callback @@ -190,10 +188,9 @@ void AudioDevice::OnStateChanged(AudioStreamState state) { void AudioDevice::OnStreamCreated( base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) { + int length) { DCHECK(message_loop()->BelongsToCurrentThread()); - // TODO(vrk): Remove cast when |length| is int instead of uint32. - DCHECK_GE(length, static_cast<uint32>(audio_parameters_.GetBytesPerBuffer())); + DCHECK_GE(length, audio_parameters_.GetBytesPerBuffer()); #if defined(OS_WIN) DCHECK(handle); DCHECK(socket_handle); @@ -202,15 +199,14 @@ void AudioDevice::OnStreamCreated( DCHECK_GE(socket_handle, 0); #endif - base::AutoLock auto_lock(audio_thread_lock_); + // We should only get this callback if stream_id_ is valid. If it is not, + // the IPC layer should have closed the shared memory and socket handles + // for us and not invoked the callback. The basic assertion is that when + // stream_id_ is 0 the AudioDevice instance is not registered as a delegate + // and hence it should not receive callbacks. + DCHECK(stream_id_); - // Takes care of the case when Stop() is called before OnStreamCreated(). - if (!stream_id_) { - base::SharedMemory::CloseHandle(handle); - // Close the socket handler. - base::SyncSocket socket(socket_handle); - return; - } + base::AutoLock auto_lock(audio_thread_lock_); DCHECK(audio_thread_.IsStopped()); audio_callback_.reset(new AudioDevice::AudioThreadCallback(audio_parameters_, @@ -224,8 +220,8 @@ void AudioDevice::OnStreamCreated( PlayOnIOThread(); } -void AudioDevice::Send(IPC::Message* message) { - filter_->Send(message); +void AudioDevice::OnIPCClosed() { + ipc_ = NULL; } void AudioDevice::WillDestroyCurrentMessageLoop() { diff --git a/content/renderer/media/audio_device.h b/content/renderer/media/audio_device.h index 1eee2c3..56c2c86 100644 --- a/content/renderer/media/audio_device.h +++ b/content/renderer/media/audio_device.h @@ -23,19 +23,19 @@ // // Task [IO thread] IPC [IO thread] // -// Start -> CreateStreamOnIOThread -----> AudioHostMsg_CreateStream ------> +// Start -> CreateStreamOnIOThread -----> CreateStream ------> // <- OnStreamCreated <- AudioMsg_NotifyStreamCreated <- -// ---> PlayOnIOThread -----------> AudioHostMsg_PlayStream --------> +// ---> PlayOnIOThread -----------> PlayStream --------> // // Optionally Play() / Pause() sequences may occur: -// Play -> PlayOnIOThread --------------> AudioHostMsg_PlayStream ---------> -// Pause -> PauseOnIOThread ------------> AudioHostMsg_PauseStream --------> +// Play -> PlayOnIOThread --------------> PlayStream ---------> +// Pause -> PauseOnIOThread ------------> PauseStream --------> // (note that Play() / Pause() sequences before OnStreamCreated are // deferred until OnStreamCreated, with the last valid state being used) // // AudioDevice::Render => audio transport on audio thread => // | -// Stop --> ShutDownOnIOThread --------> AudioHostMsg_CloseStream -> Close +// Stop --> ShutDownOnIOThread --------> CloseStream -> Close // // This class utilizes several threads during its lifetime, namely: // 1. Creating thread. @@ -70,8 +70,8 @@ #include "base/shared_memory.h" #include "content/common/content_export.h" #include "content/renderer/media/audio_device_thread.h" -#include "content/renderer/media/audio_message_filter.h" #include "content/renderer/media/scoped_loop_observer.h" +#include "media/audio/audio_output_ipc.h" #include "media/audio/audio_parameters.h" #include "media/base/audio_renderer_sink.h" @@ -79,13 +79,9 @@ namespace media { class AudioParameters; } -namespace content { -class AudioDeviceFactory; -} - class CONTENT_EXPORT AudioDevice : NON_EXPORTED_BASE(public media::AudioRendererSink), - public AudioMessageFilter::Delegate, + public media::AudioOutputIPCDelegate, NON_EXPORTED_BASE(public ScopedLoopObserver) { public: // Methods called on main render thread ------------------------------------- @@ -100,24 +96,22 @@ class CONTENT_EXPORT AudioDevice virtual bool SetVolume(double volume) OVERRIDE; // Methods called on IO thread ---------------------------------------------- - // AudioMessageFilter::Delegate methods, called by AudioMessageFilter. - virtual void OnStateChanged(AudioStreamState state) OVERRIDE; + // AudioOutputIPCDelegate methods. + virtual void OnStateChanged( + media::AudioOutputIPCDelegate::State state) OVERRIDE; virtual void OnStreamCreated(base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) OVERRIDE; - - protected: - friend class content::AudioDeviceFactory; + int length) OVERRIDE; + virtual void OnIPCClosed() OVERRIDE; // Creates an uninitialized AudioDevice. Clients must call Initialize() - // before using. The constructor is protected to ensure that the - // AudioDeviceFactory is always used for construction in Chrome. - // Tests should use a test class that inherits from AudioDevice to gain - // access to the constructor. + // before using. // TODO(tommi): When all dependencies on |content| have been removed // from AudioDevice, move this class over to media/audio. - explicit AudioDevice(const scoped_refptr<base::MessageLoopProxy>& io_loop); + AudioDevice(media::AudioOutputIPC* ipc, + const scoped_refptr<base::MessageLoopProxy>& io_loop); + protected: // Magic required by ref_counted.h to avoid any code deleting the object // accidentally while there are references to it. friend class base::RefCountedThreadSafe<AudioDevice>; @@ -134,8 +128,6 @@ class CONTENT_EXPORT AudioDevice void ShutDownOnIOThread(); void SetVolumeOnIOThread(double volume); - void Send(IPC::Message* message); - // MessageLoop::DestructionObserver implementation for the IO loop. // If the IO loop dies before we do, we shut down the audio thread from here. virtual void WillDestroyCurrentMessageLoop() OVERRIDE; @@ -144,12 +136,13 @@ class CONTENT_EXPORT AudioDevice RenderCallback* callback_; - // Cached audio message filter (lives on the main render thread). - scoped_refptr<AudioMessageFilter> filter_; + // A pointer to the IPC layer that takes care of sending requests over to + // the AudioRendererHost. + media::AudioOutputIPC* ipc_; // Our stream ID on the message filter. Only accessed on the IO thread. // Must only be modified on the IO thread. - int32 stream_id_; + int stream_id_; // State of Play() / Pause() calls before OnStreamCreated() is called. bool play_on_start_; diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc index ee7906f..e200b0a 100644 --- a/content/renderer/media/audio_device_factory.cc +++ b/content/renderer/media/audio_device_factory.cc @@ -7,6 +7,9 @@ #include "base/logging.h" #include "content/common/child_process.h" #include "content/renderer/media/audio_device.h" +#include "content/renderer/media/audio_input_device.h" +#include "content/renderer/media/audio_input_message_filter.h" +#include "content/renderer/media/audio_message_filter.h" namespace content { @@ -14,11 +17,24 @@ namespace content { AudioDeviceFactory* AudioDeviceFactory::factory_ = NULL; // static -media::AudioRendererSink* AudioDeviceFactory::Create() { - if (factory_) { - return factory_->CreateAudioDevice(); - } - return new AudioDevice( +media::AudioRendererSink* AudioDeviceFactory::NewOutputDevice() { + media::AudioRendererSink* device = NULL; + if (factory_) + device = factory_->CreateOutputDevice(); + + return device ? device : new AudioDevice( + AudioMessageFilter::Get(), + ChildProcess::current()->io_message_loop()->message_loop_proxy()); +} + +// static +AudioInputDevice* AudioDeviceFactory::NewInputDevice() { + AudioInputDevice* device = NULL; + if (factory_) + device = factory_->CreateInputDevice(); + + return device ? device : new AudioInputDevice( + AudioInputMessageFilter::Get(), ChildProcess::current()->io_message_loop()->message_loop_proxy()); } diff --git a/content/renderer/media/audio_device_factory.h b/content/renderer/media/audio_device_factory.h index b15e967..14433ce 100644 --- a/content/renderer/media/audio_device_factory.h +++ b/content/renderer/media/audio_device_factory.h @@ -12,6 +12,8 @@ namespace media { class AudioRendererSink; } +class AudioInputDevice; + namespace content { // A factory for creating AudioRendererSinks. There is a global factory @@ -23,15 +25,23 @@ class CONTENT_EXPORT AudioDeviceFactory { // Creates an AudioRendererSink using the currently registered factory, // or the default one if no factory is registered. Ownership of the returned // pointer will be passed to the caller. - static media::AudioRendererSink* Create(); + static media::AudioRendererSink* NewOutputDevice(); + + // TODO(henrika): Update AudioInputDevice to inherit from an interface + // similar to AudioRendererSink, but for input. Same for the callback + // interfaces. + static AudioInputDevice* NewInputDevice(); protected: AudioDeviceFactory(); virtual ~AudioDeviceFactory(); - // You can derive from this class and specify an implementation for this - // function to create a different kind of AudioRendererSink for testing. - virtual media::AudioRendererSink* CreateAudioDevice() = 0; + // You can derive from this class and specify an implementation for these + // 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 media::AudioRendererSink* CreateOutputDevice() = 0; + virtual AudioInputDevice* CreateInputDevice() = 0; private: // The current globally registered factory. This is NULL when we should diff --git a/content/renderer/media/audio_device_unittest.cc b/content/renderer/media/audio_device_unittest.cc index 4612ec7..996e354 100644 --- a/content/renderer/media/audio_device_unittest.cc +++ b/content/renderer/media/audio_device_unittest.cc @@ -30,16 +30,6 @@ using testing::WithArgs; namespace { -// Derived from AudioDevice to gain access to the protected constructor. -class TestAudioDevice : public AudioDevice { - public: - explicit TestAudioDevice(const scoped_refptr<base::MessageLoopProxy>& io_loop) - : AudioDevice(io_loop) {} - - protected: - virtual ~TestAudioDevice() {} -}; - class MockRenderCallback : public media::AudioRendererSink::RenderCallback { public: MockRenderCallback() {} @@ -55,29 +45,13 @@ class MockAudioMessageFilter : public AudioMessageFilter { public: MockAudioMessageFilter() {} - virtual bool Send(IPC::Message* message) OVERRIDE { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(MockAudioMessageFilter, *message) - IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) - IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) - IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) - IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) - IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) - IPC_MESSAGE_HANDLER(AudioHostMsg_FlushStream, OnFlushStream) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - EXPECT_TRUE(handled); - delete message; - return true; - } - - MOCK_METHOD2(OnCreateStream, + MOCK_METHOD2(CreateStream, void(int stream_id, const media::AudioParameters& params)); - MOCK_METHOD1(OnPlayStream, void(int stream_id)); - MOCK_METHOD1(OnCloseStream, void(int stream_id)); - MOCK_METHOD2(OnSetVolume, void(int stream_id, double volume)); - MOCK_METHOD1(OnPauseStream, void(int stream_id)); - MOCK_METHOD1(OnFlushStream, void(int stream_id)); + MOCK_METHOD1(PlayStream, void(int stream_id)); + MOCK_METHOD1(CloseStream, void(int stream_id)); + MOCK_METHOD2(SetVolume, void(int stream_id, double volume)); + MOCK_METHOD1(PauseStream, void(int stream_id)); + MOCK_METHOD1(FlushStream, void(int stream_id)); protected: virtual ~MockAudioMessageFilter() {} @@ -145,7 +119,8 @@ class AudioDeviceTest : public testing::Test { } AudioDevice* CreateAudioDevice() { - return new TestAudioDevice(io_loop_.message_loop_proxy()); + return new AudioDevice( + audio_message_filter_, io_loop_.message_loop_proxy()); } void set_stream_id(int stream_id) { stream_id_ = stream_id; } @@ -162,8 +137,7 @@ class AudioDeviceTest : public testing::Test { }; // The simplest test for AudioDevice. Used to test construction of AudioDevice -// and that the runtime environment is set up correctly (e.g. ChildProcess and -// AudioMessageFilter global pointers). +// and that the runtime environment is set up correctly. TEST_F(AudioDeviceTest, Initialize) { scoped_refptr<AudioDevice> audio_device(CreateAudioDevice()); audio_device->Initialize(default_audio_parameters_, &callback_); @@ -179,8 +153,8 @@ TEST_F(AudioDeviceTest, StartStop) { audio_device->Start(); audio_device->Stop(); - EXPECT_CALL(*audio_message_filter_, OnCreateStream(_, _)); - EXPECT_CALL(*audio_message_filter_, OnCloseStream(_)); + EXPECT_CALL(*audio_message_filter_, CreateStream(_, _)); + EXPECT_CALL(*audio_message_filter_, CloseStream(_)); io_loop_.RunAllPending(); } @@ -194,11 +168,12 @@ TEST_F(AudioDeviceTest, CreateStream) { audio_device->Start(); - EXPECT_CALL(*audio_message_filter_, OnCreateStream(_, _)) + EXPECT_CALL(*audio_message_filter_, CreateStream(_, _)) .WillOnce(WithArgs<0>(Invoke(this, &AudioDeviceTest::set_stream_id))); EXPECT_EQ(stream_id_, -1); io_loop_.RunAllPending(); + // OnCreateStream() must have been called and we should have a valid // stream id. ASSERT_NE(stream_id_, -1); @@ -211,7 +186,6 @@ TEST_F(AudioDeviceTest, CreateStream) { default_audio_parameters_.GetBytesPerBuffer()); SharedMemory shared_memory; ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(memory_size)); - // Initialize the memory. memset(shared_memory.memory(), 0xff, memory_size); CancelableSyncSocket browser_socket, renderer_socket; @@ -231,7 +205,7 @@ TEST_F(AudioDeviceTest, CreateStream) { // Respond by asking for some audio data. This should ask our callback // to provide some audio data that AudioDevice then writes into the shared // memory section. - EXPECT_CALL(*audio_message_filter_, OnPlayStream(stream_id_)) + EXPECT_CALL(*audio_message_filter_, PlayStream(stream_id_)) .WillOnce(SendPendingBytes(&browser_socket, memory_size)); // We expect calls to our audio renderer callback, which returns the number @@ -268,8 +242,7 @@ TEST_F(AudioDeviceTest, CreateStream) { io_loop_.Run(); // Close the stream sequence. - - EXPECT_CALL(*audio_message_filter_, OnCloseStream(stream_id_)); + EXPECT_CALL(*audio_message_filter_, CloseStream(stream_id_)); audio_device->Stop(); io_loop_.RunAllPending(); diff --git a/content/renderer/media/audio_input_device.cc b/content/renderer/media/audio_input_device.cc index 6d85143..2f521a8 100644 --- a/content/renderer/media/audio_input_device.cc +++ b/content/renderer/media/audio_input_device.cc @@ -8,10 +8,6 @@ #include "base/message_loop.h" #include "base/threading/thread_restrictions.h" #include "base/time.h" -#include "content/common/child_process.h" -#include "content/common/media/audio_messages.h" -#include "content/common/view_messages.h" -#include "content/renderer/render_thread_impl.h" #include "media/audio/audio_manager_base.h" #include "media/audio/audio_util.h" @@ -37,20 +33,28 @@ class AudioInputDevice::AudioThreadCallback DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); }; -AudioInputDevice::AudioInputDevice(const media::AudioParameters& params, - CaptureCallback* callback, - CaptureEventHandler* event_handler) - : ScopedLoopObserver( - ChildProcess::current()->io_message_loop()->message_loop_proxy()), - audio_parameters_(params), - callback_(callback), - event_handler_(event_handler), - volume_(1.0), +AudioInputDevice::AudioInputDevice( + media::AudioInputIPC* ipc, + const scoped_refptr<base::MessageLoopProxy>& io_loop) + : ScopedLoopObserver(io_loop), + callback_(NULL), + event_handler_(NULL), + ipc_(ipc), stream_id_(0), session_id_(0), pending_device_ready_(false), agc_is_enabled_(false) { - filter_ = RenderThreadImpl::current()->audio_input_message_filter(); + CHECK(ipc_); +} + +void AudioInputDevice::Initialize(const media::AudioParameters& params, + CaptureCallback* callback, + CaptureEventHandler* event_handler) { + DCHECK(!callback_); + DCHECK(!event_handler_); + audio_parameters_ = params; + callback_ = callback; + event_handler_ = event_handler; } void AudioInputDevice::SetDevice(int session_id) { @@ -77,14 +81,14 @@ void AudioInputDevice::Stop() { base::Bind(&AudioInputDevice::ShutDownOnIOThread, this)); } -bool AudioInputDevice::SetVolume(double volume) { - if (volume < 0 || volume > 1.0) - return false; +void AudioInputDevice::SetVolume(double volume) { + if (volume < 0 || volume > 1.0) { + DLOG(ERROR) << "Invalid volume value specified"; + return; + } message_loop()->PostTask(FROM_HERE, base::Bind(&AudioInputDevice::SetVolumeOnIOThread, this, volume)); - - return true; } void AudioInputDevice::SetAutomaticGainControl(bool enabled) { @@ -97,7 +101,7 @@ void AudioInputDevice::SetAutomaticGainControl(bool enabled) { void AudioInputDevice::OnStreamCreated( base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) { + int length) { DCHECK(message_loop()->BelongsToCurrentThread()); #if defined(OS_WIN) DCHECK(handle); @@ -109,15 +113,14 @@ void AudioInputDevice::OnStreamCreated( DCHECK(length); DVLOG(1) << "OnStreamCreated (stream_id=" << stream_id_ << ")"; - base::AutoLock auto_lock(audio_thread_lock_); + // We should only get this callback if stream_id_ is valid. If it is not, + // the IPC layer should have closed the shared memory and socket handles + // for us and not invoked the callback. The basic assertion is that when + // stream_id_ is 0 the AudioInputDevice instance is not registered as a + // delegate and hence it should not receive callbacks. + DCHECK(stream_id_); - // Takes care of the case when Stop() is called before OnStreamCreated(). - if (!stream_id_) { - base::SharedMemory::CloseHandle(handle); - // Close the socket handler. - base::SyncSocket socket(socket_handle); - return; - } + base::AutoLock auto_lock(audio_thread_lock_); DCHECK(audio_thread_.IsStopped()); audio_callback_.reset( @@ -133,7 +136,8 @@ void AudioInputDevice::OnVolume(double volume) { NOTIMPLEMENTED(); } -void AudioInputDevice::OnStateChanged(AudioStreamState state) { +void AudioInputDevice::OnStateChanged( + media::AudioInputIPCDelegate::State state) { DCHECK(message_loop()->BelongsToCurrentThread()); // Do nothing if the stream has been closed. @@ -141,11 +145,9 @@ void AudioInputDevice::OnStateChanged(AudioStreamState state) { return; switch (state) { - // TODO(xians): This should really be kAudioStreamStopped since the stream - // has been closed at this point. - case kAudioStreamPaused: + case media::AudioInputIPCDelegate::kStopped: // TODO(xians): Should we just call ShutDownOnIOThread here instead? - filter_->RemoveDelegate(stream_id_); + ipc_->RemoveDelegate(stream_id_); audio_thread_.Stop(MessageLoop::current()); audio_callback_.reset(); @@ -156,10 +158,10 @@ void AudioInputDevice::OnStateChanged(AudioStreamState state) { stream_id_ = 0; pending_device_ready_ = false; break; - case kAudioStreamPlaying: + case media::AudioInputIPCDelegate::kRecording: NOTIMPLEMENTED(); break; - case kAudioStreamError: + case media::AudioInputIPCDelegate::kError: DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)"; // Don't dereference the callback object if the audio thread // is stopped or stopping. That could mean that the callback @@ -187,11 +189,11 @@ void AudioInputDevice::OnDeviceReady(const std::string& device_id) { // If AudioInputDeviceManager returns an empty string, it means no device // is ready for start. if (device_id.empty()) { - filter_->RemoveDelegate(stream_id_); + ipc_->RemoveDelegate(stream_id_); stream_id_ = 0; } else { - Send(new AudioInputHostMsg_CreateStream(stream_id_, audio_parameters_, - device_id, agc_is_enabled_)); + ipc_->CreateStream(stream_id_, audio_parameters_, device_id, + agc_is_enabled_); } pending_device_ready_ = false; @@ -200,6 +202,10 @@ void AudioInputDevice::OnDeviceReady(const std::string& device_id) { event_handler_->OnDeviceStarted(device_id); } +void AudioInputDevice::OnIPCClosed() { + ipc_ = NULL; +} + AudioInputDevice::~AudioInputDevice() { // TODO(henrika): The current design requires that the user calls // Stop before deleting this class. @@ -213,17 +219,15 @@ void AudioInputDevice::InitializeOnIOThread() { if (stream_id_) return; - stream_id_ = filter_->AddDelegate(this); + stream_id_ = ipc_->AddDelegate(this); // If |session_id_| is not specified, it will directly create the stream; // otherwise it will send a AudioInputHostMsg_StartDevice msg to the browser // and create the stream when getting a OnDeviceReady() callback. if (!session_id_) { - Send(new AudioInputHostMsg_CreateStream( - stream_id_, audio_parameters_, - media::AudioManagerBase::kDefaultDeviceId, - agc_is_enabled_)); + ipc_->CreateStream(stream_id_, audio_parameters_, + media::AudioManagerBase::kDefaultDeviceId, agc_is_enabled_); } else { - Send(new AudioInputHostMsg_StartDevice(stream_id_, session_id_)); + ipc_->StartDevice(stream_id_, session_id_); pending_device_ready_ = true; } } @@ -236,7 +240,7 @@ void AudioInputDevice::SetSessionIdOnIOThread(int session_id) { void AudioInputDevice::StartOnIOThread() { DCHECK(message_loop()->BelongsToCurrentThread()); if (stream_id_) - Send(new AudioInputHostMsg_RecordStream(stream_id_)); + ipc_->RecordStream(stream_id_); } void AudioInputDevice::ShutDownOnIOThread() { @@ -244,8 +248,8 @@ void AudioInputDevice::ShutDownOnIOThread() { // NOTE: |completion| may be NULL. // Make sure we don't call shutdown more than once. if (stream_id_) { - filter_->RemoveDelegate(stream_id_); - Send(new AudioInputHostMsg_CloseStream(stream_id_)); + ipc_->CloseStream(stream_id_); + ipc_->RemoveDelegate(stream_id_); stream_id_ = 0; session_id_ = 0; @@ -268,7 +272,7 @@ void AudioInputDevice::ShutDownOnIOThread() { void AudioInputDevice::SetVolumeOnIOThread(double volume) { DCHECK(message_loop()->BelongsToCurrentThread()); if (stream_id_) - Send(new AudioInputHostMsg_SetVolume(stream_id_, volume)); + ipc_->SetVolume(stream_id_, volume); } void AudioInputDevice::SetAutomaticGainControlOnIOThread(bool enabled) { @@ -283,10 +287,6 @@ void AudioInputDevice::SetAutomaticGainControlOnIOThread(bool enabled) { agc_is_enabled_ = enabled; } -void AudioInputDevice::Send(IPC::Message* message) { - filter_->Send(message); -} - void AudioInputDevice::WillDestroyCurrentMessageLoop() { LOG(ERROR) << "IO loop going away before the input device has been stopped"; ShutDownOnIOThread(); @@ -315,8 +315,8 @@ void AudioInputDevice::AudioThreadCallback::Process(int pending_data) { // structure and parse out parameters and the data area. media::AudioInputBuffer* buffer = reinterpret_cast<media::AudioInputBuffer*>(shared_memory_.memory()); - uint32 size = buffer->params.size; - DCHECK_EQ(size, memory_length_ - sizeof(media::AudioInputBufferParameters)); + DCHECK_EQ(buffer->params.size, + memory_length_ - sizeof(media::AudioInputBufferParameters)); double volume = buffer->params.volume; int audio_delay_milliseconds = pending_data / bytes_per_ms_; diff --git a/content/renderer/media/audio_input_device.h b/content/renderer/media/audio_input_device.h index 8ef72b7..6351182 100644 --- a/content/renderer/media/audio_input_device.h +++ b/content/renderer/media/audio_input_device.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Low-latency audio capturing unit utilizing audio input stream provided -// by browser process through IPC. +// Low-latency audio capturing class utilizing audio input stream provided +// by a server (browser) process by use of an IPC interface. // // Relationship of classes: // @@ -11,58 +11,51 @@ // ^ ^ // | | // v IPC v -// AudioInputRendererHost <---------> AudioInputMessageFilter -// ^ +// AudioInputRendererHost <---------> media::AudioInputIPCDelegate +// ^ (impl in AudioInputMessageFilter) // | // v // AudioInputDeviceManager // // Transportation of audio samples from the browser to the render process -// is done by using shared memory in combination with a sync socket pair -// to generate a low latency transport. The AudioInputDevice user registers -// an AudioInputDevice::CaptureCallback at construction and will be called -// by the AudioInputDevice with recorded audio from the underlying audio layers. +// is done by using shared memory in combination with a SyncSocket. +// The AudioInputDevice user registers an AudioInputDevice::CaptureCallback by +// calling Initialize(). The callback will be called with recorded audio from +// the underlying audio layers. // The session ID is used by the AudioInputRendererHost to start the device // referenced by this ID. // // State sequences: // -// Task [IO thread] IPC [IO thread] -// // Sequence where session_id has not been set using SetDevice(): -// Start -> InitializeOnIOThread -----> AudioInputHostMsg_CreateStream -------> -// <- OnLowLatencyCreated <- AudioInputMsg_NotifyLowLatencyStreamCreated <- -// ---> StartOnIOThread ---------> AudioInputHostMsg_PlayStream --------> +// ('<-' signifies callbacks, -> signifies calls made by AudioInputDevice) +// Start -> InitializeOnIOThread -> CreateStream -> +// <- OnStreamCreated <- +// -> StartOnIOThread -> PlayStream -> // // Sequence where session_id has been set using SetDevice(): -// Start -> InitializeOnIOThread --> AudioInputHostMsg_StartDevice ---> -// <---- OnStarted <-------------- AudioInputMsg_NotifyDeviceStarted <---- -// -> OnDeviceReady ------------> AudioInputHostMsg_CreateStream -------> -// <- OnLowLatencyCreated <- AudioInputMsg_NotifyLowLatencyStreamCreated <- -// ---> StartOnIOThread ---------> AudioInputHostMsg_PlayStream --------> +// Start -> InitializeOnIOThread -> StartDevice -> +// <- OnDeviceReady <- +// -> CreateStream -> +// <- OnStreamCreated <- +// -> StartOnIOThread -> PlayStream -> // // AudioInputDevice::Capture => low latency audio transport on audio thread => // | -// Stop --> ShutDownOnIOThread ------> AudioInputHostMsg_CloseStream -> Close +// Stop --> ShutDownOnIOThread ------> CloseStream -> Close // -// This class utilizes three threads during its lifetime, namely: +// This class depends on two threads to function: // -// 1. Creating thread. -// Must be the main render thread. Start and Stop should be called on -// this thread. -// 2. IO thread. -// The thread within which this class receives all the IPC messages and -// IPC communications can only happen in this thread. -// 3. Audio transport thread. -// Responsible for calling the CaptrureCallback and feed audio samples from -// the audio layer in the browser process using sync sockets and shared -// memory. +// 1. An IO thread. +// This thread is used to asynchronously process Start/Stop etc operations +// that are available via the public interface. The public methods are +// asynchronous and simply post a task to the IO thread to actually perform +// the work. +// 2. Audio transport thread. +// Responsible for calling the CaptureCallback and feed audio samples from +// the server side audio layer using a socket and shared memory. // // Implementation notes: -// -// - Start() is asynchronous/non-blocking. -// - Stop() is synchronous/blocking. -// - SetDevice() is asynchronous/non-blocking. // - The user must call Stop() before deleting the class instance. #ifndef CONTENT_RENDERER_MEDIA_AUDIO_INPUT_DEVICE_H_ @@ -87,7 +80,7 @@ // OnCaptureStopped etc.) and ensure that we can deliver these notifications // to any clients using this class. class CONTENT_EXPORT AudioInputDevice - : public AudioInputMessageFilter::Delegate, + : NON_EXPORTED_BASE(public media::AudioInputIPCDelegate), NON_EXPORTED_BASE(public ScopedLoopObserver), public base::RefCountedThreadSafe<AudioInputDevice> { public: @@ -116,60 +109,52 @@ class CONTENT_EXPORT AudioInputDevice virtual ~CaptureEventHandler() {} }; - // Methods called on main render thread ------------------------------------- - AudioInputDevice(const media::AudioParameters& params, - CaptureCallback* callback, - CaptureEventHandler* event_handler); + AudioInputDevice(media::AudioInputIPC* ipc, + const scoped_refptr<base::MessageLoopProxy>& io_loop); - // Specify the |session_id| to query which device to use. This method is - // asynchronous/non-blocking. + // Initializes the AudioInputDevice. This method must be called before + // any other methods can be used. + void Initialize(const media::AudioParameters& params, + CaptureCallback* callback, + CaptureEventHandler* event_handler); + + // Specify the |session_id| to query which device to use. // Start() will use the second sequence if this method is called before. void SetDevice(int session_id); - // Starts audio capturing. This method is asynchronous/non-blocking. + // Starts audio capturing. // TODO(henrika): add support for notification when recording has started. void Start(); - // Stops audio capturing. This method is synchronous/blocking. + // Stops audio capturing. // TODO(henrika): add support for notification when recording has stopped. void Stop(); // Sets the capture volume scaling, with range [0.0, 1.0] inclusive. // Returns |true| on success. - bool SetVolume(double volume); - - // Gets the capture volume scaling, with range [0.0, 1.0] inclusive. - // Returns |true| on success. - bool GetVolume(double* volume); - - double sample_rate() const { - return audio_parameters_.sample_rate(); - } - - int buffer_size() const { - return audio_parameters_.frames_per_buffer(); - } + void SetVolume(double volume); // Sets the Automatic Gain Control state to on or off. // This method must be called before Start(). It will not have any effect // if it is called while capturing has already started. void SetAutomaticGainControl(bool enabled); + protected: // Methods called on IO thread ---------------------------------------------- - // AudioInputMessageFilter::Delegate impl., called by AudioInputMessageFilter. + // media::AudioInputIPCDelegate implementation. virtual void OnStreamCreated(base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) OVERRIDE; + int length) OVERRIDE; virtual void OnVolume(double volume) OVERRIDE; - virtual void OnStateChanged(AudioStreamState state) OVERRIDE; + virtual void OnStateChanged( + media::AudioInputIPCDelegate::State state) OVERRIDE; virtual void OnDeviceReady(const std::string& device_id) OVERRIDE; + virtual void OnIPCClosed() OVERRIDE; - protected: + friend class base::RefCountedThreadSafe<AudioInputDevice>; virtual ~AudioInputDevice(); private: - friend class base::RefCountedThreadSafe<AudioInputDevice>; - // Methods called on IO thread ---------------------------------------------- // The following methods are tasks posted on the IO thread that needs to // be executed on that thread. They interact with AudioInputMessageFilter and @@ -181,26 +166,19 @@ class CONTENT_EXPORT AudioInputDevice void SetVolumeOnIOThread(double volume); void SetAutomaticGainControlOnIOThread(bool enabled); - void Send(IPC::Message* message); - // MessageLoop::DestructionObserver implementation for the IO loop. // If the IO loop dies before we do, we shut down the audio thread from here. virtual void WillDestroyCurrentMessageLoop() OVERRIDE; - // Format media::AudioParameters audio_parameters_; CaptureCallback* callback_; CaptureEventHandler* event_handler_; - // The current volume scaling [0.0, 1.0] of the audio stream. - double volume_; - - // Cached audio input message filter (lives on the main render thread). - scoped_refptr<AudioInputMessageFilter> filter_; + media::AudioInputIPC* ipc_; // Our stream ID on the message filter. Only modified on the IO thread. - int32 stream_id_; + int stream_id_; // The media session ID used to identify which input device to be started. // Only modified on the IO thread. diff --git a/content/renderer/media/audio_input_message_filter.cc b/content/renderer/media/audio_input_message_filter.cc index 30e4b01..b523ac6 100644 --- a/content/renderer/media/audio_input_message_filter.cc +++ b/content/renderer/media/audio_input_message_filter.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -11,13 +11,24 @@ #include "content/common/media/audio_messages.h" #include "ipc/ipc_logging.h" +AudioInputMessageFilter* AudioInputMessageFilter::filter_ = NULL; + AudioInputMessageFilter::AudioInputMessageFilter() : channel_(NULL) { - VLOG(1) << "AudioInputMessageFilter()"; + DVLOG(1) << "AudioInputMessageFilter()"; + DCHECK(!filter_); + filter_ = this; } AudioInputMessageFilter::~AudioInputMessageFilter() { - VLOG(1) << "AudioInputMessageFilter::~AudioInputMessageFilter()"; + DVLOG(1) << "AudioInputMessageFilter::~AudioInputMessageFilter()"; + DCHECK_EQ(filter_, this); + filter_ = NULL; +} + +// static. +AudioInputMessageFilter* AudioInputMessageFilter::Get() { + return filter_; } bool AudioInputMessageFilter::Send(IPC::Message* message) { @@ -55,7 +66,7 @@ bool AudioInputMessageFilter::OnMessageReceived(const IPC::Message& message) { } void AudioInputMessageFilter::OnFilterAdded(IPC::Channel* channel) { - VLOG(1) << "AudioInputMessageFilter::OnFilterAdded()"; + DVLOG(1) << "AudioInputMessageFilter::OnFilterAdded()"; // Captures the channel for IPC. channel_ = channel; } @@ -66,6 +77,14 @@ void AudioInputMessageFilter::OnFilterRemoved() { void AudioInputMessageFilter::OnChannelClosing() { channel_ = NULL; + LOG_IF(WARNING, !delegates_.IsEmpty()) + << "Not all audio devices have been closed."; + + IDMap<media::AudioInputIPCDelegate>::iterator it(&delegates_); + while (!it.IsAtEnd()) { + it.GetCurrentValue()->OnIPCClosed(); + it.Advance(); + } } void AudioInputMessageFilter::OnStreamCreated( @@ -80,7 +99,7 @@ void AudioInputMessageFilter::OnStreamCreated( #if !defined(OS_WIN) base::SyncSocket::Handle socket_handle = socket_descriptor.fd; #endif - Delegate* delegate = delegates_.Lookup(stream_id); + media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id); if (!delegate) { DLOG(WARNING) << "Got audio stream event for a non-existent or removed" " audio capturer (stream_id=" << stream_id << ")."; @@ -93,7 +112,7 @@ void AudioInputMessageFilter::OnStreamCreated( } void AudioInputMessageFilter::OnStreamVolume(int stream_id, double volume) { - Delegate* delegate = delegates_.Lookup(stream_id); + media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id); if (!delegate) { DLOG(WARNING) << "Got audio stream event for a non-existent or removed" " audio capturer."; @@ -103,8 +122,8 @@ void AudioInputMessageFilter::OnStreamVolume(int stream_id, double volume) { } void AudioInputMessageFilter::OnStreamStateChanged( - int stream_id, AudioStreamState state) { - Delegate* delegate = delegates_.Lookup(stream_id); + int stream_id, media::AudioInputIPCDelegate::State state) { + media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id); if (!delegate) { DLOG(WARNING) << "Got audio stream event for a non-existent or removed" " audio renderer."; @@ -115,20 +134,43 @@ void AudioInputMessageFilter::OnStreamStateChanged( void AudioInputMessageFilter::OnDeviceStarted(int stream_id, const std::string& device_id) { - Delegate* delegate = delegates_.Lookup(stream_id); + media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id); if (!delegate) { - DLOG(WARNING) << "Got audio stream event for a non-existent or removed" - " audio renderer."; + NOTREACHED(); return; } delegate->OnDeviceReady(device_id); } -int32 AudioInputMessageFilter::AddDelegate(Delegate* delegate) { +int AudioInputMessageFilter::AddDelegate( + media::AudioInputIPCDelegate* delegate) { return delegates_.Add(delegate); } -void AudioInputMessageFilter::RemoveDelegate(int32 id) { - VLOG(1) << "AudioInputMessageFilter::RemoveDelegate(id=" << id << ")"; +void AudioInputMessageFilter::RemoveDelegate(int id) { + DVLOG(1) << "AudioInputMessageFilter::RemoveDelegate(id=" << id << ")"; delegates_.Remove(id); } + +void AudioInputMessageFilter::CreateStream(int stream_id, + const media::AudioParameters& params, const std::string& device_id, + bool automatic_gain_control) { + Send(new AudioInputHostMsg_CreateStream( + stream_id, params, device_id, automatic_gain_control)); +} + +void AudioInputMessageFilter::StartDevice(int stream_id, int session_id) { + Send(new AudioInputHostMsg_StartDevice(stream_id, session_id)); +} + +void AudioInputMessageFilter::RecordStream(int stream_id) { + Send(new AudioInputHostMsg_RecordStream(stream_id)); +} + +void AudioInputMessageFilter::CloseStream(int stream_id) { + Send(new AudioInputHostMsg_CloseStream(stream_id)); +} + +void AudioInputMessageFilter::SetVolume(int stream_id, double volume) { + Send(new AudioInputHostMsg_SetVolume(stream_id, volume)); +} diff --git a/content/renderer/media/audio_input_message_filter.h b/content/renderer/media/audio_input_message_filter.h index ba5e9de..ee99900 100644 --- a/content/renderer/media/audio_input_message_filter.h +++ b/content/renderer/media/audio_input_message_filter.h @@ -14,50 +14,36 @@ #include "base/shared_memory.h" #include "base/sync_socket.h" #include "content/common/content_export.h" -#include "content/common/media/audio_stream_state.h" #include "ipc/ipc_channel_proxy.h" #include "media/audio/audio_buffers_state.h" +#include "media/audio/audio_input_ipc.h" class CONTENT_EXPORT AudioInputMessageFilter - : public IPC::ChannelProxy::MessageFilter { + : public IPC::ChannelProxy::MessageFilter, + public NON_EXPORTED_BASE(media::AudioInputIPC) { public: - class CONTENT_EXPORT Delegate { - public: - // Called when an audio input stream has been created in the browser - // process. - virtual void OnStreamCreated(base::SharedMemoryHandle handle, - base::SyncSocket::Handle socket_handle, - uint32 length) = 0; - - // Called when notification of input stream volume is received from the - // browser process. - virtual void OnVolume(double volume) = 0; - - // Called when state of an input stream has changed in the browser process. - virtual void OnStateChanged(AudioStreamState state) = 0; - - // Called when the device referenced by the index has been started in - // the browswer process. - virtual void OnDeviceReady(const std::string& device_id) = 0; - - protected: - virtual ~Delegate() {} - }; - AudioInputMessageFilter(); - // Add a delegate to the map and return id of the entry. - int32 AddDelegate(Delegate* delegate); - - // Remove a delegate referenced by |id| from the map. - void RemoveDelegate(int32 id); + // Getter for the one AudioInputMessageFilter object. + static AudioInputMessageFilter* Get(); - // Sends an IPC message using |channel_|. - bool Send(IPC::Message* message); + // Implementation of AudioInputIPC. + virtual int AddDelegate( + media::AudioInputIPCDelegate* delegate) OVERRIDE; + virtual void RemoveDelegate(int id) OVERRIDE; + virtual void CreateStream(int stream_id, const media::AudioParameters& params, + const std::string& device_id, bool automatic_gain_control) OVERRIDE; + virtual void StartDevice(int stream_id, int session_id) OVERRIDE; + virtual void RecordStream(int stream_id) OVERRIDE; + virtual void CloseStream(int stream_id) OVERRIDE; + virtual void SetVolume(int stream_id, double volume) OVERRIDE; private: virtual ~AudioInputMessageFilter(); + // Sends an IPC message using |channel_|. + bool Send(IPC::Message* message); + // IPC::ChannelProxy::MessageFilter override. Called on IO thread. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; @@ -78,16 +64,20 @@ class CONTENT_EXPORT AudioInputMessageFilter // Received when internal state of browser process' audio input stream has // changed. - void OnStreamStateChanged(int stream_id, AudioStreamState state); + void OnStreamStateChanged(int stream_id, + media::AudioInputIPCDelegate::State state); // Notification of the opened device of an audio session. void OnDeviceStarted(int stream_id, const std::string& device_id); // A map of stream ids to delegates. - IDMap<Delegate> delegates_; + IDMap<media::AudioInputIPCDelegate> delegates_; IPC::Channel* channel_; + // The singleton instance for this filter. + static AudioInputMessageFilter* 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 8168992..ef3bd80 100644 --- a/content/renderer/media/audio_message_filter.cc +++ b/content/renderer/media/audio_message_filter.cc @@ -21,19 +21,44 @@ AudioMessageFilter* AudioMessageFilter::Get() { AudioMessageFilter::AudioMessageFilter() : channel_(NULL) { - VLOG(1) << "AudioMessageFilter::AudioMessageFilter()"; + DVLOG(1) << "AudioMessageFilter::AudioMessageFilter()"; DCHECK(!filter_); filter_ = this; } -int32 AudioMessageFilter::AddDelegate(Delegate* delegate) { +int AudioMessageFilter::AddDelegate(media::AudioOutputIPCDelegate* delegate) { return delegates_.Add(delegate); } -void AudioMessageFilter::RemoveDelegate(int32 id) { +void AudioMessageFilter::RemoveDelegate(int id) { delegates_.Remove(id); } +void AudioMessageFilter::CreateStream(int stream_id, + const media::AudioParameters& params) { + Send(new AudioHostMsg_CreateStream(stream_id, params)); +} + +void AudioMessageFilter::PlayStream(int stream_id) { + Send(new AudioHostMsg_PlayStream(stream_id)); +} + +void AudioMessageFilter::PauseStream(int stream_id) { + Send(new AudioHostMsg_PauseStream(stream_id)); +} + +void AudioMessageFilter::FlushStream(int stream_id) { + Send(new AudioHostMsg_FlushStream(stream_id)); +} + +void AudioMessageFilter::CloseStream(int stream_id) { + Send(new AudioHostMsg_CloseStream(stream_id)); +} + +void AudioMessageFilter::SetVolume(int stream_id, double volume) { + Send(new AudioHostMsg_SetVolume(stream_id, volume)); +} + bool AudioMessageFilter::Send(IPC::Message* message) { if (!channel_) { delete message; @@ -64,8 +89,7 @@ bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) { } void AudioMessageFilter::OnFilterAdded(IPC::Channel* channel) { - VLOG(1) << "AudioMessageFilter::OnFilterAdded()"; - // Captures the channel for IPC. + DVLOG(1) << "AudioMessageFilter::OnFilterAdded()"; channel_ = channel; } @@ -75,10 +99,18 @@ void AudioMessageFilter::OnFilterRemoved() { void AudioMessageFilter::OnChannelClosing() { channel_ = NULL; + LOG_IF(WARNING, !delegates_.IsEmpty()) + << "Not all audio devices have been closed."; + + IDMap<media::AudioOutputIPCDelegate>::iterator it(&delegates_); + while (!it.IsAtEnd()) { + it.GetCurrentValue()->OnIPCClosed(); + it.Advance(); + } } AudioMessageFilter::~AudioMessageFilter() { - VLOG(1) << "AudioMessageFilter::~AudioMessageFilter()"; + DVLOG(1) << "AudioMessageFilter::~AudioMessageFilter()"; DCHECK(filter_); filter_ = NULL; } @@ -95,10 +127,10 @@ void AudioMessageFilter::OnStreamCreated( #if !defined(OS_WIN) base::SyncSocket::Handle socket_handle = socket_descriptor.fd; #endif - Delegate* delegate = delegates_.Lookup(stream_id); + media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id); if (!delegate) { DLOG(WARNING) << "Got audio stream event for a non-existent or removed" - " audio renderer. (stream_id=" << stream_id << ")."; + " audio renderer. (stream_id=" << stream_id << ")."; base::SharedMemory::CloseHandle(handle); base::SyncSocket socket(socket_handle); return; @@ -107,11 +139,10 @@ void AudioMessageFilter::OnStreamCreated( } void AudioMessageFilter::OnStreamStateChanged( - int stream_id, AudioStreamState state) { - Delegate* delegate = delegates_.Lookup(stream_id); + int stream_id, media::AudioOutputIPCDelegate::State state) { + media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id); if (!delegate) { - DLOG(WARNING) << "Got audio stream event for a non-existent or removed" - " audio renderer."; + DLOG(WARNING) << "No delegate found for state change. " << state; return; } delegate->OnStateChanged(state); diff --git a/content/renderer/media/audio_message_filter.h b/content/renderer/media/audio_message_filter.h index efc80a7..c50dca4 100644 --- a/content/renderer/media/audio_message_filter.h +++ b/content/renderer/media/audio_message_filter.h @@ -14,42 +14,30 @@ #include "base/id_map.h" #include "base/shared_memory.h" #include "base/sync_socket.h" -#include "content/common/media/audio_stream_state.h" #include "content/common/content_export.h" #include "ipc/ipc_channel_proxy.h" #include "media/audio/audio_buffers_state.h" +#include "media/audio/audio_output_ipc.h" class CONTENT_EXPORT AudioMessageFilter - : public IPC::ChannelProxy::MessageFilter { + : public IPC::ChannelProxy::MessageFilter, + public NON_EXPORTED_BASE(media::AudioOutputIPC) { public: - class CONTENT_EXPORT Delegate { - public: - // Called when state of an audio stream has changed in the browser process. - virtual void OnStateChanged(AudioStreamState state) = 0; - - // Called when an audio stream has been created in the browser process. - virtual void OnStreamCreated(base::SharedMemoryHandle handle, - base::SyncSocket::Handle socket_handle, - uint32 length) = 0; - - protected: - virtual ~Delegate() {} - }; - AudioMessageFilter(); // Getter for the one AudioMessageFilter object. static AudioMessageFilter* Get(); - // Add a delegate to the map and return id of the entry. - int32 AddDelegate(Delegate* delegate); - - // Remove a delegate referenced by |id| from the map. - void RemoveDelegate(int32 id); - - // Sends an IPC message using |channel_|. - // This method is virtual so that it can be overridden in tests. - virtual bool Send(IPC::Message* message); + // media::AudioOutputIPCDelegate implementation. + virtual int AddDelegate(media::AudioOutputIPCDelegate* delegate) OVERRIDE; + virtual void RemoveDelegate(int id) OVERRIDE; + 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 FlushStream(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 thread. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; @@ -64,6 +52,9 @@ class CONTENT_EXPORT AudioMessageFilter FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Basic); FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Delegates); + // Sends an IPC message using |channel_|. + bool Send(IPC::Message* message); + // Received when browser process has created an audio output stream. void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle, #if defined(OS_WIN) @@ -73,16 +64,16 @@ class CONTENT_EXPORT AudioMessageFilter #endif uint32 length); - // Received when internal state of browser process' audio output device has // changed. - void OnStreamStateChanged(int stream_id, AudioStreamState state); + void OnStreamStateChanged(int stream_id, + media::AudioOutputIPCDelegate::State state); // The singleton instance for this filter. static AudioMessageFilter* filter_; // A map of stream ids to delegates. - IDMap<Delegate> delegates_; + IDMap<media::AudioOutputIPCDelegate> delegates_; IPC::Channel* channel_; diff --git a/content/renderer/media/audio_message_filter_unittest.cc b/content/renderer/media/audio_message_filter_unittest.cc index 2031213..26a6247 100644 --- a/content/renderer/media/audio_message_filter_unittest.cc +++ b/content/renderer/media/audio_message_filter_unittest.cc @@ -5,29 +5,33 @@ #include "base/message_loop.h" #include "content/common/media/audio_messages.h" #include "content/renderer/media/audio_message_filter.h" +#include "media/audio/audio_output_ipc.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -class MockAudioDelegate : public AudioMessageFilter::Delegate { +class MockAudioDelegate : public media::AudioOutputIPCDelegate { public: MockAudioDelegate() { Reset(); } - virtual void OnStateChanged(AudioStreamState state) { + virtual void OnStateChanged( + media::AudioOutputIPCDelegate::State state) OVERRIDE { state_changed_received_ = true; state_ = state; } virtual void OnStreamCreated(base::SharedMemoryHandle handle, base::SyncSocket::Handle, - uint32 length) { + int length) OVERRIDE { created_received_ = true; handle_ = handle; length_ = length; } + virtual void OnIPCClosed() OVERRIDE {} + virtual void OnVolume(double volume) { volume_received_ = true; volume_ = volume; @@ -35,7 +39,7 @@ class MockAudioDelegate : public AudioMessageFilter::Delegate { void Reset() { state_changed_received_ = false; - state_ = kAudioStreamError; + state_ = media::AudioOutputIPCDelegate::kError; created_received_ = false; handle_ = base::SharedMemory::NULLHandle(); @@ -46,7 +50,7 @@ class MockAudioDelegate : public AudioMessageFilter::Delegate { } bool state_changed_received() { return state_changed_received_; } - AudioStreamState state() { return state_; } + media::AudioOutputIPCDelegate::State state() { return state_; } bool created_received() { return created_received_; } base::SharedMemoryHandle handle() { return handle_; } @@ -57,11 +61,11 @@ class MockAudioDelegate : public AudioMessageFilter::Delegate { private: bool state_changed_received_; - AudioStreamState state_; + media::AudioOutputIPCDelegate::State state_; bool created_received_; base::SharedMemoryHandle handle_; - uint32 length_; + int length_; bool volume_received_; double volume_; @@ -99,9 +103,10 @@ TEST(AudioMessageFilterTest, Basic) { // AudioMsg_NotifyStreamStateChanged EXPECT_FALSE(delegate.state_changed_received()); filter->OnMessageReceived( - AudioMsg_NotifyStreamStateChanged(stream_id, kAudioStreamPlaying)); + AudioMsg_NotifyStreamStateChanged( + stream_id, media::AudioOutputIPCDelegate::kPlaying)); EXPECT_TRUE(delegate.state_changed_received()); - EXPECT_TRUE(kAudioStreamPlaying == delegate.state()); + EXPECT_EQ(media::AudioOutputIPCDelegate::kPlaying, delegate.state()); delegate.Reset(); message_loop.RunAllPending(); @@ -122,7 +127,8 @@ TEST(AudioMessageFilterTest, Delegates) { EXPECT_FALSE(delegate1.state_changed_received()); EXPECT_FALSE(delegate2.state_changed_received()); filter->OnMessageReceived( - AudioMsg_NotifyStreamStateChanged(stream_id1, kAudioStreamPlaying)); + AudioMsg_NotifyStreamStateChanged( + stream_id1, media::AudioOutputIPCDelegate::kPlaying)); EXPECT_TRUE(delegate1.state_changed_received()); EXPECT_FALSE(delegate2.state_changed_received()); delegate1.Reset(); @@ -130,23 +136,11 @@ TEST(AudioMessageFilterTest, Delegates) { EXPECT_FALSE(delegate1.state_changed_received()); EXPECT_FALSE(delegate2.state_changed_received()); filter->OnMessageReceived( - AudioMsg_NotifyStreamStateChanged(stream_id2, kAudioStreamPlaying)); + AudioMsg_NotifyStreamStateChanged( + stream_id2, media::AudioOutputIPCDelegate::kPlaying)); EXPECT_FALSE(delegate1.state_changed_received()); EXPECT_TRUE(delegate2.state_changed_received()); delegate2.Reset(); - // Remove the delegates. Make sure they won't get called. - filter->RemoveDelegate(stream_id1); - EXPECT_FALSE(delegate1.state_changed_received()); - filter->OnMessageReceived( - AudioMsg_NotifyStreamStateChanged(stream_id1, kAudioStreamPlaying)); - EXPECT_FALSE(delegate1.state_changed_received()); - - filter->RemoveDelegate(stream_id2); - EXPECT_FALSE(delegate2.state_changed_received()); - filter->OnMessageReceived( - AudioMsg_NotifyStreamStateChanged(stream_id2, kAudioStreamPlaying)); - EXPECT_FALSE(delegate2.state_changed_received()); - message_loop.RunAllPending(); } diff --git a/content/renderer/media/audio_renderer_mixer_manager.cc b/content/renderer/media/audio_renderer_mixer_manager.cc index 03e638e..411ae8b4 100644 --- a/content/renderer/media/audio_renderer_mixer_manager.cc +++ b/content/renderer/media/audio_renderer_mixer_manager.cc @@ -48,7 +48,7 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( hardware_sample_rate_, 16, hardware_buffer_size_); media::AudioRendererMixer* mixer = new media::AudioRendererMixer( - params, output_params, AudioDeviceFactory::Create()); + params, output_params, AudioDeviceFactory::NewOutputDevice()); AudioRendererMixerReference mixer_reference = { mixer, 1 }; mixers_[params] = mixer_reference; diff --git a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc index 92a44d4..5eeae9b 100644 --- a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc +++ b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc @@ -27,13 +27,18 @@ class MockAudioRenderSinkFactory : public AudioDeviceFactory { virtual ~MockAudioRenderSinkFactory() {} protected: - virtual media::MockAudioRendererSink* CreateAudioDevice() { + virtual media::MockAudioRendererSink* CreateOutputDevice() OVERRIDE { media::MockAudioRendererSink* sink = new media::MockAudioRendererSink(); EXPECT_CALL(*sink, Start()); EXPECT_CALL(*sink, Stop()); return sink; } + virtual AudioInputDevice* CreateInputDevice() OVERRIDE { + ADD_FAILURE(); + return NULL; + } + DISALLOW_COPY_AND_ASSIGN(MockAudioRenderSinkFactory); }; diff --git a/content/renderer/media/render_audiosourceprovider.cc b/content/renderer/media/render_audiosourceprovider.cc index da1e341..f879a47 100644 --- a/content/renderer/media/render_audiosourceprovider.cc +++ b/content/renderer/media/render_audiosourceprovider.cc @@ -35,7 +35,7 @@ RenderAudioSourceProvider::RenderAudioSourceProvider() default_sink_ = RenderThreadImpl::current()-> GetAudioRendererMixerManager()->CreateInput(); } else { - default_sink_ = AudioDeviceFactory::Create(); + default_sink_ = AudioDeviceFactory::NewOutputDevice(); } } diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc index f67c282..0ac56e8 100644 --- a/content/renderer/media/renderer_webaudiodevice_impl.cc +++ b/content/renderer/media/renderer_webaudiodevice_impl.cc @@ -16,7 +16,7 @@ RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl( WebAudioDevice::RenderCallback* callback) : is_running_(false), client_callback_(callback) { - audio_device_ = AudioDeviceFactory::Create(); + audio_device_ = AudioDeviceFactory::NewOutputDevice(); audio_device_->Initialize(params, this); } diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc index d1bbb1c..d2657d6 100644 --- a/content/renderer/media/webrtc_audio_device_impl.cc +++ b/content/renderer/media/webrtc_audio_device_impl.cc @@ -147,7 +147,7 @@ WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() // input side as well. DCHECK(RenderThreadImpl::current()) << "WebRtcAudioDeviceImpl must be constructed on the render thread"; - audio_output_device_ = AudioDeviceFactory::Create(); + audio_output_device_ = AudioDeviceFactory::NewOutputDevice(); DCHECK(audio_output_device_); } @@ -398,6 +398,8 @@ int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback( int32_t WebRtcAudioDeviceImpl::Init() { DVLOG(1) << "Init()"; + // TODO(henrika): After switching to using the AudioDeviceFactory for + // instantiating the input device, maybe this isn't a requirement anymore? if (!render_loop_->BelongsToCurrentThread()) { int32_t error = 0; base::WaitableEvent event(false, false); @@ -578,8 +580,8 @@ int32_t WebRtcAudioDeviceImpl::Init() { 16, in_buffer_size); // Create and configure the audio capturing client. - audio_input_device_ = new AudioInputDevice( - input_audio_parameters_, this, this); + audio_input_device_ = AudioDeviceFactory::NewInputDevice(); + audio_input_device_->Initialize(input_audio_parameters_, this, this); UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputChannelLayout", out_channel_layout, CHANNEL_LAYOUT_MAX); diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.cc b/content/renderer/pepper/pepper_platform_audio_input_impl.cc index effcf2a..61b8804 100644 --- a/content/renderer/pepper/pepper_platform_audio_input_impl.cc +++ b/content/renderer/pepper/pepper_platform_audio_input_impl.cc @@ -24,7 +24,7 @@ PepperPlatformAudioInputImpl* PepperPlatformAudioInputImpl::Create( int frames_per_buffer, webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) { scoped_refptr<PepperPlatformAudioInputImpl> audio_input( - new PepperPlatformAudioInputImpl); + new PepperPlatformAudioInputImpl()); if (audio_input->Initialize(plugin_delegate, device_id, sample_rate, frames_per_buffer, client)) { // Balanced by Release invoked in @@ -64,7 +64,7 @@ void PepperPlatformAudioInputImpl::ShutDown() { void PepperPlatformAudioInputImpl::OnStreamCreated( base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) { + int length) { #if defined(OS_WIN) DCHECK(handle); DCHECK(socket_handle); @@ -97,7 +97,9 @@ void PepperPlatformAudioInputImpl::OnStreamCreated( void PepperPlatformAudioInputImpl::OnVolume(double volume) {} -void PepperPlatformAudioInputImpl::OnStateChanged(AudioStreamState state) {} +void PepperPlatformAudioInputImpl::OnStateChanged( + media::AudioInputIPCDelegate::State state) { +} void PepperPlatformAudioInputImpl::OnDeviceReady(const std::string& device_id) { DCHECK(ChildProcess::current()->io_message_loop_proxy()-> @@ -113,11 +115,14 @@ void PepperPlatformAudioInputImpl::OnDeviceReady(const std::string& device_id) { this)); } else { // We will be notified by OnStreamCreated(). - filter_->Send(new AudioInputHostMsg_CreateStream(stream_id_, params_, - device_id, false)); + ipc_->CreateStream(stream_id_, params_, device_id, false); } } +void PepperPlatformAudioInputImpl::OnIPCClosed() { + ipc_ = NULL; +} + PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() { // Make sure we have been shut down. Warning: this may happen on the I/O // thread! @@ -135,7 +140,7 @@ PepperPlatformAudioInputImpl::PepperPlatformAudioInputImpl() stream_id_(0), main_message_loop_proxy_(base::MessageLoopProxy::current()), shutdown_called_(false) { - filter_ = RenderThreadImpl::current()->audio_input_message_filter(); + ipc_ = RenderThreadImpl::current()->audio_input_message_filter(); } bool PepperPlatformAudioInputImpl::Initialize( @@ -180,17 +185,16 @@ void PepperPlatformAudioInputImpl::InitializeOnIOThread(int session_id) { // Make sure we don't call init more than once. DCHECK_EQ(0, stream_id_); - stream_id_ = filter_->AddDelegate(this); + stream_id_ = ipc_->AddDelegate(this); DCHECK_NE(0, stream_id_); if (!session_id) { // We will be notified by OnStreamCreated(). - filter_->Send(new AudioInputHostMsg_CreateStream( - stream_id_, params_, - media::AudioManagerBase::kDefaultDeviceId, false)); + ipc_->CreateStream(stream_id_, params_, + media::AudioManagerBase::kDefaultDeviceId, false); } else { // We will be notified by OnDeviceReady(). - filter_->Send(new AudioInputHostMsg_StartDevice(stream_id_, session_id)); + ipc_->StartDevice(stream_id_, session_id); } } @@ -199,7 +203,7 @@ void PepperPlatformAudioInputImpl::StartCaptureOnIOThread() { BelongsToCurrentThread()); if (stream_id_) - filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_)); + ipc_->RecordStream(stream_id_); } void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() { @@ -208,7 +212,7 @@ void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() { // TODO(yzshen): We cannot re-start capturing if the stream is closed. if (stream_id_) - filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_)); + ipc_->CloseStream(stream_id_); } void PepperPlatformAudioInputImpl::ShutDownOnIOThread() { @@ -221,8 +225,8 @@ void PepperPlatformAudioInputImpl::ShutDownOnIOThread() { shutdown_called_ = true; if (stream_id_) { - filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_)); - filter_->RemoveDelegate(stream_id_); + ipc_->CloseStream(stream_id_); + ipc_->RemoveDelegate(stream_id_); stream_id_ = 0; } diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.h b/content/renderer/pepper/pepper_platform_audio_input_impl.h index d83a12e..864afa1 100644 --- a/content/renderer/pepper/pepper_platform_audio_input_impl.h +++ b/content/renderer/pepper/pepper_platform_audio_input_impl.h @@ -28,12 +28,12 @@ class PepperPluginDelegateImpl; // except the destructor, must be called on the main thread. The notifications // to the users of this class (via the PlatformAudioInputClient interface) are // also sent on the main thread. Internally, this class sends audio input IPC -// messages and receives AudioInputMessageFilter::Delegate notifications on the +// messages and receives media::AudioInputIPCDelegate notifications on the // I/O thread. class PepperPlatformAudioInputImpl : public webkit::ppapi::PluginDelegate::PlatformAudioInput, - public AudioInputMessageFilter::Delegate, + public media::AudioInputIPCDelegate, public base::RefCountedThreadSafe<PepperPlatformAudioInputImpl> { public: // Factory function, returns NULL on failure. StreamCreated() will be called @@ -50,13 +50,15 @@ class PepperPlatformAudioInputImpl virtual void StopCapture() OVERRIDE; virtual void ShutDown() OVERRIDE; - // AudioInputMessageFilter::Delegate. + // media::AudioInputIPCDelegate. virtual void OnStreamCreated(base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) OVERRIDE; + int length) OVERRIDE; virtual void OnVolume(double volume) OVERRIDE; - virtual void OnStateChanged(AudioStreamState state) OVERRIDE; + virtual void OnStateChanged( + media::AudioInputIPCDelegate::State state) OVERRIDE; virtual void OnDeviceReady(const std::string&) OVERRIDE; + virtual void OnIPCClosed() OVERRIDE; protected: virtual ~PepperPlatformAudioInputImpl(); @@ -89,9 +91,9 @@ class PepperPlatformAudioInputImpl // ACCESSED ON THE MAIN THREAD. webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client_; - // MessageFilter used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE + // 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> filter_; + media::AudioInputIPC* 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. diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.cc b/content/renderer/pepper/pepper_platform_audio_output_impl.cc index f964b07..5f1f57d 100644 --- a/content/renderer/pepper/pepper_platform_audio_output_impl.cc +++ b/content/renderer/pepper/pepper_platform_audio_output_impl.cc @@ -11,6 +11,7 @@ #include "content/common/child_process.h" #include "content/common/media/audio_messages.h" #include "content/renderer/media/audio_hardware.h" +#include "content/renderer/media/audio_message_filter.h" #include "content/renderer/render_thread_impl.h" namespace content { @@ -21,7 +22,7 @@ PepperPlatformAudioOutputImpl* PepperPlatformAudioOutputImpl::Create( int frames_per_buffer, webkit::ppapi::PluginDelegate::PlatformAudioOutputClient* client) { scoped_refptr<PepperPlatformAudioOutputImpl> audio_output( - new PepperPlatformAudioOutputImpl); + new PepperPlatformAudioOutputImpl()); if (audio_output->Initialize(sample_rate, frames_per_buffer, client)) { // Balanced by Release invoked in // PepperPlatformAudioOutputImpl::ShutDownOnIOThread(). @@ -31,7 +32,7 @@ PepperPlatformAudioOutputImpl* PepperPlatformAudioOutputImpl::Create( } bool PepperPlatformAudioOutputImpl::StartPlayback() { - if (filter_) { + if (ipc_) { ChildProcess::current()->io_message_loop()->PostTask( FROM_HERE, base::Bind(&PepperPlatformAudioOutputImpl::StartPlaybackOnIOThread, @@ -42,7 +43,7 @@ bool PepperPlatformAudioOutputImpl::StartPlayback() { } bool PepperPlatformAudioOutputImpl::StopPlayback() { - if (filter_) { + if (ipc_) { ChildProcess::current()->io_message_loop()->PostTask( FROM_HERE, base::Bind(&PepperPlatformAudioOutputImpl::StopPlaybackOnIOThread, @@ -61,12 +62,14 @@ void PepperPlatformAudioOutputImpl::ShutDown() { base::Bind(&PepperPlatformAudioOutputImpl::ShutDownOnIOThread, this)); } -void PepperPlatformAudioOutputImpl::OnStateChanged(AudioStreamState state) {} +void PepperPlatformAudioOutputImpl::OnStateChanged( + media::AudioOutputIPCDelegate::State state) { +} void PepperPlatformAudioOutputImpl::OnStreamCreated( base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) { + int length) { #if defined(OS_WIN) DCHECK(handle); DCHECK(socket_handle); @@ -88,6 +91,10 @@ void PepperPlatformAudioOutputImpl::OnStreamCreated( } } +void PepperPlatformAudioOutputImpl::OnIPCClosed() { + ipc_ = NULL; +} + PepperPlatformAudioOutputImpl::~PepperPlatformAudioOutputImpl() { // Make sure we have been shut down. Warning: this will usually happen on // the I/O thread! @@ -99,7 +106,7 @@ PepperPlatformAudioOutputImpl::PepperPlatformAudioOutputImpl() : client_(NULL), stream_id_(0), main_message_loop_proxy_(base::MessageLoopProxy::current()) { - filter_ = RenderThreadImpl::current()->audio_message_filter(); + ipc_ = RenderThreadImpl::current()->audio_message_filter(); } bool PepperPlatformAudioOutputImpl::Initialize( @@ -136,18 +143,18 @@ bool PepperPlatformAudioOutputImpl::Initialize( void PepperPlatformAudioOutputImpl::InitializeOnIOThread( const media::AudioParameters& params) { - stream_id_ = filter_->AddDelegate(this); - filter_->Send(new AudioHostMsg_CreateStream(stream_id_, params)); + stream_id_ = ipc_->AddDelegate(this); + ipc_->CreateStream(stream_id_, params); } void PepperPlatformAudioOutputImpl::StartPlaybackOnIOThread() { if (stream_id_) - filter_->Send(new AudioHostMsg_PlayStream(stream_id_)); + ipc_->PlayStream(stream_id_); } void PepperPlatformAudioOutputImpl::StopPlaybackOnIOThread() { if (stream_id_) - filter_->Send(new AudioHostMsg_PauseStream(stream_id_)); + ipc_->PauseStream(stream_id_); } void PepperPlatformAudioOutputImpl::ShutDownOnIOThread() { @@ -155,8 +162,8 @@ void PepperPlatformAudioOutputImpl::ShutDownOnIOThread() { if (!stream_id_) return; - filter_->Send(new AudioHostMsg_CloseStream(stream_id_)); - filter_->RemoveDelegate(stream_id_); + ipc_->CloseStream(stream_id_); + ipc_->RemoveDelegate(stream_id_); stream_id_ = 0; Release(); // Release for the delegate, balances out the reference taken in diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.h b/content/renderer/pepper/pepper_platform_audio_output_impl.h index 3b426ad..414a3cd 100644 --- a/content/renderer/pepper/pepper_platform_audio_output_impl.h +++ b/content/renderer/pepper/pepper_platform_audio_output_impl.h @@ -7,7 +7,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" -#include "content/renderer/media/audio_message_filter.h" +#include "media/audio/audio_output_ipc.h" #include "webkit/plugins/ppapi/plugin_delegate.h" namespace media{ @@ -22,7 +22,7 @@ namespace content { class PepperPlatformAudioOutputImpl : public webkit::ppapi::PluginDelegate::PlatformAudioOutput, - public AudioMessageFilter::Delegate, + public media::AudioOutputIPCDelegate, public base::RefCountedThreadSafe<PepperPlatformAudioOutputImpl> { public: // Factory function, returns NULL on failure. StreamCreated() will be called @@ -37,11 +37,13 @@ class PepperPlatformAudioOutputImpl virtual bool StopPlayback() OVERRIDE; virtual void ShutDown() OVERRIDE; - // AudioMessageFilter::Delegate. - virtual void OnStateChanged(AudioStreamState state) OVERRIDE; + // media::AudioOutputIPCDelegate implementation. + virtual void OnStateChanged( + media::AudioOutputIPCDelegate::State state) OVERRIDE; virtual void OnStreamCreated(base::SharedMemoryHandle handle, base::SyncSocket::Handle socket_handle, - uint32 length) OVERRIDE; + int length) OVERRIDE; + virtual void OnIPCClosed() OVERRIDE; protected: virtual ~PepperPlatformAudioOutputImpl(); @@ -66,9 +68,9 @@ class PepperPlatformAudioOutputImpl // ACCESSED ON THE MAIN THREAD. webkit::ppapi::PluginDelegate::PlatformAudioOutputClient* client_; - // MessageFilter used to send/receive IPC. THIS MUST ONLY BE ACCESSED ON THE + // 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> filter_; + media::AudioOutputIPC* 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. diff --git a/media/audio/audio_input_ipc.cc b/media/audio/audio_input_ipc.cc new file mode 100644 index 0000000..69253b0 --- /dev/null +++ b/media/audio/audio_input_ipc.cc @@ -0,0 +1,13 @@ +// 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 "media/audio/audio_input_ipc.h" + +namespace media { + +AudioInputIPCDelegate::~AudioInputIPCDelegate() {} + +AudioInputIPC::~AudioInputIPC() {} + +} // namespace media diff --git a/media/audio/audio_input_ipc.h b/media/audio/audio_input_ipc.h new file mode 100644 index 0000000..eb4e72d --- /dev/null +++ b/media/audio/audio_input_ipc.h @@ -0,0 +1,104 @@ +// 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 MEDIA_AUDIO_AUDIO_INPUT_IPC_H_ +#define MEDIA_AUDIO_AUDIO_INPUT_IPC_H_ + +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "media/audio/audio_parameters.h" +#include "media/base/media_export.h" + +namespace media { + +// Contains IPC notifications for the state of the server side +// (AudioInputController) audio state changes and when an AudioInputController +// has been created. Implemented by AudioInputDevice. +class MEDIA_EXPORT AudioInputIPCDelegate { + public: + // Valid states for the input stream. + enum State { + kRecording, + kStopped, + kError + }; + + // Called when an AudioInputController has been created. + // The shared memory |handle| points to a memory section that's used to + // transfer data between the AudioInputDevice and AudioInputController + // objects. The implementation of OnStreamCreated takes ownership. + // The |socket_handle| is used by the AudioInputController to signal + // notifications that more data is available and can optionally provide + // parameter changes back. The AudioInputDevice must read from this socket + // and process the shared memory whenever data is read from the socket. + virtual void OnStreamCreated(base::SharedMemoryHandle handle, + base::SyncSocket::Handle socket_handle, + int length) = 0; + + // Called when state of an audio stream has changed. + virtual void OnStateChanged(State state) = 0; + + // Called when the input stream volume has changed. + virtual void OnVolume(double volume) = 0; + + // Called when a device has been started on the server side. + // If the device could not be started, |device_id| will be empty. + virtual void OnDeviceReady(const std::string& device_id) = 0; + + // Called when the AudioInputIPC object is going away and/or when the + // IPC channel has been closed and no more IPC requests can be made. + // Implementations must clear any references to the AudioInputIPC object + // at this point. + virtual void OnIPCClosed() = 0; + + protected: + virtual ~AudioInputIPCDelegate(); +}; + +// Provides IPC functionality for an AudioInputDevice. The implementation +// should asynchronously deliver the messages to an AudioInputController object +// (or create one in the case of CreateStream()), that may live in a separate +// process. +class MEDIA_EXPORT AudioInputIPC { + public: + // Registers an AudioInputIPCDelegate and returns a |stream_id| that + // must be used with all other IPC functions in this interface. + virtual int AddDelegate(AudioInputIPCDelegate* delegate) = 0; + + // Unregisters a delegate that was previously registered via a call to + // AddDelegate(). The audio stream should be in a closed state prior to + // calling this function. + virtual void RemoveDelegate(int stream_id) = 0; + + // Sends a request to create an AudioInputController object in the peer + // process, identify it by |stream_id| and configure it to use the specified + // audio |params|. Once the stream has been created, the implementation must + // generate a notification to the AudioInputIPCDelegate and call + // OnStreamCreated(). + virtual void CreateStream(int stream_id, const AudioParameters& params, + const std::string& device_id, bool automatic_gain_control) = 0; + + // Starts the device on the server side. Once the device has started, + // or failed to start, a callback to + // AudioInputIPCDelegate::OnDeviceReady() must be made. + virtual void StartDevice(int stream_id, int session_id) = 0; + + // Corresponds to a call to AudioInputController::Record() on the server side. + virtual void RecordStream(int stream_id) = 0; + + // Sets the volume of the audio stream. + virtual void SetVolume(int stream_id, double volume) = 0; + + // Closes the audio stream and deletes the matching AudioInputController + // instance. Prior to deleting the AudioInputController object, a call to + // AudioInputController::Close must be made. + virtual void CloseStream(int stream_id) = 0; + + protected: + virtual ~AudioInputIPC(); +}; + +} // namespace media + +#endif // MEDIA_AUDIO_AUDIO_INPUT_IPC_H_ diff --git a/media/audio/audio_output_ipc.cc b/media/audio/audio_output_ipc.cc new file mode 100644 index 0000000..233a3b8 --- /dev/null +++ b/media/audio/audio_output_ipc.cc @@ -0,0 +1,13 @@ +// 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 "media/audio/audio_output_ipc.h" + +namespace media { + +AudioOutputIPCDelegate::~AudioOutputIPCDelegate() {} + +AudioOutputIPC::~AudioOutputIPC() {} + +} // namespace media diff --git a/media/audio/audio_output_ipc.h b/media/audio/audio_output_ipc.h new file mode 100644 index 0000000..6983761 --- /dev/null +++ b/media/audio/audio_output_ipc.h @@ -0,0 +1,103 @@ +// 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 MEDIA_AUDIO_AUDIO_OUTPUT_IPC_H_ +#define MEDIA_AUDIO_AUDIO_OUTPUT_IPC_H_ + +#include "base/shared_memory.h" +#include "base/sync_socket.h" +#include "media/audio/audio_parameters.h" +#include "media/base/media_export.h" + +namespace media { + +// Contains IPC notifications for the state of the server side +// (AudioOutputController) audio state changes and when an AudioOutputController +// has been created. Implemented by AudioDevice. +class MEDIA_EXPORT AudioOutputIPCDelegate { + public: + // Current status of the audio output stream in the browser process. Browser + // sends information about the current playback state and error to the + // renderer process using this type. + enum State { + kPlaying, + kPaused, + kError + }; + + // Called when state of an audio stream has changed. + virtual void OnStateChanged(State state) = 0; + + // Called when an audio stream has been created. + // The shared memory |handle| points to a memory section that's used to + // transfer audio buffers from the AudioOutputIPCDelegate back to the + // AudioRendererHost. The implementation of OnStreamCreated takes ownership. + // The |socket_handle| is used by AudioRendererHost to signal requests for + // audio data to be written into the shared memory. The AudioOutputIPCDelegate + // must read from this socket and provide audio whenever data (search for + // "pending_bytes") is received. + virtual void OnStreamCreated(base::SharedMemoryHandle handle, + base::SyncSocket::Handle socket_handle, + int length) = 0; + + // Called when the AudioOutputIPC object is going away and/or when the IPC + // channel has been closed and no more ipc requests can be made. + // Implementations must clear any references to the AudioOutputIPC object + // at this point. + virtual void OnIPCClosed() = 0; + + protected: + virtual ~AudioOutputIPCDelegate(); +}; + +// Provides IPC functionality for an AudioDevice. The implementation should +// asynchronously deliver the messages to an AudioOutputController object (or +// create one in the case of CreateStream()), that may live in a separate +// process. +class MEDIA_EXPORT AudioOutputIPC { + public: + // Registers an AudioOutputIPCDelegate and returns a |stream_id| that must + // be used with all other IPC functions in this interface. + virtual int AddDelegate(AudioOutputIPCDelegate* delegate) = 0; + + // Unregisters a delegate that was previously registered via a call to + // AddDelegate(). The audio stream should be in a closed state prior to + // calling this function. + virtual void RemoveDelegate(int stream_id) = 0; + + // Sends a request to create an AudioOutputController object in the peer + // process, identify it by |stream_id| and configure it to use the specified + // audio |params|. Once the stream has been created, the implementation must + // generate a notification to the AudioOutputIPCDelegate and call + // OnStreamCreated(). + virtual void CreateStream(int stream_id, const AudioParameters& params) = 0; + + // Starts playing the stream. This should generate a call to + // AudioOutputController::Play(). + virtual void PlayStream(int stream_id) = 0; + + // Pauses an audio stream. This should generate a call to + // AudioOutputController::Pause(). + virtual void PauseStream(int stream_id) = 0; + + // "Flushes" the audio device. This should generate a call to + // AudioOutputController::Flush(). + // TODO(tommi): This is currently neither implemented nor called. Remove? + virtual void FlushStream(int stream_id) = 0; + + // Closes the audio stream and deletes the matching AudioOutputController + // instance. Prior to deleting the AudioOutputController object, a call to + // AudioOutputController::Close must be made. + virtual void CloseStream(int stream_id) = 0; + + // Sets the volume of the audio stream. + virtual void SetVolume(int stream_id, double volume) = 0; + + protected: + virtual ~AudioOutputIPC(); +}; + +} // namespace media + +#endif // MEDIA_AUDIO_AUDIO_OUTPUT_IPC_H_ diff --git a/media/media.gyp b/media/media.gyp index 74e9b69..6481c76 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -43,6 +43,10 @@ 'audio/async_socket_io_handler_win.cc', 'audio/audio_buffers_state.cc', 'audio/audio_buffers_state.h', + 'audio/audio_input_ipc.cc', + 'audio/audio_input_ipc.h', + 'audio/audio_output_ipc.cc', + 'audio/audio_output_ipc.h', 'audio/audio_io.h', 'audio/audio_input_controller.cc', 'audio/audio_input_controller.h', |