summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 17:08:36 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 17:08:36 +0000
commit1b00e2fdfe30ebe872134af1ab07e6861d488fde (patch)
treef822b28daa0bdafc536e75a86321e72cfd043459
parent41071e4f7f0d3e51cb2f3e929fa922962e889b8f (diff)
downloadchromium_src-1b00e2fdfe30ebe872134af1ab07e6861d488fde.zip
chromium_src-1b00e2fdfe30ebe872134af1ab07e6861d488fde.tar.gz
chromium_src-1b00e2fdfe30ebe872134af1ab07e6861d488fde.tar.bz2
Hook up the device selection to the WebAudio live audio.
WebAudio live audio needs to pass the session_id to the browser process so that Chrome can open the correct input device for unitfied IO. This CL looks big because it touches quite some interfaces from the render to the browser. But the change is simple and basically adding a session_id/device_id to the classes. All the changes some together and it is very hard to break it down. It also makes the media output code more similar to the media input code as well, and it will be easier to merge them for the future. BUG=147327 TEST=http://chromium.googlecode.com/svn/trunk/samples/audio/visualizer-live.html Change the device using the camera icon on the right of the omnibox, then reload. Verify the sound is coming from the correct input device. Review URL: https://chromiumcodereview.appspot.com/15721002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203427 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.cc15
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc22
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.h3
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.cc39
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.h11
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host_unittest.cc64
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc2
-rw-r--r--content/common/media/audio_messages.h3
-rw-r--r--content/renderer/media/audio_message_filter.cc8
-rw-r--r--content/renderer/media/audio_message_filter_unittest.cc8
-rw-r--r--content/renderer/media/media_stream_impl.cc3
-rw-r--r--content/renderer/media/renderer_webaudiodevice_impl.cc8
-rw-r--r--content/renderer/media/renderer_webaudiodevice_impl.h6
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.h14
-rw-r--r--content/renderer/pepper/pepper_platform_audio_output_impl.cc3
-rw-r--r--content/renderer/renderer_webkitplatformsupport_impl.cc22
-rw-r--r--content/test/webrtc_audio_device_test.cc2
-rw-r--r--media/audio/android/audio_manager_android.cc6
-rw-r--r--media/audio/android/audio_manager_android.h6
-rw-r--r--media/audio/audio_low_latency_input_output_unittest.cc2
-rw-r--r--media/audio/audio_manager.h4
-rw-r--r--media/audio/audio_manager_base.cc77
-rw-r--r--media/audio/audio_manager_base.h32
-rw-r--r--media/audio/audio_output_controller.cc7
-rw-r--r--media/audio/audio_output_controller.h10
-rw-r--r--media/audio/audio_output_controller_unittest.cc2
-rw-r--r--media/audio/audio_output_device.cc16
-rw-r--r--media/audio/audio_output_device.h16
-rw-r--r--media/audio/audio_output_device_unittest.cc7
-rw-r--r--media/audio/audio_output_dispatcher.cc6
-rw-r--r--media/audio/audio_output_dispatcher.h7
-rw-r--r--media/audio/audio_output_dispatcher_impl.cc6
-rw-r--r--media/audio/audio_output_dispatcher_impl.h1
-rw-r--r--media/audio/audio_output_ipc.h7
-rw-r--r--media/audio/audio_output_proxy_unittest.cc48
-rw-r--r--media/audio/audio_output_resampler.cc6
-rw-r--r--media/audio/audio_output_resampler.h4
-rw-r--r--media/audio/audio_parameters.h10
-rw-r--r--media/audio/cras/audio_manager_cras.cc3
-rw-r--r--media/audio/cras/audio_manager_cras.h3
-rw-r--r--media/audio/ios/audio_manager_ios.h6
-rw-r--r--media/audio/ios/audio_manager_ios.mm10
-rw-r--r--media/audio/linux/alsa_output_unittest.cc4
-rw-r--r--media/audio/linux/audio_manager_linux.cc4
-rw-r--r--media/audio/linux/audio_manager_linux.h3
-rw-r--r--media/audio/mac/audio_auhal_mac_unittest.cc3
-rw-r--r--media/audio/mac/audio_manager_mac.cc13
-rw-r--r--media/audio/mac/audio_manager_mac.h3
-rw-r--r--media/audio/mock_audio_manager.cc6
-rw-r--r--media/audio/mock_audio_manager.h6
-rw-r--r--media/audio/openbsd/audio_manager_openbsd.cc3
-rw-r--r--media/audio/openbsd/audio_manager_openbsd.h3
-rw-r--r--media/audio/pulse/audio_manager_pulse.cc10
-rw-r--r--media/audio/pulse/audio_manager_pulse.h6
-rw-r--r--media/audio/pulse/pulse_unified.cc10
-rw-r--r--media/audio/pulse/pulse_unified.h5
-rw-r--r--media/audio/win/audio_low_latency_output_win_unittest.cc3
-rw-r--r--media/audio/win/audio_manager_win.cc4
-rw-r--r--media/audio/win/audio_manager_win.h3
-rw-r--r--media/audio/win/audio_output_win_unittest.cc60
-rw-r--r--media/audio/win/audio_unified_win.cc7
-rw-r--r--media/audio/win/audio_unified_win.h6
-rw-r--r--media/audio/win/audio_unified_win_unittest.cc3
-rw-r--r--media/base/audio_renderer_sink.h8
64 files changed, 498 insertions, 210 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 5f87a75..20cc3e3 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -29,6 +29,13 @@ AudioInputDeviceManager::AudioInputDeviceManager(
next_capture_session_id_(kFirstSessionId),
use_fake_device_(false),
audio_manager_(audio_manager) {
+ // TODO(xians): Remove this fake_device after the unittests do not need it.
+ StreamDeviceInfo fake_device(MEDIA_DEVICE_AUDIO_CAPTURE,
+ media::AudioManagerBase::kDefaultDeviceName,
+ media::AudioManagerBase::kDefaultDeviceId,
+ 44100, media::CHANNEL_LAYOUT_STEREO, false);
+ fake_device.session_id = kFakeOpenSessionId;
+ devices_.push_back(fake_device);
}
AudioInputDeviceManager::~AudioInputDeviceManager() {
@@ -134,6 +141,14 @@ void AudioInputDeviceManager::EnumerateOnDeviceThread(
stream_type, it->device_name, it->unique_id, false));
}
+ // If the |use_fake_device_| flag is on, inject the fake device if there is
+ // no available device on the OS.
+ if (use_fake_device_ && devices->empty()) {
+ devices->push_back(StreamDeviceInfo(
+ stream_type, media::AudioManagerBase::kDefaultDeviceName,
+ media::AudioManagerBase::kDefaultDeviceId, false));
+ }
+
// Return the device list through the listener by posting a task on
// IO thread since MediaStreamManager handles the callback asynchronously.
BrowserThread::PostTask(
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 38a45f2..6e3062a 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -213,9 +213,19 @@ void AudioInputRendererHost::OnCreateStream(
return;
}
+ media::AudioParameters audio_params(config.params);
+ if (media_stream_manager_->audio_input_device_manager()->
+ ShouldUseFakeDevice()) {
+ audio_params.Reset(
+ media::AudioParameters::AUDIO_FAKE,
+ config.params.channel_layout(), config.params.channels(), 0,
+ config.params.sample_rate(), config.params.bits_per_sample(),
+ config.params.frames_per_buffer());
+ }
+
// Check if we have the permission to open the device and which device to use.
std::string device_id = media::AudioManagerBase::kDefaultDeviceId;
- if (session_id != AudioInputDeviceManager::kFakeOpenSessionId) {
+ if (audio_params.format() != media::AudioParameters::AUDIO_FAKE) {
const StreamDeviceInfo* info = media_stream_manager_->
audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
if (!info) {
@@ -228,16 +238,6 @@ void AudioInputRendererHost::OnCreateStream(
device_id = info->device.id;
}
- media::AudioParameters audio_params(config.params);
- if (media_stream_manager_->audio_input_device_manager()->
- ShouldUseFakeDevice()) {
- audio_params.Reset(
- media::AudioParameters::AUDIO_FAKE,
- config.params.channel_layout(), config.params.channels(), 0,
- config.params.sample_rate(), config.params.bits_per_sample(),
- config.params.frames_per_buffer());
- }
-
// Create a new AudioEntry structure.
scoped_ptr<AudioEntry> entry(new AudioEntry());
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 077a1cc..ae52a54 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -89,8 +89,7 @@ class CONTENT_EXPORT AudioInputRendererHost
// Creates an audio input stream with the specified format whose data is
// consumed by an entity in the render view referenced by |render_view_id|.
// |session_id| is used to find out which device to be used for the stream.
- // When it is AudioInputDeviceManager::kFakeOpenSessionId, it uses the the
- // default device. Upon success/failure, the peer is notified via the
+ // Upon success/failure, the peer is notified via the
// NotifyStreamCreated message.
void OnCreateStream(int stream_id,
int render_view_id,
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 3b21720..9f4c406 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -12,12 +12,15 @@
#include "base/shared_memory.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/media_internals.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/audio_sync_reader.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/media/audio_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/media_observer.h"
#include "content/public/common/content_switches.h"
+#include "media/audio/audio_manager_base.h"
#include "media/audio/shared_memory_util.h"
#include "media/base/audio_bus.h"
#include "media/base/limits.h"
@@ -33,6 +36,7 @@ class AudioRendererHost::AudioEntry
int stream_id,
int render_view_id,
const media::AudioParameters& params,
+ const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader);
virtual ~AudioEntry();
@@ -86,13 +90,14 @@ class AudioRendererHost::AudioEntry
AudioRendererHost::AudioEntry::AudioEntry(
AudioRendererHost* host, int stream_id, int render_view_id,
const media::AudioParameters& params,
+ const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader)
: host_(host),
stream_id_(stream_id),
render_view_id_(render_view_id),
controller_(media::AudioOutputController::Create(
- host->audio_manager_, this, params, reader.get())),
+ host->audio_manager_, this, params, input_device_id, reader.get())),
shared_memory_(shared_memory.Pass()),
reader_(reader.Pass()) {
DCHECK(controller_);
@@ -106,12 +111,15 @@ AudioRendererHost::AudioRendererHost(
int render_process_id,
media::AudioManager* audio_manager,
AudioMirroringManager* mirroring_manager,
- MediaInternals* media_internals)
+ MediaInternals* media_internals,
+ MediaStreamManager* media_stream_manager)
: render_process_id_(render_process_id),
audio_manager_(audio_manager),
mirroring_manager_(mirroring_manager),
- media_internals_(media_internals) {
+ media_internals_(media_internals),
+ media_stream_manager_(media_stream_manager) {
DCHECK(audio_manager_);
+ DCHECK(media_stream_manager_);
}
AudioRendererHost::~AudioRendererHost() {
@@ -267,12 +275,14 @@ bool AudioRendererHost::OnMessageReceived(const IPC::Message& message,
}
void AudioRendererHost::OnCreateStream(
- int stream_id, int render_view_id, const media::AudioParameters& params) {
+ int stream_id, int render_view_id, int session_id,
+ const media::AudioParameters& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "AudioRendererHost@" << this
<< "::OnCreateStream(stream_id=" << stream_id
- << ", render_view_id=" << render_view_id << ")";
+ << ", render_view_id=" << render_view_id
+ << ", session_id=" << session_id << ")";
DCHECK_GT(render_view_id, 0);
// media::AudioParameters is validated in the deserializer.
@@ -284,6 +294,22 @@ void AudioRendererHost::OnCreateStream(
return;
}
+ // When the |input_channels| is valid, clients are trying to create a unified
+ // IO stream which opens an input device mapping to the |session_id|.
+ std::string input_device_id;
+ if (input_channels > 0) {
+ const StreamDeviceInfo* info = media_stream_manager_->
+ audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
+ if (!info) {
+ SendErrorMessage(stream_id);
+ DLOG(WARNING) << "No permission has been granted to input stream with "
+ << "session_id=" << session_id;
+ return;
+ }
+
+ input_device_id = info->device.id;
+ }
+
// Calculate output and input memory size.
int output_memory_size = AudioBus::CalculateMemorySize(params);
int frames = params.frames_per_buffer();
@@ -310,7 +336,8 @@ void AudioRendererHost::OnCreateStream(
}
scoped_ptr<AudioEntry> entry(new AudioEntry(
- this, stream_id, render_view_id, params, shared_memory.Pass(),
+ this, stream_id, render_view_id, params, input_device_id,
+ shared_memory.Pass(),
reader.PassAs<media::AudioOutputController::SyncReader>()));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
index 803539c..b249ef4 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -61,6 +61,7 @@ namespace content {
class AudioMirroringManager;
class MediaInternals;
+class MediaStreamManager;
class ResourceContext;
class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
@@ -69,7 +70,8 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
AudioRendererHost(int render_process_id,
media::AudioManager* audio_manager,
AudioMirroringManager* mirroring_manager,
- MediaInternals* media_internals);
+ MediaInternals* media_internals,
+ MediaStreamManager* media_stream_manager);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -96,10 +98,14 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
// Creates an audio output stream with the specified format whose data is
// produced by an entity in the render view referenced by |render_view_id|.
+ // |session_id| is used for unified IO to find out which input device to be
+ // opened for the stream. For clients that do not use unified IO,
+ // |session_id| will be ignored.
// Upon success/failure, the peer is notified via the NotifyStreamCreated
// message.
void OnCreateStream(int stream_id,
int render_view_id,
+ int session_id,
const media::AudioParameters& params);
// Play the audio stream referenced by |stream_id|.
@@ -143,6 +149,9 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
AudioMirroringManager* const mirroring_manager_;
MediaInternals* const media_internals_;
+ // Used to access to AudioInputDeviceManager.
+ MediaStreamManager* media_stream_manager_;
+
// A map of stream IDs to audio sources.
AudioEntryMap audio_entries_;
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 6a674a4..7068b1c 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -9,12 +9,16 @@
#include "base/process_util.h"
#include "base/sync_socket.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/mock_media_observer.h"
#include "content/common/media/audio_messages.h"
+#include "content/common/media/media_stream_options.h"
#include "ipc/ipc_message_utils.h"
#include "media/audio/audio_manager.h"
+#include "media/audio/audio_manager_base.h"
#include "media/audio/fake_audio_output_stream.h"
#include "net/url_request/url_request_context.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -56,11 +60,13 @@ class MockAudioRendererHost : public AudioRendererHost {
explicit MockAudioRendererHost(
media::AudioManager* audio_manager,
AudioMirroringManager* mirroring_manager,
- MediaInternals* media_internals)
+ MediaInternals* media_internals,
+ MediaStreamManager* media_stream_manager)
: AudioRendererHost(kRenderProcessId,
audio_manager,
mirroring_manager,
- media_internals),
+ media_internals,
+ media_stream_manager),
shared_memory_length_(0) {
}
@@ -170,9 +176,12 @@ class AudioRendererHostTest : public testing::Test {
ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
message_loop_.get()));
audio_manager_.reset(media::AudioManager::Create());
+ media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
+ media_stream_manager_->UseFakeDevice();
observer_.reset(new MockMediaInternals());
host_ = new MockAudioRendererHost(
- audio_manager_.get(), &mirroring_manager_, observer_.get());
+ audio_manager_.get(), &mirroring_manager_, observer_.get(),
+ media_stream_manager_.get());
// Simulate IPC channel connected.
host_->OnChannelConnected(base::GetCurrentProcId());
@@ -188,11 +197,14 @@ class AudioRendererHostTest : public testing::Test {
// We need to continue running message_loop_ to complete all destructions.
SyncWithAudioThread();
-
audio_manager_.reset();
io_thread_.reset();
ui_thread_.reset();
+
+ // Delete the IO message loop. This will cause the MediaStreamManager to be
+ // notified so it will stop its device thread and device managers.
+ message_loop_.reset();
}
void Create() {
@@ -208,6 +220,7 @@ class AudioRendererHostTest : public testing::Test {
// we receive the created message.
host_->OnCreateStream(kStreamId,
kRenderViewId,
+ 0,
media::AudioParameters(
media::AudioParameters::AUDIO_FAKE,
media::CHANNEL_LAYOUT_STEREO,
@@ -229,6 +242,43 @@ class AudioRendererHostTest : public testing::Test {
EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
}
+ void CreateUnifiedStream() {
+ EXPECT_CALL(*observer_,
+ OnSetAudioStreamStatus(_, kStreamId, "created"));
+ EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _))
+ .WillOnce(QuitMessageLoop(message_loop_.get()));
+ EXPECT_CALL(mirroring_manager_,
+ AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
+ .RetiresOnSaturation();
+ // Send a create stream message to the audio output stream and wait until
+ // we receive the created message.
+ // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
+ // pass the permission check.
+ host_->OnCreateStream(kStreamId,
+ kRenderViewId,
+ AudioInputDeviceManager::kFakeOpenSessionId,
+ media::AudioParameters(
+ media::AudioParameters::AUDIO_FAKE,
+ media::CHANNEL_LAYOUT_STEREO,
+ 2,
+ media::AudioParameters::kAudioCDSampleRate, 16,
+ media::AudioParameters::kAudioCDSampleRate / 10));
+ message_loop_->Run();
+
+ // At some point in the future, a corresponding RemoveDiverter() call must
+ // be made.
+ EXPECT_CALL(mirroring_manager_,
+ RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull()))
+ .RetiresOnSaturation();
+
+ // All created streams should ultimately be closed.
+ EXPECT_CALL(*observer_,
+ OnSetAudioStreamStatus(_, kStreamId, "closed"));
+
+ // Expect the audio stream will be deleted at some later point.
+ EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId));
+ }
+
void Close() {
// Send a message to AudioRendererHost to tell it we want to close the
// stream.
@@ -315,6 +365,7 @@ class AudioRendererHostTest : public testing::Test {
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<media::AudioManager> audio_manager_;
+ scoped_ptr<MediaStreamManager> media_stream_manager_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
};
@@ -379,6 +430,11 @@ TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
Close();
}
+TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
+ CreateUnifiedStream();
+ Close();
+}
+
// TODO(hclam): Add tests for data conversation in low latency mode.
} // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 7d623d9..7dc135c 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -600,7 +600,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
media_stream_manager));
channel_->AddFilter(new AudioRendererHost(
GetID(), audio_manager, BrowserMainLoop::GetAudioMirroringManager(),
- media_internals));
+ media_internals, media_stream_manager));
channel_->AddFilter(new VideoCaptureHost());
channel_->AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(),
diff --git a/content/common/media/audio_messages.h b/content/common/media/audio_messages.h
index dc844eb..d52712d 100644
--- a/content/common/media/audio_messages.h
+++ b/content/common/media/audio_messages.h
@@ -96,9 +96,10 @@ IPC_MESSAGE_CONTROL2(AudioInputMsg_NotifyStreamVolume,
// Request that is sent to the browser for creating an audio output stream.
// |render_view_id| is the routing ID for the render view producing the audio
// data.
-IPC_MESSAGE_CONTROL3(AudioHostMsg_CreateStream,
+IPC_MESSAGE_CONTROL4(AudioHostMsg_CreateStream,
int /* stream_id */,
int /* render_view_id */,
+ int /* session_id */,
media::AudioParameters /* params */)
// Request that is sent to the browser for creating an audio input stream.
diff --git a/content/renderer/media/audio_message_filter.cc b/content/renderer/media/audio_message_filter.cc
index 1cb5352..4523f01 100644
--- a/content/renderer/media/audio_message_filter.cc
+++ b/content/renderer/media/audio_message_filter.cc
@@ -25,7 +25,8 @@ class AudioMessageFilter::AudioOutputIPCImpl
// media::AudioOutputIPC implementation.
virtual void CreateStream(media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params) OVERRIDE;
+ const media::AudioParameters& params,
+ int session_id) OVERRIDE;
virtual void PlayStream() OVERRIDE;
virtual void PauseStream() OVERRIDE;
virtual void CloseStream() OVERRIDE;
@@ -75,13 +76,14 @@ scoped_ptr<media::AudioOutputIPC> AudioMessageFilter::CreateAudioOutputIPC(
void AudioMessageFilter::AudioOutputIPCImpl::CreateStream(
media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params) {
+ const media::AudioParameters& params,
+ int session_id) {
DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
DCHECK(delegate);
DCHECK_EQ(stream_id_, kStreamIDNotSet);
stream_id_ = filter_->delegates_.Add(delegate);
filter_->Send(new AudioHostMsg_CreateStream(
- stream_id_, render_view_id_, params));
+ stream_id_, render_view_id_, session_id, params));
}
void AudioMessageFilter::AudioOutputIPCImpl::PlayStream() {
diff --git a/content/renderer/media/audio_message_filter_unittest.cc b/content/renderer/media/audio_message_filter_unittest.cc
index 81db84e..fa8823f 100644
--- a/content/renderer/media/audio_message_filter_unittest.cc
+++ b/content/renderer/media/audio_message_filter_unittest.cc
@@ -79,7 +79,8 @@ TEST(AudioMessageFilterTest, Basic) {
MockAudioDelegate delegate;
const scoped_ptr<media::AudioOutputIPC> ipc =
filter->CreateAudioOutputIPC(kRenderViewId);
- ipc->CreateStream(&delegate, media::AudioParameters());
+ static const int kSessionId = 0;
+ ipc->CreateStream(&delegate, media::AudioParameters(), kSessionId);
static const int kStreamId = 1;
EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId));
@@ -128,8 +129,9 @@ TEST(AudioMessageFilterTest, Delegates) {
filter->CreateAudioOutputIPC(kRenderViewId);
const scoped_ptr<media::AudioOutputIPC> ipc2 =
filter->CreateAudioOutputIPC(kRenderViewId);
- ipc1->CreateStream(&delegate1, media::AudioParameters());
- ipc2->CreateStream(&delegate2, media::AudioParameters());
+ static const int kSessionId = 0;
+ ipc1->CreateStream(&delegate1, media::AudioParameters(), kSessionId);
+ ipc2->CreateStream(&delegate2, media::AudioParameters(), kSessionId);
static const int kStreamId1 = 1;
static const int kStreamId2 = 2;
EXPECT_EQ(&delegate1, filter->delegates_.Lookup(kStreamId1));
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index 7f2de52..fa307dd 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -91,7 +91,8 @@ void CreateWebKitSourceVector(
UTF8ToUTF16(devices[i].device.name));
webkit_sources[i].setExtraData(
new content::MediaStreamSourceExtraData(devices[i], webkit_sources[i]));
- webkit_sources[i].setDeviceId(UTF8ToUTF16(devices[i].device.id.c_str()));
+ webkit_sources[i].setDeviceId(UTF8ToUTF16(
+ base::IntToString(devices[i].session_id)));
}
}
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc
index 43a4a61..b088b4e 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -22,9 +22,11 @@ namespace content {
RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
const media::AudioParameters& params,
- WebAudioDevice::RenderCallback* callback)
+ WebAudioDevice::RenderCallback* callback,
+ int session_id)
: params_(params),
- client_callback_(callback) {
+ client_callback_(callback),
+ session_id_(session_id) {
DCHECK(client_callback_);
}
@@ -51,7 +53,7 @@ void RendererWebAudioDeviceImpl::start() {
web_view ? RenderViewImpl::FromWebView(web_view) : NULL;
output_device_ = AudioDeviceFactory::NewOutputDevice(
render_view ? render_view->routing_id() : MSG_ROUTING_NONE);
- output_device_->Initialize(params_, this);
+ output_device_->InitializeUnifiedStream(params_, this, session_id_);
output_device_->Start();
// Note: Default behavior is to auto-play on start.
}
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.h b/content/renderer/media/renderer_webaudiodevice_impl.h
index 23a46ab..5a8161f 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -23,7 +23,8 @@ class RendererWebAudioDeviceImpl
public media::AudioRendererSink::RenderCallback {
public:
RendererWebAudioDeviceImpl(const media::AudioParameters& params,
- WebKit::WebAudioDevice::RenderCallback* callback);
+ WebKit::WebAudioDevice::RenderCallback* callback,
+ int session_id);
virtual ~RendererWebAudioDeviceImpl();
// WebKit::WebAudioDevice implementation.
@@ -54,6 +55,9 @@ class RendererWebAudioDeviceImpl
// When non-NULL, we are started. When NULL, we are stopped.
scoped_refptr<media::AudioOutputDevice> output_device_;
+ // ID to allow browser to select the correct input device for unified IO.
+ int session_id_;
+
DISALLOW_COPY_AND_ASSIGN(RendererWebAudioDeviceImpl);
};
diff --git a/content/renderer/media/webrtc_audio_device_impl.h b/content/renderer/media/webrtc_audio_device_impl.h
index e740a59..960d0d0 100644
--- a/content/renderer/media/webrtc_audio_device_impl.h
+++ b/content/renderer/media/webrtc_audio_device_impl.h
@@ -24,13 +24,11 @@
// webrtc::AudioDeviceModule which makes it possible for a user (e.g. webrtc::
// VoiceEngine) to register this class as an external AudioDeviceModule (ADM).
// Then WebRtcAudioDeviceImpl::SetSessionId() needs to be called to set the
-// session id that tells which device to use. The user can either get the
-// session id from the MediaStream or use a value of 1 (AudioInputDeviceManager
-// ::kFakeOpenSessionId), the later will open the default device without going
-// through the MediaStream. The user can then call WebRtcAudioDeviceImpl::
-// StartPlayout() and WebRtcAudioDeviceImpl::StartRecording() from the render
-// process to initiate and start audio rendering and capturing in the browser
-// process. IPC is utilized to set up the media streams.
+// session id that tells which device to use. The user can then call
+// WebRtcAudioDeviceImpl::StartPlayout() and
+// WebRtcAudioDeviceImpl::StartRecording() from the render process to initiate
+// and start audio rendering and capturing in the browser process. IPC is
+// utilized to set up the media streams.
//
// Usage example:
//
@@ -39,7 +37,7 @@
// {
// scoped_refptr<WebRtcAudioDeviceImpl> external_adm;
// external_adm = new WebRtcAudioDeviceImpl();
-// external_adm->SetSessionId(1);
+// external_adm->SetSessionId(session_id);
// VoiceEngine* voe = VoiceEngine::Create();
// VoEBase* base = VoEBase::GetInterface(voe);
// base->Init(external_adm);
diff --git a/content/renderer/pepper/pepper_platform_audio_output_impl.cc b/content/renderer/pepper/pepper_platform_audio_output_impl.cc
index e53dd6d..05600dd 100644
--- a/content/renderer/pepper/pepper_platform_audio_output_impl.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output_impl.cc
@@ -138,8 +138,9 @@ void PepperPlatformAudioOutputImpl::InitializeOnIOThread(
const media::AudioParameters& params) {
DCHECK(ChildProcess::current()->io_message_loop_proxy()->
BelongsToCurrentThread());
+ const int kSessionId = 0;
if (ipc_)
- ipc_->CreateStream(this, params);
+ ipc_->CreateStream(this, params, kSessionId);
}
void PepperPlatformAudioOutputImpl::StartPlaybackOnIOThread() {
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 133bfc2..4cf27f0 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -10,6 +10,7 @@
#include "base/metrics/histogram.h"
#include "base/platform_file.h"
#include "base/shared_memory.h"
+#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "content/common/database_util.h"
#include "content/common/file_utilities_messages.h"
@@ -680,16 +681,6 @@ RendererWebKitPlatformSupportImpl::createAudioDevice(
double sample_rate,
WebAudioDevice::RenderCallback* callback,
const WebKit::WebString& input_device_id) {
- if (input_device_id != "default") {
- // Only allow audio input if we know for sure that WebKit is giving us the
- // "default" input device.
- // TODO(crogers): add support for non-default audio input devices when
- // using synchronized audio I/O in WebAudio.
- if (input_channels > 0)
- DLOG(WARNING) << "createAudioDevice(): request for audio input ignored";
- input_channels = 0;
- }
-
// The |channels| does not exactly identify the channel layout of the
// device. The switch statement below assigns a best guess to the channel
// layout based on number of channels.
@@ -725,12 +716,21 @@ RendererWebKitPlatformSupportImpl::createAudioDevice(
layout = media::CHANNEL_LAYOUT_STEREO;
}
+ int session_id = 0;
+ if (input_device_id.isNull() ||
+ !base::StringToInt(UTF16ToUTF8(input_device_id), &session_id)) {
+ if (input_channels > 0)
+ DLOG(WARNING) << "createAudioDevice(): request for audio input ignored";
+
+ input_channels = 0;
+ }
+
media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
layout, input_channels,
static_cast<int>(sample_rate), 16, buffer_size);
- return new RendererWebAudioDeviceImpl(params, callback);
+ return new RendererWebAudioDeviceImpl(params, callback, session_id);
}
//------------------------------------------------------------------------------
diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc
index 7bd5b30..acb14a2 100644
--- a/content/test/webrtc_audio_device_test.cc
+++ b/content/test/webrtc_audio_device_test.cc
@@ -240,7 +240,7 @@ void WebRTCAudioDeviceTest::CreateChannel(const char* name) {
static const int kRenderProcessId = 1;
audio_render_host_ = new AudioRendererHost(
kRenderProcessId, audio_manager_.get(), mirroring_manager_.get(),
- media_internals_.get());
+ media_internals_.get(), media_stream_manager_.get());
audio_render_host_->OnChannelConnected(base::GetCurrentProcId());
audio_input_renderer_host_ = new AudioInputRendererHost(
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc
index fa042b5..ce172b5 100644
--- a/media/audio/android/audio_manager_android.cc
+++ b/media/audio/android/audio_manager_android.cc
@@ -69,9 +69,9 @@ AudioParameters AudioManagerAndroid::GetInputStreamParameters(
}
AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
AudioOutputStream* stream =
- AudioManagerBase::MakeAudioOutputStream(params);
+ AudioManagerBase::MakeAudioOutputStream(params, std::string());
if (stream && output_stream_count() == 1)
RegisterHeadsetReceiver();
return stream;
@@ -105,7 +105,7 @@ AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
}
AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
return new OpenSLESOutputStream(this, params);
}
diff --git a/media/audio/android/audio_manager_android.h b/media/audio/android/audio_manager_android.h
index 422924f..fa1c373 100644
--- a/media/audio/android/audio_manager_android.h
+++ b/media/audio/android/audio_manager_android.h
@@ -24,7 +24,8 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
const std::string& device_id) OVERRIDE;
virtual AudioOutputStream* MakeAudioOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual void ReleaseOutputStream(AudioOutputStream* stream) OVERRIDE;
@@ -34,7 +35,8 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc
index 0dc434f..4dd22ab 100644
--- a/media/audio/audio_low_latency_input_output_unittest.cc
+++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -309,7 +309,7 @@ class AudioOutputStreamTraits {
static StreamType* CreateStream(AudioManager* audio_manager,
const AudioParameters& params) {
- return audio_manager->MakeAudioOutputStream(params);
+ return audio_manager->MakeAudioOutputStream(params, std::string());
}
};
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index a20af4a..b513ec9 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -82,14 +82,14 @@ class MEDIA_EXPORT AudioManager {
//
// Do not free the returned AudioOutputStream. It is owned by AudioManager.
virtual AudioOutputStream* MakeAudioOutputStream(
- const AudioParameters& params) = 0;
+ const AudioParameters& params, const std::string& input_device_id) = 0;
// Creates new audio output proxy. A proxy implements
// AudioOutputStream interface, but unlike regular output stream
// created with MakeAudioOutputStream() it opens device only when a
// sound is actually playing.
virtual AudioOutputStream* MakeAudioOutputStreamProxy(
- const AudioParameters& params) = 0;
+ const AudioParameters& params, const std::string& input_device_id) = 0;
// Factory to create audio recording streams.
// |channels| can be 1 or 2.
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 310e4be..176b38b 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -32,6 +32,44 @@ static const int kMaxInputChannels = 2;
const char AudioManagerBase::kDefaultDeviceName[] = "Default";
const char AudioManagerBase::kDefaultDeviceId[] = "default";
+struct AudioManagerBase::DispatcherParams {
+ DispatcherParams(const AudioParameters& input,
+ const AudioParameters& output,
+ const std::string& device_id)
+ : input_params(input),
+ output_params(output),
+ input_device_id(device_id) {}
+ ~DispatcherParams() {}
+
+ const AudioParameters input_params;
+ const AudioParameters output_params;
+ const std::string input_device_id;
+ scoped_refptr<AudioOutputDispatcher> dispatcher;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DispatcherParams);
+};
+
+class AudioManagerBase::CompareByParams {
+ public:
+ explicit CompareByParams(const DispatcherParams* dispatcher)
+ : dispatcher_(dispatcher) {}
+ bool operator()(DispatcherParams* dispatcher_in) const {
+ // We will reuse the existing dispatcher when:
+ // 1) Unified IO is not used, input_params and output_params of the
+ // existing dispatcher are the same as the requested dispatcher.
+ // 2) Unified IO is used, input_params, output_params and input_device_id
+ // of the existing dispatcher are the same as the request dispatcher.
+ return (dispatcher_->input_params == dispatcher_in->input_params &&
+ dispatcher_->output_params == dispatcher_in->output_params &&
+ (!dispatcher_->input_params.input_channels() ||
+ dispatcher_->input_device_id == dispatcher_in->input_device_id));
+ }
+
+ private:
+ const DispatcherParams* dispatcher_;
+};
+
AudioManagerBase::AudioManagerBase()
: num_active_input_streams_(0),
max_num_output_streams_(kDefaultMaxOutputStreams),
@@ -77,7 +115,8 @@ scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() {
}
AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params,
+ const std::string& input_device_id) {
// TODO(miu): Fix ~50 call points across several unit test modules to call
// this method on the audio thread, then uncomment the following:
// DCHECK(message_loop_->BelongsToCurrentThread());
@@ -105,7 +144,7 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
stream = MakeLinearOutputStream(params);
break;
case AudioParameters::AUDIO_PCM_LOW_LATENCY:
- stream = MakeLowLatencyOutputStream(params);
+ stream = MakeLowLatencyOutputStream(params, input_device_id);
break;
case AudioParameters::AUDIO_FAKE:
stream = FakeAudioOutputStream::MakeFakeStream(this, params);
@@ -165,7 +204,7 @@ AudioInputStream* AudioManagerBase::MakeAudioInputStream(
}
AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
#if defined(OS_IOS)
// IOS implements audio input only.
NOTIMPLEMENTED();
@@ -199,26 +238,34 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
}
}
- std::pair<AudioParameters, AudioParameters> dispatcher_key =
- std::make_pair(params, output_params);
- AudioOutputDispatchersMap::iterator it =
- output_dispatchers_.find(dispatcher_key);
- if (it != output_dispatchers_.end())
- return new AudioOutputProxy(it->second);
+ DispatcherParams* dispatcher_params =
+ new DispatcherParams(params, output_params, input_device_id);
+
+ AudioOutputDispatchers::iterator it =
+ std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
+ CompareByParams(dispatcher_params));
+ if (it != output_dispatchers_.end()) {
+ delete dispatcher_params;
+ return new AudioOutputProxy((*it)->dispatcher);
+ }
const base::TimeDelta kCloseDelay =
base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds);
if (output_params.format() != AudioParameters::AUDIO_FAKE) {
scoped_refptr<AudioOutputDispatcher> dispatcher =
- new AudioOutputResampler(this, params, output_params, kCloseDelay);
- output_dispatchers_[dispatcher_key] = dispatcher;
+ new AudioOutputResampler(this, params, output_params, input_device_id,
+ kCloseDelay);
+ dispatcher_params->dispatcher = dispatcher;
+ output_dispatchers_.push_back(dispatcher_params);
return new AudioOutputProxy(dispatcher);
}
scoped_refptr<AudioOutputDispatcher> dispatcher =
- new AudioOutputDispatcherImpl(this, output_params, kCloseDelay);
- output_dispatchers_[dispatcher_key] = dispatcher;
+ new AudioOutputDispatcherImpl(this, output_params, input_device_id,
+ kCloseDelay);
+ dispatcher_params->dispatcher = dispatcher;
+ output_dispatchers_.push_back(dispatcher_params);
return new AudioOutputProxy(dispatcher);
#endif // defined(OS_IOS)
}
@@ -292,9 +339,9 @@ void AudioManagerBase::ShutdownOnAudioThread() {
// the audio_thread_ member pointer when we get here, we can't verify exactly
// what thread we're running on. The method is not public though and only
// called from one place, so we'll leave it at that.
- AudioOutputDispatchersMap::iterator it = output_dispatchers_.begin();
+ AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
for (; it != output_dispatchers_.end(); ++it) {
- scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it).second;
+ scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher;
if (dispatcher) {
dispatcher->Shutdown();
// All AudioOutputProxies must have been freed before Shutdown is called.
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index 3d75b77..d266253 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -5,17 +5,19 @@
#ifndef MEDIA_AUDIO_AUDIO_MANAGER_BASE_H_
#define MEDIA_AUDIO_AUDIO_MANAGER_BASE_H_
-#include <map>
#include <string>
#include <utility>
#include "base/atomic_ref_count.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
#include "media/audio/audio_manager.h"
+#include "media/audio/audio_output_dispatcher.h"
+
#if defined(OS_WIN)
#include "base/win/scoped_com_initializer.h"
#endif
@@ -48,13 +50,15 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
media::AudioDeviceNames* device_names) OVERRIDE;
virtual AudioOutputStream* MakeAudioOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioOutputStream* MakeAudioOutputStreamProxy(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual bool IsRecordingInProcess() OVERRIDE;
@@ -71,8 +75,9 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
const AudioParameters& params) = 0;
// Creates the output stream for the |AUDIO_PCM_LOW_LATENCY| format.
+ // |input_device_id| is used by unified IO to open the correct input device.
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) = 0;
+ const AudioParameters& params, const std::string& input_device_id) = 0;
// Creates the input stream for the |AUDIO_PCM_LINEAR| format. The legacy
// name is also from |AUDIO_PCM_LINEAR|.
@@ -96,12 +101,6 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
protected:
AudioManagerBase();
- // TODO(dalecurtis): This must change to map both input and output parameters
- // to a single dispatcher, otherwise on a device state change we'll just get
- // the exact same invalid dispatcher.
- typedef std::map<std::pair<AudioParameters, AudioParameters>,
- scoped_refptr<AudioOutputDispatcher> >
- AudioOutputDispatchersMap;
// Shuts down the audio thread and releases all the audio output dispatchers
// on the audio thread. All audio streams should be freed before Shutdown()
@@ -124,15 +123,16 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
virtual AudioParameters GetPreferredOutputStreamParameters(
const AudioParameters& input_params) = 0;
- // Map of cached AudioOutputDispatcher instances. Must only be touched
- // from the audio thread (no locking).
- AudioOutputDispatchersMap output_dispatchers_;
-
// Get number of input or output streams.
int input_stream_count() { return num_input_streams_; }
int output_stream_count() { return num_output_streams_; }
private:
+ struct DispatcherParams;
+ typedef ScopedVector<DispatcherParams> AudioOutputDispatchers;
+
+ class CompareByParams;
+
// Called by Shutdown().
void ShutdownOnAudioThread();
@@ -165,6 +165,10 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
// and GetMessageLoop() starts returning NULL.
scoped_refptr<base::MessageLoopProxy> message_loop_;
+ // Map of cached AudioOutputDispatcher instances. Must only be touched
+ // from the audio thread (no locking).
+ AudioOutputDispatchers output_dispatchers_;
+
DISALLOW_COPY_AND_ASSIGN(AudioManagerBase);
};
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 350c5a1..b95e8e8 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -39,10 +39,12 @@ const int AudioOutputController::kPollPauseInMilliseconds = 3;
AudioOutputController::AudioOutputController(AudioManager* audio_manager,
EventHandler* handler,
const AudioParameters& params,
+ const std::string& input_device_id,
SyncReader* sync_reader)
: audio_manager_(audio_manager),
params_(params),
handler_(handler),
+ input_device_id_(input_device_id),
stream_(NULL),
diverting_to_stream_(NULL),
volume_(1.0),
@@ -67,6 +69,7 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create(
AudioManager* audio_manager,
EventHandler* event_handler,
const AudioParameters& params,
+ const std::string& input_device_id,
SyncReader* sync_reader) {
DCHECK(audio_manager);
DCHECK(sync_reader);
@@ -75,7 +78,7 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create(
return NULL;
scoped_refptr<AudioOutputController> controller(new AudioOutputController(
- audio_manager, event_handler, params, sync_reader));
+ audio_manager, event_handler, params, input_device_id, sync_reader));
controller->message_loop_->PostTask(FROM_HERE, base::Bind(
&AudioOutputController::DoCreate, controller, false));
return controller;
@@ -114,7 +117,7 @@ void AudioOutputController::DoCreate(bool is_for_device_change) {
DCHECK_EQ(kEmpty, state_);
stream_ = diverting_to_stream_ ? diverting_to_stream_ :
- audio_manager_->MakeAudioOutputStreamProxy(params_);
+ audio_manager_->MakeAudioOutputStreamProxy(params_, input_device_id_);
if (!stream_) {
state_ = kError;
handler_->OnError();
diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h
index 0a83bae..1e56633 100644
--- a/media/audio/audio_output_controller.h
+++ b/media/audio/audio_output_controller.h
@@ -112,7 +112,8 @@ class MEDIA_EXPORT AudioOutputController
// outlive AudioOutputController.
static scoped_refptr<AudioOutputController> Create(
AudioManager* audio_manager, EventHandler* event_handler,
- const AudioParameters& params, SyncReader* sync_reader);
+ const AudioParameters& params, const std::string& input_device_id,
+ SyncReader* sync_reader);
// Methods to control playback of the stream.
@@ -177,7 +178,9 @@ class MEDIA_EXPORT AudioOutputController
static const int kPollPauseInMilliseconds;
AudioOutputController(AudioManager* audio_manager, EventHandler* handler,
- const AudioParameters& params, SyncReader* sync_reader);
+ const AudioParameters& params,
+ const std::string& input_device_id,
+ SyncReader* sync_reader);
// The following methods are executed on the audio manager thread.
void DoCreate(bool is_for_device_change);
@@ -210,6 +213,9 @@ class MEDIA_EXPORT AudioOutputController
const AudioParameters params_;
EventHandler* const handler_;
+ // Used by the unified IO to open the correct input device.
+ std::string input_device_id_;
+
// Note: It's important to invalidate the weak pointers whenever stream_ is
// changed. See comment for weak_this_.
AudioOutputStream* stream_;
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index c6c2d45..96662ec 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -122,7 +122,7 @@ class AudioOutputControllerTest : public testing::Test {
}
controller_ = AudioOutputController::Create(
- audio_manager_.get(), &mock_event_handler_, params_,
+ audio_manager_.get(), &mock_event_handler_, params_, std::string(),
&mock_sync_reader_);
if (controller_)
controller_->SetVolume(kTestVolume);
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc
index 192823a..b0319df 100644
--- a/media/audio/audio_output_device.cc
+++ b/media/audio/audio_output_device.cc
@@ -48,6 +48,7 @@ AudioOutputDevice::AudioOutputDevice(
ipc_(ipc.Pass()),
state_(IDLE),
play_on_start_(true),
+ session_id_(-1),
stopping_hack_(false) {
CHECK(ipc_);
@@ -59,12 +60,19 @@ AudioOutputDevice::AudioOutputDevice(
COMPILE_ASSERT(PAUSED < PLAYING, invalid_enum_value_assignment_3);
}
-void AudioOutputDevice::Initialize(const AudioParameters& params,
- RenderCallback* callback) {
- DCHECK(!callback_) << "Calling Initialize() twice?";
+void AudioOutputDevice::InitializeUnifiedStream(const AudioParameters& params,
+ RenderCallback* callback,
+ int session_id) {
+ DCHECK(!callback_) << "Calling InitializeUnifiedStream() twice?";
DCHECK(params.IsValid());
audio_parameters_ = params;
callback_ = callback;
+ session_id_ = session_id;
+}
+
+void AudioOutputDevice::Initialize(const AudioParameters& params,
+ RenderCallback* callback) {
+ InitializeUnifiedStream(params, callback, 0);
}
AudioOutputDevice::~AudioOutputDevice() {
@@ -117,7 +125,7 @@ void AudioOutputDevice::CreateStreamOnIOThread(const AudioParameters& params) {
DCHECK(message_loop()->BelongsToCurrentThread());
if (state_ == IDLE) {
state_ = CREATING_STREAM;
- ipc_->CreateStream(this, params);
+ ipc_->CreateStream(this, params, session_id_);
}
}
diff --git a/media/audio/audio_output_device.h b/media/audio/audio_output_device.h
index a16b9ed..2af4f48 100644
--- a/media/audio/audio_output_device.h
+++ b/media/audio/audio_output_device.h
@@ -81,6 +81,18 @@ class MEDIA_EXPORT AudioOutputDevice
AudioOutputDevice(scoped_ptr<AudioOutputIPC> ipc,
const scoped_refptr<base::MessageLoopProxy>& io_loop);
+ // Initialize function for clients wishing to have unified input and
+ // output, |params| may specify |input_channels| > 0, representing a
+ // number of input channels which will be at the same sample-rate
+ // and buffer-size as the output as specified in |params|. |session_id| is
+ // used for the browser to select the correct input device.
+ // In this case, the callback's RenderIO() method will be called instead
+ // of Render(), providing the synchronized input data at the same time as
+ // when new output data is to be rendered.
+ void InitializeUnifiedStream(const AudioParameters& params,
+ RenderCallback* callback,
+ int session_id);
+
// AudioRendererSink implementation.
virtual void Initialize(const AudioParameters& params,
RenderCallback* callback) OVERRIDE;
@@ -144,6 +156,10 @@ class MEDIA_EXPORT AudioOutputDevice
// State of Play() / Pause() calls before OnStreamCreated() is called.
bool play_on_start_;
+ // The media session ID used to identify which input device to be started.
+ // Only used by Unified IO.
+ int session_id_;
+
// Our audio thread callback class. See source file for details.
class AudioThreadCallback;
diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc
index 4605e63..5616ff9 100644
--- a/media/audio/audio_output_device_unittest.cc
+++ b/media/audio/audio_output_device_unittest.cc
@@ -49,8 +49,9 @@ class MockAudioOutputIPC : public AudioOutputIPC {
MockAudioOutputIPC() {}
virtual ~MockAudioOutputIPC() {}
- MOCK_METHOD2(CreateStream, void(AudioOutputIPCDelegate* delegate,
- const AudioParameters& params));
+ MOCK_METHOD3(CreateStream, void(AudioOutputIPCDelegate* delegate,
+ const AudioParameters& params,
+ int session_id));
MOCK_METHOD0(PlayStream, void());
MOCK_METHOD0(PauseStream, void());
MOCK_METHOD0(CloseStream, void());
@@ -169,7 +170,7 @@ AudioOutputDeviceTest::~AudioOutputDeviceTest() {
void AudioOutputDeviceTest::StartAudioDevice() {
audio_device_->Start();
- EXPECT_CALL(*audio_output_ipc_, CreateStream(audio_device_.get(), _));
+ EXPECT_CALL(*audio_output_ipc_, CreateStream(audio_device_.get(), _, 0));
io_loop_.RunUntilIdle();
}
diff --git a/media/audio/audio_output_dispatcher.cc b/media/audio/audio_output_dispatcher.cc
index be9cb57..de30b1c 100644
--- a/media/audio/audio_output_dispatcher.cc
+++ b/media/audio/audio_output_dispatcher.cc
@@ -10,10 +10,12 @@ namespace media {
AudioOutputDispatcher::AudioOutputDispatcher(
AudioManager* audio_manager,
- const AudioParameters& params)
+ const AudioParameters& params,
+ const std::string& input_device_id)
: audio_manager_(audio_manager),
message_loop_(base::MessageLoop::current()),
- params_(params) {
+ params_(params),
+ input_device_id_(input_device_id) {
// We expect to be instantiated on the audio thread. Otherwise the
// message_loop_ member will point to the wrong message loop!
DCHECK(audio_manager->GetMessageLoop()->BelongsToCurrentThread());
diff --git a/media/audio/audio_output_dispatcher.h b/media/audio/audio_output_dispatcher.h
index e07d181..98dc89b 100644
--- a/media/audio/audio_output_dispatcher.h
+++ b/media/audio/audio_output_dispatcher.h
@@ -37,7 +37,8 @@ class MEDIA_EXPORT AudioOutputDispatcher
: public base::RefCountedThreadSafe<AudioOutputDispatcher> {
public:
AudioOutputDispatcher(AudioManager* audio_manager,
- const AudioParameters& params);
+ const AudioParameters& params,
+ const std::string& input_device_id);
// Called by AudioOutputProxy to open the stream.
// Returns false, if it fails to open it.
@@ -64,6 +65,9 @@ class MEDIA_EXPORT AudioOutputDispatcher
// Called on the audio thread when the AudioManager is shutting down.
virtual void Shutdown() = 0;
+ // Accessor to the input device id used by unified IO.
+ const std::string& input_device_id() const { return input_device_id_; }
+
protected:
friend class base::RefCountedThreadSafe<AudioOutputDispatcher>;
friend class AudioOutputProxyTest;
@@ -75,6 +79,7 @@ class MEDIA_EXPORT AudioOutputDispatcher
AudioManager* audio_manager_;
base::MessageLoop* message_loop_;
AudioParameters params_;
+ const std::string input_device_id_;
private:
DISALLOW_COPY_AND_ASSIGN(AudioOutputDispatcher);
diff --git a/media/audio/audio_output_dispatcher_impl.cc b/media/audio/audio_output_dispatcher_impl.cc
index 046bdd8..17f14c2 100644
--- a/media/audio/audio_output_dispatcher_impl.cc
+++ b/media/audio/audio_output_dispatcher_impl.cc
@@ -19,8 +19,9 @@ namespace media {
AudioOutputDispatcherImpl::AudioOutputDispatcherImpl(
AudioManager* audio_manager,
const AudioParameters& params,
+ const std::string& input_device_id,
const base::TimeDelta& close_delay)
- : AudioOutputDispatcher(audio_manager, params),
+ : AudioOutputDispatcher(audio_manager, params, input_device_id),
pause_delay_(base::TimeDelta::FromMicroseconds(
2 * params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
static_cast<float>(params.sample_rate()))),
@@ -166,7 +167,8 @@ void AudioOutputDispatcherImpl::Shutdown() {
bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
- AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(params_);
+ AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(
+ params_, input_device_id_);
if (!stream)
return false;
diff --git a/media/audio/audio_output_dispatcher_impl.h b/media/audio/audio_output_dispatcher_impl.h
index 85a84f7..90ac5db 100644
--- a/media/audio/audio_output_dispatcher_impl.h
+++ b/media/audio/audio_output_dispatcher_impl.h
@@ -35,6 +35,7 @@ class MEDIA_EXPORT AudioOutputDispatcherImpl : public AudioOutputDispatcher {
// the audio device is closed.
AudioOutputDispatcherImpl(AudioManager* audio_manager,
const AudioParameters& params,
+ const std::string& input_device_id,
const base::TimeDelta& close_delay);
// Opens a new physical stream if there are no pending streams in
diff --git a/media/audio/audio_output_ipc.h b/media/audio/audio_output_ipc.h
index 78cf2e7..84f8c6a 100644
--- a/media/audio/audio_output_ipc.h
+++ b/media/audio/audio_output_ipc.h
@@ -61,10 +61,13 @@ class MEDIA_EXPORT AudioOutputIPC {
// Sends a request to create an AudioOutputController object in the peer
// process and configures it to use the specified audio |params| including
- // number of synchronized input channels. Once the stream has been created,
+ // number of synchronized input channels.|session_id| is used by the browser
+ // to select the correct input device if the input channel in |params| is
+ // valid, otherwise it will be ignored. Once the stream has been created,
// the implementation will notify |delegate| by calling OnStreamCreated().
virtual void CreateStream(AudioOutputIPCDelegate* delegate,
- const AudioParameters& params) = 0;
+ const AudioParameters& params,
+ int session_id) = 0;
// Starts playing the stream. This should generate a call to
// AudioOutputController::Play().
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc
index fcbf56c..7e2a3eb 100644
--- a/media/audio/audio_output_proxy_unittest.cc
+++ b/media/audio/audio_output_proxy_unittest.cc
@@ -95,10 +95,10 @@ class MockAudioManager : public AudioManagerBase {
MOCK_METHOD0(HasAudioOutputDevices, bool());
MOCK_METHOD0(HasAudioInputDevices, bool());
MOCK_METHOD0(GetAudioInputDeviceModel, string16());
- MOCK_METHOD1(MakeAudioOutputStream, AudioOutputStream*(
- const AudioParameters& params));
- MOCK_METHOD1(MakeAudioOutputStreamProxy, AudioOutputStream*(
- const AudioParameters& params));
+ MOCK_METHOD2(MakeAudioOutputStream, AudioOutputStream*(
+ const AudioParameters& params, const std::string& input_device_id));
+ MOCK_METHOD2(MakeAudioOutputStreamProxy, AudioOutputStream*(
+ const AudioParameters& params, const std::string& input_device_id));
MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
MOCK_METHOD0(ShowAudioInputSettings, void());
@@ -109,8 +109,8 @@ class MockAudioManager : public AudioManagerBase {
MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
const AudioParameters& params));
- MOCK_METHOD1(MakeLowLatencyOutputStream, AudioOutputStream*(
- const AudioParameters& params));
+ MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
+ const AudioParameters& params, const std::string& input_device_id));
MOCK_METHOD2(MakeLinearInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
@@ -161,6 +161,7 @@ class AudioOutputProxyTest : public testing::Test {
CHANNEL_LAYOUT_STEREO, 8000, 16, 2048);
dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(),
params_,
+ std::string(),
close_delay);
// Necessary to know how long the dispatcher will wait before posting
@@ -186,7 +187,7 @@ class AudioOutputProxyTest : public testing::Test {
void OpenAndClose(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -203,7 +204,7 @@ class AudioOutputProxyTest : public testing::Test {
void StartAndStop(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -229,7 +230,7 @@ class AudioOutputProxyTest : public testing::Test {
void CloseAfterStop(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -261,7 +262,7 @@ class AudioOutputProxyTest : public testing::Test {
void TwoStreams(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -283,7 +284,7 @@ class AudioOutputProxyTest : public testing::Test {
void OpenFailed(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(false));
@@ -301,7 +302,7 @@ class AudioOutputProxyTest : public testing::Test {
void CreateAndWait(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -328,7 +329,7 @@ class AudioOutputProxyTest : public testing::Test {
MockAudioOutputStream stream1(&manager_, params_);
MockAudioOutputStream stream2(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream1))
.WillOnce(Return(&stream2));
@@ -366,7 +367,7 @@ class AudioOutputProxyTest : public testing::Test {
MockAudioOutputStream stream1(&manager_, params_);
MockAudioOutputStream stream2(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream1))
.WillOnce(Return(&stream2));
@@ -406,7 +407,7 @@ class AudioOutputProxyTest : public testing::Test {
void StartFailed(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
.WillOnce(Return(true));
@@ -425,7 +426,7 @@ class AudioOutputProxyTest : public testing::Test {
Mock::VerifyAndClear(&stream);
// |stream| is closed at this point. Start() should reopen it again.
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.Times(2)
.WillRepeatedly(Return(reinterpret_cast<AudioOutputStream*>(NULL)));
@@ -467,7 +468,7 @@ class AudioOutputResamplerTest : public AudioOutputProxyTest {
AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
16000, 16, 1024);
resampler_ = new AudioOutputResampler(
- &manager(), params_, resampler_params_, close_delay);
+ &manager(), params_, resampler_params_, std::string(), close_delay);
}
virtual void OnStart() OVERRIDE {
@@ -576,7 +577,7 @@ TEST_F(AudioOutputResamplerTest, StartFailed) {
// ensure AudioOutputResampler falls back to the high latency path.
TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.Times(2)
.WillOnce(Return(static_cast<AudioOutputStream*>(NULL)))
.WillRepeatedly(Return(&stream));
@@ -596,7 +597,7 @@ TEST_F(AudioOutputResamplerTest, LowLatencyCreateFailedFallback) {
TEST_F(AudioOutputResamplerTest, LowLatencyOpenFailedFallback) {
MockAudioOutputStream failed_stream(&manager_, params_);
MockAudioOutputStream okay_stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.Times(2)
.WillOnce(Return(&failed_stream))
.WillRepeatedly(Return(&okay_stream));
@@ -627,7 +628,7 @@ TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) {
#else
static const int kFallbackCount = 1;
#endif
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.Times(kFallbackCount)
.WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
@@ -637,7 +638,8 @@ TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) {
testing::Property(&AudioParameters::format, AudioParameters::AUDIO_FAKE),
testing::Property(&AudioParameters::sample_rate, params_.sample_rate()),
testing::Property(
- &AudioParameters::frames_per_buffer, params_.frames_per_buffer()))))
+ &AudioParameters::frames_per_buffer, params_.frames_per_buffer())),
+ _))
.Times(1)
.WillOnce(Return(&okay_stream));
EXPECT_CALL(okay_stream, Open())
@@ -662,7 +664,7 @@ TEST_F(AudioOutputResamplerTest, AllFallbackFailed) {
#else
static const int kFallbackCount = 2;
#endif
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.Times(kFallbackCount)
.WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
@@ -680,7 +682,7 @@ TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) {
MockAudioOutputStream stream3(&manager_, params_);
// Setup the mock such that all three streams are successfully created.
- EXPECT_CALL(manager(), MakeAudioOutputStream(_))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream1))
.WillOnce(Return(&stream2))
.WillOnce(Return(&stream3))
diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc
index 6750efc..ea1848e 100644
--- a/media/audio/audio_output_resampler.cc
+++ b/media/audio/audio_output_resampler.cc
@@ -148,10 +148,12 @@ static AudioParameters SetupFallbackParams(
AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager,
const AudioParameters& input_params,
const AudioParameters& output_params,
+ const std::string& input_device_id,
const base::TimeDelta& close_delay)
- : AudioOutputDispatcher(audio_manager, input_params),
+ : AudioOutputDispatcher(audio_manager, input_params, input_device_id),
close_delay_(close_delay),
output_params_(output_params),
+ input_device_id_(input_device_id),
streams_opened_(false) {
DCHECK(input_params.IsValid());
DCHECK(output_params.IsValid());
@@ -171,7 +173,7 @@ void AudioOutputResampler::Initialize() {
DCHECK(!streams_opened_);
DCHECK(callbacks_.empty());
dispatcher_ = new AudioOutputDispatcherImpl(
- audio_manager_, output_params_, close_delay_);
+ audio_manager_, output_params_, input_device_id_, close_delay_);
}
bool AudioOutputResampler::OpenStream() {
diff --git a/media/audio/audio_output_resampler.h b/media/audio/audio_output_resampler.h
index 057cf34..e2633da 100644
--- a/media/audio/audio_output_resampler.h
+++ b/media/audio/audio_output_resampler.h
@@ -40,6 +40,7 @@ class MEDIA_EXPORT AudioOutputResampler : public AudioOutputDispatcher {
AudioOutputResampler(AudioManager* audio_manager,
const AudioParameters& input_params,
const AudioParameters& output_params,
+ const std::string& input_device_id,
const base::TimeDelta& close_delay);
// AudioOutputDispatcher interface.
@@ -73,6 +74,9 @@ class MEDIA_EXPORT AudioOutputResampler : public AudioOutputDispatcher {
// AudioParameters used to setup the output stream.
AudioParameters output_params_;
+ // Device ID to be used by the unified IO to open the correct input device.
+ const std::string input_device_id_;
+
// Whether any streams have been opened through |dispatcher_|, if so we can't
// fallback on future OpenStream() failures.
bool streams_opened_;
diff --git a/media/audio/audio_parameters.h b/media/audio/audio_parameters.h
index dcc9eae..02a6f96 100644
--- a/media/audio/audio_parameters.h
+++ b/media/audio/audio_parameters.h
@@ -79,6 +79,16 @@ class MEDIA_EXPORT AudioParameters {
// Set to CHANNEL_LAYOUT_DISCRETE with given number of channels.
void SetDiscreteChannels(int channels);
+ // Comparison with other AudioParams.
+ bool operator==(const AudioParameters& other) const {
+ return format_ == other.format() &&
+ channel_layout_ == other.channel_layout() &&
+ channels_ == other.channels() &&
+ input_channels_ == other.input_channels() &&
+ bits_per_sample_ == other.bits_per_sample() &&
+ frames_per_buffer_ == other.frames_per_buffer();
+ }
+
private:
Format format_; // Format of the stream.
ChannelLayout channel_layout_; // Order of surround sound channels.
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 52fb97e..e1a140e 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -74,8 +74,9 @@ AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
}
AudioOutputStream* AudioManagerCras::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ // TODO(dgreid): Open the correct input device for unified IO.
return MakeOutputStream(params);
}
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h
index 2c38c8e..4e69c8f 100644
--- a/media/audio/cras/audio_manager_cras.h
+++ b/media/audio/cras/audio_manager_cras.h
@@ -30,7 +30,8 @@ class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/ios/audio_manager_ios.h b/media/audio/ios/audio_manager_ios.h
index 1c4013a..1975150 100644
--- a/media/audio/ios/audio_manager_ios.h
+++ b/media/audio/ios/audio_manager_ios.h
@@ -21,7 +21,8 @@ class MEDIA_EXPORT AudioManagerIOS : public AudioManagerBase {
virtual bool HasAudioOutputDevices() OVERRIDE;
virtual bool HasAudioInputDevices() OVERRIDE;
virtual AudioOutputStream* MakeAudioOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioParameters GetInputStreamParameters(
@@ -31,7 +32,8 @@ class MEDIA_EXPORT AudioManagerIOS : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/ios/audio_manager_ios.mm b/media/audio/ios/audio_manager_ios.mm
index 0e0a194..4947930 100644
--- a/media/audio/ios/audio_manager_ios.mm
+++ b/media/audio/ios/audio_manager_ios.mm
@@ -62,7 +62,7 @@ AudioParameters AudioManagerIOS::GetInputStreamParameters(
}
AudioOutputStream* AudioManagerIOS::MakeAudioOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
return NULL;
}
@@ -82,24 +82,24 @@ AudioInputStream* AudioManagerIOS::MakeAudioInputStream(
}
AudioOutputStream* AudioManagerIOS::MakeLinearOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
return NULL;
}
AudioOutputStream* AudioManagerIOS::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
return NULL;
}
AudioInputStream* AudioManagerIOS::MakeLinearInputStream(
- const AudioParameters& params, const std::string& device_id) {
+ const AudioParameters& params, const std::string& device_id) {
return MakeAudioInputStream(params, device_id);
}
AudioInputStream* AudioManagerIOS::MakeLowLatencyInputStream(
- const AudioParameters& params, const std::string& device_id) {
+ const AudioParameters& params, const std::string& device_id) {
NOTIMPLEMENTED(); // Only linear audio input is supported on iOS.
return MakeAudioInputStream(params, device_id);
}
diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/linux/alsa_output_unittest.cc
index 0dc19f5..02cbd42 100644
--- a/media/audio/linux/alsa_output_unittest.cc
+++ b/media/audio/linux/alsa_output_unittest.cc
@@ -83,8 +83,8 @@ class MockAudioManagerLinux : public AudioManagerLinux {
MOCK_METHOD0(HasAudioInputDevices, bool());
MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
const AudioParameters& params));
- MOCK_METHOD1(MakeLowLatencyOutputStream, AudioOutputStream*(
- const AudioParameters& params));
+ MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
+ const AudioParameters& params, const std::string& input_device_id));
MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index c898f81..3115523 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -256,8 +256,10 @@ AudioOutputStream* AudioManagerLinux::MakeLinearOutputStream(
}
AudioOutputStream* AudioManagerLinux::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params,
+ const std::string& input_device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ // TODO(xians): Use input_device_id for unified IO.
return MakeOutputStream(params);
}
diff --git a/media/audio/linux/audio_manager_linux.h b/media/audio/linux/audio_manager_linux.h
index 4c89773..28abaa1 100644
--- a/media/audio/linux/audio_manager_linux.h
+++ b/media/audio/linux/audio_manager_linux.h
@@ -34,7 +34,8 @@ class MEDIA_EXPORT AudioManagerLinux : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/mac/audio_auhal_mac_unittest.cc b/media/audio/mac/audio_auhal_mac_unittest.cc
index cab8c28..b4cf8c6 100644
--- a/media/audio/mac/audio_auhal_mac_unittest.cc
+++ b/media/audio/mac/audio_auhal_mac_unittest.cc
@@ -100,7 +100,8 @@ class AudioOutputStreamWrapper {
sample_rate_, bits_per_sample_,
samples_per_packet_);
- AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params);
+ AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params,
+ std::string());
EXPECT_TRUE(aos);
return aos;
}
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 3671317..33dcff0 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -421,11 +421,11 @@ AudioParameters AudioManagerMac::GetInputStreamParameters(
AudioOutputStream* AudioManagerMac::MakeLinearOutputStream(
const AudioParameters& params) {
- return MakeLowLatencyOutputStream(params);
+ return MakeLowLatencyOutputStream(params, std::string());
}
AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
// Handle basic output with no input channels.
if (params.input_channels() == 0) {
AudioDeviceID device = kAudioObjectUnknown;
@@ -462,7 +462,8 @@ AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
LOG(INFO) << "Using AGGREGATE audio device";
}
- if (device != kAudioObjectUnknown)
+ if (device != kAudioObjectUnknown &&
+ input_device_id == AudioManagerBase::kDefaultDeviceId)
return new AUHALStream(this, params, device);
// Fallback to AudioSynchronizedStream which will handle completely
@@ -471,9 +472,13 @@ AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
// kAudioDeviceUnknown translates to "use default" here.
// TODO(crogers): consider tracking UMA stats on AUHALStream
// versus AudioSynchronizedStream.
+ AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, input_device_id);
+ if (audio_device_id == kAudioObjectUnknown)
+ return NULL;
+
return new AudioSynchronizedStream(this,
params,
- kAudioDeviceUnknown,
+ audio_device_id,
kAudioDeviceUnknown);
}
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index af867d8..0691ec2 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -36,7 +36,8 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc
index 1209e19..49bc8d1 100644
--- a/media/audio/mock_audio_manager.cc
+++ b/media/audio/mock_audio_manager.cc
@@ -37,13 +37,15 @@ void MockAudioManager::GetAudioInputDeviceNames(
}
media::AudioOutputStream* MockAudioManager::MakeAudioOutputStream(
- const media::AudioParameters& params) {
+ const media::AudioParameters& params,
+ const std::string& input_device_id) {
NOTREACHED();
return NULL;
}
media::AudioOutputStream* MockAudioManager::MakeAudioOutputStreamProxy(
- const media::AudioParameters& params) {
+ const media::AudioParameters& params,
+ const std::string& input_device_id) {
NOTREACHED();
return NULL;
}
diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h
index 3a0e907..8042eda 100644
--- a/media/audio/mock_audio_manager.h
+++ b/media/audio/mock_audio_manager.h
@@ -35,10 +35,12 @@ class MockAudioManager : public media::AudioManager {
media::AudioDeviceNames* device_names) OVERRIDE;
virtual media::AudioOutputStream* MakeAudioOutputStream(
- const media::AudioParameters& params) OVERRIDE;
+ const media::AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual media::AudioOutputStream* MakeAudioOutputStreamProxy(
- const media::AudioParameters& params) OVERRIDE;
+ const media::AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual media::AudioInputStream* MakeAudioInputStream(
const media::AudioParameters& params,
diff --git a/media/audio/openbsd/audio_manager_openbsd.cc b/media/audio/openbsd/audio_manager_openbsd.cc
index 681f219..4005aeb 100644
--- a/media/audio/openbsd/audio_manager_openbsd.cc
+++ b/media/audio/openbsd/audio_manager_openbsd.cc
@@ -91,7 +91,8 @@ AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
}
AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params,
+ const std::string& input_device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format);
return MakeOutputStream(params);
}
diff --git a/media/audio/openbsd/audio_manager_openbsd.h b/media/audio/openbsd/audio_manager_openbsd.h
index d981612..a1adcb6 100644
--- a/media/audio/openbsd/audio_manager_openbsd.h
+++ b/media/audio/openbsd/audio_manager_openbsd.h
@@ -26,7 +26,8 @@ class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index fed919a..3dcdd89 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -112,13 +112,13 @@ AudioParameters AudioManagerPulse::GetInputStreamParameters(
AudioOutputStream* AudioManagerPulse::MakeLinearOutputStream(
const AudioParameters& params) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
- return MakeOutputStream(params);
+ return MakeOutputStream(params, std::string());
}
AudioOutputStream* AudioManagerPulse::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
- return MakeOutputStream(params);
+ return MakeOutputStream(params, input_device_id);
}
AudioInputStream* AudioManagerPulse::MakeLinearInputStream(
@@ -162,9 +162,9 @@ AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters(
}
AudioOutputStream* AudioManagerPulse::MakeOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
if (params.input_channels()) {
- return new PulseAudioUnifiedStream(params, this);
+ return new PulseAudioUnifiedStream(params, input_device_id, this);
}
return new PulseAudioOutputStream(params, this);
diff --git a/media/audio/pulse/audio_manager_pulse.h b/media/audio/pulse/audio_manager_pulse.h
index 9dacb9c..d5cb93e 100644
--- a/media/audio/pulse/audio_manager_pulse.h
+++ b/media/audio/pulse/audio_manager_pulse.h
@@ -34,7 +34,8 @@ class MEDIA_EXPORT AudioManagerPulse : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
@@ -60,7 +61,8 @@ class MEDIA_EXPORT AudioManagerPulse : public AudioManagerBase {
void* user_data);
// Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
- AudioOutputStream* MakeOutputStream(const AudioParameters& params);
+ AudioOutputStream* MakeOutputStream(const AudioParameters& params,
+ const std::string& input_device_id);
// Called by MakeLinearInputStream and MakeLowLatencyInputStream.
AudioInputStream* MakeInputStream(const AudioParameters& params,
diff --git a/media/audio/pulse/pulse_unified.cc b/media/audio/pulse/pulse_unified.cc
index 87bb6ae..ee14341 100644
--- a/media/audio/pulse/pulse_unified.cc
+++ b/media/audio/pulse/pulse_unified.cc
@@ -41,9 +41,12 @@ void PulseAudioUnifiedStream::ReadCallback(pa_stream* handle, size_t length,
static_cast<PulseAudioUnifiedStream*>(user_data)->ReadData();
}
-PulseAudioUnifiedStream::PulseAudioUnifiedStream(const AudioParameters& params,
- AudioManagerBase* manager)
+PulseAudioUnifiedStream::PulseAudioUnifiedStream(
+ const AudioParameters& params,
+ const std::string& input_device_id,
+ AudioManagerBase* manager)
: params_(params),
+ input_device_id_(input_device_id),
manager_(manager),
pa_context_(NULL),
pa_mainloop_(NULL),
@@ -77,9 +80,8 @@ bool PulseAudioUnifiedStream::Open() {
params_, &StreamNotifyCallback, NULL, this))
return false;
- // TODO(xians): Add support for non-default device.
if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &input_stream_,
- params_, AudioManagerBase::kDefaultDeviceId,
+ params_, input_device_id_,
&StreamNotifyCallback, this))
return false;
diff --git a/media/audio/pulse/pulse_unified.h b/media/audio/pulse/pulse_unified.h
index d7476a8..a800d09 100644
--- a/media/audio/pulse/pulse_unified.h
+++ b/media/audio/pulse/pulse_unified.h
@@ -6,6 +6,7 @@
#define MEDIA_AUDIO_PULSE_PULSE_UNIFIED_H_
#include <pulse/pulseaudio.h>
+#include <string>
#include "base/memory/scoped_ptr.h"
#include "media/audio/audio_io.h"
@@ -20,6 +21,7 @@ class SeekableBuffer;
class PulseAudioUnifiedStream : public AudioOutputStream {
public:
PulseAudioUnifiedStream(const AudioParameters& params,
+ const std::string& input_device_id,
AudioManagerBase* manager);
virtual ~PulseAudioUnifiedStream();
@@ -51,6 +53,9 @@ class PulseAudioUnifiedStream : public AudioOutputStream {
// AudioParameters from the constructor.
const AudioParameters params_;
+ // Device unique ID of the input device.
+ const std::string input_device_id_;
+
// Audio manager that created us. Used to report that we've closed.
AudioManagerBase* manager_;
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc
index 5f1f1a6..af60be6 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -232,7 +232,8 @@ class AudioOutputStreamWrapper {
AudioOutputStream* CreateOutputStream() {
AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(
AudioParameters(format_, channel_layout_, sample_rate_,
- bits_per_sample_, samples_per_packet_));
+ bits_per_sample_, samples_per_packet_),
+ std::string());
EXPECT_TRUE(aos);
return aos;
}
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index cfeecc7..b8b5d89 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -301,7 +301,7 @@ AudioOutputStream* AudioManagerWin::MakeLinearOutputStream(
// - PCMWaveOutAudioOutputStream: Based on the waveOut API.
// - WASAPIAudioOutputStream: Based on Core Audio (WASAPI) API.
AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
- const AudioParameters& params) {
+ const AudioParameters& params, const std::string& input_device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
if (params.channels() > kWinMaxChannels)
return NULL;
@@ -316,7 +316,7 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
// TODO(crogers): support more than stereo input.
if (params.input_channels() > 0) {
DVLOG(1) << "WASAPIUnifiedStream is created.";
- return new WASAPIUnifiedStream(this, params);
+ return new WASAPIUnifiedStream(this, params, input_device_id);
}
return new WASAPIAudioOutputStream(this, params, eConsole);
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index 46d7aa4..65cc73b 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -34,7 +34,8 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
virtual AudioOutputStream* MakeLinearOutputStream(
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
- const AudioParameters& params) OVERRIDE;
+ const AudioParameters& params,
+ const std::string& input_device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc
index ad20327..4e13d84 100644
--- a/media/audio/win/audio_output_win_unittest.cc
+++ b/media/audio/win/audio_output_win_unittest.cc
@@ -184,7 +184,8 @@ TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
- 8000, 16, 256));
+ 8000, 16, 256),
+ std::string());
ASSERT_TRUE(NULL != oas);
oas->Close();
}
@@ -199,22 +200,30 @@ TEST(WinAudioTest, SanityOnMakeParams) {
AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
- AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0)));
+ AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
- media::limits::kMaxSamplesPerPacket + 1)));
+ media::limits::kMaxSamplesPerPacket + 1),
+ std::string()));
}
// Test that it can be opened and closed.
@@ -227,7 +236,8 @@ TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
- 8000, 16, 256));
+ 8000, 16, 256),
+ std::string());
ASSERT_TRUE(NULL != oas);
EXPECT_TRUE(oas->Open());
oas->Close();
@@ -243,7 +253,8 @@ TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
- 8000, 16, 1024 * 1024 * 1024));
+ 8000, 16, 1024 * 1024 * 1024),
+ std::string());
EXPECT_TRUE(NULL == oas);
if (oas)
oas->Close();
@@ -261,7 +272,8 @@ TEST(WinAudioTest, PCMWaveSlowSource) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
- 16000, 16, 256));
+ 16000, 16, 256),
+ std::string());
ASSERT_TRUE(NULL != oas);
TestSourceLaggy test_laggy(2, 90);
EXPECT_TRUE(oas->Open());
@@ -289,7 +301,8 @@ TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
- AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
+ AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
@@ -319,7 +332,8 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
- AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
+ AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
@@ -347,7 +361,8 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate / 2, 16,
- samples_100_ms));
+ samples_100_ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
@@ -386,7 +401,8 @@ TEST(WinAudioTest, PushSourceFile16KHz) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
- kSampleRate, 16, kSamples100ms));
+ kSampleRate, 16, kSamples100ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
EXPECT_TRUE(oas->Open());
@@ -422,7 +438,8 @@ TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
- AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
+ AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
@@ -468,7 +485,8 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
CHANNEL_LAYOUT_MONO, sample_rate,
- 16, n * samples_10_ms));
+ 16, n * samples_10_ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200, sample_rate);
@@ -501,7 +519,8 @@ TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
- AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
+ AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
+ std::string());
ASSERT_TRUE(NULL != oas);
NiceMock<MockAudioSource> source;
@@ -660,7 +679,8 @@ TEST(WinAudioTest, SyncSocketBasic) {
CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
- AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params);
+ AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
+ std::string());
ASSERT_TRUE(NULL != oas);
ASSERT_TRUE(oas->Open());
diff --git a/media/audio/win/audio_unified_win.cc b/media/audio/win/audio_unified_win.cc
index 6e00b28..c69d114 100644
--- a/media/audio/win/audio_unified_win.cc
+++ b/media/audio/win/audio_unified_win.cc
@@ -109,12 +109,14 @@ static double FrameCountToMilliseconds(int num_frames,
namespace media {
WASAPIUnifiedStream::WASAPIUnifiedStream(AudioManagerWin* manager,
- const AudioParameters& params)
+ const AudioParameters& params,
+ const std::string& input_device_id)
: creating_thread_id_(base::PlatformThread::CurrentId()),
manager_(manager),
params_(params),
input_channels_(params.input_channels()),
output_channels_(params.channels()),
+ input_device_id_(input_device_id),
share_mode_(CoreAudioUtil::GetShareMode()),
audio_io_thread_(NULL),
opened_(false),
@@ -328,7 +330,8 @@ bool WASAPIUnifiedStream::Open() {
return false;
// Capture side (always event driven but format depends on varispeed or not):
-
+ // TODO(henrika): Open the correct input device with |input_device_id_|,
+ // http://crbug.com/147327.
ScopedComPtr<IAudioClient> audio_input_client =
CoreAudioUtil::CreateDefaultClient(eCapture, eConsole);
if (!audio_input_client)
diff --git a/media/audio/win/audio_unified_win.h b/media/audio/win/audio_unified_win.h
index 3561ae4..76c5329 100644
--- a/media/audio/win/audio_unified_win.h
+++ b/media/audio/win/audio_unified_win.h
@@ -84,7 +84,8 @@ class MEDIA_EXPORT WASAPIUnifiedStream
// The ctor takes all the usual parameters, plus |manager| which is the
// the audio manager who is creating this object.
WASAPIUnifiedStream(AudioManagerWin* manager,
- const AudioParameters& params);
+ const AudioParameters& params,
+ const std::string& input_device_id);
// The dtor is typically called by the AudioManager only and it is usually
// triggered by calling AudioOutputStream::Close().
@@ -183,6 +184,9 @@ class MEDIA_EXPORT WASAPIUnifiedStream
int input_channels_;
int output_channels_;
+ // Unique ID of the input device to be opened.
+ const std::string input_device_id_;
+
// The sharing mode for the streams.
// Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE
// where AUDCLNT_SHAREMODE_SHARED is the default.
diff --git a/media/audio/win/audio_unified_win_unittest.cc b/media/audio/win/audio_unified_win_unittest.cc
index 4830ff0..6fad0b7 100644
--- a/media/audio/win/audio_unified_win_unittest.cc
+++ b/media/audio/win/audio_unified_win_unittest.cc
@@ -215,7 +215,8 @@ class AudioUnifiedStreamWrapper {
private:
AudioOutputStream* CreateOutputStream() {
- AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_);
+ AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
+ std::string());
EXPECT_TRUE(aos);
return aos;
}
diff --git a/media/base/audio_renderer_sink.h b/media/base/audio_renderer_sink.h
index 0d3c6c7..b2f4ba0a 100644
--- a/media/base/audio_renderer_sink.h
+++ b/media/base/audio_renderer_sink.h
@@ -7,6 +7,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
@@ -41,13 +42,6 @@ class AudioRendererSink
// Sets important information about the audio stream format.
// It must be called before any of the other methods.
- // For clients wishing to have synchronized input and output,
- // |params| may specify |input_channels| > 0, representing a
- // number of input channels which will be at the same sample-rate
- // and buffer-size as the output as specified in |params|.
- // In this case, the callback's RenderIO() method will be called instead
- // of Render(), providing the synchronized input data at the same time as
- // when new output data is to be rendered.
virtual void Initialize(const AudioParameters& params,
RenderCallback* callback) = 0;