summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.cc15
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.h3
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager_unittest.cc6
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc8
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.cc7
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host_unittest.cc23
-rw-r--r--content/common/media/audio_messages.h10
-rw-r--r--content/common/media/audio_stream_state.h17
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/renderer/media/audio_device.cc52
-rw-r--r--content/renderer/media/audio_device.h47
-rw-r--r--content/renderer/media/audio_device_factory.cc26
-rw-r--r--content/renderer/media/audio_device_factory.h18
-rw-r--r--content/renderer/media/audio_device_unittest.cc57
-rw-r--r--content/renderer/media/audio_input_device.cc108
-rw-r--r--content/renderer/media/audio_input_device.h120
-rw-r--r--content/renderer/media/audio_input_message_filter.cc70
-rw-r--r--content/renderer/media/audio_input_message_filter.h58
-rw-r--r--content/renderer/media/audio_message_filter.cc55
-rw-r--r--content/renderer/media/audio_message_filter.h47
-rw-r--r--content/renderer/media/audio_message_filter_unittest.cc42
-rw-r--r--content/renderer/media/audio_renderer_mixer_manager.cc2
-rw-r--r--content/renderer/media/audio_renderer_mixer_manager_unittest.cc7
-rw-r--r--content/renderer/media/render_audiosourceprovider.cc2
-rw-r--r--content/renderer/media/renderer_webaudiodevice_impl.cc2
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.cc8
-rw-r--r--content/renderer/pepper/pepper_platform_audio_input_impl.cc34
-rw-r--r--content/renderer/pepper/pepper_platform_audio_input_impl.h16
-rw-r--r--content/renderer/pepper/pepper_platform_audio_output_impl.cc31
-rw-r--r--content/renderer/pepper/pepper_platform_audio_output_impl.h16
-rw-r--r--media/audio/audio_input_ipc.cc13
-rw-r--r--media/audio/audio_input_ipc.h104
-rw-r--r--media/audio/audio_output_ipc.cc13
-rw-r--r--media/audio/audio_output_ipc.h103
-rw-r--r--media/media.gyp4
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',