summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-07 21:32:50 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-07 21:32:50 +0000
commite8ff1ad4a40d8f525a457b1231f31ff1068fc7a7 (patch)
tree11aef20f75aab3889614f2b05f70fe7ffae92709
parent1d62cf79f609fba47ef680bf5acc9b453d4229ea (diff)
downloadchromium_src-e8ff1ad4a40d8f525a457b1231f31ff1068fc7a7.zip
chromium_src-e8ff1ad4a40d8f525a457b1231f31ff1068fc7a7.tar.gz
chromium_src-e8ff1ad4a40d8f525a457b1231f31ff1068fc7a7.tar.bz2
Remove the unified IO code on the browser.
Unified IO is not used any more and it should be removed. BUG=337096 TEST=bots, and nothing breaks. Review URL: https://codereview.chromium.org/153623004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249790 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/media/media_internals.cc9
-rw-r--r--content/browser/media/media_internals_unittest.cc10
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc2
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.cc38
-rw-r--r--content/browser/renderer_host/media/audio_sync_reader.cc26
-rw-r--r--content/browser/renderer_host/media/audio_sync_reader.h9
-rw-r--r--media/audio/alsa/alsa_output_unittest.cc5
-rw-r--r--media/audio/alsa/audio_manager_alsa.cc4
-rw-r--r--media/audio/alsa/audio_manager_alsa.h3
-rw-r--r--media/audio/android/audio_android_unittest.cc12
-rw-r--r--media/audio/android/audio_manager_android.cc9
-rw-r--r--media/audio/android/audio_manager_android.h6
-rw-r--r--media/audio/audio_logging.h8
-rw-r--r--media/audio/audio_low_latency_input_output_unittest.cc3
-rw-r--r--media/audio/audio_manager.h11
-rw-r--r--media/audio/audio_manager_base.cc31
-rw-r--r--media/audio/audio_manager_base.h10
-rw-r--r--media/audio/audio_output_controller.cc9
-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_dispatcher.cc6
-rw-r--r--media/audio/audio_output_dispatcher.h9
-rw-r--r--media/audio/audio_output_dispatcher_impl.cc8
-rw-r--r--media/audio/audio_output_dispatcher_impl.h1
-rw-r--r--media/audio/audio_output_proxy_unittest.cc53
-rw-r--r--media/audio/audio_output_resampler.cc9
-rw-r--r--media/audio/audio_output_resampler.h1
-rw-r--r--media/audio/cras/cras_unified_unittest.cc5
-rw-r--r--media/audio/fake_audio_log_factory.cc3
-rw-r--r--media/audio/fake_audio_manager.cc3
-rw-r--r--media/audio/fake_audio_manager.h3
-rw-r--r--media/audio/mac/aggregate_device_manager.cc371
-rw-r--r--media/audio/mac/aggregate_device_manager.h58
-rw-r--r--media/audio/mac/audio_auhal_mac_unittest.cc2
-rw-r--r--media/audio/mac/audio_manager_mac.cc78
-rw-r--r--media/audio/mac/audio_manager_mac.h8
-rw-r--r--media/audio/mac/audio_synchronized_mac.cc976
-rw-r--r--media/audio/mac/audio_synchronized_mac.h216
-rw-r--r--media/audio/mac/audio_unified_mac.cc397
-rw-r--r--media/audio/mac/audio_unified_mac.h100
-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.cc14
-rw-r--r--media/audio/pulse/audio_manager_pulse.h6
-rw-r--r--media/audio/pulse/pulse_unified.cc292
-rw-r--r--media/audio/pulse/pulse_unified.h90
-rw-r--r--media/audio/sounds/audio_stream_handler.cc2
-rw-r--r--media/audio/win/audio_low_latency_output_win_unittest.cc2
-rw-r--r--media/audio/win/audio_manager_win.cc13
-rw-r--r--media/audio/win/audio_manager_win.h3
-rw-r--r--media/audio/win/audio_output_win_unittest.cc40
-rw-r--r--media/audio/win/audio_unified_win.cc984
-rw-r--r--media/audio/win/audio_unified_win.h352
-rw-r--r--media/audio/win/audio_unified_win_unittest.cc356
-rw-r--r--media/media.gyp13
57 files changed, 142 insertions, 4567 deletions
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc
index 1ee42d1..f2e9072 100644
--- a/content/browser/media/media_internals.cc
+++ b/content/browser/media/media_internals.cc
@@ -39,8 +39,7 @@ class AudioLogImpl : public media::AudioLog {
virtual void OnCreated(int component_id,
const media::AudioParameters& params,
- const std::string& input_device_id,
- const std::string& output_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual void OnStarted(int component_id) OVERRIDE;
virtual void OnStopped(int component_id) OVERRIDE;
virtual void OnClosed(int component_id) OVERRIDE;
@@ -72,17 +71,15 @@ AudioLogImpl::~AudioLogImpl() {}
void AudioLogImpl::OnCreated(int component_id,
const media::AudioParameters& params,
- const std::string& input_device_id,
- const std::string& output_device_id) {
+ const std::string& device_id) {
base::DictionaryValue dict;
StoreComponentMetadata(component_id, &dict);
dict.SetString(kAudioLogStatusKey, "created");
- dict.SetString("input_device_id", input_device_id);
+ dict.SetString("device_id", device_id);
dict.SetInteger("input_channels", params.input_channels());
dict.SetInteger("frames_per_buffer", params.frames_per_buffer());
dict.SetInteger("sample_rate", params.sample_rate());
- dict.SetString("output_device_id", output_device_id);
dict.SetInteger("channels", params.channels());
dict.SetString("channel_layout",
ChannelLayoutToString(params.channel_layout()));
diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc
index 2947104..01e48e0 100644
--- a/content/browser/media/media_internals_unittest.cc
+++ b/content/browser/media/media_internals_unittest.cc
@@ -16,8 +16,7 @@
namespace {
const int kTestComponentID = 0;
-const char kTestInputDeviceID[] = "test-input-id";
-const char kTestOutputDeviceID[] = "test-output-id";
+const char kTestDeviceID[] = "test-device-id";
} // namespace
namespace content {
@@ -87,7 +86,7 @@ class MediaInternalsTest
TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
audio_log_->OnCreated(
- kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID);
+ kTestComponentID, test_params_, kTestDeviceID);
base::RunLoop().RunUntilIdle();
ExpectString("channel_layout",
@@ -96,8 +95,7 @@ TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
ExpectInt("frames_per_buffer", test_params_.frames_per_buffer());
ExpectInt("channels", test_params_.channels());
ExpectInt("input_channels", test_params_.input_channels());
- ExpectString("output_device_id", kTestOutputDeviceID);
- ExpectString("input_device_id", kTestInputDeviceID);
+ ExpectString("device_id", kTestDeviceID);
ExpectInt("component_id", kTestComponentID);
ExpectInt("component_type", test_component_);
ExpectStatus("created");
@@ -128,7 +126,7 @@ TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
TEST_P(MediaInternalsTest, AudioLogCreateClose) {
audio_log_->OnCreated(
- kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID);
+ kTestComponentID, test_params_, kTestDeviceID);
base::RunLoop().RunUntilIdle();
ExpectStatus("created");
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 93ed16c..6a75f54 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -314,7 +314,7 @@ void AudioInputRendererHost::OnCreateStream(
MediaStreamManager::SendMessageToNativeLog(
"Audio input stream created successfully.");
- audio_log_->OnCreated(stream_id, audio_params, device_id, std::string());
+ audio_log_->OnCreated(stream_id, audio_params, device_id);
}
void AudioInputRendererHost::OnRecordStream(int stream_id) {
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 165989e..a1f3710 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -36,7 +36,6 @@ class AudioRendererHost::AudioEntry
int render_view_id,
const media::AudioParameters& params,
const std::string& output_device_id,
- const std::string& input_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader);
virtual ~AudioEntry();
@@ -89,15 +88,13 @@ AudioRendererHost::AudioEntry::AudioEntry(
AudioRendererHost* host, int stream_id, int render_view_id,
const media::AudioParameters& params,
const std::string& output_device_id,
- 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, output_device_id,
- input_device_id, reader.get())),
+ host->audio_manager_, this, params, output_device_id, reader.get())),
shared_memory_(shared_memory.Pass()),
reader_(reader.Pass()) {
DCHECK(controller_.get());
@@ -314,45 +311,24 @@ void AudioRendererHost::OnCreateStream(
DCHECK_GT(render_view_id, 0);
// media::AudioParameters is validated in the deserializer.
- int input_channels = params.input_channels();
- if (input_channels < 0 ||
- input_channels > media::limits::kMaxChannels ||
- LookupById(stream_id) != NULL) {
+ if (LookupById(stream_id) != NULL) {
SendErrorMessage(stream_id);
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|.
// Initialize the |output_device_id| to an empty string which indicates that
// the default device should be used. If a StreamDeviceInfo instance was found
// though, then we use the matched output device.
- std::string input_device_id, output_device_id;
+ std::string output_device_id;
const StreamDeviceInfo* info = media_stream_manager_->
audio_input_device_manager()->GetOpenedDeviceInfoById(session_id);
if (info)
output_device_id = info->device.matched_output_device_id;
- if (input_channels > 0) {
- 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();
- int input_memory_size = AudioBus::CalculateMemorySize(input_channels, frames);
-
// Create the shared memory and share with the renderer process.
// For synchronized I/O (if input_channels > 0) then we allocate
// extra memory after the output data for the input data.
- uint32 shared_memory_size = output_memory_size + input_memory_size;
+ uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);;
scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
SendErrorMessage(stream_id);
@@ -360,7 +336,7 @@ void AudioRendererHost::OnCreateStream(
}
scoped_ptr<AudioSyncReader> reader(
- new AudioSyncReader(shared_memory.get(), params, input_channels));
+ new AudioSyncReader(shared_memory.get(), params));
if (!reader->Init()) {
SendErrorMessage(stream_id);
return;
@@ -373,14 +349,14 @@ void AudioRendererHost::OnCreateStream(
scoped_ptr<AudioEntry> entry(new AudioEntry(
this, stream_id, render_view_id, params, output_device_id,
- input_device_id, shared_memory.Pass(),
+ shared_memory.Pass(),
reader.PassAs<media::AudioOutputController::SyncReader>()));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
render_process_id_, entry->render_view_id(), entry->controller());
}
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
- audio_log_->OnCreated(stream_id, params, input_device_id, output_device_id);
+ audio_log_->OnCreated(stream_id, params, output_device_id);
}
void AudioRendererHost::OnPlayStream(int stream_id) {
diff --git a/content/browser/renderer_host/media/audio_sync_reader.cc b/content/browser/renderer_host/media/audio_sync_reader.cc
index a51d3d1..d491fe2 100644
--- a/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -18,10 +18,8 @@ using media::AudioBus;
namespace content {
AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
- const media::AudioParameters& params,
- int input_channels)
+ const media::AudioParameters& params)
: shared_memory_(shared_memory),
- input_channels_(input_channels),
mute_audio_(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMuteAudio)),
packet_size_(shared_memory_->requested_size()),
@@ -34,18 +32,7 @@ AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
maximum_wait_time_(base::TimeDelta::FromMilliseconds(20)),
#endif
buffer_index_(0) {
- int input_memory_size = 0;
- int output_memory_size = AudioBus::CalculateMemorySize(params);
- if (input_channels_ > 0) {
- // The input storage is after the output storage.
- int frames = params.frames_per_buffer();
- input_memory_size = AudioBus::CalculateMemorySize(input_channels_, frames);
- char* input_data =
- static_cast<char*>(shared_memory_->memory()) + output_memory_size;
- input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data);
- input_bus_->Zero();
- }
- DCHECK_EQ(packet_size_, output_memory_size + input_memory_size);
+ DCHECK_EQ(packet_size_, AudioBus::CalculateMemorySize(params));
output_bus_ = AudioBus::WrapMemory(params, shared_memory->memory());
output_bus_->Zero();
}
@@ -79,15 +66,6 @@ void AudioSyncReader::Read(const AudioBus* source, AudioBus* dest) {
return;
}
- // Copy optional synchronized live audio input for consumption by renderer
- // process.
- if (input_bus_) {
- if (source)
- source->CopyTo(input_bus_.get());
- else
- input_bus_->Zero();
- }
-
if (mute_audio_)
dest->Zero();
else
diff --git a/content/browser/renderer_host/media/audio_sync_reader.h b/content/browser/renderer_host/media/audio_sync_reader.h
index f3a2833..f7db13c 100644
--- a/content/browser/renderer_host/media/audio_sync_reader.h
+++ b/content/browser/renderer_host/media/audio_sync_reader.h
@@ -26,8 +26,7 @@ namespace content {
class AudioSyncReader : public media::AudioOutputController::SyncReader {
public:
AudioSyncReader(base::SharedMemory* shared_memory,
- const media::AudioParameters& params,
- int input_channels);
+ const media::AudioParameters& params);
virtual ~AudioSyncReader();
@@ -52,9 +51,6 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
const base::SharedMemory* const shared_memory_;
- // Number of input channels for synchronized I/O.
- const int input_channels_;
-
// Mutes all incoming samples. This is used to prevent audible sound
// during automated testing.
const bool mute_audio_;
@@ -69,9 +65,6 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
// Shared memory wrapper used for transferring audio data to Read() callers.
scoped_ptr<media::AudioBus> output_bus_;
- // Shared memory wrapper used for transferring audio data from Read() callers.
- scoped_ptr<media::AudioBus> input_bus_;
-
// Maximum amount of audio data which can be transferred in one Read() call.
const int packet_size_;
diff --git a/media/audio/alsa/alsa_output_unittest.cc b/media/audio/alsa/alsa_output_unittest.cc
index 07ce8ea..8b0aeae 100644
--- a/media/audio/alsa/alsa_output_unittest.cc
+++ b/media/audio/alsa/alsa_output_unittest.cc
@@ -75,10 +75,9 @@ class MockAudioManagerAlsa : public AudioManagerAlsa {
MOCK_METHOD0(HasAudioInputDevices, bool());
MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
const AudioParameters& params));
- MOCK_METHOD3(MakeLowLatencyOutputStream, AudioOutputStream*(
+ MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id));
+ const std::string& device_id));
MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc
index ac61a5f..7d6421f 100644
--- a/media/audio/alsa/audio_manager_alsa.cc
+++ b/media/audio/alsa/audio_manager_alsa.cc
@@ -283,11 +283,9 @@ AudioOutputStream* AudioManagerAlsa::MakeLinearOutputStream(
AudioOutputStream* AudioManagerAlsa::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
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/alsa/audio_manager_alsa.h b/media/audio/alsa/audio_manager_alsa.h
index 155089f..d08c3ba 100644
--- a/media/audio/alsa/audio_manager_alsa.h
+++ b/media/audio/alsa/audio_manager_alsa.h
@@ -37,8 +37,7 @@ class MEDIA_EXPORT AudioManagerAlsa : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc
index 91bf5d8..a8d66a6 100644
--- a/media/audio/android/audio_android_unittest.cc
+++ b/media/audio/android/audio_android_unittest.cc
@@ -438,7 +438,7 @@ class AudioAndroidOutputTest : public testing::Test {
const int num_callbacks =
(kCallbackTestTimeMs / expected_time_between_callbacks_ms);
AudioOutputStream* stream = audio_manager()->MakeAudioOutputStream(
- params, std::string(), std::string());
+ params, std::string());
EXPECT_TRUE(stream);
int count = 0;
@@ -621,7 +621,7 @@ TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) {
TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStream) {
AudioParameters params = GetDefaultOutputStreamParameters();
AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
- params, std::string(), std::string());
+ params, std::string());
EXPECT_TRUE(aos);
aos->Close();
}
@@ -640,7 +640,7 @@ TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) {
TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStream) {
AudioParameters params = GetDefaultOutputStreamParameters();
AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
- params, std::string(), std::string());
+ params, std::string());
EXPECT_TRUE(aos);
EXPECT_TRUE(aos->Open());
aos->Close();
@@ -701,7 +701,7 @@ TEST_F(AudioAndroidOutputTest, DISABLED_RunOutputStreamWithFileAsSource) {
AudioParameters params = GetDefaultOutputStreamParameters();
VLOG(1) << params;
AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
- params, std::string(), std::string());
+ params, std::string());
EXPECT_TRUE(aos);
std::string file_name;
@@ -770,7 +770,7 @@ TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) {
AudioParameters out_params =
audio_manager()->GetDefaultOutputStreamParameters();
AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
- out_params, std::string(), std::string());
+ out_params, std::string());
EXPECT_TRUE(aos);
std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm",
@@ -829,7 +829,7 @@ TEST_P(AudioAndroidInputTest,
io_params, AudioManagerBase::kDefaultDeviceId);
EXPECT_TRUE(ais);
AudioOutputStream* aos = audio_manager()->MakeAudioOutputStream(
- io_params, std::string(), std::string());
+ io_params, std::string());
EXPECT_TRUE(aos);
FullDuplexAudioSinkSource full_duplex(io_params);
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc
index 33e9e08..a8d81c7 100644
--- a/media/audio/android/audio_manager_android.cc
+++ b/media/audio/android/audio_manager_android.cc
@@ -122,12 +122,10 @@ AudioParameters AudioManagerAndroid::GetInputStreamParameters(
AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
bool had_no_streams = HadNoAudioStreams();
AudioOutputStream* stream =
- AudioManagerBase::MakeAudioOutputStream(params, std::string(),
- std::string());
+ AudioManagerBase::MakeAudioOutputStream(params, std::string());
// The audio manager for Android creates streams intended for real-time
// VoIP sessions and therefore sets the audio mode to MODE_IN_COMMUNICATION.
@@ -187,8 +185,7 @@ AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
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 670c094..ac67d08 100644
--- a/media/audio/android/audio_manager_android.h
+++ b/media/audio/android/audio_manager_android.h
@@ -33,8 +33,7 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
virtual AudioOutputStream* MakeAudioOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeAudioInputStream(
const AudioParameters& params,
const std::string& device_id) OVERRIDE;
@@ -46,8 +45,7 @@ class MEDIA_EXPORT AudioManagerAndroid : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params,
const std::string& device_id) OVERRIDE;
diff --git a/media/audio/audio_logging.h b/media/audio/audio_logging.h
index 1d8366b..913b8ec 100644
--- a/media/audio/audio_logging.h
+++ b/media/audio/audio_logging.h
@@ -20,13 +20,11 @@ class AudioLog {
virtual ~AudioLog() {}
// Called when an audio component is created. |params| are the parameters of
- // the created stream. |input_device_id| and |output_device_id| are the
- // respective device ids for input and output. Either one or both may be
- // specified.
+ // the created stream. |device_id| is the id of the audio device opened by
+ // the created stream.
virtual void OnCreated(int component_id,
const media::AudioParameters& params,
- const std::string& input_device_id,
- const std::string& output_device_id) = 0;
+ const std::string& device_id) = 0;
// Called when an audio component is started, generally this is synonymous
// with "playing."
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc
index 0fff86c..df94a3f 100644
--- a/media/audio/audio_low_latency_input_output_unittest.cc
+++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -312,8 +312,7 @@ class AudioOutputStreamTraits {
static StreamType* CreateStream(AudioManager* audio_manager,
const AudioParameters& params) {
- return audio_manager->MakeAudioOutputStream(params, std::string(),
- std::string());
+ return audio_manager->MakeAudioOutputStream(params, std::string());
}
};
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 04e89a6..a15dab5 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -88,11 +88,6 @@ class MEDIA_EXPORT AudioManager {
// To create a stream for the default output device, pass an empty string
// for |device_id|, otherwise the specified audio device will be opened.
//
- // The |input_device_id| is used for low-latency unified streams
- // (input+output) only and then only if the audio parameters specify a >0
- // input channel count. In other cases this id is ignored and should be
- // empty.
- //
// Returns NULL if the combination of the parameters is not supported, or if
// we have reached some other platform specific limit.
//
@@ -105,8 +100,7 @@ class MEDIA_EXPORT AudioManager {
// Do not free the returned AudioOutputStream. It is owned by AudioManager.
virtual AudioOutputStream* MakeAudioOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) = 0;
+ const std::string& device_id) = 0;
// Creates new audio output proxy. A proxy implements
// AudioOutputStream interface, but unlike regular output stream
@@ -114,8 +108,7 @@ class MEDIA_EXPORT AudioManager {
// sound is actually playing.
virtual AudioOutputStream* MakeAudioOutputStreamProxy(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) = 0;
+ const std::string& 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 f4cd60e..f9dcafe 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -37,17 +37,13 @@ const char AudioManagerBase::kLoopbackInputDeviceId[] = "loopback";
struct AudioManagerBase::DispatcherParams {
DispatcherParams(const AudioParameters& input,
const AudioParameters& output,
- const std::string& output_device_id,
- const std::string& input_device_id)
+ const std::string& output_device_id)
: input_params(input),
- output_params(output),
- input_device_id(input_device_id),
- output_device_id(output_device_id) {}
+ output_params(output) {}
~DispatcherParams() {}
const AudioParameters input_params;
const AudioParameters output_params;
- const std::string input_device_id;
const std::string output_device_id;
scoped_refptr<AudioOutputDispatcher> dispatcher;
@@ -63,13 +59,11 @@ class AudioManagerBase::CompareByParams {
// 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.
+ // 2) Unified IO is used, input_params and output_params 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_->output_device_id == dispatcher_in->output_device_id &&
- (!dispatcher_->input_params.input_channels() ||
- dispatcher_->input_device_id == dispatcher_in->input_device_id));
+ dispatcher_->output_device_id == dispatcher_in->output_device_id);
}
private:
@@ -139,8 +133,7 @@ AudioManagerBase::GetWorkerTaskRunner() {
AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& 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(task_runner_->BelongsToCurrentThread());
@@ -170,7 +163,7 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
stream = MakeLinearOutputStream(params);
break;
case AudioParameters::AUDIO_PCM_LOW_LATENCY:
- stream = MakeLowLatencyOutputStream(params, device_id, input_device_id);
+ stream = MakeLowLatencyOutputStream(params, device_id);
break;
case AudioParameters::AUDIO_FAKE:
stream = FakeAudioOutputStream::MakeFakeStream(this, params);
@@ -232,8 +225,7 @@ AudioInputStream* AudioManagerBase::MakeAudioInputStream(
AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
DCHECK(task_runner_->BelongsToCurrentThread());
// If the caller supplied an empty device id to select the default device,
@@ -273,8 +265,7 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
}
DispatcherParams* dispatcher_params =
- new DispatcherParams(params, output_params, output_device_id,
- input_device_id);
+ new DispatcherParams(params, output_params, output_device_id);
AudioOutputDispatchers::iterator it =
std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
@@ -289,12 +280,12 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
scoped_refptr<AudioOutputDispatcher> dispatcher;
if (output_params.format() != AudioParameters::AUDIO_FAKE) {
dispatcher = new AudioOutputResampler(this, params, output_params,
- output_device_id, input_device_id,
+ output_device_id,
kCloseDelay);
} else {
dispatcher = new AudioOutputDispatcherImpl(this, output_params,
output_device_id,
- input_device_id, kCloseDelay);
+ kCloseDelay);
}
dispatcher_params->dispatcher = dispatcher;
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index e1ec49b..4c088fb 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -64,16 +64,14 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
virtual AudioOutputStream* MakeAudioOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioOutputStream* MakeAudioOutputStreamProxy(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
// Called internally by the audio stream when it has been closed.
virtual void ReleaseOutputStream(AudioOutputStream* stream);
@@ -85,11 +83,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,
- const std::string& device_id,
- const std::string& input_device_id) = 0;
+ const std::string& device_id) = 0;
// Creates the input stream for the |AUDIO_PCM_LINEAR| format. The legacy
// name is also from |AUDIO_PCM_LINEAR|.
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 0d9b0e8..405a02f 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -36,13 +36,11 @@ AudioOutputController::AudioOutputController(
EventHandler* handler,
const AudioParameters& params,
const std::string& output_device_id,
- const std::string& input_device_id,
SyncReader* sync_reader)
: audio_manager_(audio_manager),
params_(params),
handler_(handler),
output_device_id_(output_device_id),
- input_device_id_(input_device_id),
stream_(NULL),
diverting_to_stream_(NULL),
volume_(1.0),
@@ -72,7 +70,6 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create(
EventHandler* event_handler,
const AudioParameters& params,
const std::string& output_device_id,
- const std::string& input_device_id,
SyncReader* sync_reader) {
DCHECK(audio_manager);
DCHECK(sync_reader);
@@ -81,8 +78,7 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create(
return NULL;
scoped_refptr<AudioOutputController> controller(new AudioOutputController(
- audio_manager, event_handler, params, output_device_id, input_device_id,
- sync_reader));
+ audio_manager, event_handler, params, output_device_id, sync_reader));
controller->message_loop_->PostTask(FROM_HERE, base::Bind(
&AudioOutputController::DoCreate, controller, false));
return controller;
@@ -141,8 +137,7 @@ void AudioOutputController::DoCreate(bool is_for_device_change) {
stream_ = diverting_to_stream_ ?
diverting_to_stream_ :
- audio_manager_->MakeAudioOutputStreamProxy(params_, output_device_id_,
- input_device_id_);
+ audio_manager_->MakeAudioOutputStreamProxy(params_, output_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 121b446..1a250f9 100644
--- a/media/audio/audio_output_controller.h
+++ b/media/audio/audio_output_controller.h
@@ -107,13 +107,11 @@ class MEDIA_EXPORT AudioOutputController
// OnCreated() call from the same audio manager thread. |audio_manager| must
// outlive AudioOutputController.
// The |output_device_id| can be either empty (default device) or specify a
- // specific hardware device for audio output. The |input_device_id| is
- // used only for unified audio when opening up input and output at the same
- // time (controlled by |params.input_channel_count()|).
+ // specific hardware device for audio output.
static scoped_refptr<AudioOutputController> Create(
AudioManager* audio_manager, EventHandler* event_handler,
const AudioParameters& params, const std::string& output_device_id,
- const std::string& input_device_id, SyncReader* sync_reader);
+ SyncReader* sync_reader);
// Methods to control playback of the stream.
@@ -193,7 +191,6 @@ class MEDIA_EXPORT AudioOutputController
AudioOutputController(AudioManager* audio_manager, EventHandler* handler,
const AudioParameters& params,
const std::string& output_device_id,
- const std::string& input_device_id,
SyncReader* sync_reader);
// The following methods are executed on the audio manager thread.
@@ -234,9 +231,6 @@ class MEDIA_EXPORT AudioOutputController
// default output device.
std::string output_device_id_;
- // Used by the unified IO to open the correct input device.
- const std::string input_device_id_;
-
AudioOutputStream* stream_;
// When non-NULL, audio is being diverted to this stream.
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index 288acd9..b4270e6 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -121,7 +121,7 @@ class AudioOutputControllerTest : public testing::Test {
controller_ = AudioOutputController::Create(
audio_manager_.get(), &mock_event_handler_, params_, std::string(),
- std::string(), &mock_sync_reader_);
+ &mock_sync_reader_);
if (controller_.get())
controller_->SetVolume(kTestVolume);
diff --git a/media/audio/audio_output_dispatcher.cc b/media/audio/audio_output_dispatcher.cc
index 1e78c9d..7f3dd10 100644
--- a/media/audio/audio_output_dispatcher.cc
+++ b/media/audio/audio_output_dispatcher.cc
@@ -11,13 +11,11 @@ namespace media {
AudioOutputDispatcher::AudioOutputDispatcher(
AudioManager* audio_manager,
const AudioParameters& params,
- const std::string& output_device_id,
- const std::string& input_device_id)
+ const std::string& device_id)
: audio_manager_(audio_manager),
task_runner_(audio_manager->GetTaskRunner()),
params_(params),
- output_device_id_(output_device_id),
- input_device_id_(input_device_id) {
+ device_id_(device_id) {
// We expect to be instantiated on the audio thread. Otherwise the
// |task_runner_| member will point to the wrong message loop!
DCHECK(audio_manager->GetTaskRunner()->BelongsToCurrentThread());
diff --git a/media/audio/audio_output_dispatcher.h b/media/audio/audio_output_dispatcher.h
index 69c5f16..d070b6b 100644
--- a/media/audio/audio_output_dispatcher.h
+++ b/media/audio/audio_output_dispatcher.h
@@ -38,8 +38,7 @@ class MEDIA_EXPORT AudioOutputDispatcher
public:
AudioOutputDispatcher(AudioManager* audio_manager,
const AudioParameters& params,
- const std::string& output_device_id,
- const std::string& input_device_id);
+ const std::string& device_id);
// Called by AudioOutputProxy to open the stream.
// Returns false, if it fails to open it.
@@ -73,8 +72,7 @@ class MEDIA_EXPORT AudioOutputDispatcher
virtual void CloseStreamsForWedgeFix() = 0;
virtual void RestartStreamsForWedgeFix() = 0;
- // Accessor to the input device id used by unified IO.
- const std::string& input_device_id() const { return input_device_id_; }
+ const std::string& device_id() const { return device_id_; }
protected:
friend class base::RefCountedThreadSafe<AudioOutputDispatcher>;
@@ -85,8 +83,7 @@ class MEDIA_EXPORT AudioOutputDispatcher
AudioManager* audio_manager_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
const AudioParameters params_;
- std::string output_device_id_;
- const std::string input_device_id_;
+ std::string 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 d2e1d1c..5db170e 100644
--- a/media/audio/audio_output_dispatcher_impl.cc
+++ b/media/audio/audio_output_dispatcher_impl.cc
@@ -19,12 +19,10 @@ AudioOutputDispatcherImpl::AudioOutputDispatcherImpl(
AudioManager* audio_manager,
const AudioParameters& params,
const std::string& output_device_id,
- const std::string& input_device_id,
const base::TimeDelta& close_delay)
: AudioOutputDispatcher(audio_manager,
params,
- output_device_id,
- input_device_id),
+ output_device_id),
idle_proxies_(0),
close_timer_(FROM_HERE,
close_delay,
@@ -131,7 +129,7 @@ void AudioOutputDispatcherImpl::Shutdown() {
bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
DCHECK(task_runner_->BelongsToCurrentThread());
AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(
- params_, output_device_id_, input_device_id_);
+ params_, device_id_);
if (!stream)
return false;
@@ -143,7 +141,7 @@ bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
const int stream_id = audio_stream_id_++;
audio_stream_ids_[stream] = stream_id;
audio_log_->OnCreated(
- stream_id, params_, input_device_id_, output_device_id_);
+ stream_id, params_, device_id_);
idle_streams_.push_back(stream);
return true;
diff --git a/media/audio/audio_output_dispatcher_impl.h b/media/audio/audio_output_dispatcher_impl.h
index 037e114..cb1ddb9 100644
--- a/media/audio/audio_output_dispatcher_impl.h
+++ b/media/audio/audio_output_dispatcher_impl.h
@@ -36,7 +36,6 @@ class MEDIA_EXPORT AudioOutputDispatcherImpl : public AudioOutputDispatcher {
AudioOutputDispatcherImpl(AudioManager* audio_manager,
const AudioParameters& params,
const std::string& output_device_id,
- 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_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc
index 1c37dc5..534a6d9 100644
--- a/media/audio/audio_output_proxy_unittest.cc
+++ b/media/audio/audio_output_proxy_unittest.cc
@@ -93,14 +93,12 @@ class MockAudioManager : public AudioManagerBase {
MOCK_METHOD0(HasAudioOutputDevices, bool());
MOCK_METHOD0(HasAudioInputDevices, bool());
MOCK_METHOD0(GetAudioInputDeviceModel, base::string16());
- MOCK_METHOD3(MakeAudioOutputStream, AudioOutputStream*(
+ MOCK_METHOD2(MakeAudioOutputStream, AudioOutputStream*(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id));
- MOCK_METHOD3(MakeAudioOutputStreamProxy, AudioOutputStream*(
+ const std::string& device_id));
+ MOCK_METHOD2(MakeAudioOutputStreamProxy, AudioOutputStream*(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id));
+ const std::string& device_id));
MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
MOCK_METHOD0(ShowAudioInputSettings, void());
@@ -112,9 +110,8 @@ class MockAudioManager : public AudioManagerBase {
MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
const AudioParameters& params));
- MOCK_METHOD3(MakeLowLatencyOutputStream, AudioOutputStream*(
- const AudioParameters& params, const std::string& device_id,
- const std::string& input_device_id));
+ MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
+ const AudioParameters& params, const std::string& device_id));
MOCK_METHOD2(MakeLinearInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
@@ -168,7 +165,6 @@ class AudioOutputProxyTest : public testing::Test {
dispatcher_impl_ = new AudioOutputDispatcherImpl(&manager(),
params_,
std::string(),
- std::string(),
close_delay);
}
@@ -199,7 +195,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));
@@ -213,7 +209,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));
@@ -236,7 +232,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 +257,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));
@@ -280,7 +276,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));
@@ -297,7 +293,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));
@@ -314,7 +310,7 @@ class AudioOutputProxyTest : public testing::Test {
void OneStream_TwoPlays(AudioOutputDispatcher* dispatcher) {
MockAudioOutputStream stream(&manager_, params_);
- EXPECT_CALL(manager(), MakeAudioOutputStream(_, _, _))
+ EXPECT_CALL(manager(), MakeAudioOutputStream(_, _))
.WillOnce(Return(&stream));
EXPECT_CALL(stream, Open())
@@ -346,7 +342,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));
@@ -383,7 +379,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));
@@ -394,7 +390,7 @@ class AudioOutputProxyTest : public testing::Test {
WaitForCloseTimer(&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)));
@@ -434,8 +430,7 @@ class AudioOutputResamplerTest : public AudioOutputProxyTest {
AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
16000, 16, 1024);
resampler_ = new AudioOutputResampler(
- &manager(), params_, resampler_params_, std::string(), std::string(),
- close_delay);
+ &manager(), params_, resampler_params_, std::string(), close_delay);
}
virtual void OnStart() OVERRIDE {
@@ -535,7 +530,7 @@ TEST_F(AudioOutputResamplerTest, StartFailed) { StartFailed(resampler_); }
// 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));
@@ -552,7 +547,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));
@@ -580,7 +575,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)));
@@ -591,7 +586,7 @@ TEST_F(AudioOutputResamplerTest, HighLatencyFallbackFailed) {
testing::Property(&AudioParameters::sample_rate, params_.sample_rate()),
testing::Property(
&AudioParameters::frames_per_buffer, params_.frames_per_buffer())),
- _, _))
+ _))
.Times(1)
.WillOnce(Return(&okay_stream));
EXPECT_CALL(okay_stream, Open())
@@ -613,7 +608,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)));
@@ -629,7 +624,7 @@ TEST_F(AudioOutputResamplerTest, LowLatencyOpenEventuallyFails) {
MockAudioOutputStream stream2(&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))
.WillRepeatedly(Return(static_cast<AudioOutputStream*>(NULL)));
@@ -685,7 +680,7 @@ TEST_F(AudioOutputResamplerTest, WedgeFix) {
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 e6fcc56..a5514c5 100644
--- a/media/audio/audio_output_resampler.cc
+++ b/media/audio/audio_output_resampler.cc
@@ -135,7 +135,7 @@ void AudioOutputResampler::SetupFallbackParams() {
AudioParameters::AUDIO_PCM_LINEAR, params_.channel_layout(),
params_.sample_rate(), params_.bits_per_sample(),
frames_per_buffer);
- output_device_id_ = "";
+ device_id_ = "";
Initialize();
#endif
}
@@ -144,10 +144,8 @@ AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager,
const AudioParameters& input_params,
const AudioParameters& output_params,
const std::string& output_device_id,
- const std::string& input_device_id,
const base::TimeDelta& close_delay)
- : AudioOutputDispatcher(audio_manager, input_params, output_device_id,
- input_device_id),
+ : AudioOutputDispatcher(audio_manager, input_params, output_device_id),
close_delay_(close_delay),
output_params_(output_params),
streams_opened_(false) {
@@ -169,8 +167,7 @@ void AudioOutputResampler::Initialize() {
DCHECK(!streams_opened_);
DCHECK(callbacks_.empty());
dispatcher_ = new AudioOutputDispatcherImpl(
- audio_manager_, output_params_, output_device_id_, input_device_id_,
- close_delay_);
+ audio_manager_, output_params_, device_id_, close_delay_);
}
bool AudioOutputResampler::OpenStream() {
diff --git a/media/audio/audio_output_resampler.h b/media/audio/audio_output_resampler.h
index a8fca23..80c9d77 100644
--- a/media/audio/audio_output_resampler.h
+++ b/media/audio/audio_output_resampler.h
@@ -41,7 +41,6 @@ class MEDIA_EXPORT AudioOutputResampler : public AudioOutputDispatcher {
const AudioParameters& input_params,
const AudioParameters& output_params,
const std::string& output_device_id,
- const std::string& input_device_id,
const base::TimeDelta& close_delay);
// AudioOutputDispatcher interface.
diff --git a/media/audio/cras/cras_unified_unittest.cc b/media/audio/cras/cras_unified_unittest.cc
index ee36b10..9d282bb 100644
--- a/media/audio/cras/cras_unified_unittest.cc
+++ b/media/audio/cras/cras_unified_unittest.cc
@@ -37,10 +37,9 @@ class MockAudioManagerCras : public AudioManagerCras {
MOCK_METHOD0(HasAudioInputDevices, bool());
MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
const AudioParameters& params));
- MOCK_METHOD3(MakeLowLatencyOutputStream,
+ MOCK_METHOD2(MakeLowLatencyOutputStream,
AudioOutputStream*(const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id));
+ const std::string& device_id));
MOCK_METHOD2(MakeLinearOutputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
diff --git a/media/audio/fake_audio_log_factory.cc b/media/audio/fake_audio_log_factory.cc
index 6f752e5..5e2d134 100644
--- a/media/audio/fake_audio_log_factory.cc
+++ b/media/audio/fake_audio_log_factory.cc
@@ -12,8 +12,7 @@ class FakeAudioLogImpl : public AudioLog {
virtual ~FakeAudioLogImpl() {}
virtual void OnCreated(int component_id,
const media::AudioParameters& params,
- const std::string& input_device_id,
- const std::string& output_device_id) OVERRIDE {}
+ const std::string& device_id) OVERRIDE {}
virtual void OnStarted(int component_id) OVERRIDE {}
virtual void OnStopped(int component_id) OVERRIDE {}
virtual void OnClosed(int component_id) OVERRIDE {}
diff --git a/media/audio/fake_audio_manager.cc b/media/audio/fake_audio_manager.cc
index bfe9a0a..e5d9bd4 100644
--- a/media/audio/fake_audio_manager.cc
+++ b/media/audio/fake_audio_manager.cc
@@ -33,8 +33,7 @@ AudioOutputStream* FakeAudioManager::MakeLinearOutputStream(
AudioOutputStream* FakeAudioManager::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
return FakeAudioOutputStream::MakeFakeStream(this, params);
}
diff --git a/media/audio/fake_audio_manager.h b/media/audio/fake_audio_manager.h
index b5c4520..9fbf140 100644
--- a/media/audio/fake_audio_manager.h
+++ b/media/audio/fake_audio_manager.h
@@ -26,8 +26,7 @@ class MEDIA_EXPORT FakeAudioManager : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(const AudioParameters& params,
const std::string& device_id)
OVERRIDE;
diff --git a/media/audio/mac/aggregate_device_manager.cc b/media/audio/mac/aggregate_device_manager.cc
deleted file mode 100644
index c7f3233..0000000
--- a/media/audio/mac/aggregate_device_manager.cc
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/mac/aggregate_device_manager.h"
-
-#include <CoreAudio/AudioHardware.h>
-#include <string>
-
-#include "base/mac/mac_logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "media/audio/audio_parameters.h"
-#include "media/audio/mac/audio_manager_mac.h"
-
-using base::ScopedCFTypeRef;
-
-namespace media {
-
-AggregateDeviceManager::AggregateDeviceManager()
- : plugin_id_(kAudioObjectUnknown),
- input_device_(kAudioDeviceUnknown),
- output_device_(kAudioDeviceUnknown),
- aggregate_device_(kAudioObjectUnknown) {
-}
-
-AggregateDeviceManager::~AggregateDeviceManager() {
- DestroyAggregateDevice();
-}
-
-AudioDeviceID AggregateDeviceManager::GetDefaultAggregateDevice() {
- AudioDeviceID current_input_device;
- AudioDeviceID current_output_device;
- AudioManagerMac::GetDefaultInputDevice(&current_input_device);
- AudioManagerMac::GetDefaultOutputDevice(&current_output_device);
-
- if (AudioManagerMac::HardwareSampleRateForDevice(current_input_device) !=
- AudioManagerMac::HardwareSampleRateForDevice(current_output_device)) {
- // TODO(crogers): with some extra work we can make aggregate devices work
- // if the clock domain is the same but the sample-rate differ.
- // For now we fallback to the synchronized path.
- return kAudioDeviceUnknown;
- }
-
- // Use a lazily created aggregate device if it's already available
- // and still appropriate.
- if (aggregate_device_ != kAudioObjectUnknown) {
- // TODO(crogers): handle default device changes for synchronized I/O.
- // For now, we check to make sure the default devices haven't changed
- // since we lazily created the aggregate device.
- if (current_input_device == input_device_ &&
- current_output_device == output_device_)
- return aggregate_device_;
-
- // For now, once lazily created don't attempt to create another
- // aggregate device.
- return kAudioDeviceUnknown;
- }
-
- input_device_ = current_input_device;
- output_device_ = current_output_device;
-
- // Only create an aggregrate device if the clock domains match.
- UInt32 input_clockdomain = GetClockDomain(input_device_);
- UInt32 output_clockdomain = GetClockDomain(output_device_);
- DVLOG(1) << "input_clockdomain: " << input_clockdomain;
- DVLOG(1) << "output_clockdomain: " << output_clockdomain;
-
- if (input_clockdomain == 0 || input_clockdomain != output_clockdomain)
- return kAudioDeviceUnknown;
-
- OSStatus result = CreateAggregateDevice(
- input_device_,
- output_device_,
- &aggregate_device_);
- if (result != noErr)
- DestroyAggregateDevice();
-
- return aggregate_device_;
-}
-
-CFStringRef AggregateDeviceManager::GetDeviceUID(AudioDeviceID id) {
- static const AudioObjectPropertyAddress kDeviceUIDAddress = {
- kAudioDevicePropertyDeviceUID,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- // As stated in the CoreAudio header (AudioHardwareBase.h),
- // the caller is responsible for releasing the device_UID.
- CFStringRef device_UID;
- UInt32 size = sizeof(device_UID);
- OSStatus result = AudioObjectGetPropertyData(
- id,
- &kDeviceUIDAddress,
- 0,
- 0,
- &size,
- &device_UID);
-
- return (result == noErr) ? device_UID : NULL;
-}
-
-void AggregateDeviceManager::GetDeviceName(
- AudioDeviceID id, char* name, UInt32 size) {
- static const AudioObjectPropertyAddress kDeviceNameAddress = {
- kAudioDevicePropertyDeviceName,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- OSStatus result = AudioObjectGetPropertyData(
- id,
- &kDeviceNameAddress,
- 0,
- 0,
- &size,
- name);
-
- if (result != noErr && size > 0)
- name[0] = 0;
-}
-
-UInt32 AggregateDeviceManager::GetClockDomain(AudioDeviceID device_id) {
- static const AudioObjectPropertyAddress kClockDomainAddress = {
- kAudioDevicePropertyClockDomain,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- UInt32 clockdomain = 0;
- UInt32 size = sizeof(UInt32);
- OSStatus result = AudioObjectGetPropertyData(
- device_id,
- &kClockDomainAddress,
- 0,
- 0,
- &size,
- &clockdomain);
-
- return (result == noErr) ? clockdomain : 0;
-}
-
-OSStatus AggregateDeviceManager::GetPluginID(AudioObjectID* id) {
- DCHECK(id);
-
- // Get the audio hardware plugin.
- CFStringRef bundle_name = CFSTR("com.apple.audio.CoreAudio");
-
- AudioValueTranslation plugin_translation;
- plugin_translation.mInputData = &bundle_name;
- plugin_translation.mInputDataSize = sizeof(bundle_name);
- plugin_translation.mOutputData = id;
- plugin_translation.mOutputDataSize = sizeof(*id);
-
- static const AudioObjectPropertyAddress kPlugInAddress = {
- kAudioHardwarePropertyPlugInForBundleID,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- UInt32 size = sizeof(plugin_translation);
- OSStatus result = AudioObjectGetPropertyData(
- kAudioObjectSystemObject,
- &kPlugInAddress,
- 0,
- 0,
- &size,
- &plugin_translation);
-
- DVLOG(1) << "CoreAudio plugin ID: " << *id;
-
- return result;
-}
-
-CFMutableDictionaryRef
-AggregateDeviceManager::CreateAggregateDeviceDictionary(
- AudioDeviceID input_id,
- AudioDeviceID output_id) {
- CFMutableDictionaryRef aggregate_device_dict = CFDictionaryCreateMutable(
- NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- if (!aggregate_device_dict)
- return NULL;
-
- const CFStringRef kAggregateDeviceName =
- CFSTR("ChromeAggregateAudioDevice");
- const CFStringRef kAggregateDeviceUID =
- CFSTR("com.google.chrome.AggregateAudioDevice");
-
- // Add name and UID of the device to the dictionary.
- CFDictionaryAddValue(
- aggregate_device_dict,
- CFSTR(kAudioAggregateDeviceNameKey),
- kAggregateDeviceName);
- CFDictionaryAddValue(
- aggregate_device_dict,
- CFSTR(kAudioAggregateDeviceUIDKey),
- kAggregateDeviceUID);
-
- // Add a "private aggregate key" to the dictionary.
- // The 1 value means that the created aggregate device will
- // only be accessible from the process that created it, and
- // won't be visible to outside processes.
- int value = 1;
- ScopedCFTypeRef<CFNumberRef> aggregate_device_number(CFNumberCreate(
- NULL,
- kCFNumberIntType,
- &value));
- CFDictionaryAddValue(
- aggregate_device_dict,
- CFSTR(kAudioAggregateDeviceIsPrivateKey),
- aggregate_device_number);
-
- return aggregate_device_dict;
-}
-
-CFMutableArrayRef
-AggregateDeviceManager::CreateSubDeviceArray(
- CFStringRef input_device_UID, CFStringRef output_device_UID) {
- CFMutableArrayRef sub_devices_array = CFArrayCreateMutable(
- NULL,
- 0,
- &kCFTypeArrayCallBacks);
-
- CFArrayAppendValue(sub_devices_array, input_device_UID);
- CFArrayAppendValue(sub_devices_array, output_device_UID);
-
- return sub_devices_array;
-}
-
-OSStatus AggregateDeviceManager::CreateAggregateDevice(
- AudioDeviceID input_id,
- AudioDeviceID output_id,
- AudioDeviceID* aggregate_device) {
- DCHECK(aggregate_device);
-
- const size_t kMaxDeviceNameLength = 256;
-
- scoped_ptr<char[]> input_device_name(new char[kMaxDeviceNameLength]);
- GetDeviceName(
- input_id,
- input_device_name.get(),
- sizeof(input_device_name));
- DVLOG(1) << "Input device: \n" << input_device_name;
-
- scoped_ptr<char[]> output_device_name(new char[kMaxDeviceNameLength]);
- GetDeviceName(
- output_id,
- output_device_name.get(),
- sizeof(output_device_name));
- DVLOG(1) << "Output device: \n" << output_device_name;
-
- OSStatus result = GetPluginID(&plugin_id_);
- if (result != noErr)
- return result;
-
- // Create a dictionary for the aggregate device.
- ScopedCFTypeRef<CFMutableDictionaryRef> aggregate_device_dict(
- CreateAggregateDeviceDictionary(input_id, output_id));
- if (!aggregate_device_dict)
- return -1;
-
- // Create the aggregate device.
- static const AudioObjectPropertyAddress kCreateAggregateDeviceAddress = {
- kAudioPlugInCreateAggregateDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- UInt32 size = sizeof(*aggregate_device);
- result = AudioObjectGetPropertyData(
- plugin_id_,
- &kCreateAggregateDeviceAddress,
- sizeof(aggregate_device_dict),
- &aggregate_device_dict,
- &size,
- aggregate_device);
- if (result != noErr) {
- DLOG(ERROR) << "Error creating aggregate audio device!";
- return result;
- }
-
- // Set the sub-devices for the aggregate device.
- // In this case we use two: the input and output devices.
-
- ScopedCFTypeRef<CFStringRef> input_device_UID(GetDeviceUID(input_id));
- ScopedCFTypeRef<CFStringRef> output_device_UID(GetDeviceUID(output_id));
- if (!input_device_UID || !output_device_UID) {
- DLOG(ERROR) << "Error getting audio device UID strings.";
- return -1;
- }
-
- ScopedCFTypeRef<CFMutableArrayRef> sub_devices_array(
- CreateSubDeviceArray(input_device_UID, output_device_UID));
- if (sub_devices_array == NULL) {
- DLOG(ERROR) << "Error creating sub-devices array.";
- return -1;
- }
-
- static const AudioObjectPropertyAddress kSetSubDevicesAddress = {
- kAudioAggregateDevicePropertyFullSubDeviceList,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- size = sizeof(CFMutableArrayRef);
- result = AudioObjectSetPropertyData(
- *aggregate_device,
- &kSetSubDevicesAddress,
- 0,
- NULL,
- size,
- &sub_devices_array);
- if (result != noErr) {
- DLOG(ERROR) << "Error setting aggregate audio device sub-devices!";
- return result;
- }
-
- // Use the input device as the master device.
- static const AudioObjectPropertyAddress kSetMasterDeviceAddress = {
- kAudioAggregateDevicePropertyMasterSubDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- size = sizeof(CFStringRef);
- result = AudioObjectSetPropertyData(
- *aggregate_device,
- &kSetMasterDeviceAddress,
- 0,
- NULL,
- size,
- &input_device_UID);
- if (result != noErr) {
- DLOG(ERROR) << "Error setting aggregate audio device master device!";
- return result;
- }
-
- DVLOG(1) << "New aggregate device: " << *aggregate_device;
- return noErr;
-}
-
-void AggregateDeviceManager::DestroyAggregateDevice() {
- if (aggregate_device_ == kAudioObjectUnknown)
- return;
-
- static const AudioObjectPropertyAddress kDestroyAddress = {
- kAudioPlugInDestroyAggregateDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- UInt32 size = sizeof(aggregate_device_);
- OSStatus result = AudioObjectGetPropertyData(
- plugin_id_,
- &kDestroyAddress,
- 0,
- NULL,
- &size,
- &aggregate_device_);
- if (result != noErr) {
- DLOG(ERROR) << "Error destroying aggregate audio device!";
- return;
- }
-
- aggregate_device_ = kAudioObjectUnknown;
-}
-
-} // namespace media
diff --git a/media/audio/mac/aggregate_device_manager.h b/media/audio/mac/aggregate_device_manager.h
deleted file mode 100644
index 7b8b71f..0000000
--- a/media/audio/mac/aggregate_device_manager.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_MAC_AGGREGATE_DEVICE_MANAGER_H_
-#define MEDIA_AUDIO_MAC_AGGREGATE_DEVICE_MANAGER_H_
-
-#include <CoreAudio/CoreAudio.h>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "media/base/media_export.h"
-
-namespace media {
-
-class MEDIA_EXPORT AggregateDeviceManager {
- public:
- AggregateDeviceManager();
- ~AggregateDeviceManager();
-
- // Lazily creates an aggregate device based on the default
- // input and output devices.
- // It will either return a valid device or kAudioDeviceUnknown
- // if the default devices are not suitable for aggregate devices.
- AudioDeviceID GetDefaultAggregateDevice();
-
- private:
- // The caller is responsible for releasing the CFStringRef.
- static CFStringRef GetDeviceUID(AudioDeviceID id);
-
- static void GetDeviceName(AudioDeviceID id, char* name, UInt32 size);
- static UInt32 GetClockDomain(AudioDeviceID device_id);
- static OSStatus GetPluginID(AudioObjectID* id);
-
- CFMutableDictionaryRef CreateAggregateDeviceDictionary(
- AudioDeviceID input_id,
- AudioDeviceID output_id);
-
- CFMutableArrayRef CreateSubDeviceArray(CFStringRef input_device_UID,
- CFStringRef output_device_UID);
-
- OSStatus CreateAggregateDevice(AudioDeviceID input_id,
- AudioDeviceID output_id,
- AudioDeviceID* aggregate_device);
- void DestroyAggregateDevice();
-
- AudioObjectID plugin_id_;
- AudioDeviceID input_device_;
- AudioDeviceID output_device_;
-
- AudioDeviceID aggregate_device_;
-
- DISALLOW_COPY_AND_ASSIGN(AggregateDeviceManager);
-};
-
-} // namespace media
-
-#endif // MEDIA_AUDIO_MAC_AGGREGATE_DEVICE_MANAGER_H_
diff --git a/media/audio/mac/audio_auhal_mac_unittest.cc b/media/audio/mac/audio_auhal_mac_unittest.cc
index 9babd80..fd0ffff 100644
--- a/media/audio/mac/audio_auhal_mac_unittest.cc
+++ b/media/audio/mac/audio_auhal_mac_unittest.cc
@@ -45,7 +45,7 @@ class AUHALStreamTest : public testing::Test {
AudioOutputStream* Create() {
return manager_->MakeAudioOutputStream(
- manager_->GetDefaultOutputStreamParameters(), "", "");
+ manager_->GetDefaultOutputStreamParameters(), "");
}
bool CanRunAudioTests() {
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index c08efff..e86e7b48 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -20,8 +20,6 @@
#include "media/audio/mac/audio_input_mac.h"
#include "media/audio/mac/audio_low_latency_input_mac.h"
#include "media/audio/mac/audio_low_latency_output_mac.h"
-#include "media/audio/mac/audio_synchronized_mac.h"
-#include "media/audio/mac/audio_unified_mac.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/channel_layout.h"
#include "media/base/limits.h"
@@ -56,16 +54,6 @@ static bool HasAudioHardware(AudioObjectPropertySelector selector) {
output_device_id != kAudioObjectUnknown;
}
-// Returns true if the default input device is the same as
-// the default output device.
-bool AudioManagerMac::HasUnifiedDefaultIO() {
- AudioDeviceID input_id, output_id;
- if (!GetDefaultInputDevice(&input_id) || !GetDefaultOutputDevice(&output_id))
- return false;
-
- return input_id == output_id;
-}
-
// Retrieves information on audio devices, and prepends the default
// device to the list if the list is non-empty.
static void GetAudioDeviceInfo(bool is_input,
@@ -566,72 +554,18 @@ std::string AudioManagerMac::GetAssociatedOutputDeviceID(
AudioOutputStream* AudioManagerMac::MakeLinearOutputStream(
const AudioParameters& params) {
- return MakeLowLatencyOutputStream(params, std::string(), std::string());
+ return MakeLowLatencyOutputStream(params, std::string());
}
AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
- // Handle basic output with no input channels.
- if (params.input_channels() == 0) {
- AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id);
- if (device == kAudioObjectUnknown) {
- DLOG(ERROR) << "Failed to open output device: " << device_id;
- return NULL;
- }
- return new AUHALStream(this, params, device);
- }
-
- DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
-
- // TODO(xians): support more than stereo input.
- if (params.input_channels() != 2) {
- // WebAudio is currently hard-coded to 2 channels so we should not
- // see this case.
- NOTREACHED() << "Only stereo input is currently supported!";
+ const std::string& device_id) {
+ AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id);
+ if (device == kAudioObjectUnknown) {
+ DLOG(ERROR) << "Failed to open output device: " << device_id;
return NULL;
}
-
- AudioDeviceID device = kAudioObjectUnknown;
- if (HasUnifiedDefaultIO()) {
- // For I/O, the simplest case is when the default input and output
- // devices are the same.
- GetDefaultOutputDevice(&device);
- VLOG(0) << "UNIFIED: default input and output devices are identical";
- } else {
- // Some audio hardware is presented as separate input and output devices
- // even though they are really the same physical hardware and
- // share the same "clock domain" at the lowest levels of the driver.
- // A common of example of this is the "built-in" audio hardware:
- // "Built-in Line Input"
- // "Built-in Output"
- // We would like to use an "aggregate" device for these situations, since
- // CoreAudio will make the most efficient use of the shared "clock domain"
- // so we get the lowest latency and use fewer threads.
- device = aggregate_device_manager_.GetDefaultAggregateDevice();
- if (device != kAudioObjectUnknown)
- VLOG(0) << "Using AGGREGATE audio device";
- }
-
- if (device != kAudioObjectUnknown &&
- input_device_id == AudioManagerBase::kDefaultDeviceId)
- return new AUHALStream(this, params, device);
-
- // Fallback to AudioSynchronizedStream which will handle completely
- // different and arbitrary combinations of input and output devices
- // even running at different sample-rates.
- // kAudioDeviceUnknown translates to "use default" here.
- // TODO(xians): 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,
- audio_device_id,
- kAudioDeviceUnknown);
+ return new AUHALStream(this, params, device);
}
std::string AudioManagerMac::GetDefaultOutputDeviceID() {
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index 641f9d3..0d4e05f 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -11,7 +11,6 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "media/audio/audio_manager_base.h"
-#include "media/audio/mac/aggregate_device_manager.h"
#include "media/audio/mac/audio_device_listener_mac.h"
namespace media {
@@ -40,8 +39,7 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
@@ -80,8 +78,6 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
const AudioParameters& input_params) OVERRIDE;
private:
- bool HasUnifiedDefaultIO();
-
// Helper methods for constructing AudioDeviceListenerMac on the audio thread.
void CreateDeviceListener();
void DestroyDeviceListener();
@@ -99,8 +95,6 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
int current_sample_rate_;
AudioDeviceID current_output_device_;
- AggregateDeviceManager aggregate_device_manager_;
-
// Helper class which monitors power events to determine if output streams
// should defer Start() calls. Required to workaround an OSX bug. See
// http://crbug.com/160920 for more details.
diff --git a/media/audio/mac/audio_synchronized_mac.cc b/media/audio/mac/audio_synchronized_mac.cc
deleted file mode 100644
index a9bc88e..0000000
--- a/media/audio/mac/audio_synchronized_mac.cc
+++ /dev/null
@@ -1,976 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/mac/audio_synchronized_mac.h"
-
-#include <CoreServices/CoreServices.h>
-#include <algorithm>
-
-#include "base/basictypes.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "base/mac/mac_logging.h"
-#include "media/audio/mac/audio_manager_mac.h"
-#include "media/base/channel_mixer.h"
-
-namespace media {
-
-static const int kHardwareBufferSize = 128;
-static const int kFifoSize = 16384;
-
-// TODO(crogers): handle the non-stereo case.
-static const int kChannels = 2;
-
-// This value was determined empirically for minimum latency while still
-// guarding against FIFO under-runs.
-static const int kBaseTargetFifoFrames = 256 + 64;
-
-// If the input and output sample-rate don't match, then we need to maintain
-// an additional safety margin due to the callback timing jitter and the
-// varispeed buffering. This value was empirically tuned.
-static const int kAdditionalTargetFifoFrames = 128;
-
-static void ZeroBufferList(AudioBufferList* buffer_list) {
- for (size_t i = 0; i < buffer_list->mNumberBuffers; ++i)
- memset(buffer_list->mBuffers[i].mData,
- 0,
- buffer_list->mBuffers[i].mDataByteSize);
-}
-
-static void WrapBufferList(AudioBufferList* buffer_list,
- AudioBus* bus,
- int frames) {
- DCHECK(buffer_list);
- DCHECK(bus);
- int channels = bus->channels();
- int buffer_list_channels = buffer_list->mNumberBuffers;
-
- // Copy pointers from AudioBufferList.
- int source_idx = 0;
- for (int i = 0; i < channels; ++i) {
- bus->SetChannelData(
- i, static_cast<float*>(buffer_list->mBuffers[source_idx].mData));
-
- // It's ok to pass in a |buffer_list| with fewer channels, in which
- // case we just duplicate the last channel.
- if (source_idx < buffer_list_channels - 1)
- ++source_idx;
- }
-
- // Finally set the actual length.
- bus->set_frames(frames);
-}
-
-AudioSynchronizedStream::AudioSynchronizedStream(
- AudioManagerMac* manager,
- const AudioParameters& params,
- AudioDeviceID input_id,
- AudioDeviceID output_id)
- : manager_(manager),
- params_(params),
- input_sample_rate_(0),
- output_sample_rate_(0),
- input_id_(input_id),
- output_id_(output_id),
- input_buffer_list_(NULL),
- fifo_(kChannels, kFifoSize),
- target_fifo_frames_(kBaseTargetFifoFrames),
- average_delta_(0.0),
- fifo_rate_compensation_(1.0),
- input_unit_(0),
- varispeed_unit_(0),
- output_unit_(0),
- first_input_time_(-1),
- is_running_(false),
- hardware_buffer_size_(kHardwareBufferSize),
- channels_(kChannels) {
- VLOG(1) << "AudioSynchronizedStream::AudioSynchronizedStream()";
-}
-
-AudioSynchronizedStream::~AudioSynchronizedStream() {
- DCHECK(!input_unit_);
- DCHECK(!output_unit_);
- DCHECK(!varispeed_unit_);
-}
-
-bool AudioSynchronizedStream::Open() {
- if (params_.channels() != kChannels) {
- LOG(ERROR) << "Only stereo output is currently supported.";
- return false;
- }
-
- // Create the input, output, and varispeed AudioUnits.
- OSStatus result = CreateAudioUnits();
- if (result != noErr) {
- LOG(ERROR) << "Cannot create AudioUnits.";
- return false;
- }
-
- result = SetupInput(input_id_);
- if (result != noErr) {
- LOG(ERROR) << "Error configuring input AudioUnit.";
- return false;
- }
-
- result = SetupOutput(output_id_);
- if (result != noErr) {
- LOG(ERROR) << "Error configuring output AudioUnit.";
- return false;
- }
-
- result = SetupCallbacks();
- if (result != noErr) {
- LOG(ERROR) << "Error setting up callbacks on AudioUnits.";
- return false;
- }
-
- result = SetupStreamFormats();
- if (result != noErr) {
- LOG(ERROR) << "Error configuring stream formats on AudioUnits.";
- return false;
- }
-
- AllocateInputData();
-
- // Final initialization of the AudioUnits.
- result = AudioUnitInitialize(input_unit_);
- if (result != noErr) {
- LOG(ERROR) << "Error initializing input AudioUnit.";
- return false;
- }
-
- result = AudioUnitInitialize(output_unit_);
- if (result != noErr) {
- LOG(ERROR) << "Error initializing output AudioUnit.";
- return false;
- }
-
- result = AudioUnitInitialize(varispeed_unit_);
- if (result != noErr) {
- LOG(ERROR) << "Error initializing varispeed AudioUnit.";
- return false;
- }
-
- if (input_sample_rate_ != output_sample_rate_) {
- // Add extra safety margin.
- target_fifo_frames_ += kAdditionalTargetFifoFrames;
- }
-
- // Buffer initial silence corresponding to target I/O buffering.
- fifo_.Clear();
- scoped_ptr<AudioBus> silence =
- AudioBus::Create(channels_, target_fifo_frames_);
- silence->Zero();
- fifo_.Push(silence.get());
-
- return true;
-}
-
-void AudioSynchronizedStream::Close() {
- DCHECK(!is_running_);
-
- if (input_buffer_list_) {
- free(input_buffer_list_);
- input_buffer_list_ = 0;
- input_bus_.reset(NULL);
- wrapper_bus_.reset(NULL);
- }
-
- if (input_unit_) {
- AudioUnitUninitialize(input_unit_);
- CloseComponent(input_unit_);
- }
-
- if (output_unit_) {
- AudioUnitUninitialize(output_unit_);
- CloseComponent(output_unit_);
- }
-
- if (varispeed_unit_) {
- AudioUnitUninitialize(varispeed_unit_);
- CloseComponent(varispeed_unit_);
- }
-
- input_unit_ = NULL;
- output_unit_ = NULL;
- varispeed_unit_ = NULL;
-
- // Inform the audio manager that we have been closed. This can cause our
- // destruction.
- manager_->ReleaseOutputStream(this);
-}
-
-void AudioSynchronizedStream::Start(AudioSourceCallback* callback) {
- DCHECK(callback);
- DCHECK(input_unit_);
- DCHECK(output_unit_);
- DCHECK(varispeed_unit_);
-
- if (is_running_ || !input_unit_ || !output_unit_ || !varispeed_unit_)
- return;
-
- source_ = callback;
-
- // Reset state variables each time we Start().
- fifo_rate_compensation_ = 1.0;
- average_delta_ = 0.0;
-
- OSStatus result = noErr;
-
- if (!is_running_) {
- first_input_time_ = -1;
-
- result = AudioOutputUnitStart(input_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr) {
- result = AudioOutputUnitStart(output_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
- }
- }
-
- is_running_ = true;
-}
-
-void AudioSynchronizedStream::Stop() {
- OSStatus result = noErr;
- if (is_running_) {
- result = AudioOutputUnitStop(input_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr) {
- result = AudioOutputUnitStop(output_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
- }
- }
-
- if (result == noErr)
- is_running_ = false;
-}
-
-bool AudioSynchronizedStream::IsRunning() {
- return is_running_;
-}
-
-// TODO(crogers): implement - or remove from AudioOutputStream.
-void AudioSynchronizedStream::SetVolume(double volume) {}
-void AudioSynchronizedStream::GetVolume(double* volume) {}
-
-OSStatus AudioSynchronizedStream::SetOutputDeviceAsCurrent(
- AudioDeviceID output_id) {
- OSStatus result = noErr;
-
- // Get the default output device if device is unknown.
- if (output_id == kAudioDeviceUnknown) {
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
- pa.mScope = kAudioObjectPropertyScopeGlobal;
- pa.mElement = kAudioObjectPropertyElementMaster;
- UInt32 size = sizeof(output_id);
-
- result = AudioObjectGetPropertyData(
- kAudioObjectSystemObject,
- &pa,
- 0,
- 0,
- &size,
- &output_id);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
- }
-
- // Set the render frame size.
- UInt32 frame_size = hardware_buffer_size_;
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioDevicePropertyBufferFrameSize;
- pa.mScope = kAudioDevicePropertyScopeInput;
- pa.mElement = kAudioObjectPropertyElementMaster;
- result = AudioObjectSetPropertyData(
- output_id,
- &pa,
- 0,
- 0,
- sizeof(frame_size),
- &frame_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- output_info_.Initialize(output_id, false);
-
- // Set the Current Device to the Default Output Unit.
- result = AudioUnitSetProperty(
- output_unit_,
- kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global,
- 0,
- &output_info_.id_,
- sizeof(output_info_.id_));
-
- OSSTATUS_DCHECK(result == noErr, result);
- return result;
-}
-
-OSStatus AudioSynchronizedStream::SetInputDeviceAsCurrent(
- AudioDeviceID input_id) {
- OSStatus result = noErr;
-
- // Get the default input device if device is unknown.
- if (input_id == kAudioDeviceUnknown) {
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioHardwarePropertyDefaultInputDevice;
- pa.mScope = kAudioObjectPropertyScopeGlobal;
- pa.mElement = kAudioObjectPropertyElementMaster;
- UInt32 size = sizeof(input_id);
-
- result = AudioObjectGetPropertyData(
- kAudioObjectSystemObject,
- &pa,
- 0,
- 0,
- &size,
- &input_id);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
- }
-
- // Set the render frame size.
- UInt32 frame_size = hardware_buffer_size_;
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioDevicePropertyBufferFrameSize;
- pa.mScope = kAudioDevicePropertyScopeInput;
- pa.mElement = kAudioObjectPropertyElementMaster;
- result = AudioObjectSetPropertyData(
- input_id,
- &pa,
- 0,
- 0,
- sizeof(frame_size),
- &frame_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- input_info_.Initialize(input_id, true);
-
- // Set the Current Device to the AUHAL.
- // This should be done only after I/O has been enabled on the AUHAL.
- result = AudioUnitSetProperty(
- input_unit_,
- kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global,
- 0,
- &input_info_.id_,
- sizeof(input_info_.id_));
-
- OSSTATUS_DCHECK(result == noErr, result);
- return result;
-}
-
-OSStatus AudioSynchronizedStream::CreateAudioUnits() {
- // Q: Why do we need a varispeed unit?
- // A: If the input device and the output device are running at
- // different sample rates and/or on different clocks, we will need
- // to compensate to avoid a pitch change and
- // to avoid buffer under and over runs.
- ComponentDescription varispeed_desc;
- varispeed_desc.componentType = kAudioUnitType_FormatConverter;
- varispeed_desc.componentSubType = kAudioUnitSubType_Varispeed;
- varispeed_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- varispeed_desc.componentFlags = 0;
- varispeed_desc.componentFlagsMask = 0;
-
- Component varispeed_comp = FindNextComponent(NULL, &varispeed_desc);
- if (varispeed_comp == NULL)
- return -1;
-
- OSStatus result = OpenAComponent(varispeed_comp, &varispeed_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Open input AudioUnit.
- ComponentDescription input_desc;
- input_desc.componentType = kAudioUnitType_Output;
- input_desc.componentSubType = kAudioUnitSubType_HALOutput;
- input_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- input_desc.componentFlags = 0;
- input_desc.componentFlagsMask = 0;
-
- Component input_comp = FindNextComponent(NULL, &input_desc);
- if (input_comp == NULL)
- return -1;
-
- result = OpenAComponent(input_comp, &input_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Open output AudioUnit.
- ComponentDescription output_desc;
- output_desc.componentType = kAudioUnitType_Output;
- output_desc.componentSubType = kAudioUnitSubType_DefaultOutput;
- output_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- output_desc.componentFlags = 0;
- output_desc.componentFlagsMask = 0;
-
- Component output_comp = FindNextComponent(NULL, &output_desc);
- if (output_comp == NULL)
- return -1;
-
- result = OpenAComponent(output_comp, &output_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- return noErr;
-}
-
-OSStatus AudioSynchronizedStream::SetupInput(AudioDeviceID input_id) {
- // The AUHAL used for input needs to be initialized
- // before anything is done to it.
- OSStatus result = AudioUnitInitialize(input_unit_);
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // We must enable the Audio Unit (AUHAL) for input and disable output
- // BEFORE setting the AUHAL's current device.
- result = EnableIO();
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- result = SetInputDeviceAsCurrent(input_id);
- OSSTATUS_DCHECK(result == noErr, result);
-
- return result;
-}
-
-OSStatus AudioSynchronizedStream::EnableIO() {
- // Enable input on the AUHAL.
- UInt32 enable_io = 1;
- OSStatus result = AudioUnitSetProperty(
- input_unit_,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Input,
- 1, // input element
- &enable_io,
- sizeof(enable_io));
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Disable Output on the AUHAL.
- enable_io = 0;
- result = AudioUnitSetProperty(
- input_unit_,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Output,
- 0, // output element
- &enable_io,
- sizeof(enable_io));
-
- OSSTATUS_DCHECK(result == noErr, result);
- return result;
-}
-
-OSStatus AudioSynchronizedStream::SetupOutput(AudioDeviceID output_id) {
- OSStatus result = noErr;
-
- result = SetOutputDeviceAsCurrent(output_id);
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Tell the output unit not to reset timestamps.
- // Otherwise sample rate changes will cause sync loss.
- UInt32 start_at_zero = 0;
- result = AudioUnitSetProperty(
- output_unit_,
- kAudioOutputUnitProperty_StartTimestampsAtZero,
- kAudioUnitScope_Global,
- 0,
- &start_at_zero,
- sizeof(start_at_zero));
-
- OSSTATUS_DCHECK(result == noErr, result);
-
- return result;
-}
-
-OSStatus AudioSynchronizedStream::SetupCallbacks() {
- // Set the input callback.
- AURenderCallbackStruct callback;
- callback.inputProc = InputProc;
- callback.inputProcRefCon = this;
- OSStatus result = AudioUnitSetProperty(
- input_unit_,
- kAudioOutputUnitProperty_SetInputCallback,
- kAudioUnitScope_Global,
- 0,
- &callback,
- sizeof(callback));
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Set the output callback.
- callback.inputProc = OutputProc;
- callback.inputProcRefCon = this;
- result = AudioUnitSetProperty(
- output_unit_,
- kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input,
- 0,
- &callback,
- sizeof(callback));
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Set the varispeed callback.
- callback.inputProc = VarispeedProc;
- callback.inputProcRefCon = this;
- result = AudioUnitSetProperty(
- varispeed_unit_,
- kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input,
- 0,
- &callback,
- sizeof(callback));
-
- OSSTATUS_DCHECK(result == noErr, result);
-
- return result;
-}
-
-OSStatus AudioSynchronizedStream::SetupStreamFormats() {
- AudioStreamBasicDescription asbd, asbd_dev1_in, asbd_dev2_out;
-
- // Get the Stream Format (Output client side).
- UInt32 property_size = sizeof(asbd_dev1_in);
- OSStatus result = AudioUnitGetProperty(
- input_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 1,
- &asbd_dev1_in,
- &property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Get the Stream Format (client side).
- property_size = sizeof(asbd);
- result = AudioUnitGetProperty(
- input_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 1,
- &asbd,
- &property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Get the Stream Format (Output client side).
- property_size = sizeof(asbd_dev2_out);
- result = AudioUnitGetProperty(
- output_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 0,
- &asbd_dev2_out,
- &property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Set the format of all the AUs to the input/output devices channel count.
- // For a simple case, you want to set this to
- // the lower of count of the channels in the input device vs output device.
- asbd.mChannelsPerFrame = std::min(asbd_dev1_in.mChannelsPerFrame,
- asbd_dev2_out.mChannelsPerFrame);
-
- // We must get the sample rate of the input device and set it to the
- // stream format of AUHAL.
- Float64 rate = 0;
- property_size = sizeof(rate);
-
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioDevicePropertyNominalSampleRate;
- pa.mScope = kAudioObjectPropertyScopeWildcard;
- pa.mElement = kAudioObjectPropertyElementMaster;
- result = AudioObjectGetPropertyData(
- input_info_.id_,
- &pa,
- 0,
- 0,
- &property_size,
- &rate);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- input_sample_rate_ = rate;
-
- asbd.mSampleRate = rate;
- property_size = sizeof(asbd);
-
- // Set the new formats to the AUs...
- result = AudioUnitSetProperty(
- input_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 1,
- &asbd,
- property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- result = AudioUnitSetProperty(
- varispeed_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 0,
- &asbd,
- property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Set the correct sample rate for the output device,
- // but keep the channel count the same.
- property_size = sizeof(rate);
-
- pa.mSelector = kAudioDevicePropertyNominalSampleRate;
- pa.mScope = kAudioObjectPropertyScopeWildcard;
- pa.mElement = kAudioObjectPropertyElementMaster;
- result = AudioObjectGetPropertyData(
- output_info_.id_,
- &pa,
- 0,
- 0,
- &property_size,
- &rate);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- output_sample_rate_ = rate;
-
- // The requested sample-rate must match the hardware sample-rate.
- if (output_sample_rate_ != params_.sample_rate()) {
- LOG(ERROR) << "Requested sample-rate: " << params_.sample_rate()
- << " must match the hardware sample-rate: " << output_sample_rate_;
- return kAudioDeviceUnsupportedFormatError;
- }
-
- asbd.mSampleRate = rate;
- property_size = sizeof(asbd);
-
- // Set the new audio stream formats for the rest of the AUs...
- result = AudioUnitSetProperty(
- varispeed_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 0,
- &asbd,
- property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- result = AudioUnitSetProperty(
- output_unit_,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 0,
- &asbd,
- property_size);
-
- OSSTATUS_DCHECK(result == noErr, result);
- return result;
-}
-
-void AudioSynchronizedStream::AllocateInputData() {
- // Get the native number of input channels that the hardware supports.
- int hardware_channels = 0;
- bool got_hardware_channels = AudioManagerMac::GetDeviceChannels(
- input_id_, kAudioDevicePropertyScopeInput, &hardware_channels);
- if (!got_hardware_channels || hardware_channels > 2) {
- // Only mono and stereo are supported on the input side. When it fails to
- // get the native channel number or the native channel number is bigger
- // than 2, we open the device in stereo mode.
- hardware_channels = 2;
- }
-
- // Allocate storage for the AudioBufferList used for the
- // input data from the input AudioUnit.
- // We allocate enough space for with one AudioBuffer per channel.
- size_t malloc_size = offsetof(AudioBufferList, mBuffers[0]) +
- (sizeof(AudioBuffer) * hardware_channels);
-
- input_buffer_list_ = static_cast<AudioBufferList*>(malloc(malloc_size));
- input_buffer_list_->mNumberBuffers = hardware_channels;
-
- input_bus_ = AudioBus::Create(hardware_channels, hardware_buffer_size_);
- wrapper_bus_ = AudioBus::CreateWrapper(channels_);
- if (hardware_channels != params_.input_channels()) {
- ChannelLayout hardware_channel_layout =
- GuessChannelLayout(hardware_channels);
- ChannelLayout requested_channel_layout =
- GuessChannelLayout(params_.input_channels());
- channel_mixer_.reset(new ChannelMixer(hardware_channel_layout,
- requested_channel_layout));
- mixer_bus_ = AudioBus::Create(params_.input_channels(),
- hardware_buffer_size_);
- }
-
- // Allocate buffers for AudioBufferList.
- UInt32 buffer_size_bytes = input_bus_->frames() * sizeof(Float32);
- for (size_t i = 0; i < input_buffer_list_->mNumberBuffers; ++i) {
- input_buffer_list_->mBuffers[i].mNumberChannels = 1;
- input_buffer_list_->mBuffers[i].mDataByteSize = buffer_size_bytes;
- input_buffer_list_->mBuffers[i].mData = input_bus_->channel(i);
- }
-}
-
-OSStatus AudioSynchronizedStream::HandleInputCallback(
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- TRACE_EVENT0("audio", "AudioSynchronizedStream::HandleInputCallback");
-
- if (first_input_time_ < 0.0)
- first_input_time_ = time_stamp->mSampleTime;
-
- // Get the new audio input data.
- OSStatus result = AudioUnitRender(
- input_unit_,
- io_action_flags,
- time_stamp,
- bus_number,
- number_of_frames,
- input_buffer_list_);
-
- // TODO(xians): Add back the DCHECK after synchronize IO supports all
- // combination of input and output params. See http://issue/246521.
- if (result != noErr)
- return result;
-
- // Buffer input into FIFO.
- int available_frames = fifo_.max_frames() - fifo_.frames();
- if (input_bus_->frames() <= available_frames) {
- if (channel_mixer_) {
- channel_mixer_->Transform(input_bus_.get(), mixer_bus_.get());
- fifo_.Push(mixer_bus_.get());
- } else {
- fifo_.Push(input_bus_.get());
- }
- }
-
- return result;
-}
-
-OSStatus AudioSynchronizedStream::HandleVarispeedCallback(
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- // Create a wrapper bus on the AudioBufferList.
- WrapBufferList(io_data, wrapper_bus_.get(), number_of_frames);
-
- if (fifo_.frames() < static_cast<int>(number_of_frames)) {
- // We don't DCHECK here, since this is a possible run-time condition
- // if the machine is bogged down.
- wrapper_bus_->Zero();
- return noErr;
- }
-
- // Read from the FIFO to feed the varispeed.
- fifo_.Consume(wrapper_bus_.get(), 0, number_of_frames);
-
- return noErr;
-}
-
-OSStatus AudioSynchronizedStream::HandleOutputCallback(
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- // Input callback hasn't run yet or we've suddenly changed sample-rates
- // -> silence.
- if (first_input_time_ < 0.0 ||
- static_cast<int>(number_of_frames) != params_.frames_per_buffer()) {
- ZeroBufferList(io_data);
- return noErr;
- }
-
- // Use the varispeed playback rate to offset small discrepancies
- // in hardware clocks, and also any differences in sample-rate
- // between input and output devices.
-
- // Calculate a varispeed rate scalar factor to compensate for drift between
- // input and output. We use the actual number of frames still in the FIFO
- // compared with the ideal value of |target_fifo_frames_|.
- int delta = fifo_.frames() - target_fifo_frames_;
-
- // Average |delta| because it can jitter back/forth quite frequently
- // by +/- the hardware buffer-size *if* the input and output callbacks are
- // happening at almost exactly the same time. Also, if the input and output
- // sample-rates are different then |delta| will jitter quite a bit due to
- // the rate conversion happening in the varispeed, plus the jittering of
- // the callbacks. The average value is what's important here.
- average_delta_ += (delta - average_delta_) * 0.1;
-
- // Compute a rate compensation which always attracts us back to the
- // |target_fifo_frames_| over a period of kCorrectionTimeSeconds.
- const double kCorrectionTimeSeconds = 0.1;
- double correction_time_frames = kCorrectionTimeSeconds * output_sample_rate_;
- fifo_rate_compensation_ =
- (correction_time_frames + average_delta_) / correction_time_frames;
-
- // Adjust for FIFO drift.
- OSStatus result = AudioUnitSetParameter(
- varispeed_unit_,
- kVarispeedParam_PlaybackRate,
- kAudioUnitScope_Global,
- 0,
- fifo_rate_compensation_,
- 0);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Render to the output using the varispeed.
- result = AudioUnitRender(
- varispeed_unit_,
- io_action_flags,
- time_stamp,
- 0,
- number_of_frames,
- io_data);
-
- OSSTATUS_DCHECK(result == noErr, result);
- if (result != noErr)
- return result;
-
- // Create a wrapper bus on the AudioBufferList.
- WrapBufferList(io_data, wrapper_bus_.get(), number_of_frames);
-
- // Process in-place!
- source_->OnMoreIOData(wrapper_bus_.get(),
- wrapper_bus_.get(),
- AudioBuffersState(0, 0));
-
- return noErr;
-}
-
-OSStatus AudioSynchronizedStream::InputProc(
- void* user_data,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- AudioSynchronizedStream* stream =
- static_cast<AudioSynchronizedStream*>(user_data);
- DCHECK(stream);
-
- return stream->HandleInputCallback(
- io_action_flags,
- time_stamp,
- bus_number,
- number_of_frames,
- io_data);
-}
-
-OSStatus AudioSynchronizedStream::VarispeedProc(
- void* user_data,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- AudioSynchronizedStream* stream =
- static_cast<AudioSynchronizedStream*>(user_data);
- DCHECK(stream);
-
- return stream->HandleVarispeedCallback(
- io_action_flags,
- time_stamp,
- bus_number,
- number_of_frames,
- io_data);
-}
-
-OSStatus AudioSynchronizedStream::OutputProc(
- void* user_data,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data) {
- AudioSynchronizedStream* stream =
- static_cast<AudioSynchronizedStream*>(user_data);
- DCHECK(stream);
-
- return stream->HandleOutputCallback(
- io_action_flags,
- time_stamp,
- bus_number,
- number_of_frames,
- io_data);
-}
-
-void AudioSynchronizedStream::AudioDeviceInfo::Initialize(
- AudioDeviceID id, bool is_input) {
- id_ = id;
- is_input_ = is_input;
- if (id_ == kAudioDeviceUnknown)
- return;
-
- UInt32 property_size = sizeof(buffer_size_frames_);
-
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioDevicePropertyBufferFrameSize;
- pa.mScope = kAudioObjectPropertyScopeWildcard;
- pa.mElement = kAudioObjectPropertyElementMaster;
- OSStatus result = AudioObjectGetPropertyData(
- id_,
- &pa,
- 0,
- 0,
- &property_size,
- &buffer_size_frames_);
-
- OSSTATUS_DCHECK(result == noErr, result);
-}
-
-} // namespace media
diff --git a/media/audio/mac/audio_synchronized_mac.h b/media/audio/mac/audio_synchronized_mac.h
deleted file mode 100644
index a6db48e..0000000
--- a/media/audio/mac/audio_synchronized_mac.h
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
-#define MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
-
-#include <AudioToolbox/AudioToolbox.h>
-#include <AudioUnit/AudioUnit.h>
-#include <CoreAudio/CoreAudio.h>
-
-#include "base/compiler_specific.h"
-#include "base/synchronization/lock.h"
-#include "media/audio/audio_io.h"
-#include "media/audio/audio_parameters.h"
-#include "media/base/audio_bus.h"
-#include "media/base/audio_fifo.h"
-
-namespace media {
-
-class AudioManagerMac;
-class ChannelMixer;
-
-// AudioSynchronizedStream allows arbitrary combinations of input and output
-// devices running off different clocks and using different drivers, with
-// potentially differing sample-rates. It implements AudioOutputStream
-// and shuttles its synchronized I/O data using AudioSourceCallback.
-//
-// It is required to first acquire the native sample rate of the selected
-// output device and then use the same rate when creating this object.
-//
-// ............................................................................
-// Theory of Operation:
-// .
-// INPUT THREAD . OUTPUT THREAD
-// +-----------------+ +------+ .
-// | Input AudioUnit | --> | | .
-// +-----------------+ | | .
-// | FIFO | .
-// | | +-----------+
-// | | -----> | Varispeed |
-// | | +-----------+
-// +------+ . |
-// . | +-----------+
-// . OnMoreIOData() --> | Output AU |
-// . +-----------+
-//
-// The input AudioUnit's InputProc is called on one thread which feeds the
-// FIFO. The output AudioUnit's OutputProc is called on a second thread
-// which pulls on the varispeed to get the current input data. The varispeed
-// handles mismatches between input and output sample-rate and also clock drift
-// between the input and output drivers. The varispeed consumes its data from
-// the FIFO and adjusts its rate dynamically according to the amount
-// of data buffered in the FIFO. If the FIFO starts getting too much data
-// buffered then the varispeed will speed up slightly to compensate
-// and similarly if the FIFO doesn't have enough data buffered then the
-// varispeed will slow down slightly.
-//
-// Finally, once the input data is available then OnMoreIOData() is called
-// which is given this input, and renders the output which is finally sent
-// to the Output AudioUnit.
-class AudioSynchronizedStream : public AudioOutputStream {
- public:
- // The ctor takes all the usual parameters, plus |manager| which is the
- // the audio manager who is creating this object.
- AudioSynchronizedStream(AudioManagerMac* manager,
- const AudioParameters& params,
- AudioDeviceID input_id,
- AudioDeviceID output_id);
-
- virtual ~AudioSynchronizedStream();
-
- // Implementation of AudioOutputStream.
- virtual bool Open() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void Start(AudioSourceCallback* callback) OVERRIDE;
- virtual void Stop() OVERRIDE;
-
- virtual void SetVolume(double volume) OVERRIDE;
- virtual void GetVolume(double* volume) OVERRIDE;
-
- OSStatus SetInputDeviceAsCurrent(AudioDeviceID input_id);
- OSStatus SetOutputDeviceAsCurrent(AudioDeviceID output_id);
- AudioDeviceID GetInputDeviceID() { return input_info_.id_; }
- AudioDeviceID GetOutputDeviceID() { return output_info_.id_; }
-
- bool IsRunning();
-
- private:
- // Initialization.
- OSStatus CreateAudioUnits();
- OSStatus SetupInput(AudioDeviceID input_id);
- OSStatus EnableIO();
- OSStatus SetupOutput(AudioDeviceID output_id);
- OSStatus SetupCallbacks();
- OSStatus SetupStreamFormats();
- void AllocateInputData();
-
- // Handlers for the AudioUnit callbacks.
- OSStatus HandleInputCallback(AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data);
-
- OSStatus HandleVarispeedCallback(AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data);
-
- OSStatus HandleOutputCallback(AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data);
-
- // AudioUnit callbacks.
- static OSStatus InputProc(void* user_data,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data);
-
- static OSStatus VarispeedProc(void* user_data,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data);
-
- static OSStatus OutputProc(void* user_data,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* time_stamp,
- UInt32 bus_number,
- UInt32 number_of_frames,
- AudioBufferList* io_data);
-
- // Our creator.
- AudioManagerMac* manager_;
-
- // Client parameters.
- AudioParameters params_;
-
- double input_sample_rate_;
- double output_sample_rate_;
-
- // Pointer to the object that will provide the audio samples.
- AudioSourceCallback* source_;
-
- // Values used in Open().
- AudioDeviceID input_id_;
- AudioDeviceID output_id_;
-
- // The input AudioUnit renders its data here.
- AudioBufferList* input_buffer_list_;
-
- // Holds the actual data for |input_buffer_list_|.
- scoped_ptr<AudioBus> input_bus_;
-
- // Used to overlay AudioBufferLists.
- scoped_ptr<AudioBus> wrapper_bus_;
-
- class AudioDeviceInfo {
- public:
- AudioDeviceInfo()
- : id_(kAudioDeviceUnknown),
- is_input_(false),
- buffer_size_frames_(0) {}
- void Initialize(AudioDeviceID inID, bool isInput);
- bool IsInitialized() const { return id_ != kAudioDeviceUnknown; }
-
- AudioDeviceID id_;
- bool is_input_;
- UInt32 buffer_size_frames_;
- };
-
- AudioDeviceInfo input_info_;
- AudioDeviceInfo output_info_;
-
- // Used for input to output buffering.
- AudioFifo fifo_;
-
- // The optimal number of frames we'd like to keep in the FIFO at all times.
- int target_fifo_frames_;
-
- // A running average of the measured delta between actual number of frames
- // in the FIFO versus |target_fifo_frames_|.
- double average_delta_;
-
- // A varispeed rate scalar which is calculated based on FIFO drift.
- double fifo_rate_compensation_;
-
- // AudioUnits.
- AudioUnit input_unit_;
- AudioUnit varispeed_unit_;
- AudioUnit output_unit_;
-
- double first_input_time_;
-
- bool is_running_;
- int hardware_buffer_size_;
- int channels_;
-
- // Channel mixer used to transform mono to stereo data. It is only created
- // if the input_hardware_channels is mono.
- scoped_ptr<ChannelMixer> channel_mixer_;
- scoped_ptr<AudioBus> mixer_bus_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioSynchronizedStream);
-};
-
-} // namespace media
-
-#endif // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
diff --git a/media/audio/mac/audio_unified_mac.cc b/media/audio/mac/audio_unified_mac.cc
deleted file mode 100644
index d1dc007..0000000
--- a/media/audio/mac/audio_unified_mac.cc
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/mac/audio_unified_mac.h"
-
-#include <CoreServices/CoreServices.h>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/mac/mac_logging.h"
-#include "media/audio/mac/audio_manager_mac.h"
-
-namespace media {
-
-// TODO(crogers): support more than hard-coded stereo input.
-// Ideally we would like to receive this value as a constructor argument.
-static const int kDefaultInputChannels = 2;
-
-AudioHardwareUnifiedStream::AudioHardwareUnifiedStream(
- AudioManagerMac* manager, const AudioParameters& params)
- : manager_(manager),
- source_(NULL),
- client_input_channels_(kDefaultInputChannels),
- volume_(1.0f),
- input_channels_(0),
- output_channels_(0),
- input_channels_per_frame_(0),
- output_channels_per_frame_(0),
- io_proc_id_(0),
- device_(kAudioObjectUnknown),
- is_playing_(false) {
- DCHECK(manager_);
-
- // A frame is one sample across all channels. In interleaved audio the per
- // frame fields identify the set of n |channels|. In uncompressed audio, a
- // packet is always one frame.
- format_.mSampleRate = params.sample_rate();
- format_.mFormatID = kAudioFormatLinearPCM;
- format_.mFormatFlags = kLinearPCMFormatFlagIsPacked |
- kLinearPCMFormatFlagIsSignedInteger;
- format_.mBitsPerChannel = params.bits_per_sample();
- format_.mChannelsPerFrame = params.channels();
- format_.mFramesPerPacket = 1;
- format_.mBytesPerPacket = (format_.mBitsPerChannel * params.channels()) / 8;
- format_.mBytesPerFrame = format_.mBytesPerPacket;
- format_.mReserved = 0;
-
- // Calculate the number of sample frames per callback.
- number_of_frames_ = params.GetBytesPerBuffer() / format_.mBytesPerPacket;
-
- input_bus_ = AudioBus::Create(client_input_channels_,
- params.frames_per_buffer());
- output_bus_ = AudioBus::Create(params);
-}
-
-AudioHardwareUnifiedStream::~AudioHardwareUnifiedStream() {
- DCHECK_EQ(device_, kAudioObjectUnknown);
-}
-
-bool AudioHardwareUnifiedStream::Open() {
- // Obtain the current output device selected by the user.
- AudioObjectPropertyAddress pa;
- pa.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
- pa.mScope = kAudioObjectPropertyScopeGlobal;
- pa.mElement = kAudioObjectPropertyElementMaster;
-
- UInt32 size = sizeof(device_);
-
- OSStatus result = AudioObjectGetPropertyData(
- kAudioObjectSystemObject,
- &pa,
- 0,
- 0,
- &size,
- &device_);
-
- if ((result != kAudioHardwareNoError) || (device_ == kAudioDeviceUnknown)) {
- LOG(ERROR) << "Cannot open unified AudioDevice.";
- return false;
- }
-
- // The requested sample-rate must match the hardware sample-rate.
- Float64 sample_rate = 0.0;
- size = sizeof(sample_rate);
-
- pa.mSelector = kAudioDevicePropertyNominalSampleRate;
- pa.mScope = kAudioObjectPropertyScopeWildcard;
- pa.mElement = kAudioObjectPropertyElementMaster;
-
- result = AudioObjectGetPropertyData(
- device_,
- &pa,
- 0,
- 0,
- &size,
- &sample_rate);
-
- if (result != noErr || sample_rate != format_.mSampleRate) {
- LOG(ERROR) << "Requested sample-rate: " << format_.mSampleRate
- << " must match the hardware sample-rate: " << sample_rate;
- return false;
- }
-
- // Configure buffer frame size.
- UInt32 frame_size = number_of_frames_;
-
- pa.mSelector = kAudioDevicePropertyBufferFrameSize;
- pa.mScope = kAudioDevicePropertyScopeInput;
- pa.mElement = kAudioObjectPropertyElementMaster;
- result = AudioObjectSetPropertyData(
- device_,
- &pa,
- 0,
- 0,
- sizeof(frame_size),
- &frame_size);
-
- if (result != noErr) {
- LOG(ERROR) << "Unable to set input buffer frame size: " << frame_size;
- return false;
- }
-
- pa.mScope = kAudioDevicePropertyScopeOutput;
- result = AudioObjectSetPropertyData(
- device_,
- &pa,
- 0,
- 0,
- sizeof(frame_size),
- &frame_size);
-
- if (result != noErr) {
- LOG(ERROR) << "Unable to set output buffer frame size: " << frame_size;
- return false;
- }
-
- DVLOG(1) << "Sample rate: " << sample_rate;
- DVLOG(1) << "Frame size: " << frame_size;
-
- // Determine the number of input and output channels.
- // We handle both the interleaved and non-interleaved cases.
-
- // Get input stream configuration.
- pa.mSelector = kAudioDevicePropertyStreamConfiguration;
- pa.mScope = kAudioDevicePropertyScopeInput;
- pa.mElement = kAudioObjectPropertyElementMaster;
-
- result = AudioObjectGetPropertyDataSize(device_, &pa, 0, 0, &size);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr && size > 0) {
- // Allocate storage.
- scoped_ptr<uint8[]> input_list_storage(new uint8[size]);
- AudioBufferList& input_list =
- *reinterpret_cast<AudioBufferList*>(input_list_storage.get());
-
- result = AudioObjectGetPropertyData(
- device_,
- &pa,
- 0,
- 0,
- &size,
- &input_list);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr) {
- // Determine number of input channels.
- input_channels_per_frame_ = input_list.mNumberBuffers > 0 ?
- input_list.mBuffers[0].mNumberChannels : 0;
- if (input_channels_per_frame_ == 1 && input_list.mNumberBuffers > 1) {
- // Non-interleaved.
- input_channels_ = input_list.mNumberBuffers;
- } else {
- // Interleaved.
- input_channels_ = input_channels_per_frame_;
- }
- }
- }
-
- DVLOG(1) << "Input channels: " << input_channels_;
- DVLOG(1) << "Input channels per frame: " << input_channels_per_frame_;
-
- // The hardware must have at least the requested input channels.
- if (result != noErr || client_input_channels_ > input_channels_) {
- LOG(ERROR) << "AudioDevice does not support requested input channels.";
- return false;
- }
-
- // Get output stream configuration.
- pa.mSelector = kAudioDevicePropertyStreamConfiguration;
- pa.mScope = kAudioDevicePropertyScopeOutput;
- pa.mElement = kAudioObjectPropertyElementMaster;
-
- result = AudioObjectGetPropertyDataSize(device_, &pa, 0, 0, &size);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr && size > 0) {
- // Allocate storage.
- scoped_ptr<uint8[]> output_list_storage(new uint8[size]);
- AudioBufferList& output_list =
- *reinterpret_cast<AudioBufferList*>(output_list_storage.get());
-
- result = AudioObjectGetPropertyData(
- device_,
- &pa,
- 0,
- 0,
- &size,
- &output_list);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr) {
- // Determine number of output channels.
- output_channels_per_frame_ = output_list.mBuffers[0].mNumberChannels;
- if (output_channels_per_frame_ == 1 && output_list.mNumberBuffers > 1) {
- // Non-interleaved.
- output_channels_ = output_list.mNumberBuffers;
- } else {
- // Interleaved.
- output_channels_ = output_channels_per_frame_;
- }
- }
- }
-
- DVLOG(1) << "Output channels: " << output_channels_;
- DVLOG(1) << "Output channels per frame: " << output_channels_per_frame_;
-
- // The hardware must have at least the requested output channels.
- if (result != noErr ||
- output_channels_ < static_cast<int>(format_.mChannelsPerFrame)) {
- LOG(ERROR) << "AudioDevice does not support requested output channels.";
- return false;
- }
-
- // Setup the I/O proc.
- result = AudioDeviceCreateIOProcID(device_, RenderProc, this, &io_proc_id_);
- if (result != noErr) {
- LOG(ERROR) << "Error creating IOProc.";
- return false;
- }
-
- return true;
-}
-
-void AudioHardwareUnifiedStream::Close() {
- DCHECK(!is_playing_);
-
- OSStatus result = AudioDeviceDestroyIOProcID(device_, io_proc_id_);
- OSSTATUS_DCHECK(result == noErr, result);
-
- io_proc_id_ = 0;
- device_ = kAudioObjectUnknown;
-
- // Inform the audio manager that we have been closed. This can cause our
- // destruction.
- manager_->ReleaseOutputStream(this);
-}
-
-void AudioHardwareUnifiedStream::Start(AudioSourceCallback* callback) {
- DCHECK(callback);
- DCHECK_NE(device_, kAudioObjectUnknown);
- DCHECK(!is_playing_);
- if (device_ == kAudioObjectUnknown || is_playing_)
- return;
-
- source_ = callback;
-
- OSStatus result = AudioDeviceStart(device_, io_proc_id_);
- OSSTATUS_DCHECK(result == noErr, result);
-
- if (result == noErr)
- is_playing_ = true;
-}
-
-void AudioHardwareUnifiedStream::Stop() {
- if (!is_playing_)
- return;
-
- if (device_ != kAudioObjectUnknown) {
- OSStatus result = AudioDeviceStop(device_, io_proc_id_);
- OSSTATUS_DCHECK(result == noErr, result);
- }
-
- is_playing_ = false;
- source_ = NULL;
-}
-
-void AudioHardwareUnifiedStream::SetVolume(double volume) {
- volume_ = static_cast<float>(volume);
- // TODO(crogers): set volume property
-}
-
-void AudioHardwareUnifiedStream::GetVolume(double* volume) {
- *volume = volume_;
-}
-
-// Pulls on our provider with optional input, asking it to render output.
-// Note to future hackers of this function: Do not add locks here because this
-// is running on a real-time thread (for low-latency).
-OSStatus AudioHardwareUnifiedStream::Render(
- AudioDeviceID device,
- const AudioTimeStamp* now,
- const AudioBufferList* input_data,
- const AudioTimeStamp* input_time,
- AudioBufferList* output_data,
- const AudioTimeStamp* output_time) {
- // Convert the input data accounting for possible interleaving.
- // TODO(crogers): it's better to simply memcpy() if source is already planar.
- if (input_channels_ >= client_input_channels_) {
- for (int channel_index = 0; channel_index < client_input_channels_;
- ++channel_index) {
- float* source;
-
- int source_channel_index = channel_index;
-
- if (input_channels_per_frame_ > 1) {
- // Interleaved.
- source = static_cast<float*>(input_data->mBuffers[0].mData) +
- source_channel_index;
- } else {
- // Non-interleaved.
- source = static_cast<float*>(
- input_data->mBuffers[source_channel_index].mData);
- }
-
- float* p = input_bus_->channel(channel_index);
- for (int i = 0; i < number_of_frames_; ++i) {
- p[i] = *source;
- source += input_channels_per_frame_;
- }
- }
- } else if (input_channels_) {
- input_bus_->Zero();
- }
-
- // Give the client optional input data and have it render the output data.
- source_->OnMoreIOData(input_bus_.get(),
- output_bus_.get(),
- AudioBuffersState(0, 0));
-
- // TODO(crogers): handle final Core Audio 5.1 layout for 5.1 audio.
-
- // Handle interleaving as necessary.
- // TODO(crogers): it's better to simply memcpy() if dest is already planar.
-
- for (int channel_index = 0;
- channel_index < static_cast<int>(format_.mChannelsPerFrame);
- ++channel_index) {
- float* dest;
-
- int dest_channel_index = channel_index;
-
- if (output_channels_per_frame_ > 1) {
- // Interleaved.
- dest = static_cast<float*>(output_data->mBuffers[0].mData) +
- dest_channel_index;
- } else {
- // Non-interleaved.
- dest = static_cast<float*>(
- output_data->mBuffers[dest_channel_index].mData);
- }
-
- float* p = output_bus_->channel(channel_index);
- for (int i = 0; i < number_of_frames_; ++i) {
- *dest = p[i];
- dest += output_channels_per_frame_;
- }
- }
-
- return noErr;
-}
-
-OSStatus AudioHardwareUnifiedStream::RenderProc(
- AudioDeviceID device,
- const AudioTimeStamp* now,
- const AudioBufferList* input_data,
- const AudioTimeStamp* input_time,
- AudioBufferList* output_data,
- const AudioTimeStamp* output_time,
- void* user_data) {
- AudioHardwareUnifiedStream* audio_output =
- static_cast<AudioHardwareUnifiedStream*>(user_data);
- DCHECK(audio_output);
- if (!audio_output)
- return -1;
-
- return audio_output->Render(
- device,
- now,
- input_data,
- input_time,
- output_data,
- output_time);
-}
-
-} // namespace media
diff --git a/media/audio/mac/audio_unified_mac.h b/media/audio/mac/audio_unified_mac.h
deleted file mode 100644
index ff090e3..0000000
--- a/media/audio/mac/audio_unified_mac.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_MAC_AUDIO_UNIFIED_MAC_H_
-#define MEDIA_AUDIO_MAC_AUDIO_UNIFIED_MAC_H_
-
-#include <CoreAudio/CoreAudio.h>
-
-#include "base/memory/scoped_ptr.h"
-#include "media/audio/audio_io.h"
-#include "media/audio/audio_parameters.h"
-
-namespace media {
-
-class AudioManagerMac;
-
-// Implementation of AudioOutputStream for Mac OS X using the
-// CoreAudio AudioHardware API suitable for low-latency unified audio I/O
-// when using devices which support *both* input and output
-// in the same driver. This is the case with professional
-// USB and Firewire devices.
-//
-// Please note that it's required to first get the native sample-rate of the
-// default output device and use that sample-rate when creating this object.
-class AudioHardwareUnifiedStream : public AudioOutputStream {
- public:
- // The ctor takes all the usual parameters, plus |manager| which is the
- // the audio manager who is creating this object.
- AudioHardwareUnifiedStream(AudioManagerMac* manager,
- const AudioParameters& params);
- // The dtor is typically called by the AudioManager only and it is usually
- // triggered by calling AudioOutputStream::Close().
- virtual ~AudioHardwareUnifiedStream();
-
- // Implementation of AudioOutputStream.
- virtual bool Open() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void Start(AudioSourceCallback* callback) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void SetVolume(double volume) OVERRIDE;
- virtual void GetVolume(double* volume) OVERRIDE;
-
- int input_channels() const { return input_channels_; }
- int output_channels() const { return output_channels_; }
-
- private:
- OSStatus Render(AudioDeviceID device,
- const AudioTimeStamp* now,
- const AudioBufferList* input_data,
- const AudioTimeStamp* input_time,
- AudioBufferList* output_data,
- const AudioTimeStamp* output_time);
-
- static OSStatus RenderProc(AudioDeviceID device,
- const AudioTimeStamp* now,
- const AudioBufferList* input_data,
- const AudioTimeStamp* input_time,
- AudioBufferList* output_data,
- const AudioTimeStamp* output_time,
- void* user_data);
-
- // Our creator, the audio manager needs to be notified when we close.
- AudioManagerMac* manager_;
-
- // Pointer to the object that will provide the audio samples.
- AudioSourceCallback* source_;
-
- // Structure that holds the stream format details such as bitrate.
- AudioStreamBasicDescription format_;
-
- // Hardware buffer size.
- int number_of_frames_;
-
- // Number of audio channels provided to the client via OnMoreIOData().
- int client_input_channels_;
-
- // Volume level from 0 to 1.
- float volume_;
-
- // Number of input and output channels queried from the hardware.
- int input_channels_;
- int output_channels_;
- int input_channels_per_frame_;
- int output_channels_per_frame_;
-
- AudioDeviceIOProcID io_proc_id_;
- AudioDeviceID device_;
- bool is_playing_;
-
- // Intermediate buffers used with call to OnMoreIOData().
- scoped_ptr<AudioBus> input_bus_;
- scoped_ptr<AudioBus> output_bus_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioHardwareUnifiedStream);
-};
-
-} // namespace media
-
-#endif // MEDIA_AUDIO_MAC_AUDIO_UNIFIED_MAC_H_
diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc
index 5984790..318bf09 100644
--- a/media/audio/mock_audio_manager.cc
+++ b/media/audio/mock_audio_manager.cc
@@ -47,16 +47,14 @@ void MockAudioManager::GetAudioOutputDeviceNames(
media::AudioOutputStream* MockAudioManager::MakeAudioOutputStream(
const media::AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
NOTREACHED();
return NULL;
}
media::AudioOutputStream* MockAudioManager::MakeAudioOutputStreamProxy(
const media::AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
NOTREACHED();
return NULL;
}
diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h
index 0cd79e7..8ca4009 100644
--- a/media/audio/mock_audio_manager.h
+++ b/media/audio/mock_audio_manager.h
@@ -40,13 +40,11 @@ class MockAudioManager : public media::AudioManager {
virtual media::AudioOutputStream* MakeAudioOutputStream(
const media::AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual media::AudioOutputStream* MakeAudioOutputStreamProxy(
const media::AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& 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 b378b02..141689a 100644
--- a/media/audio/openbsd/audio_manager_openbsd.cc
+++ b/media/audio/openbsd/audio_manager_openbsd.cc
@@ -92,8 +92,7 @@ AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
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 113f591..53b7dfb 100644
--- a/media/audio/openbsd/audio_manager_openbsd.h
+++ b/media/audio/openbsd/audio_manager_openbsd.h
@@ -27,8 +27,7 @@ class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& 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 da106c2..ea328ad 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -16,7 +16,6 @@
#include "media/audio/audio_parameters.h"
#include "media/audio/pulse/pulse_input.h"
#include "media/audio/pulse/pulse_output.h"
-#include "media/audio/pulse/pulse_unified.h"
#include "media/audio/pulse/pulse_util.h"
#include "media/base/channel_layout.h"
@@ -133,16 +132,15 @@ AudioParameters AudioManagerPulse::GetInputStreamParameters(
AudioOutputStream* AudioManagerPulse::MakeLinearOutputStream(
const AudioParameters& params) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
- return MakeOutputStream(params, std::string());
+ return MakeOutputStream(params);
}
AudioOutputStream* AudioManagerPulse::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
- return MakeOutputStream(params, input_device_id);
+ return MakeOutputStream(params);
}
AudioInputStream* AudioManagerPulse::MakeLinearInputStream(
@@ -189,11 +187,7 @@ AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters(
}
AudioOutputStream* AudioManagerPulse::MakeOutputStream(
- const AudioParameters& params, const std::string& input_device_id) {
- if (params.input_channels()) {
- return new PulseAudioUnifiedStream(params, input_device_id, this);
- }
-
+ const AudioParameters& params) {
return new PulseAudioOutputStream(params, this);
}
diff --git a/media/audio/pulse/audio_manager_pulse.h b/media/audio/pulse/audio_manager_pulse.h
index 45fb8cb..b3b0031 100644
--- a/media/audio/pulse/audio_manager_pulse.h
+++ b/media/audio/pulse/audio_manager_pulse.h
@@ -37,8 +37,7 @@ class MEDIA_EXPORT AudioManagerPulse : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) OVERRIDE;
virtual AudioInputStream* MakeLowLatencyInputStream(
@@ -70,8 +69,7 @@ class MEDIA_EXPORT AudioManagerPulse : public AudioManagerBase {
void* user_data);
// Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
- AudioOutputStream* MakeOutputStream(const AudioParameters& params,
- const std::string& input_device_id);
+ AudioOutputStream* MakeOutputStream(const AudioParameters& params);
// 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
deleted file mode 100644
index cd17b01..0000000
--- a/media/audio/pulse/pulse_unified.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/pulse/pulse_unified.h"
-
-#include "base/single_thread_task_runner.h"
-#include "base/time/time.h"
-#include "media/audio/audio_manager_base.h"
-#include "media/audio/audio_parameters.h"
-#include "media/audio/pulse/pulse_util.h"
-#include "media/base/seekable_buffer.h"
-
-namespace media {
-
-using pulse::AutoPulseLock;
-using pulse::WaitForOperationCompletion;
-
-static const int kFifoSizeInPackets = 10;
-
-// static, pa_stream_notify_cb
-void PulseAudioUnifiedStream::StreamNotifyCallback(pa_stream* s,
- void* user_data) {
- PulseAudioUnifiedStream* stream =
- static_cast<PulseAudioUnifiedStream*>(user_data);
-
- // Forward unexpected failures to the AudioSourceCallback if available. All
- // these variables are only modified under pa_threaded_mainloop_lock() so this
- // should be thread safe.
- if (s && stream->source_callback_ &&
- pa_stream_get_state(s) == PA_STREAM_FAILED) {
- stream->source_callback_->OnError(stream);
- }
-
- pa_threaded_mainloop_signal(stream->pa_mainloop_, 0);
-}
-
-// static, used by pa_stream_set_read_callback.
-void PulseAudioUnifiedStream::ReadCallback(pa_stream* handle, size_t length,
- void* user_data) {
- static_cast<PulseAudioUnifiedStream*>(user_data)->ReadData();
-}
-
-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),
- input_stream_(NULL),
- output_stream_(NULL),
- volume_(1.0f),
- source_callback_(NULL) {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
- CHECK(params_.IsValid());
- input_bus_ = AudioBus::Create(params_);
- output_bus_ = AudioBus::Create(params_);
-}
-
-PulseAudioUnifiedStream::~PulseAudioUnifiedStream() {
- // All internal structures should already have been freed in Close(), which
- // calls AudioManagerBase::ReleaseOutputStream() which deletes this object.
- DCHECK(!input_stream_);
- DCHECK(!output_stream_);
- DCHECK(!pa_context_);
- DCHECK(!pa_mainloop_);
-}
-
-bool PulseAudioUnifiedStream::Open() {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
- // Prepare the recording buffers for the callbacks.
- fifo_.reset(new media::SeekableBuffer(
- 0, kFifoSizeInPackets * params_.GetBytesPerBuffer()));
- input_data_buffer_.reset(new uint8[params_.GetBytesPerBuffer()]);
-
- if (!pulse::CreateOutputStream(&pa_mainloop_, &pa_context_, &output_stream_,
- params_, &StreamNotifyCallback, NULL, this))
- return false;
-
- if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &input_stream_,
- params_, input_device_id_,
- &StreamNotifyCallback, this))
- return false;
-
- DCHECK(pa_mainloop_);
- DCHECK(pa_context_);
- DCHECK(input_stream_);
- DCHECK(output_stream_);
- return true;
-}
-
-void PulseAudioUnifiedStream::Reset() {
- if (!pa_mainloop_) {
- DCHECK(!input_stream_);
- DCHECK(!output_stream_);
- DCHECK(!pa_context_);
- return;
- }
-
- {
- AutoPulseLock auto_lock(pa_mainloop_);
-
- // Close the input stream.
- if (input_stream_) {
- // Disable all the callbacks before disconnecting.
- pa_stream_set_state_callback(input_stream_, NULL, NULL);
- pa_stream_flush(input_stream_, NULL, NULL);
- pa_stream_disconnect(input_stream_);
-
- // Release PulseAudio structures.
- pa_stream_unref(input_stream_);
- input_stream_ = NULL;
- }
-
- // Close the ouput stream.
- if (output_stream_) {
- // Release PulseAudio output stream structures.
- pa_stream_set_state_callback(output_stream_, NULL, NULL);
- pa_stream_disconnect(output_stream_);
- pa_stream_unref(output_stream_);
- output_stream_ = NULL;
- }
-
- if (pa_context_) {
- pa_context_disconnect(pa_context_);
- pa_context_set_state_callback(pa_context_, NULL, NULL);
- pa_context_unref(pa_context_);
- pa_context_ = NULL;
- }
- }
-
- pa_threaded_mainloop_stop(pa_mainloop_);
- pa_threaded_mainloop_free(pa_mainloop_);
- pa_mainloop_ = NULL;
-}
-
-void PulseAudioUnifiedStream::Close() {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
- Reset();
-
- // Signal to the manager that we're closed and can be removed.
- // This should be the last call in the function as it deletes "this".
- manager_->ReleaseOutputStream(this);
-}
-
-void PulseAudioUnifiedStream::WriteData(size_t requested_bytes) {
- CHECK_EQ(requested_bytes, static_cast<size_t>(params_.GetBytesPerBuffer()));
-
- void* buffer = NULL;
- int frames_filled = 0;
- if (source_callback_) {
- CHECK_GE(pa_stream_begin_write(
- output_stream_, &buffer, &requested_bytes), 0);
- uint32 hardware_delay = pulse::GetHardwareLatencyInBytes(
- output_stream_, params_.sample_rate(),
- params_.GetBytesPerFrame());
- fifo_->Read(input_data_buffer_.get(), requested_bytes);
- input_bus_->FromInterleaved(
- input_data_buffer_.get(), params_.frames_per_buffer(), 2);
-
- frames_filled = source_callback_->OnMoreIOData(
- input_bus_.get(),
- output_bus_.get(),
- AudioBuffersState(0, hardware_delay));
- }
-
- // Zero the unfilled data so it plays back as silence.
- if (frames_filled < output_bus_->frames()) {
- output_bus_->ZeroFramesPartial(
- frames_filled, output_bus_->frames() - frames_filled);
- }
-
- // Note: If this ever changes to output raw float the data must be clipped
- // and sanitized since it may come from an untrusted source such as NaCl.
- output_bus_->Scale(volume_);
- output_bus_->ToInterleaved(
- output_bus_->frames(), params_.bits_per_sample() / 8, buffer);
-
- if (pa_stream_write(output_stream_, buffer, requested_bytes, NULL, 0LL,
- PA_SEEK_RELATIVE) < 0) {
- if (source_callback_) {
- source_callback_->OnError(this);
- }
- }
-}
-
-void PulseAudioUnifiedStream::ReadData() {
- do {
- size_t length = 0;
- const void* data = NULL;
- pa_stream_peek(input_stream_, &data, &length);
- if (!data || length == 0)
- break;
-
- fifo_->Append(reinterpret_cast<const uint8*>(data), length);
-
- // Deliver the recording data to the renderer and drive the playout.
- int packet_size = params_.GetBytesPerBuffer();
- while (fifo_->forward_bytes() >= packet_size) {
- WriteData(packet_size);
- }
-
- // Checks if we still have data.
- pa_stream_drop(input_stream_);
- } while (pa_stream_readable_size(input_stream_) > 0);
-
- pa_threaded_mainloop_signal(pa_mainloop_, 0);
-}
-
-void PulseAudioUnifiedStream::Start(AudioSourceCallback* callback) {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
- CHECK(callback);
- CHECK(input_stream_);
- CHECK(output_stream_);
- AutoPulseLock auto_lock(pa_mainloop_);
-
- // Ensure the context and stream are ready.
- if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY &&
- pa_stream_get_state(output_stream_) != PA_STREAM_READY &&
- pa_stream_get_state(input_stream_) != PA_STREAM_READY) {
- callback->OnError(this);
- return;
- }
-
- source_callback_ = callback;
-
- fifo_->Clear();
-
- // Uncork (resume) the input stream.
- pa_stream_set_read_callback(input_stream_, &ReadCallback, this);
- pa_stream_readable_size(input_stream_);
- pa_operation* operation = pa_stream_cork(input_stream_, 0, NULL, NULL);
- WaitForOperationCompletion(pa_mainloop_, operation);
-
- // Uncork (resume) the output stream.
- // We use the recording stream to drive the playback, so we do not need to
- // register the write callback using pa_stream_set_write_callback().
- operation = pa_stream_cork(output_stream_, 0,
- &pulse::StreamSuccessCallback, pa_mainloop_);
- WaitForOperationCompletion(pa_mainloop_, operation);
-}
-
-void PulseAudioUnifiedStream::Stop() {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
-
- // Cork (pause) the stream. Waiting for the main loop lock will ensure
- // outstanding callbacks have completed.
- AutoPulseLock auto_lock(pa_mainloop_);
-
- // Set |source_callback_| to NULL so all FulfillWriteRequest() calls which may
- // occur while waiting on the flush and cork exit immediately.
- source_callback_ = NULL;
-
- // Set the read callback to NULL before flushing the stream, otherwise it
- // will cause deadlock on the operation.
- pa_stream_set_read_callback(input_stream_, NULL, NULL);
- pa_operation* operation = pa_stream_flush(
- input_stream_, &pulse::StreamSuccessCallback, pa_mainloop_);
- WaitForOperationCompletion(pa_mainloop_, operation);
-
- operation = pa_stream_cork(input_stream_, 1, &pulse::StreamSuccessCallback,
- pa_mainloop_);
- WaitForOperationCompletion(pa_mainloop_, operation);
-
- // Flush the stream prior to cork, doing so after will cause hangs. Write
- // callbacks are suspended while inside pa_threaded_mainloop_lock() so this
- // is all thread safe.
- operation = pa_stream_flush(
- output_stream_, &pulse::StreamSuccessCallback, pa_mainloop_);
- WaitForOperationCompletion(pa_mainloop_, operation);
-
- operation = pa_stream_cork(output_stream_, 1, &pulse::StreamSuccessCallback,
- pa_mainloop_);
- WaitForOperationCompletion(pa_mainloop_, operation);
-}
-
-void PulseAudioUnifiedStream::SetVolume(double volume) {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
-
- volume_ = static_cast<float>(volume);
-}
-
-void PulseAudioUnifiedStream::GetVolume(double* volume) {
- DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
-
- *volume = volume_;
-}
-
-} // namespace media
diff --git a/media/audio/pulse/pulse_unified.h b/media/audio/pulse/pulse_unified.h
deleted file mode 100644
index a800d09..0000000
--- a/media/audio/pulse/pulse_unified.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_PULSE_PULSE_UNIFIED_H_
-#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"
-#include "media/audio/audio_parameters.h"
-#include "media/base/audio_fifo.h"
-
-namespace media {
-
-class AudioManagerBase;
-class SeekableBuffer;
-
-class PulseAudioUnifiedStream : public AudioOutputStream {
- public:
- PulseAudioUnifiedStream(const AudioParameters& params,
- const std::string& input_device_id,
- AudioManagerBase* manager);
-
- virtual ~PulseAudioUnifiedStream();
-
- // Implementation of PulseAudioUnifiedStream.
- virtual bool Open() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void Start(AudioSourceCallback* callback) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void SetVolume(double volume) OVERRIDE;
- virtual void GetVolume(double* volume) OVERRIDE;
-
- private:
- // Called by PulseAudio when |pa_stream_| change state. If an unexpected
- // failure state change happens and |source_callback_| is set
- // this method will forward the error via OnError().
- static void StreamNotifyCallback(pa_stream* s, void* user_data);
-
- // Called by PulseAudio recording stream when it has data.
- static void ReadCallback(pa_stream* s, size_t length, void* user_data);
-
- // Helpers for ReadCallback() to read and write data.
- void WriteData(size_t requested_bytes);
- void ReadData();
-
- // Close() helper function to free internal structs.
- void Reset();
-
- // 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_;
-
- // PulseAudio API structs.
- pa_context* pa_context_;
- pa_threaded_mainloop* pa_mainloop_;
- pa_stream* input_stream_;
- pa_stream* output_stream_;
-
- // Float representation of volume from 0.0 to 1.0.
- float volume_;
-
- // Callback to audio data source. Must only be modified while holding a lock
- // on |pa_mainloop_| via pa_threaded_mainloop_lock().
- AudioSourceCallback* source_callback_;
-
- scoped_ptr<AudioBus> input_bus_;
- scoped_ptr<AudioBus> output_bus_;
-
- // Used for input to output buffering.
- scoped_ptr<media::SeekableBuffer> fifo_;
-
- // Temporary storage for recorded data. It gets a packet of data from
- // |fifo_| and deliver the data to OnMoreIOData() callback.
- scoped_ptr<uint8[]> input_data_buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(PulseAudioUnifiedStream);
-};
-
-} // namespace media
-
-#endif // MEDIA_AUDIO_PULSE_PULSE_UNIFIED_H_
diff --git a/media/audio/sounds/audio_stream_handler.cc b/media/audio/sounds/audio_stream_handler.cc
index f286356..9452f04 100644
--- a/media/audio/sounds/audio_stream_handler.cc
+++ b/media/audio/sounds/audio_stream_handler.cc
@@ -59,7 +59,7 @@ class AudioStreamHandler::AudioStreamContainer
p.bits_per_sample(),
kDefaultFrameCount);
stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(
- params, std::string(), std::string());
+ params, std::string());
if (!stream_ || !stream_->Open()) {
LOG(ERROR) << "Failed to open an output stream.";
return;
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 66d3891..c2b4d97 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -224,7 +224,7 @@ class AudioOutputStreamWrapper {
AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(
AudioParameters(format_, channel_layout_, sample_rate_,
bits_per_sample_, samples_per_packet_),
- std::string(), std::string());
+ 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 ec963a7..a8678cd 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -26,7 +26,6 @@
#include "media/audio/win/audio_low_latency_input_win.h"
#include "media/audio/win/audio_low_latency_output_win.h"
#include "media/audio/win/audio_manager_win.h"
-#include "media/audio/win/audio_unified_win.h"
#include "media/audio/win/core_audio_util_win.h"
#include "media/audio/win/device_enumeration_win.h"
#include "media/audio/win/wavein_input_win.h"
@@ -353,8 +352,7 @@ AudioOutputStream* AudioManagerWin::MakeLinearOutputStream(
// - WASAPIAudioOutputStream: Based on Core Audio (WASAPI) API.
AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) {
+ const std::string& device_id) {
DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
if (params.channels() > kWinMaxChannels)
return NULL;
@@ -369,15 +367,6 @@ AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream(
this, params, NumberOfWaveOutBuffers(), WAVE_MAPPER);
}
- // TODO(rtoy): support more than stereo input.
- if (params.input_channels() > 0) {
- DVLOG(1) << "WASAPIUnifiedStream is created.";
- DLOG_IF(ERROR, !device_id.empty() &&
- device_id != AudioManagerBase::kDefaultDeviceId)
- << "Opening by device id not supported by WASAPIUnifiedStream";
- return new WASAPIUnifiedStream(this, params, input_device_id);
- }
-
// Pass an empty string to indicate that we want the default device
// since we consistently only check for an empty string in
// WASAPIAudioOutputStream.
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index c2ac8d7..3a05ee6 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -39,8 +39,7 @@ class MEDIA_EXPORT AudioManagerWin : public AudioManagerBase {
const AudioParameters& params) OVERRIDE;
virtual AudioOutputStream* MakeLowLatencyOutputStream(
const AudioParameters& params,
- const std::string& device_id,
- const std::string& input_device_id) OVERRIDE;
+ const std::string& 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 dcb5ca3..72edad6 100644
--- a/media/audio/win/audio_output_win_unittest.cc
+++ b/media/audio/win/audio_output_win_unittest.cc
@@ -175,7 +175,7 @@ TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
8000, 16, 256),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
oas->Close();
}
@@ -191,29 +191,29 @@ TEST(WinAudioTest, SanityOnMakeParams) {
AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
- std::string(), std::string()));
+ std::string()));
EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
media::limits::kMaxSamplesPerPacket + 1),
- std::string(), std::string()));
+ std::string()));
}
// Test that it can be opened and closed.
@@ -227,7 +227,7 @@ TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
8000, 16, 256),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
EXPECT_TRUE(oas->Open());
oas->Close();
@@ -244,7 +244,7 @@ TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
8000, 16, 1024 * 1024 * 1024),
- std::string(), std::string());
+ std::string());
EXPECT_TRUE(NULL == oas);
if (oas)
oas->Close();
@@ -263,7 +263,7 @@ TEST(WinAudioTest, PCMWaveSlowSource) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
16000, 16, 256),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
TestSourceLaggy test_laggy(2, 90);
EXPECT_TRUE(oas->Open());
@@ -292,7 +292,7 @@ TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
@@ -323,7 +323,7 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
@@ -352,7 +352,7 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate / 2, 16,
samples_100_ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
@@ -392,7 +392,7 @@ TEST(WinAudioTest, PushSourceFile16KHz) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
kSampleRate, 16, kSamples100ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
EXPECT_TRUE(oas->Open());
@@ -429,7 +429,7 @@ TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
@@ -476,7 +476,7 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
CHANNEL_LAYOUT_MONO, sample_rate,
16, n * samples_10_ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(1, 200, sample_rate);
@@ -510,7 +510,7 @@ TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
- std::string(), std::string());
+ std::string());
ASSERT_TRUE(NULL != oas);
NiceMock<MockAudioSourceCallback> source;
@@ -664,7 +664,7 @@ TEST(WinAudioTest, SyncSocketBasic) {
AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
- std::string(), std::string());
+ 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
deleted file mode 100644
index 901c8b8..0000000
--- a/media/audio/win/audio_unified_win.cc
+++ /dev/null
@@ -1,984 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/win/audio_unified_win.h"
-
-#include <Functiondiscoverykeys_devpkey.h>
-
-#include "base/debug/trace_event.h"
-#ifndef NDEBUG
-#include "base/file_util.h"
-#include "base/path_service.h"
-#endif
-#include "base/time/time.h"
-#include "base/win/scoped_com_initializer.h"
-#include "media/audio/win/audio_manager_win.h"
-#include "media/audio/win/avrt_wrapper_win.h"
-#include "media/audio/win/core_audio_util_win.h"
-
-using base::win::ScopedComPtr;
-using base::win::ScopedCOMInitializer;
-using base::win::ScopedCoMem;
-
-// Smoothing factor in exponential smoothing filter where 0 < alpha < 1.
-// Larger values of alpha reduce the level of smoothing.
-// See http://en.wikipedia.org/wiki/Exponential_smoothing for details.
-static const double kAlpha = 0.1;
-
-// Compute a rate compensation which always attracts us back to a specified
-// target level over a period of |kCorrectionTimeSeconds|.
-static const double kCorrectionTimeSeconds = 0.1;
-
-#ifndef NDEBUG
-// Max number of columns in the output text file |kUnifiedAudioDebugFileName|.
-// See LogElementNames enumerator for details on what each column represents.
-static const size_t kMaxNumSampleTypes = 4;
-
-static const size_t kMaxNumParams = 2;
-
-// Max number of rows in the output file |kUnifiedAudioDebugFileName|.
-// Each row corresponds to one set of sample values for (approximately) the
-// same time instant (stored in the first column).
-static const size_t kMaxFileSamples = 10000;
-
-// Name of output debug file used for off-line analysis of measurements which
-// can be utilized for performance tuning of this class.
-static const char kUnifiedAudioDebugFileName[] = "unified_win_debug.txt";
-
-// Name of output debug file used for off-line analysis of measurements.
-// This file will contain a list of audio parameters.
-static const char kUnifiedAudioParamsFileName[] = "unified_win_params.txt";
-#endif
-
-// Use the acquired IAudioClock interface to derive a time stamp of the audio
-// sample which is currently playing through the speakers.
-static double SpeakerStreamPosInMilliseconds(IAudioClock* clock) {
- UINT64 device_frequency = 0, position = 0;
- if (FAILED(clock->GetFrequency(&device_frequency)) ||
- FAILED(clock->GetPosition(&position, NULL))) {
- return 0.0;
- }
- return base::Time::kMillisecondsPerSecond *
- (static_cast<double>(position) / device_frequency);
-}
-
-// Get a time stamp in milliseconds given number of audio frames in |num_frames|
-// using the current sample rate |fs| as scale factor.
-// Example: |num_frames| = 960 and |fs| = 48000 => 20 [ms].
-static double CurrentStreamPosInMilliseconds(UINT64 num_frames, DWORD fs) {
- return base::Time::kMillisecondsPerSecond *
- (static_cast<double>(num_frames) / fs);
-}
-
-// Convert a timestamp in milliseconds to byte units given the audio format
-// in |format|.
-// Example: |ts_milliseconds| equals 10, sample rate is 48000 and frame size
-// is 4 bytes per audio frame => 480 * 4 = 1920 [bytes].
-static int MillisecondsToBytes(double ts_milliseconds,
- const WAVEFORMATPCMEX& format) {
- double seconds = ts_milliseconds / base::Time::kMillisecondsPerSecond;
- return static_cast<int>(seconds * format.Format.nSamplesPerSec *
- format.Format.nBlockAlign + 0.5);
-}
-
-// Convert frame count to milliseconds given the audio format in |format|.
-static double FrameCountToMilliseconds(int num_frames,
- const WAVEFORMATPCMEX& format) {
- return (base::Time::kMillisecondsPerSecond * num_frames) /
- static_cast<double>(format.Format.nSamplesPerSec);
-}
-
-namespace media {
-
-WASAPIUnifiedStream::WASAPIUnifiedStream(AudioManagerWin* manager,
- 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()),
- opened_(false),
- volume_(1.0),
- output_buffer_size_frames_(0),
- input_buffer_size_frames_(0),
- endpoint_render_buffer_size_frames_(0),
- endpoint_capture_buffer_size_frames_(0),
- num_written_frames_(0),
- total_delay_ms_(0.0),
- total_delay_bytes_(0),
- source_(NULL),
- input_callback_received_(false),
- io_sample_rate_ratio_(1),
- target_fifo_frames_(0),
- average_delta_(0),
- fifo_rate_compensation_(1),
- update_output_delay_(false),
- capture_delay_ms_(0) {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::WASAPIUnifiedStream");
- VLOG(1) << "WASAPIUnifiedStream::WASAPIUnifiedStream()";
- DCHECK(manager_);
-
- VLOG(1) << "Input channels : " << input_channels_;
- VLOG(1) << "Output channels: " << output_channels_;
- VLOG(1) << "Sample rate : " << params_.sample_rate();
- VLOG(1) << "Buffer size : " << params.frames_per_buffer();
-
-#ifndef NDEBUG
- input_time_stamps_.reset(new int64[kMaxFileSamples]);
- num_frames_in_fifo_.reset(new int[kMaxFileSamples]);
- resampler_margin_.reset(new int[kMaxFileSamples]);
- fifo_rate_comps_.reset(new double[kMaxFileSamples]);
- num_elements_.reset(new int[kMaxNumSampleTypes]);
- std::fill(num_elements_.get(), num_elements_.get() + kMaxNumSampleTypes, 0);
- input_params_.reset(new int[kMaxNumParams]);
- output_params_.reset(new int[kMaxNumParams]);
-#endif
-
- DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE)
- << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled.";
-
- // Load the Avrt DLL if not already loaded. Required to support MMCSS.
- bool avrt_init = avrt::Initialize();
- DCHECK(avrt_init) << "Failed to load the avrt.dll";
-
- // All events are auto-reset events and non-signaled initially.
-
- // Create the event which the audio engine will signal each time a buffer
- // has been recorded.
- capture_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
-
- // Create the event which will be set in Stop() when straeming shall stop.
- stop_streaming_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
-}
-
-WASAPIUnifiedStream::~WASAPIUnifiedStream() {
- VLOG(1) << "WASAPIUnifiedStream::~WASAPIUnifiedStream()";
-#ifndef NDEBUG
- base::FilePath data_file_name;
- PathService::Get(base::DIR_EXE, &data_file_name);
- data_file_name = data_file_name.AppendASCII(kUnifiedAudioDebugFileName);
- data_file_ = base::OpenFile(data_file_name, "wt");
- DVLOG(1) << ">> Output file " << data_file_name.value() << " is created.";
-
- size_t n = 0;
- size_t elements_to_write = *std::min_element(
- num_elements_.get(), num_elements_.get() + kMaxNumSampleTypes);
- while (n < elements_to_write) {
- fprintf(data_file_, "%I64d %d %d %10.9f\n",
- input_time_stamps_[n],
- num_frames_in_fifo_[n],
- resampler_margin_[n],
- fifo_rate_comps_[n]);
- ++n;
- }
- base::CloseFile(data_file_);
-
- base::FilePath param_file_name;
- PathService::Get(base::DIR_EXE, &param_file_name);
- param_file_name = param_file_name.AppendASCII(kUnifiedAudioParamsFileName);
- param_file_ = base::OpenFile(param_file_name, "wt");
- DVLOG(1) << ">> Output file " << param_file_name.value() << " is created.";
- fprintf(param_file_, "%d %d\n", input_params_[0], input_params_[1]);
- fprintf(param_file_, "%d %d\n", output_params_[0], output_params_[1]);
- base::CloseFile(param_file_);
-#endif
-}
-
-bool WASAPIUnifiedStream::Open() {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::Open");
- DVLOG(1) << "WASAPIUnifiedStream::Open()";
- DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
- if (opened_)
- return true;
-
- AudioParameters hw_output_params;
- HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(
- eRender, eConsole, &hw_output_params);
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get preferred output audio parameters.";
- return false;
- }
-
- AudioParameters hw_input_params;
- if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
- // Query native parameters for the default capture device.
- hr = CoreAudioUtil::GetPreferredAudioParameters(
- eCapture, eConsole, &hw_input_params);
- } else {
- // Query native parameters for the capture device given by
- // |input_device_id_|.
- hr = CoreAudioUtil::GetPreferredAudioParameters(
- input_device_id_, &hw_input_params);
- }
- if (FAILED(hr)) {
- LOG(ERROR) << "Failed to get preferred input audio parameters.";
- return false;
- }
-
- // It is currently only possible to open up the output audio device using
- // the native number of channels.
- if (output_channels_ != hw_output_params.channels()) {
- LOG(ERROR) << "Audio device does not support requested output channels.";
- return false;
- }
-
- // It is currently only possible to open up the input audio device using
- // the native number of channels. If the client asks for a higher channel
- // count, we will do channel upmixing in this class. The most typical
- // example is that the client provides stereo but the hardware can only be
- // opened in mono mode. We will do mono to stereo conversion in this case.
- if (input_channels_ < hw_input_params.channels()) {
- LOG(ERROR) << "Audio device does not support requested input channels.";
- return false;
- } else if (input_channels_ > hw_input_params.channels()) {
- ChannelLayout input_layout =
- GuessChannelLayout(hw_input_params.channels());
- ChannelLayout output_layout = GuessChannelLayout(input_channels_);
- channel_mixer_.reset(new ChannelMixer(input_layout, output_layout));
- DVLOG(1) << "Remixing input channel layout from " << input_layout
- << " to " << output_layout << "; from "
- << hw_input_params.channels() << " channels to "
- << input_channels_;
- }
-
- if (hw_output_params.sample_rate() != params_.sample_rate()) {
- LOG(ERROR) << "Requested sample-rate: " << params_.sample_rate()
- << " must match the hardware sample-rate: "
- << hw_output_params.sample_rate();
- return false;
- }
-
- if (hw_output_params.frames_per_buffer() != params_.frames_per_buffer()) {
- LOG(ERROR) << "Requested buffer size: " << params_.frames_per_buffer()
- << " must match the hardware buffer size: "
- << hw_output_params.frames_per_buffer();
- return false;
- }
-
- // Set up WAVEFORMATPCMEX structures for input and output given the specified
- // audio parameters.
- SetIOFormats(hw_input_params, params_);
-
- // Create the input and output busses.
- input_bus_ = AudioBus::Create(
- hw_input_params.channels(), input_buffer_size_frames_);
- output_bus_ = AudioBus::Create(params_);
-
- // One extra bus is needed for the input channel mixing case.
- if (channel_mixer_) {
- DCHECK_LT(hw_input_params.channels(), input_channels_);
- // The size of the |channel_bus_| must be the same as the size of the
- // output bus to ensure that the channel manager can deal with both
- // resampled and non-resampled data as input.
- channel_bus_ = AudioBus::Create(
- input_channels_, params_.frames_per_buffer());
- }
-
- // Check if FIFO and resampling is required to match the input rate to the
- // output rate. If so, a special thread loop, optimized for this case, will
- // be used. This mode is also called varispeed mode.
- // Note that we can also use this mode when input and output rates are the
- // same but native buffer sizes differ (can happen if two different audio
- // devices are used). For this case, the resampler uses a target ratio of
- // 1.0 but SetRatio is called to compensate for clock-drift. The FIFO is
- // required to compensate for the difference in buffer sizes.
- // TODO(henrika): we could perhaps improve the performance for the second
- // case here by only using the FIFO and avoid resampling. Not sure how much
- // that would give and we risk not compensation for clock drift.
- if (hw_input_params.sample_rate() != params_.sample_rate() ||
- hw_input_params.frames_per_buffer() != params_.frames_per_buffer()) {
- DoVarispeedInitialization(hw_input_params, params_);
- }
-
- // Render side (event driven only in varispeed mode):
-
- ScopedComPtr<IAudioClient> audio_output_client =
- CoreAudioUtil::CreateDefaultClient(eRender, eConsole);
- if (!audio_output_client)
- return false;
-
- if (!CoreAudioUtil::IsFormatSupported(audio_output_client,
- share_mode_,
- &output_format_)) {
- return false;
- }
-
- if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
- // The |render_event_| will be NULL unless varispeed mode is utilized.
- hr = CoreAudioUtil::SharedModeInitialize(
- audio_output_client, &output_format_, render_event_.Get(),
- &endpoint_render_buffer_size_frames_);
- } else {
- // TODO(henrika): add support for AUDCLNT_SHAREMODE_EXCLUSIVE.
- }
- if (FAILED(hr))
- return false;
-
- ScopedComPtr<IAudioRenderClient> audio_render_client =
- CoreAudioUtil::CreateRenderClient(audio_output_client);
- if (!audio_render_client)
- return false;
-
- // Capture side (always event driven but format depends on varispeed or not):
-
- ScopedComPtr<IAudioClient> audio_input_client;
- if (input_device_id_ == AudioManagerBase::kDefaultDeviceId) {
- audio_input_client = CoreAudioUtil::CreateDefaultClient(eCapture, eConsole);
- } else {
- ScopedComPtr<IMMDevice> audio_input_device(
- CoreAudioUtil::CreateDevice(input_device_id_));
- audio_input_client = CoreAudioUtil::CreateClient(audio_input_device);
- }
- if (!audio_input_client)
- return false;
-
- if (!CoreAudioUtil::IsFormatSupported(audio_input_client,
- share_mode_,
- &input_format_)) {
- return false;
- }
-
- if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
- // Include valid event handle for event-driven initialization.
- // The input side is always event driven independent of if varispeed is
- // used or not.
- hr = CoreAudioUtil::SharedModeInitialize(
- audio_input_client, &input_format_, capture_event_.Get(),
- &endpoint_capture_buffer_size_frames_);
- } else {
- // TODO(henrika): add support for AUDCLNT_SHAREMODE_EXCLUSIVE.
- }
- if (FAILED(hr))
- return false;
-
- ScopedComPtr<IAudioCaptureClient> audio_capture_client =
- CoreAudioUtil::CreateCaptureClient(audio_input_client);
- if (!audio_capture_client)
- return false;
-
- // Varispeed mode requires additional preparations.
- if (VarispeedMode())
- ResetVarispeed();
-
- // Store all valid COM interfaces.
- audio_output_client_ = audio_output_client;
- audio_render_client_ = audio_render_client;
- audio_input_client_ = audio_input_client;
- audio_capture_client_ = audio_capture_client;
-
- opened_ = true;
- return SUCCEEDED(hr);
-}
-
-void WASAPIUnifiedStream::Start(AudioSourceCallback* callback) {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::Start");
- DVLOG(1) << "WASAPIUnifiedStream::Start()";
- DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
- CHECK(callback);
- CHECK(opened_);
-
- if (audio_io_thread_) {
- CHECK_EQ(callback, source_);
- return;
- }
-
- source_ = callback;
-
- if (VarispeedMode()) {
- ResetVarispeed();
- fifo_rate_compensation_ = 1.0;
- average_delta_ = 0.0;
- input_callback_received_ = false;
- update_output_delay_ = false;
- }
-
- // Create and start the thread that will listen for capture events.
- // We will also listen on render events on the same thread if varispeed
- // mode is utilized.
- audio_io_thread_.reset(
- new base::DelegateSimpleThread(this, "wasapi_io_thread"));
- audio_io_thread_->Start();
- if (!audio_io_thread_->HasBeenStarted()) {
- DLOG(ERROR) << "Failed to start WASAPI IO thread.";
- return;
- }
-
- // Start input streaming data between the endpoint buffer and the audio
- // engine.
- HRESULT hr = audio_input_client_->Start();
- if (FAILED(hr)) {
- StopAndJoinThread(hr);
- return;
- }
-
- // Ensure that the endpoint buffer is prepared with silence.
- if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
- if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence(
- audio_output_client_, audio_render_client_)) {
- DLOG(WARNING) << "Failed to prepare endpoint buffers with silence.";
- return;
- }
- }
- num_written_frames_ = endpoint_render_buffer_size_frames_;
-
- // Start output streaming data between the endpoint buffer and the audio
- // engine.
- hr = audio_output_client_->Start();
- if (FAILED(hr)) {
- StopAndJoinThread(hr);
- return;
- }
-}
-
-void WASAPIUnifiedStream::Stop() {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::Stop");
- DVLOG(1) << "WASAPIUnifiedStream::Stop()";
- DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
- if (!audio_io_thread_)
- return;
-
- // Stop input audio streaming.
- HRESULT hr = audio_input_client_->Stop();
- if (FAILED(hr)) {
- DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
- << "Failed to stop input streaming: " << std::hex << hr;
- }
-
- // Stop output audio streaming.
- hr = audio_output_client_->Stop();
- if (FAILED(hr)) {
- DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
- << "Failed to stop output streaming: " << std::hex << hr;
- }
-
- // Wait until the thread completes and perform cleanup.
- SetEvent(stop_streaming_event_.Get());
- audio_io_thread_->Join();
- audio_io_thread_.reset();
-
- // Ensure that we don't quit the main thread loop immediately next
- // time Start() is called.
- ResetEvent(stop_streaming_event_.Get());
-
- // Clear source callback, it'll be set again on the next Start() call.
- source_ = NULL;
-
- // Flush all pending data and reset the audio clock stream position to 0.
- hr = audio_output_client_->Reset();
- if (FAILED(hr)) {
- DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
- << "Failed to reset output streaming: " << std::hex << hr;
- }
-
- audio_input_client_->Reset();
- if (FAILED(hr)) {
- DLOG_IF(ERROR, hr != AUDCLNT_E_NOT_INITIALIZED)
- << "Failed to reset input streaming: " << std::hex << hr;
- }
-
- // Extra safety check to ensure that the buffers are cleared.
- // If the buffers are not cleared correctly, the next call to Start()
- // would fail with AUDCLNT_E_BUFFER_ERROR at IAudioRenderClient::GetBuffer().
- // TODO(henrika): this check is is only needed for shared-mode streams.
- UINT32 num_queued_frames = 0;
- audio_output_client_->GetCurrentPadding(&num_queued_frames);
- DCHECK_EQ(0u, num_queued_frames);
-}
-
-void WASAPIUnifiedStream::Close() {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::Close");
- DVLOG(1) << "WASAPIUnifiedStream::Close()";
- DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_);
-
- // It is valid to call Close() before calling open or Start().
- // It is also valid to call Close() after Start() has been called.
- Stop();
-
- // Inform the audio manager that we have been closed. This will cause our
- // destruction.
- manager_->ReleaseOutputStream(this);
-}
-
-void WASAPIUnifiedStream::SetVolume(double volume) {
- DVLOG(1) << "SetVolume(volume=" << volume << ")";
- if (volume < 0 || volume > 1)
- return;
- volume_ = volume;
-}
-
-void WASAPIUnifiedStream::GetVolume(double* volume) {
- DVLOG(1) << "GetVolume()";
- *volume = static_cast<double>(volume_);
-}
-
-
-void WASAPIUnifiedStream::ProvideInput(int frame_delay, AudioBus* audio_bus) {
- // TODO(henrika): utilize frame_delay?
- // A non-zero framed delay means multiple callbacks were necessary to
- // fulfill the requested number of frames.
- if (frame_delay > 0)
- DVLOG(3) << "frame_delay: " << frame_delay;
-
-#ifndef NDEBUG
- resampler_margin_[num_elements_[RESAMPLER_MARGIN]] =
- fifo_->frames() - audio_bus->frames();
- num_elements_[RESAMPLER_MARGIN]++;
-#endif
-
- if (fifo_->frames() < audio_bus->frames()) {
- DVLOG(ERROR) << "Not enough data in the FIFO ("
- << fifo_->frames() << " < " << audio_bus->frames() << ")";
- audio_bus->Zero();
- return;
- }
-
- fifo_->Consume(audio_bus, 0, audio_bus->frames());
-}
-
-void WASAPIUnifiedStream::SetIOFormats(const AudioParameters& input_params,
- const AudioParameters& output_params) {
- for (int n = 0; n < 2; ++n) {
- const AudioParameters& params = (n == 0) ? input_params : output_params;
- WAVEFORMATPCMEX* xformat = (n == 0) ? &input_format_ : &output_format_;
- WAVEFORMATEX* format = &xformat->Format;
-
- // Begin with the WAVEFORMATEX structure that specifies the basic format.
- format->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- format->nChannels = params.channels();
- format->nSamplesPerSec = params.sample_rate();
- format->wBitsPerSample = params.bits_per_sample();
- format->nBlockAlign = (format->wBitsPerSample / 8) * format->nChannels;
- format->nAvgBytesPerSec = format->nSamplesPerSec * format->nBlockAlign;
- format->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
-
- // Add the parts which are unique to WAVE_FORMAT_EXTENSIBLE.
- // Note that we always open up using the native channel layout.
- (*xformat).Samples.wValidBitsPerSample = format->wBitsPerSample;
- (*xformat).dwChannelMask =
- CoreAudioUtil::GetChannelConfig(
- std::string(), n == 0 ? eCapture : eRender);
- (*xformat).SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- }
-
- input_buffer_size_frames_ = input_params.frames_per_buffer();
- output_buffer_size_frames_ = output_params.frames_per_buffer();
- VLOG(1) << "#audio frames per input buffer : " << input_buffer_size_frames_;
- VLOG(1) << "#audio frames per output buffer: " << output_buffer_size_frames_;
-
-#ifndef NDEBUG
- input_params_[0] = input_format_.Format.nSamplesPerSec;
- input_params_[1] = input_buffer_size_frames_;
- output_params_[0] = output_format_.Format.nSamplesPerSec;
- output_params_[1] = output_buffer_size_frames_;
-#endif
-}
-
-void WASAPIUnifiedStream::DoVarispeedInitialization(
- const AudioParameters& input_params, const AudioParameters& output_params) {
- DVLOG(1) << "WASAPIUnifiedStream::DoVarispeedInitialization()";
-
- // A FIFO is required in this mode for input to output buffering.
- // Note that it will add some latency.
- fifo_.reset(new AudioFifo(input_params.channels(), kFifoSize));
- VLOG(1) << "Using FIFO of size " << fifo_->max_frames()
- << " (#channels=" << input_params.channels() << ")";
-
- // Create the multi channel resampler using the initial sample rate ratio.
- // We will call MultiChannelResampler::SetRatio() during runtime to
- // allow arbitrary combinations of input and output devices running off
- // different clocks and using different drivers, with potentially
- // differing sample-rates. Note that the requested block size is given by
- // the native input buffer size |input_buffer_size_frames_|.
- io_sample_rate_ratio_ = input_params.sample_rate() /
- static_cast<double>(output_params.sample_rate());
- DVLOG(2) << "io_sample_rate_ratio: " << io_sample_rate_ratio_;
- resampler_.reset(new MultiChannelResampler(
- input_params.channels(), io_sample_rate_ratio_, input_buffer_size_frames_,
- base::Bind(&WASAPIUnifiedStream::ProvideInput, base::Unretained(this))));
- VLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
- << output_params.sample_rate();
-
- // The optimal number of frames we'd like to keep in the FIFO at all times.
- // The actual size will vary but the goal is to ensure that the average size
- // is given by this value.
- target_fifo_frames_ = kTargetFifoSafetyFactor * input_buffer_size_frames_;
- VLOG(1) << "Target FIFO size: " << target_fifo_frames_;
-
- // Create the event which the audio engine will signal each time it
- // wants an audio buffer to render.
- render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
-
- // Allocate memory for temporary audio bus used to store resampled input
- // audio.
- resampled_bus_ = AudioBus::Create(
- input_params.channels(), output_buffer_size_frames_);
-
- // Buffer initial silence corresponding to target I/O buffering.
- ResetVarispeed();
-}
-
-void WASAPIUnifiedStream::ResetVarispeed() {
- DCHECK(VarispeedMode());
-
- // Buffer initial silence corresponding to target I/O buffering.
- fifo_->Clear();
- scoped_ptr<AudioBus> silence =
- AudioBus::Create(input_format_.Format.nChannels,
- target_fifo_frames_);
- silence->Zero();
- fifo_->Push(silence.get());
- resampler_->Flush();
-}
-
-void WASAPIUnifiedStream::Run() {
- ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
-
- // Increase the thread priority.
- audio_io_thread_->SetThreadPriority(base::kThreadPriority_RealtimeAudio);
-
- // Enable MMCSS to ensure that this thread receives prioritized access to
- // CPU resources.
- // TODO(henrika): investigate if it is possible to include these additional
- // settings in SetThreadPriority() as well.
- DWORD task_index = 0;
- HANDLE mm_task = avrt::AvSetMmThreadCharacteristics(L"Pro Audio",
- &task_index);
- bool mmcss_is_ok =
- (mm_task && avrt::AvSetMmThreadPriority(mm_task, AVRT_PRIORITY_CRITICAL));
- if (!mmcss_is_ok) {
- // Failed to enable MMCSS on this thread. It is not fatal but can lead
- // to reduced QoS at high load.
- DWORD err = GetLastError();
- LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ").";
- }
-
- // The IAudioClock interface enables us to monitor a stream's data
- // rate and the current position in the stream. Allocate it before we
- // start spinning.
- ScopedComPtr<IAudioClock> audio_output_clock;
- HRESULT hr = audio_output_client_->GetService(
- __uuidof(IAudioClock), audio_output_clock.ReceiveVoid());
- LOG_IF(WARNING, FAILED(hr)) << "Failed to create IAudioClock: "
- << std::hex << hr;
-
- bool streaming = true;
- bool error = false;
-
- HANDLE wait_array[3];
- size_t num_handles = 0;
- wait_array[num_handles++] = stop_streaming_event_;
- wait_array[num_handles++] = capture_event_;
- if (render_event_) {
- // One extra event handle is needed in varispeed mode.
- wait_array[num_handles++] = render_event_;
- }
-
- // Keep streaming audio until stop event is signaled.
- // Capture events are always used but render events are only active in
- // varispeed mode.
- while (streaming && !error) {
- // Wait for a close-down event, or a new capture event.
- DWORD wait_result = WaitForMultipleObjects(num_handles,
- wait_array,
- FALSE,
- INFINITE);
- switch (wait_result) {
- case WAIT_OBJECT_0 + 0:
- // |stop_streaming_event_| has been set.
- streaming = false;
- break;
- case WAIT_OBJECT_0 + 1:
- // |capture_event_| has been set
- if (VarispeedMode()) {
- ProcessInputAudio();
- } else {
- ProcessInputAudio();
- ProcessOutputAudio(audio_output_clock);
- }
- break;
- case WAIT_OBJECT_0 + 2:
- DCHECK(VarispeedMode());
- // |render_event_| has been set
- ProcessOutputAudio(audio_output_clock);
- break;
- default:
- error = true;
- break;
- }
- }
-
- if (streaming && error) {
- // Stop audio streaming since something has gone wrong in our main thread
- // loop. Note that, we are still in a "started" state, hence a Stop() call
- // is required to join the thread properly.
- audio_input_client_->Stop();
- audio_output_client_->Stop();
- PLOG(ERROR) << "WASAPI streaming failed.";
- }
-
- // Disable MMCSS.
- if (mm_task && !avrt::AvRevertMmThreadCharacteristics(mm_task)) {
- PLOG(WARNING) << "Failed to disable MMCSS";
- }
-}
-
-void WASAPIUnifiedStream::ProcessInputAudio() {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::ProcessInputAudio");
-
- BYTE* data_ptr = NULL;
- UINT32 num_captured_frames = 0;
- DWORD flags = 0;
- UINT64 device_position = 0;
- UINT64 capture_time_stamp = 0;
-
- const int bytes_per_sample = input_format_.Format.wBitsPerSample >> 3;
-
- base::TimeTicks now_tick = base::TimeTicks::HighResNow();
-
-#ifndef NDEBUG
- if (VarispeedMode()) {
- input_time_stamps_[num_elements_[INPUT_TIME_STAMP]] =
- now_tick.ToInternalValue();
- num_elements_[INPUT_TIME_STAMP]++;
- }
-#endif
-
- // Retrieve the amount of data in the capture endpoint buffer.
- // |endpoint_capture_time_stamp| is the value of the performance
- // counter at the time that the audio endpoint device recorded
- // the device position of the first audio frame in the data packet.
- HRESULT hr = audio_capture_client_->GetBuffer(&data_ptr,
- &num_captured_frames,
- &flags,
- &device_position,
- &capture_time_stamp);
- if (FAILED(hr)) {
- DLOG(ERROR) << "Failed to get data from the capture buffer";
- return;
- }
-
- if (hr == AUDCLNT_S_BUFFER_EMPTY) {
- // The return coded is a success code but a new packet is *not* available
- // and none of the output parameters in the GetBuffer() call contains valid
- // values. Best we can do is to deliver silence and avoid setting
- // |input_callback_received_| since this only seems to happen for the
- // initial event(s) on some devices.
- input_bus_->Zero();
- } else {
- // Valid data has been recorded and it is now OK to set the flag which
- // informs the render side that capturing has started.
- input_callback_received_ = true;
- }
-
- if (num_captured_frames != 0) {
- if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
- // Clear out the capture buffer since silence is reported.
- input_bus_->Zero();
- } else {
- // Store captured data in an audio bus after de-interleaving
- // the data to match the audio bus structure.
- input_bus_->FromInterleaved(
- data_ptr, num_captured_frames, bytes_per_sample);
- }
- }
-
- hr = audio_capture_client_->ReleaseBuffer(num_captured_frames);
- DLOG_IF(ERROR, FAILED(hr)) << "Failed to release capture buffer";
-
- // Buffer input into FIFO if varispeed mode is used. The render event
- // will drive resampling of this data to match the output side.
- if (VarispeedMode()) {
- int available_frames = fifo_->max_frames() - fifo_->frames();
- if (input_bus_->frames() <= available_frames) {
- fifo_->Push(input_bus_.get());
- }
-#ifndef NDEBUG
- num_frames_in_fifo_[num_elements_[NUM_FRAMES_IN_FIFO]] =
- fifo_->frames();
- num_elements_[NUM_FRAMES_IN_FIFO]++;
-#endif
- }
-
- // Save resource by not asking for new delay estimates each time.
- // These estimates are fairly stable and it is perfectly safe to only
- // sample at a rate of ~1Hz.
- // TODO(henrika): we might have to increase the update rate in varispeed
- // mode since the delay variations are higher in this mode.
- if ((now_tick - last_delay_sample_time_).InMilliseconds() >
- kTimeDiffInMillisecondsBetweenDelayMeasurements &&
- input_callback_received_) {
- // Calculate the estimated capture delay, i.e., the latency between
- // the recording time and the time we when we are notified about
- // the recorded data. Note that the capture time stamp is given in
- // 100-nanosecond (0.1 microseconds) units.
- base::TimeDelta diff =
- now_tick - base::TimeTicks::FromInternalValue(0.1 * capture_time_stamp);
- capture_delay_ms_ = diff.InMillisecondsF();
-
- last_delay_sample_time_ = now_tick;
- update_output_delay_ = true;
- }
-}
-
-void WASAPIUnifiedStream::ProcessOutputAudio(IAudioClock* audio_output_clock) {
- TRACE_EVENT0("audio", "WASAPIUnifiedStream::ProcessOutputAudio");
-
- if (!input_callback_received_) {
- if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) {
- if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence(
- audio_output_client_, audio_render_client_))
- DLOG(WARNING) << "Failed to prepare endpoint buffers with silence.";
- }
- return;
- }
-
- // Rate adjusted resampling is required in varispeed mode. It means that
- // recorded audio samples will be read from the FIFO, resampled to match the
- // output sample-rate and then stored in |resampled_bus_|.
- if (VarispeedMode()) {
- // Calculate a varispeed rate scalar factor to compensate for drift between
- // input and output. We use the actual number of frames still in the FIFO
- // compared with the ideal value of |target_fifo_frames_|.
- int delta = fifo_->frames() - target_fifo_frames_;
-
- // Average |delta| because it can jitter back/forth quite frequently
- // by +/- the hardware buffer-size *if* the input and output callbacks are
- // happening at almost exactly the same time. Also, if the input and output
- // sample-rates are different then |delta| will jitter quite a bit due to
- // the rate conversion happening in the varispeed, plus the jittering of
- // the callbacks. The average value is what's important here.
- // We use an exponential smoothing filter to reduce the variations.
- average_delta_ += kAlpha * (delta - average_delta_);
-
- // Compute a rate compensation which always attracts us back to the
- // |target_fifo_frames_| over a period of kCorrectionTimeSeconds.
- double correction_time_frames =
- kCorrectionTimeSeconds * output_format_.Format.nSamplesPerSec;
- fifo_rate_compensation_ =
- (correction_time_frames + average_delta_) / correction_time_frames;
-
-#ifndef NDEBUG
- fifo_rate_comps_[num_elements_[RATE_COMPENSATION]] =
- fifo_rate_compensation_;
- num_elements_[RATE_COMPENSATION]++;
-#endif
-
- // Adjust for FIFO drift.
- const double new_ratio = io_sample_rate_ratio_ * fifo_rate_compensation_;
- resampler_->SetRatio(new_ratio);
- // Get resampled input audio from FIFO where the size is given by the
- // output side.
- resampler_->Resample(resampled_bus_->frames(), resampled_bus_.get());
- }
-
- // Derive a new total delay estimate if the capture side has set the
- // |update_output_delay_| flag.
- if (update_output_delay_) {
- // Calculate the estimated render delay, i.e., the time difference
- // between the time when data is added to the endpoint buffer and
- // when the data is played out on the actual speaker.
- const double stream_pos = CurrentStreamPosInMilliseconds(
- num_written_frames_ + output_buffer_size_frames_,
- output_format_.Format.nSamplesPerSec);
- const double speaker_pos =
- SpeakerStreamPosInMilliseconds(audio_output_clock);
- const double render_delay_ms = stream_pos - speaker_pos;
- const double fifo_delay_ms = VarispeedMode() ?
- FrameCountToMilliseconds(target_fifo_frames_, input_format_) : 0;
-
- // Derive the total delay, i.e., the sum of the input and output
- // delays. Also convert the value into byte units. An extra FIFO delay
- // is added for varispeed usage cases.
- total_delay_ms_ = VarispeedMode() ?
- capture_delay_ms_ + render_delay_ms + fifo_delay_ms :
- capture_delay_ms_ + render_delay_ms;
- DVLOG(2) << "total_delay_ms : " << total_delay_ms_;
- DVLOG(3) << " capture_delay_ms: " << capture_delay_ms_;
- DVLOG(3) << " render_delay_ms : " << render_delay_ms;
- DVLOG(3) << " fifo_delay_ms : " << fifo_delay_ms;
- total_delay_bytes_ = MillisecondsToBytes(total_delay_ms_, output_format_);
-
- // Wait for new signal from the capture side.
- update_output_delay_ = false;
- }
-
- // Select source depending on if varispeed is utilized or not.
- // Also, the source might be the output of a channel mixer if channel mixing
- // is required to match the native input channels to the number of input
- // channels used by the client (given by |input_channels_| in this case).
- AudioBus* input_bus = VarispeedMode() ?
- resampled_bus_.get() : input_bus_.get();
- if (channel_mixer_) {
- DCHECK_EQ(input_bus->frames(), channel_bus_->frames());
- // Most common case is 1->2 channel upmixing.
- channel_mixer_->Transform(input_bus, channel_bus_.get());
- // Use the output from the channel mixer as new input bus.
- input_bus = channel_bus_.get();
- }
-
- // Prepare for rendering by calling OnMoreIOData().
- int frames_filled = source_->OnMoreIOData(
- input_bus,
- output_bus_.get(),
- AudioBuffersState(0, total_delay_bytes_));
- DCHECK_EQ(frames_filled, output_bus_->frames());
-
- // Keep track of number of rendered frames since we need it for
- // our delay calculations.
- num_written_frames_ += frames_filled;
-
- // Derive the the amount of available space in the endpoint buffer.
- // Avoid render attempt if there is no room for a captured packet.
- UINT32 num_queued_frames = 0;
- audio_output_client_->GetCurrentPadding(&num_queued_frames);
- if (endpoint_render_buffer_size_frames_ - num_queued_frames <
- output_buffer_size_frames_)
- return;
-
- // Grab all available space in the rendering endpoint buffer
- // into which the client can write a data packet.
- uint8* audio_data = NULL;
- HRESULT hr = audio_render_client_->GetBuffer(output_buffer_size_frames_,
- &audio_data);
- if (FAILED(hr)) {
- DLOG(ERROR) << "Failed to access render buffer";
- return;
- }
-
- const int bytes_per_sample = output_format_.Format.wBitsPerSample >> 3;
-
- // Convert the audio bus content to interleaved integer data using
- // |audio_data| as destination.
- output_bus_->Scale(volume_);
- output_bus_->ToInterleaved(
- output_buffer_size_frames_, bytes_per_sample, audio_data);
-
- // Release the buffer space acquired in the GetBuffer() call.
- audio_render_client_->ReleaseBuffer(output_buffer_size_frames_, 0);
- DLOG_IF(ERROR, FAILED(hr)) << "Failed to release render buffer";
-
- return;
-}
-
-void WASAPIUnifiedStream::HandleError(HRESULT err) {
- CHECK((started() && GetCurrentThreadId() == audio_io_thread_->tid()) ||
- (!started() && GetCurrentThreadId() == creating_thread_id_));
- NOTREACHED() << "Error code: " << std::hex << err;
- if (source_)
- source_->OnError(this);
-}
-
-void WASAPIUnifiedStream::StopAndJoinThread(HRESULT err) {
- CHECK(GetCurrentThreadId() == creating_thread_id_);
- DCHECK(audio_io_thread_.get());
- SetEvent(stop_streaming_event_.Get());
- audio_io_thread_->Join();
- audio_io_thread_.reset();
- HandleError(err);
-}
-
-} // namespace media
diff --git a/media/audio/win/audio_unified_win.h b/media/audio/win/audio_unified_win.h
deleted file mode 100644
index 76c5329..0000000
--- a/media/audio/win/audio_unified_win.h
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_WIN_AUDIO_UNIFIED_WIN_H_
-#define MEDIA_AUDIO_WIN_AUDIO_UNIFIED_WIN_H_
-
-#include <Audioclient.h>
-#include <MMDeviceAPI.h>
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/win/scoped_co_mem.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/scoped_handle.h"
-#include "media/audio/audio_io.h"
-#include "media/audio/audio_parameters.h"
-#include "media/base/audio_fifo.h"
-#include "media/base/channel_mixer.h"
-#include "media/base/media_export.h"
-#include "media/base/multi_channel_resampler.h"
-
-namespace media {
-
-class AudioManagerWin;
-
-// Implementation of AudioOutputStream for Windows using the Core Audio API
-// where both capturing and rendering takes place on the same thread to enable
-// audio I/O. This class allows arbitrary combinations of input and output
-// devices running off different clocks and using different drivers, with
-// potentially differing sample-rates.
-//
-// It is required to first acquire the native sample rate of the selected
-// output device and then use the same rate when creating this object.
-// The inner operation depends on the input sample rate which is determined
-// during construction. Three different main modes are supported:
-//
-// 1) input rate == output rate => input side drives output side directly.
-// 2) input rate != output rate => both sides are driven independently by
-// events and a FIFO plus a resampling unit is used to compensate for
-// differences in sample rates between the two sides.
-// 3) input rate == output rate but native buffer sizes are not identical =>
-// same inner functionality as in (2) to compensate for the differences
-// in buffer sizes and also compensate for any potential clock drift
-// between the two devices.
-//
-// Mode detection is is done at construction and using mode (1) will lead to
-// best performance (lower delay and no "varispeed distortion"), i.e., it is
-// recommended to use same sample rates for input and output. Mode (2) uses a
-// resampler which supports rate adjustments to fine tune for things like
-// clock drift and differences in sample rates between different devices.
-// Mode (2) - which uses a FIFO and a adjustable multi-channel resampler -
-// is also called the varispeed mode and it is used for case (3) as well to
-// compensate for the difference in buffer sizes mainly.
-// Mode (3) can happen if two different audio devices are used.
-// As an example: some devices needs a buffer size of 441 @ 44.1kHz and others
-// 448 @ 44.1kHz. This is a rare case and will only happen for sample rates
-// which are even multiples of 11025 Hz (11025, 22050, 44100, 88200 etc.).
-//
-// Implementation notes:
-//
-// - Open() can fail if the input and output parameters do not fulfill
-// certain conditions. See source for Open() for more details.
-// - Channel mixing will be performed if the clients asks for a larger
-// number of channels than the native audio layer provides.
-// Example: client wants stereo but audio layer provides mono. In this case
-// upmixing from mono to stereo (1->2) will be done.
-//
-// TODO(henrika):
-//
-// - Add support for exclusive mode.
-// - Add support for KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, i.e., 32-bit float
-// as internal sample-value representation.
-// - Perform fine-tuning for non-matching sample rates to reduce latency.
-//
-class MEDIA_EXPORT WASAPIUnifiedStream
- : public AudioOutputStream,
- public base::DelegateSimpleThread::Delegate {
- public:
- // 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 std::string& input_device_id);
-
- // The dtor is typically called by the AudioManager only and it is usually
- // triggered by calling AudioOutputStream::Close().
- virtual ~WASAPIUnifiedStream();
-
- // Implementation of AudioOutputStream.
- virtual bool Open() OVERRIDE;
- virtual void Start(AudioSourceCallback* callback) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void SetVolume(double volume) OVERRIDE;
- virtual void GetVolume(double* volume) OVERRIDE;
-
- bool started() const {
- return audio_io_thread_.get() != NULL;
- }
-
- // Returns true if input sample rate differs from the output sample rate.
- // A FIFO and a adjustable multi-channel resampler are utilized in this mode.
- bool VarispeedMode() const { return (fifo_ && resampler_); }
-
- private:
- enum {
- // Time in milliseconds between two successive delay measurements.
- // We save resources by not updating the delay estimates for each capture
- // event (typically 100Hz rate).
- kTimeDiffInMillisecondsBetweenDelayMeasurements = 1000,
-
- // Max possible FIFO size.
- kFifoSize = 16384,
-
- // This value was determined empirically for minimum latency while still
- // guarding against FIFO under-runs. The actual target size will be equal
- // to kTargetFifoSafetyFactor * (native input buffer size).
- // TODO(henrika): tune this value for lowest possible latency for all
- // possible sample rate combinations.
- kTargetFifoSafetyFactor = 2
- };
-
- // Additional initialization required when input and output sample rate
- // differs. Allocates resources for |fifo_|, |resampler_|, |render_event_|,
- // and the |capture_bus_| and configures the |input_format_| structure
- // given the provided input and output audio parameters.
- void DoVarispeedInitialization(const AudioParameters& input_params,
- const AudioParameters& output_params);
-
- // Clears varispeed related components such as the FIFO and the resampler.
- void ResetVarispeed();
-
- // Builds WAVEFORMATEX structures for input and output based on input and
- // output audio parameters.
- void SetIOFormats(const AudioParameters& input_params,
- const AudioParameters& output_params);
-
- // DelegateSimpleThread::Delegate implementation.
- virtual void Run() OVERRIDE;
-
- // MultiChannelResampler::MultiChannelAudioSourceProvider implementation.
- // Callback for providing more data into the resampler.
- // Only used in varispeed mode, i.e., when input rate != output rate.
- virtual void ProvideInput(int frame_delay, AudioBus* audio_bus);
-
- // Issues the OnError() callback to the |source_|.
- void HandleError(HRESULT err);
-
- // Stops and joins the audio thread in case of an error.
- void StopAndJoinThread(HRESULT err);
-
- // Converts unique endpoint ID to user-friendly device name.
- std::string GetDeviceName(LPCWSTR device_id) const;
-
- // Called on the audio IO thread for each capture event.
- // Buffers captured audio into a FIFO if varispeed is used or into an audio
- // bus if input and output sample rates are identical.
- void ProcessInputAudio();
-
- // Called on the audio IO thread for each render event when varispeed is
- // active or for each capture event when varispeed is not used.
- // In varispeed mode, it triggers a resampling callback, which reads from the
- // FIFO, and calls AudioSourceCallback::OnMoreIOData using the resampled
- // input signal and at the same time asks for data to play out.
- // If input and output rates are the same - instead of reading from the FIFO
- // and do resampling - we read directly from the audio bus used to store
- // captured data in ProcessInputAudio.
- void ProcessOutputAudio(IAudioClock* audio_output_clock);
-
- // Contains the thread ID of the creating thread.
- base::PlatformThreadId creating_thread_id_;
-
- // Our creator, the audio manager needs to be notified when we close.
- AudioManagerWin* manager_;
-
- // Contains the audio parameter structure provided at construction.
- AudioParameters params_;
- // For convenience, same as in params_.
- 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.
- AUDCLNT_SHAREMODE share_mode_;
-
- // Rendering and capturing is driven by this thread (no message loop).
- // All OnMoreIOData() callbacks will be called from this thread.
- scoped_ptr<base::DelegateSimpleThread> audio_io_thread_;
-
- // Contains the desired audio output format which is set up at construction.
- // It is required to first acquire the native sample rate of the selected
- // output device and then use the same rate when creating this object.
- WAVEFORMATPCMEX output_format_;
-
- // Contains the native audio input format which is set up at construction
- // if varispeed mode is utilized.
- WAVEFORMATPCMEX input_format_;
-
- // True when successfully opened.
- bool opened_;
-
- // Volume level from 0 to 1 used for output scaling.
- double volume_;
-
- // Size in audio frames of each audio packet where an audio packet
- // is defined as the block of data which the destination is expected to
- // receive in each OnMoreIOData() callback.
- size_t output_buffer_size_frames_;
-
- // Size in audio frames of each audio packet where an audio packet
- // is defined as the block of data which the source is expected to
- // deliver in each OnMoreIOData() callback.
- size_t input_buffer_size_frames_;
-
- // Length of the audio endpoint buffer.
- uint32 endpoint_render_buffer_size_frames_;
- uint32 endpoint_capture_buffer_size_frames_;
-
- // Counts the number of audio frames written to the endpoint buffer.
- uint64 num_written_frames_;
-
- // Time stamp for last delay measurement.
- base::TimeTicks last_delay_sample_time_;
-
- // Contains the total (sum of render and capture) delay in milliseconds.
- double total_delay_ms_;
-
- // Contains the total (sum of render and capture and possibly FIFO) delay
- // in bytes. The update frequency is set by a constant called
- // |kTimeDiffInMillisecondsBetweenDelayMeasurements|.
- int total_delay_bytes_;
-
- // Pointer to the client that will deliver audio samples to be played out.
- AudioSourceCallback* source_;
-
- // IMMDevice interfaces which represents audio endpoint devices.
- base::win::ScopedComPtr<IMMDevice> endpoint_render_device_;
- base::win::ScopedComPtr<IMMDevice> endpoint_capture_device_;
-
- // IAudioClient interfaces which enables a client to create and initialize
- // an audio stream between an audio application and the audio engine.
- base::win::ScopedComPtr<IAudioClient> audio_output_client_;
- base::win::ScopedComPtr<IAudioClient> audio_input_client_;
-
- // IAudioRenderClient interfaces enables a client to write output
- // data to a rendering endpoint buffer.
- base::win::ScopedComPtr<IAudioRenderClient> audio_render_client_;
-
- // IAudioCaptureClient interfaces enables a client to read input
- // data from a capturing endpoint buffer.
- base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_;
-
- // The audio engine will signal this event each time a buffer has been
- // recorded.
- base::win::ScopedHandle capture_event_;
-
- // The audio engine will signal this event each time it needs a new
- // audio buffer to play out.
- // Only utilized in varispeed mode.
- base::win::ScopedHandle render_event_;
-
- // This event will be signaled when streaming shall stop.
- base::win::ScopedHandle stop_streaming_event_;
-
- // Container for retrieving data from AudioSourceCallback::OnMoreIOData().
- scoped_ptr<AudioBus> output_bus_;
-
- // Container for sending data to AudioSourceCallback::OnMoreIOData().
- scoped_ptr<AudioBus> input_bus_;
-
- // Container for storing output from the channel mixer.
- scoped_ptr<AudioBus> channel_bus_;
-
- // All members below are only allocated, or used, in varispeed mode:
-
- // Temporary storage of resampled input audio data.
- scoped_ptr<AudioBus> resampled_bus_;
-
- // Set to true first time a capture event has been received in varispeed
- // mode.
- bool input_callback_received_;
-
- // MultiChannelResampler is a multi channel wrapper for SincResampler;
- // allowing high quality sample rate conversion of multiple channels at once.
- scoped_ptr<MultiChannelResampler> resampler_;
-
- // Resampler I/O ratio.
- double io_sample_rate_ratio_;
-
- // Used for input to output buffering.
- scoped_ptr<AudioFifo> fifo_;
-
- // The channel mixer is only created and utilized if number of input channels
- // is larger than the native number of input channels (e.g client wants
- // stereo but the audio device only supports mono).
- scoped_ptr<ChannelMixer> channel_mixer_;
-
- // The optimal number of frames we'd like to keep in the FIFO at all times.
- int target_fifo_frames_;
-
- // A running average of the measured delta between actual number of frames
- // in the FIFO versus |target_fifo_frames_|.
- double average_delta_;
-
- // A varispeed rate scalar which is calculated based on FIFO drift.
- double fifo_rate_compensation_;
-
- // Set to true when input side signals output side that a new delay
- // estimate is needed.
- bool update_output_delay_;
-
- // Capture side stores its delay estimate so the sum can be derived in
- // the render side.
- double capture_delay_ms_;
-
- // TODO(henrika): possibly remove these members once the performance is
- // properly tuned. Only used for off-line debugging.
-#ifndef NDEBUG
- enum LogElementNames {
- INPUT_TIME_STAMP,
- NUM_FRAMES_IN_FIFO,
- RESAMPLER_MARGIN,
- RATE_COMPENSATION
- };
-
- scoped_ptr<int64[]> input_time_stamps_;
- scoped_ptr<int[]> num_frames_in_fifo_;
- scoped_ptr<int[]> resampler_margin_;
- scoped_ptr<double[]> fifo_rate_comps_;
- scoped_ptr<int[]> num_elements_;
- scoped_ptr<int[]> input_params_;
- scoped_ptr<int[]> output_params_;
-
- FILE* data_file_;
- FILE* param_file_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(WASAPIUnifiedStream);
-};
-
-} // namespace media
-
-#endif // MEDIA_AUDIO_WIN_AUDIO_UNIFIED_WIN_H_
diff --git a/media/audio/win/audio_unified_win_unittest.cc b/media/audio/win/audio_unified_win_unittest.cc
deleted file mode 100644
index fadec61..0000000
--- a/media/audio/win/audio_unified_win_unittest.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
-#include "base/test/test_timeouts.h"
-#include "base/time/time.h"
-#include "base/win/scoped_com_initializer.h"
-#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager.h"
-#include "media/audio/mock_audio_source_callback.h"
-#include "media/audio/win/audio_unified_win.h"
-#include "media/audio/win/core_audio_util_win.h"
-#include "media/base/channel_mixer.h"
-#include "media/base/media_switches.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::Between;
-using ::testing::DoAll;
-using ::testing::NotNull;
-using ::testing::Return;
-using base::win::ScopedCOMInitializer;
-
-namespace media {
-
-static const size_t kMaxDeltaSamples = 1000;
-static const char kDeltaTimeMsFileName[] = "unified_delta_times_ms.txt";
-
-// Verify that the delay estimate in the OnMoreIOData() callback is larger
-// than an expected minumum value.
-MATCHER_P(DelayGreaterThan, value, "") {
- return (arg.hardware_delay_bytes > value.hardware_delay_bytes);
-}
-
-// Used to terminate a loop from a different thread than the loop belongs to.
-// |loop| should be a MessageLoopProxy.
-ACTION_P(QuitLoop, loop) {
- loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
-}
-
-// AudioOutputStream::AudioSourceCallback implementation which enables audio
-// play-through. It also creates a text file that contains times between two
-// successive callbacks. Units are in milliseconds. This file can be used for
-// off-line analysis of the callback sequence.
-class UnifiedSourceCallback : public AudioOutputStream::AudioSourceCallback {
- public:
- explicit UnifiedSourceCallback()
- : previous_call_time_(base::TimeTicks::Now()),
- text_file_(NULL),
- elements_to_write_(0) {
- delta_times_.reset(new int[kMaxDeltaSamples]);
- }
-
- virtual ~UnifiedSourceCallback() {
- base::FilePath file_name;
- EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_name));
- file_name = file_name.AppendASCII(kDeltaTimeMsFileName);
-
- EXPECT_TRUE(!text_file_);
- text_file_ = base::OpenFile(file_name, "wt");
- DLOG_IF(ERROR, !text_file_) << "Failed to open log file.";
- VLOG(0) << ">> Output file " << file_name.value() << " has been created.";
-
- // Write the array which contains delta times to a text file.
- size_t elements_written = 0;
- while (elements_written < elements_to_write_) {
- fprintf(text_file_, "%d\n", delta_times_[elements_written]);
- ++elements_written;
- }
- base::CloseFile(text_file_);
- }
-
- virtual int OnMoreData(AudioBus* dest,
- AudioBuffersState buffers_state) {
- NOTREACHED();
- return 0;
- };
-
- virtual int OnMoreIOData(AudioBus* source,
- AudioBus* dest,
- AudioBuffersState buffers_state) {
- // Store time between this callback and the previous callback.
- const base::TimeTicks now_time = base::TimeTicks::Now();
- const int diff = (now_time - previous_call_time_).InMilliseconds();
- previous_call_time_ = now_time;
- if (elements_to_write_ < kMaxDeltaSamples) {
- delta_times_[elements_to_write_] = diff;
- ++elements_to_write_;
- }
-
- // Play out the recorded audio samples in loop back. Perform channel mixing
- // if required using a channel mixer which is created only if needed.
- if (source->channels() == dest->channels()) {
- source->CopyTo(dest);
- } else {
- // A channel mixer is required for converting audio between two different
- // channel layouts.
- if (!channel_mixer_) {
- // Guessing the channel layout will work OK for this unit test.
- // Main thing is that the number of channels is correct.
- ChannelLayout input_layout = GuessChannelLayout(source->channels());
- ChannelLayout output_layout = GuessChannelLayout(dest->channels());
- channel_mixer_.reset(new ChannelMixer(input_layout, output_layout));
- DVLOG(1) << "Remixing channel layout from " << input_layout
- << " to " << output_layout << "; from "
- << source->channels() << " channels to "
- << dest->channels() << " channels.";
- }
- if (channel_mixer_)
- channel_mixer_->Transform(source, dest);
- }
- return source->frames();
- };
-
- virtual void OnError(AudioOutputStream* stream) {
- NOTREACHED();
- }
-
- private:
- base::TimeTicks previous_call_time_;
- scoped_ptr<int[]> delta_times_;
- FILE* text_file_;
- size_t elements_to_write_;
- scoped_ptr<ChannelMixer> channel_mixer_;
-};
-
-// Convenience method which ensures that we fulfill all required conditions
-// to run unified audio tests on Windows.
-static bool CanRunUnifiedAudioTests(AudioManager* audio_man) {
- if (!CoreAudioUtil::IsSupported()) {
- LOG(WARNING) << "This tests requires Windows Vista or higher.";
- return false;
- }
-
- if (!audio_man->HasAudioOutputDevices()) {
- LOG(WARNING) << "No output devices detected.";
- return false;
- }
-
- if (!audio_man->HasAudioInputDevices()) {
- LOG(WARNING) << "No input devices detected.";
- return false;
- }
-
- return true;
-}
-
-// Convenience class which simplifies creation of a unified AudioOutputStream
-// object.
-class AudioUnifiedStreamWrapper {
- public:
- explicit AudioUnifiedStreamWrapper(AudioManager* audio_manager)
- : com_init_(ScopedCOMInitializer::kMTA),
- audio_man_(audio_manager) {
- // We open up both both sides (input and output) using the preferred
- // set of audio parameters. These parameters corresponds to the mix format
- // that the audio engine uses internally for processing of shared-mode
- // output streams.
- AudioParameters out_params;
- EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
- eRender, eConsole, &out_params)));
-
- // WebAudio is the only real user of unified audio and it always asks
- // for stereo.
- // TODO(henrika): extend support to other input channel layouts as well.
- const int kInputChannels = 2;
-
- params_.Reset(out_params.format(),
- out_params.channel_layout(),
- out_params.channels(),
- kInputChannels,
- out_params.sample_rate(),
- out_params.bits_per_sample(),
- out_params.frames_per_buffer());
- }
-
- ~AudioUnifiedStreamWrapper() {}
-
- // Creates an AudioOutputStream object using default parameters.
- WASAPIUnifiedStream* Create() {
- return static_cast<WASAPIUnifiedStream*>(CreateOutputStream());
- }
-
- // Creates an AudioOutputStream object using default parameters but a
- // specified input device.
- WASAPIUnifiedStream* Create(const std::string device_id) {
- return static_cast<WASAPIUnifiedStream*>(CreateOutputStream(device_id));
- }
-
- AudioParameters::Format format() const { return params_.format(); }
- int channels() const { return params_.channels(); }
- int bits_per_sample() const { return params_.bits_per_sample(); }
- int sample_rate() const { return params_.sample_rate(); }
- int frames_per_buffer() const { return params_.frames_per_buffer(); }
- int bytes_per_buffer() const { return params_.GetBytesPerBuffer(); }
- int input_channels() const { return params_.input_channels(); }
-
- private:
- AudioOutputStream* CreateOutputStream() {
- // Get the unique device ID of the default capture device instead of using
- // AudioManagerBase::kDefaultDeviceId since it provides slightly better
- // test coverage and will utilize the same code path as if a non default
- // input device was used.
- ScopedComPtr<IMMDevice> audio_device =
- CoreAudioUtil::CreateDefaultDevice(eCapture, eConsole);
- AudioDeviceName name;
- EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDeviceName(audio_device, &name)));
- const std::string& input_device_id = name.unique_id;
- EXPECT_TRUE(CoreAudioUtil::DeviceIsDefault(eCapture, eConsole,
- input_device_id));
-
- // Create the unified audio I/O stream using the default input device.
- AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
- "", input_device_id);
- EXPECT_TRUE(aos);
- return aos;
- }
-
- AudioOutputStream* CreateOutputStream(const std::string& input_device_id) {
- // Create the unified audio I/O stream using the specified input device.
- AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(params_,
- "", input_device_id);
- EXPECT_TRUE(aos);
- return aos;
- }
-
- ScopedCOMInitializer com_init_;
- AudioManager* audio_man_;
- AudioParameters params_;
-};
-
-// Convenience method which creates a default WASAPIUnifiedStream object.
-static WASAPIUnifiedStream* CreateDefaultUnifiedStream(
- AudioManager* audio_manager) {
- AudioUnifiedStreamWrapper aosw(audio_manager);
- return aosw.Create();
-}
-
-// Convenience method which creates a default WASAPIUnifiedStream object but
-// with a specified audio input device.
-static WASAPIUnifiedStream* CreateDefaultUnifiedStream(
- AudioManager* audio_manager, const std::string& device_id) {
- AudioUnifiedStreamWrapper aosw(audio_manager);
- return aosw.Create(device_id);
-}
-
-// Test Open(), Close() calling sequence.
-TEST(WASAPIUnifiedStreamTest, OpenAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- WASAPIUnifiedStream* wus = CreateDefaultUnifiedStream(audio_manager.get());
- EXPECT_TRUE(wus->Open());
- wus->Close();
-}
-
-// Test Open(), Close() calling sequence for all available capture devices.
-TEST(WASAPIUnifiedStreamTest, OpenAndCloseForAllInputDevices) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- AudioDeviceNames device_names;
- audio_manager->GetAudioInputDeviceNames(&device_names);
- for (AudioDeviceNames::iterator i = device_names.begin();
- i != device_names.end(); ++i) {
- WASAPIUnifiedStream* wus = CreateDefaultUnifiedStream(
- audio_manager.get(), i->unique_id);
- EXPECT_TRUE(wus->Open());
- wus->Close();
- }
-}
-
-// Test Open(), Start(), Close() calling sequence.
-TEST(WASAPIUnifiedStreamTest, OpenStartAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- MockAudioSourceCallback source;
- AudioUnifiedStreamWrapper ausw(audio_manager.get());
- WASAPIUnifiedStream* wus = ausw.Create();
-
- EXPECT_TRUE(wus->Open());
- EXPECT_CALL(source, OnError(wus))
- .Times(0);
- EXPECT_CALL(source, OnMoreIOData(NotNull(), NotNull(), _))
- .Times(Between(0, 1))
- .WillOnce(Return(ausw.frames_per_buffer()));
- wus->Start(&source);
- wus->Close();
-}
-
-// Verify that IO callbacks starts as they should.
-TEST(WASAPIUnifiedStreamTest, StartLoopbackAudio) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- base::MessageLoopForUI loop;
- MockAudioSourceCallback source;
- AudioUnifiedStreamWrapper ausw(audio_manager.get());
- WASAPIUnifiedStream* wus = ausw.Create();
-
- // Set up expected minimum delay estimation where we use a minium delay
- // which is equal to the sum of render and capture sizes. We can never
- // reach a delay lower than this value.
- AudioBuffersState min_total_audio_delay(0, 2 * ausw.bytes_per_buffer());
-
- EXPECT_TRUE(wus->Open());
- EXPECT_CALL(source, OnError(wus))
- .Times(0);
- EXPECT_CALL(source, OnMoreIOData(
- NotNull(), NotNull(), DelayGreaterThan(min_total_audio_delay)))
- .Times(AtLeast(2))
- .WillOnce(Return(ausw.frames_per_buffer()))
- .WillOnce(DoAll(
- QuitLoop(loop.message_loop_proxy()),
- Return(ausw.frames_per_buffer())));
- wus->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
- TestTimeouts::action_timeout());
- loop.Run();
- wus->Stop();
- wus->Close();
-}
-
-// Perform a real-time test in loopback where the recorded audio is echoed
-// back to the speaker. This test allows the user to verify that the audio
-// sounds OK. A text file with name |kDeltaTimeMsFileName| is also generated.
-TEST(WASAPIUnifiedStreamTest, DISABLED_RealTimePlayThrough) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
- if (!CanRunUnifiedAudioTests(audio_manager.get()))
- return;
-
- base::MessageLoopForUI loop;
- UnifiedSourceCallback source;
- WASAPIUnifiedStream* wus = CreateDefaultUnifiedStream(audio_manager.get());
-
- EXPECT_TRUE(wus->Open());
- wus->Start(&source);
- loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
- base::TimeDelta::FromMilliseconds(10000));
- loop.Run();
- wus->Close();
-}
-
-} // namespace media
diff --git a/media/media.gyp b/media/media.gyp
index 3bf503f..4ae986d 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -131,8 +131,6 @@
'audio/fake_audio_output_stream.cc',
'audio/fake_audio_output_stream.h',
'audio/linux/audio_manager_linux.cc',
- 'audio/mac/aggregate_device_manager.cc',
- 'audio/mac/aggregate_device_manager.h',
'audio/mac/audio_auhal_mac.cc',
'audio/mac/audio_auhal_mac.h',
'audio/mac/audio_device_listener_mac.cc',
@@ -145,10 +143,6 @@
'audio/mac/audio_low_latency_output_mac.h',
'audio/mac/audio_manager_mac.cc',
'audio/mac/audio_manager_mac.h',
- 'audio/mac/audio_synchronized_mac.cc',
- 'audio/mac/audio_synchronized_mac.h',
- 'audio/mac/audio_unified_mac.cc',
- 'audio/mac/audio_unified_mac.h',
'audio/null_audio_sink.cc',
'audio/null_audio_sink.h',
'audio/openbsd/audio_manager_openbsd.cc',
@@ -159,8 +153,6 @@
'audio/pulse/pulse_input.h',
'audio/pulse/pulse_output.cc',
'audio/pulse/pulse_output.h',
- 'audio/pulse/pulse_unified.cc',
- 'audio/pulse/pulse_unified.h',
'audio/pulse/pulse_util.cc',
'audio/pulse/pulse_util.h',
'audio/sample_rates.cc',
@@ -187,8 +179,6 @@
'audio/win/audio_low_latency_output_win.h',
'audio/win/audio_manager_win.cc',
'audio/win/audio_manager_win.h',
- 'audio/win/audio_unified_win.cc',
- 'audio/win/audio_unified_win.h',
'audio/win/avrt_wrapper_win.cc',
'audio/win/avrt_wrapper_win.h',
'audio/win/core_audio_util_win.cc',
@@ -769,8 +759,6 @@
'audio/pulse/pulse_input.h',
'audio/pulse/pulse_output.cc',
'audio/pulse/pulse_output.h',
- 'audio/pulse/pulse_unified.cc',
- 'audio/pulse/pulse_unified.h',
'audio/pulse/pulse_util.cc',
'audio/pulse/pulse_util.h',
],
@@ -939,7 +927,6 @@
'audio/win/audio_low_latency_input_win_unittest.cc',
'audio/win/audio_low_latency_output_win_unittest.cc',
'audio/win/audio_output_win_unittest.cc',
- 'audio/win/audio_unified_win_unittest.cc',
'audio/win/core_audio_util_win_unittest.cc',
'base/android/media_codec_bridge_unittest.cc',
'base/android/media_source_player_unittest.cc',