summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-20 17:28:44 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-20 17:28:44 +0000
commit855cb828e518efd40ac97d08107ad58d996698be (patch)
tree1a28a6429c873ac637362ebcc8000011095c5779 /content/browser
parenta42a7ee454165d73e161448383cdf3dc3b1f164a (diff)
downloadchromium_src-855cb828e518efd40ac97d08107ad58d996698be.zip
chromium_src-855cb828e518efd40ac97d08107ad58d996698be.tar.gz
chromium_src-855cb828e518efd40ac97d08107ad58d996698be.tar.bz2
Hooking up AudioInputDeviceManager to AudioInputRendererHost and MediaStreamManager.
Review URL: http://codereview.chromium.org/7462012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101975 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.cc14
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager_event_handler.h14
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager_unittest.cc14
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc87
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.h62
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc20
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h5
7 files changed, 185 insertions, 31 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 8fafb01..e1970c1 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -11,8 +11,8 @@
namespace media_stream {
-const int AudioInputDeviceManager::kFakeOpenSessionId = 0;
-const int AudioInputDeviceManager::kInvalidSessionId = -1;
+const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
+const int AudioInputDeviceManager::kInvalidSessionId = 0;
const int AudioInputDeviceManager::kInvalidDevice = -1;
const int AudioInputDeviceManager::kDefaultDeviceIndex = 0;
@@ -111,14 +111,14 @@ void AudioInputDeviceManager::Start(
// And we do not store the info for the kFakeOpenSessionId but return
// the callback immediately.
if (session_id == kFakeOpenSessionId) {
- event_handler->OnStartDevice(session_id, kDefaultDeviceIndex);
+ event_handler->OnDeviceStarted(session_id, kDefaultDeviceIndex);
return;
}
// If session has been started, post a callback with an error.
if (event_handlers_.find(session_id) != event_handlers_.end()) {
// Session has been started, post a callback with error.
- event_handler->OnStartDevice(session_id, kInvalidDevice);
+ event_handler->OnDeviceStarted(session_id, kInvalidDevice);
return;
}
@@ -265,7 +265,7 @@ void AudioInputDeviceManager::ClosedOnIOThread(int session_id) {
EventHandlerMap::iterator it = event_handlers_.find(session_id);
if (it != event_handlers_.end()) {
// The device hasn't been stopped, send stop signal.
- it->second->OnStopDevice(session_id);
+ it->second->OnDeviceStopped(session_id);
event_handlers_.erase(session_id);
}
listener_->Closed(kAudioCapture, session_id);
@@ -286,8 +286,8 @@ void AudioInputDeviceManager::StartedOnIOThread(int session_id, int index) {
if (it == event_handlers_.end())
return;
- // Post a callback through the event handler to start the device.
- it->second->OnStartDevice(session_id, index);
+ // Post a callback through the event handler to create an audio stream.
+ it->second->OnDeviceStarted(session_id, index);
}
void AudioInputDeviceManager::StoppedOnIOThread(int session_id) {
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_event_handler.h b/content/browser/renderer_host/media/audio_input_device_manager_event_handler.h
index 75cb984..3790e4e 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager_event_handler.h
+++ b/content/browser/renderer_host/media/audio_input_device_manager_event_handler.h
@@ -12,12 +12,14 @@ namespace media_stream {
class AudioInputDeviceManagerEventHandler {
public:
- // Used to start the device referenced by session id and index.
- virtual void OnStartDevice(int session_id, int index) = 0;
-
- // Used to stop the device referenced by session id. This method is used
- // only when users call Close() without calling Stop() on a started device.
- virtual void OnStopDevice(int session_id) = 0;
+ // Called by AudioInputDeviceManager to create an audio stream using the
+ // device index when the device has been started.
+ virtual void OnDeviceStarted(int session_id, int index) = 0;
+
+ // Called by AudioInputDeviceManager to stop the audio stream when a device
+ // has been stopped. This method is used only when users call Close() without
+ // calling Stop() on a started device.
+ virtual void OnDeviceStopped(int session_id) = 0;
virtual ~AudioInputDeviceManagerEventHandler() {}
};
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 de27d5d..f7cc6ff 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
@@ -52,8 +52,8 @@ class MockAudioInputDeviceManagerEventHandler
MockAudioInputDeviceManagerEventHandler() {}
virtual ~MockAudioInputDeviceManagerEventHandler() {}
- MOCK_METHOD2(OnStartDevice, void(int, int));
- MOCK_METHOD1(OnStopDevice, void(int));
+ MOCK_METHOD2(OnDeviceStarted, void(int, int));
+ MOCK_METHOD1(OnDeviceStopped, void(int));
private:
DISALLOW_COPY_AND_ASSIGN(MockAudioInputDeviceManagerEventHandler);
@@ -294,7 +294,7 @@ TEST_F(AudioInputDeviceManagerTest, StartAndStopDevice) {
session_id[index]))
.Times(1);
EXPECT_CALL(*audio_input_event_handler,
- OnStartDevice(session_id[index], index))
+ OnDeviceStarted(session_id[index], index))
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture,
session_id[index]))
@@ -332,12 +332,12 @@ TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopDevice) {
session_id[index]))
.Times(1);
EXPECT_CALL(*audio_input_event_handler,
- OnStartDevice(session_id[index], index))
+ OnDeviceStarted(session_id[index], index))
.Times(1);
// Event Handler should get a stop device notification as no stop is called
// before closing the device.
EXPECT_CALL(*audio_input_event_handler,
- OnStopDevice(session_id[index]))
+ OnDeviceStopped(session_id[index]))
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture,
session_id[index]))
@@ -381,10 +381,10 @@ TEST_F(AudioInputDeviceManagerTest, StartDeviceTwice) {
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, second_session_id))
.Times(1);
EXPECT_CALL(*first_audio_input_event_handler,
- OnStartDevice(first_session_id, 0))
+ OnDeviceStarted(first_session_id, 0))
.Times(1);
EXPECT_CALL(*second_audio_input_event_handler,
- OnStartDevice(second_session_id, 0))
+ OnDeviceStarted(second_session_id, 0))
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, first_session_id))
.Times(1);
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 f8b92db..84532ba 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -8,7 +8,9 @@
#include "base/process.h"
#include "base/shared_memory.h"
#include "content/browser/renderer_host/media/audio_common.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_input_sync_writer.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/media/audio_messages.h"
#include "ipc/ipc_logging.h"
@@ -167,6 +169,7 @@ bool AudioInputRendererHost::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(AudioInputRendererHost, message, *message_was_ok)
+ IPC_MESSAGE_HANDLER(AudioInputHostMsg_StartDevice, OnStartDevice)
IPC_MESSAGE_HANDLER(AudioInputHostMsg_CreateStream, OnCreateStream)
IPC_MESSAGE_HANDLER(AudioInputHostMsg_RecordStream, OnRecordStream)
IPC_MESSAGE_HANDLER(AudioInputHostMsg_CloseStream, OnCloseStream)
@@ -177,6 +180,25 @@ bool AudioInputRendererHost::OnMessageReceived(const IPC::Message& message,
return handled;
}
+void AudioInputRendererHost::OnStartDevice(int stream_id, int session_id) {
+ VLOG(1) << "AudioInputRendererHost::OnStartDevice(stream_id="
+ << stream_id << ", session_id = " << session_id << ")";
+
+ // Get access to the AudioInputDeviceManager to start the device.
+ // TODO(mflodman): Get AudioInputDeviceManager from MediaStreamManager.
+ media_stream::AudioInputDeviceManager* audio_input_man = NULL;
+ if (!audio_input_man) {
+ SendErrorMessage(stream_id);
+ return;
+ }
+
+ // Add the session entry to the map.
+ session_entries_[session_id] = stream_id;
+
+ // Start the device with the session_id. If the device is started
+ // successfully, OnDeviceStarted() callback will be triggered.
+ audio_input_man->Start(session_id, this);
+}
void AudioInputRendererHost::OnCreateStream(
int stream_id, const AudioParameters& params, bool low_latency) {
@@ -257,6 +279,11 @@ void AudioInputRendererHost::OnCloseStream(int stream_id) {
if (entry)
CloseAndDeleteStream(entry);
+
+ int session_id = LookupSessionById(stream_id);
+
+ if (session_id)
+ StopAndDeleteDevice(session_id);
}
void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) {
@@ -300,6 +327,54 @@ void AudioInputRendererHost::DeleteEntries() {
}
}
+void AudioInputRendererHost::OnDeviceStarted(int session_id, int index) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ SessionEntryMap::iterator it = session_entries_.find(session_id);
+ if (it == session_entries_.end()) {
+ DLOG(WARNING) << "AudioInputRendererHost::OnDeviceStarted()"
+ " session does not exist.";
+ return;
+ }
+
+ // Notify the renderer that the device has been started.
+ Send(new AudioInputMsg_NotifyDeviceStarted(it->second, index));
+}
+
+void AudioInputRendererHost::OnDeviceStopped(int session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ SessionEntryMap::iterator it = session_entries_.find(session_id);
+ // Return if the stream has been closed.
+ if (it == session_entries_.end())
+ return;
+
+ int stream_id = it->second;
+ AudioEntry* entry = LookupById(stream_id);
+
+ if (entry) {
+ // 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));
+ }
+
+ // Delete the session entry.
+ session_entries_.erase(it);
+}
+
+void AudioInputRendererHost::StopAndDeleteDevice(int session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // TODO(mflodman): Get AudioInputDeviceManager from MediaStreamManager.
+ media_stream::AudioInputDeviceManager* audio_input_man = NULL;
+ if (audio_input_man)
+ audio_input_man->Stop(session_id);
+
+ // Delete the session entry.
+ session_entries_.erase(session_id);
+}
+
void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
if (!entry->pending_close) {
entry->pending_close = true;
@@ -360,3 +435,15 @@ AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
}
return NULL;
}
+
+int AudioInputRendererHost::LookupSessionById(int stream_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ for (SessionEntryMap::iterator it = session_entries_.begin();
+ it != session_entries_.end(); ++it) {
+ if (stream_id == it->second) {
+ return it->first;
+ }
+ }
+ return 0;
+}
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.h b/content/browser/renderer_host/media/audio_input_renderer_host.h
index 5fde275..94ef85e 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -5,6 +5,42 @@
// AudioInputRendererHost serves audio related requests from audio capturer
// which lives inside the render process and provide access to audio hardware.
//
+// OnCreateStream() request is only available in the low latency mode. It will
+// creates a shared memory, a SyncWriter and a AudioInputController for the
+// input stream.
+
+// OnCloseStream() will close the input stream.
+//
+// Create stream sequence:
+//
+// OnCreateStream -> AudioInputController::CreateLowLatency() ->
+// DoCompleteCreation -> AudioInputMsg_NotifyLowLatencyStreamCreated
+//
+// Close stream sequence:
+// OnCloseStream -> AudioInputController::Close
+//
+// For the OnStartDevice() request, AudioInputRendererHost starts the device
+// referenced by the session id, and a OnDeviceStarted() callback with the
+// index of the opened device will be received later. Then it will send a IPC
+// message to notify the renderer that the device is ready, so that renderer
+// can continue with the OnCreateStream() request.
+//
+// OnDeviceStopped() is called when the user closes the device through
+// AudioInputDeviceManager without calling Stop() before. What
+// AudioInputRenderHost::OnDeviceStopped() does is to send a IPC mesaage to
+// notify the renderer in order to stop the stream.
+//
+// Start device sequence:
+//
+// OnStartDevice -> AudioInputDeviceManager::Start ->
+// AudioInputDeviceManagerEventHandler::OnDeviceStarted ->
+// AudioInputMsg_NotifyDeviceStarted
+//
+// Shutdown device sequence:
+//
+// OnDeviceStopped -> CloseAndDeleteStream
+// AudioInputMsg_NotifyStreamStateChanged
+//
// This class is owned by BrowserRenderProcessHost and instantiated on UI
// thread. All other operations and method calls happen on IO thread, so we
// need to be extra careful about the lifetime of this object. AudioManager is a
@@ -28,6 +64,7 @@
#include "base/shared_memory.h"
#include "content/browser/browser_message_filter.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager_event_handler.h"
#include "media/audio/audio_input_controller.h"
#include "media/audio/audio_io.h"
#include "media/audio/simple_sources.h"
@@ -37,7 +74,8 @@ struct AudioParameters;
class AudioInputRendererHost
: public BrowserMessageFilter,
- public media::AudioInputController::EventHandler {
+ public media::AudioInputController::EventHandler,
+ public media_stream::AudioInputDeviceManagerEventHandler {
public:
struct AudioEntry {
AudioEntry();
@@ -60,8 +98,6 @@ class AudioInputRendererHost
bool pending_close;
};
- typedef std::map<int, AudioEntry*> AudioEntryMap;
-
// Called from UI thread from the owner of this object.
AudioInputRendererHost();
@@ -80,6 +116,10 @@ class AudioInputRendererHost
const uint8* data,
uint32 size);
+ // media_stream::AudioInputDeviceManagerEventHandler implementation.
+ virtual void OnDeviceStarted(int session_id, int index);
+ virtual void OnDeviceStopped(int session_id);
+
private:
// TODO(henrika): extend test suite (compare AudioRenderHost)
friend class BrowserThread;
@@ -89,6 +129,10 @@ class AudioInputRendererHost
// Methods called on IO thread ----------------------------------------------
+ // Start the audio input device with the session id. If the device
+ // starts successfully, it will trigger OnDeviceStarted() callback.
+ void OnStartDevice(int stream_id, int session_id);
+
// Audio related IPC message handlers.
// Creates an audio input stream with the specified format. If this call is
// successful this object would keep an internal entry of the stream for the
@@ -139,6 +183,9 @@ class AudioInputRendererHost
// Delete audio entry and close the related audio input stream.
void DeleteEntryOnError(AudioEntry* entry);
+ // Stop the device and delete its audio session entry.
+ void StopAndDeleteDevice(int stream_id);
+
// A helper method to look up a AudioEntry identified by |stream_id|.
// Returns NULL if not found.
AudioEntry* LookupById(int stream_id);
@@ -148,9 +195,18 @@ class AudioInputRendererHost
// event is received.
AudioEntry* LookupByController(media::AudioInputController* controller);
+ // A helper method to look up a session identified by |stream_id|.
+ // Returns 0 if not found.
+ int LookupSessionById(int stream_id);
+
// A map of stream IDs to audio sources.
+ typedef std::map<int, AudioEntry*> AudioEntryMap;
AudioEntryMap audio_entries_;
+ // A map of session IDs to audio session sources.
+ typedef std::map<int, int> SessionEntryMap;
+ SessionEntryMap session_entries_;
+
DISALLOW_COPY_AND_ASSIGN(AudioInputRendererHost);
};
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 786cb26..3348a1b9 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -17,7 +17,7 @@
namespace media_stream {
-// TODO(mflodman) Find out who should own MediaStreamManager.
+// TODO(mflodman): Find out who should own MediaStreamManager.
base::LazyInstance<MediaStreamManager> g_media_stream_manager(
base::LINKER_INITIALIZED);
@@ -63,6 +63,12 @@ VideoCaptureManager* MediaStreamManager::video_capture_manager() {
return video_capture_manager_;
}
+AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(mflodman): Add when audio input manager is available.
+ return NULL;
+}
+
void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
int render_process_id,
int render_view_id,
@@ -71,7 +77,7 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
std::string* label) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // TODO(mflodman) Remove next line when audio is supported.
+ // TODO(mflodman): Remove next line when audio is supported.
(const_cast<StreamOptions&>(options)).audio = false;
// Create a new request based on options.
@@ -111,7 +117,7 @@ void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) {
request->audio_devices.begin(); it != request->audio_devices.end();
++it) {
if (it->in_use == true) {
- // TODO(mflodman) Add when audio input device manager is available.
+ // TODO(mflodman): Add when audio input device manager is available.
}
}
}
@@ -139,7 +145,7 @@ void MediaStreamManager::StopGeneratedStream(const std::string& label) {
for (StreamDeviceInfoArray::iterator audio_it =
it->second.audio_devices.begin();
audio_it != it->second.audio_devices.end(); ++audio_it) {
- // TODO(mflodman) Add code when audio input manager exists.
+ // TODO(mflodman): Add code when audio input manager exists.
NOTREACHED();
}
for (StreamDeviceInfoArray::iterator video_it =
@@ -356,7 +362,7 @@ void MediaStreamManager::UseFakeDevice() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
video_capture_manager_->UseFakeDevice();
device_settings_->UseFakeUI();
- // TODO(mflodman) Add audio manager when available.
+ // TODO(mflodman): Add audio manager when available.
}
bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
@@ -389,7 +395,7 @@ MediaStreamProvider* MediaStreamManager::GetDeviceManager(
if (stream_type == kVideoCapture) {
return video_capture_manager_;
} else if (stream_type == kAudioCapture) {
- // TODO(mflodman) Add support when audio input manager is available.
+ // TODO(mflodman): Add support when audio input manager is available.
NOTREACHED();
return NULL;
}
@@ -404,7 +410,7 @@ MediaStreamManager::MediaStreamManager()
device_settings_(NULL) {
device_settings_ = new MediaStreamDeviceSettings(this);
video_capture_manager_->Register(this);
- // TODO(mflodman) Add when audio input manager is available.
+ // TODO(mflodman): Add when audio input manager is available.
}
MediaStreamManager::DeviceRequest::DeviceRequest()
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index f5792ce..27fea0c 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -30,6 +30,7 @@
namespace media_stream {
+class AudioInputDeviceManager;
class MediaStreamDeviceSettings;
class MediaStreamRequester;
class VideoCaptureManager;
@@ -49,6 +50,9 @@ class MediaStreamManager
// Used to access VideoCaptuerManager.
VideoCaptureManager* video_capture_manager();
+ // Used to access AudioInputDeviceManager.
+ AudioInputDeviceManager* audio_input_device_manager();
+
// GenerateStream opens new media devices according to |components|. The
// request is identified using |label|, which is pointing to an already
// created std::string.
@@ -113,7 +117,6 @@ class MediaStreamManager
MediaStreamManager();
VideoCaptureManager* video_capture_manager_;
- // TODO(mflodman) Add AudioInputManager.
// Keeps track of device types currently being enumerated to not enumerate
// when not necessary.