summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-24 09:41:12 +0000
committerhenrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-24 09:41:12 +0000
commitf5968e6ada72f515d7d183e67e35f90d7704daee (patch)
tree28f4fcbe9850f52dc7196c5a1db394b0aa2d577a /content
parenta80a258880e3ababe9f806dd9bb4d60ad90473ae (diff)
downloadchromium_src-f5968e6ada72f515d7d183e67e35f90d7704daee.zip
chromium_src-f5968e6ada72f515d7d183e67e35f90d7704daee.tar.gz
chromium_src-f5968e6ada72f515d7d183e67e35f90d7704daee.tar.bz2
Low-latency AudioInputStream implementation based on WASAPI for Windows.
Requires Windows Vista or higher. BUG=none TEST=Attached unit test (requires undefined CHROME_HEADLESS) Review URL: http://codereview.chromium.org/8283032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106899 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/render_message_filter.cc6
-rw-r--r--content/browser/renderer_host/render_message_filter.h1
-rw-r--r--content/common/view_messages.h4
-rw-r--r--content/renderer/media/audio_input_device.cc4
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.cc69
5 files changed, 60 insertions, 24 deletions
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 5f3e5cd..0ee35cd 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -355,6 +355,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnCacheableMetadataAvailable)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen)
IPC_MESSAGE_HANDLER(ViewHostMsg_AsyncOpenFile, OnAsyncOpenFile)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareInputSampleRate,
+ OnGetHardwareInputSampleRate)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareSampleRate,
OnGetHardwareSampleRate)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvent, OnMediaLogEvent)
@@ -602,6 +604,10 @@ void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
*route_id = render_widget_helper_->GetNextRoutingID();
}
+void RenderMessageFilter::OnGetHardwareInputSampleRate(double* sample_rate) {
+ *sample_rate = media::GetAudioInputHardwareSampleRate();
+}
+
void RenderMessageFilter::OnGetHardwareSampleRate(double* sample_rate) {
*sample_rate = media::GetAudioHardwareSampleRate();
}
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 1fbf322..22b9616 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -182,6 +182,7 @@ class RenderMessageFilter : public BrowserMessageFilter {
void OnCheckNotificationPermission(const GURL& source_url,
int* permission_level);
+ void OnGetHardwareInputSampleRate(double* sample_rate);
void OnGetHardwareSampleRate(double* sample_rate);
// Used to ask the browser to allocate a block of shared memory for the
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 2e06adc..03fa43c 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -686,6 +686,10 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetCSSColors,
IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GenerateRoutingID,
int /* routing_id */)
+// Asks the browser for the default audio input hardware sample-rate.
+IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetHardwareInputSampleRate,
+ double /* sample_rate */)
+
// Asks the browser for the default audio hardware sample-rate.
IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetHardwareSampleRate,
double /* sample_rate */)
diff --git a/content/renderer/media/audio_input_device.cc b/content/renderer/media/audio_input_device.cc
index 0dd06b8..ce0da67 100644
--- a/content/renderer/media/audio_input_device.cc
+++ b/content/renderer/media/audio_input_device.cc
@@ -30,7 +30,11 @@ AudioInputDevice::AudioInputDevice(size_t buffer_size,
#if defined(OS_MACOSX)
VLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X.";
audio_parameters_.format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
+#elif defined(OS_WIN)
+ VLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows.";
+ audio_parameters_.format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
#else
+ // TODO(henrika): add support for AUDIO_PCM_LOW_LATENCY on Linux as well.
audio_parameters_.format = AudioParameters::AUDIO_PCM_LINEAR;
#endif
audio_parameters_.channels = channels;
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
index eb2cef33..cb5728ec 100644
--- a/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -6,12 +6,22 @@
#include "base/bind.h"
#include "base/string_util.h"
+#include "content/common/view_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "media/audio/audio_util.h"
static const int64 kMillisecondsBetweenProcessCalls = 5000;
static const char kVersion[] = "WebRTC AudioDevice 1.0.0.Chrome";
+static int GetAudioInputHardwareSampleRate() {
+ static double input_sample_rate = 0;
+ if (!input_sample_rate) {
+ RenderThreadImpl::current()->Send(
+ new ViewHostMsg_GetHardwareInputSampleRate(&input_sample_rate));
+ }
+ return static_cast<int>(input_sample_rate);
+}
+
WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
: ref_count_(0),
render_loop_(base::MessageLoopProxy::current()),
@@ -72,8 +82,6 @@ void WebRtcAudioDeviceImpl::Render(
int samples_per_sec = static_cast<int>(output_sample_rate_);
if (samples_per_sec == 44100) {
// Even if the hardware runs at 44.1kHz, we use 44.0 internally.
- // Can only happen on Mac OS X currently since Windows and Mac
- // both uses 48kHz.
samples_per_sec = 44000;
}
uint32_t samples_per_10_msec = (samples_per_sec / 100);
@@ -132,7 +140,11 @@ void WebRtcAudioDeviceImpl::Capture(
input_buffer_.get(),
number_of_frames);
- const int samples_per_sec = static_cast<int>(input_sample_rate_);
+ int samples_per_sec = static_cast<int>(input_sample_rate_);
+ if (samples_per_sec == 44100) {
+ // Even if the hardware runs at 44.1kHz, we use 44.0 internally.
+ samples_per_sec = 44000;
+ }
const int samples_per_10_msec = (samples_per_sec / 100);
const int bytes_per_10_msec =
channels * samples_per_10_msec * bytes_per_sample_;
@@ -274,14 +286,16 @@ int32_t WebRtcAudioDeviceImpl::Init() {
DCHECK(!input_buffer_.get());
DCHECK(!output_buffer_.get());
- // TODO(henrika): add AudioInputDevice::GetAudioHardwareSampleRate().
- // Assume that input and output sample rates are identical for now.
-
// Ask the browser for the default audio output hardware sample-rate.
// This request is based on a synchronous IPC message.
int output_sample_rate =
static_cast<int>(AudioDevice::GetAudioHardwareSampleRate());
- VLOG(1) << "Audio hardware sample rate: " << output_sample_rate;
+ VLOG(1) << "Audio output hardware sample rate: " << output_sample_rate;
+
+ // Ask the browser for the default audio input hardware sample-rate.
+ // This request is based on a synchronous IPC message.
+ int input_sample_rate = GetAudioInputHardwareSampleRate();
+ VLOG(1) << "Audio input hardware sample rate: " << input_sample_rate;
int input_channels = 0;
int output_channels = 0;
@@ -291,21 +305,32 @@ int32_t WebRtcAudioDeviceImpl::Init() {
// For real-time audio (in combination with the webrtc::VoiceEngine) it
// is convenient to use audio buffers of size N*10ms.
+
#if defined(OS_WIN)
if (output_sample_rate != 48000) {
DLOG(ERROR) << "Only 48kHz sample rate is supported on Windows.";
return -1;
}
- input_channels = 1;
+
+ // Use stereo recording on Windows since low-latency Core Audio (WASAPI)
+ // does not support mono.
+ input_channels = 2;
output_channels = 1;
- // Capture side: AUDIO_PCM_LINEAR on Windows is based on a callback-
- // driven Wave implementation where 3 buffers are used for recording audio.
- // Each buffer is of the size that we specify here and using more than one
- // does not increase the delay but only adds robustness against dropping
- // audio. It might also affect the initial start-up time before callbacks
- // start to pump. Real-time tests have shown that a buffer size of 10ms
- // works fine on the capture side.
- input_buffer_size = 480;
+
+ // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI)
+ // API which was introduced in Windows Vista. For lower Windows versions,
+ // a callback-driven Wave implementation is used instead. An input buffer
+ // size of 10ms works well for both these implementations.
+
+ // Use different buffer sizes depending on the current hardware sample rate.
+ if (input_sample_rate == 48000) {
+ input_buffer_size = 480;
+ } else {
+ // We do run at 44.1kHz at the actual audio layer, but ask for frames
+ // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
+ input_buffer_size = 440;
+ }
+
// Rendering side: AUDIO_PCM_LOW_LATENCY on Windows is based on a callback-
// driven Wave implementation where 2 buffers are fed to the audio driver
// before actual rendering starts. Initial real-time tests have shown that
@@ -320,6 +345,7 @@ int32_t WebRtcAudioDeviceImpl::Init() {
}
input_channels = 1;
output_channels = 1;
+
// Rendering side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback-
// driven Core Audio implementation. Tests have shown that 10ms is a suitable
// frame size to use, both for 48kHz and 44.1kHz.
@@ -347,6 +373,7 @@ int32_t WebRtcAudioDeviceImpl::Init() {
}
input_channels = 1;
output_channels = 1;
+
// Based on tests using the current ALSA implementation in Chrome, we have
// found that the best combination is 20ms on the input side and 10ms on the
// output side.
@@ -367,17 +394,11 @@ int32_t WebRtcAudioDeviceImpl::Init() {
input_buffer_size_ = input_buffer_size;
input_channels_ = input_channels;
- // TODO(henrika): we use same rate as on output for now.
- input_sample_rate_ = output_sample_rate_;
+ input_sample_rate_ = input_sample_rate;
// Create and configure the audio capturing client.
audio_input_device_ = new AudioInputDevice(
- input_buffer_size, input_channels, output_sample_rate, this, this);
-#if defined(OS_MACOSX)
- // We create the input device for Mac as well but the performance
- // will be very bad.
- DLOG(WARNING) << "Real-time recording is not yet supported on Mac OS X";
-#endif
+ input_buffer_size, input_channels, input_sample_rate, this, this);
// Create and configure the audio rendering client.
audio_output_device_ = new AudioDevice(