summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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_hardware.cc15
-rw-r--r--content/renderer/media/audio_hardware.h4
-rw-r--r--content/renderer/media/webrtc_audio_device_impl.cc43
-rw-r--r--content/renderer/media/webrtc_audio_device_unittest.cc20
-rw-r--r--content/test/webrtc_audio_device_test.cc8
-rw-r--r--content/test/webrtc_audio_device_test.h2
-rw-r--r--media/audio/audio_util.cc16
-rw-r--r--media/audio/audio_util.h3
-rw-r--r--media/audio/win/audio_low_latency_input_win.cc48
-rw-r--r--media/audio/win/audio_low_latency_input_win.h10
13 files changed, 135 insertions, 45 deletions
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 6429524..23e4e25 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -380,6 +380,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnGetHardwareInputSampleRate)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareSampleRate,
OnGetHardwareSampleRate)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareInputChannelCount,
+ OnGetHardwareInputChannelCount)
IPC_MESSAGE_HANDLER(ViewHostMsg_MediaLogEvent, OnMediaLogEvent)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
@@ -673,6 +675,10 @@ void RenderMessageFilter::OnGetHardwareSampleRate(double* sample_rate) {
*sample_rate = media::GetAudioHardwareSampleRate();
}
+void RenderMessageFilter::OnGetHardwareInputChannelCount(uint32* channels) {
+ *channels = static_cast<uint32>(media::GetAudioInputHardwareChannelCount());
+}
+
void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message,
const GURL& url,
const GURL& referrer,
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index f0519fd..445bcd9 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -175,6 +175,7 @@ class RenderMessageFilter : public content::BrowserMessageFilter {
void OnGetHardwareBufferSize(uint32* buffer_size);
void OnGetHardwareInputSampleRate(double* sample_rate);
void OnGetHardwareSampleRate(double* sample_rate);
+ void OnGetHardwareInputChannelCount(uint32* channels);
// Used to ask the browser to allocate a block of shared memory for the
// renderer to send back data in, since shared memory can't be created
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index cf5b4a8..d21f4ce 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -697,6 +697,10 @@ IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetHardwareInputSampleRate,
IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetHardwareSampleRate,
double /* sample_rate */)
+// Asks the browser for the default number of audio input channels.
+IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetHardwareInputChannelCount,
+ uint32 /* channels */)
+
// Asks the browser for CPU usage of the renderer process in percents.
IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetCPUUsage,
int /* CPU usage in percents */)
diff --git a/content/renderer/media/audio_hardware.cc b/content/renderer/media/audio_hardware.cc
index 24df14f..183ebec 100644
--- a/content/renderer/media/audio_hardware.cc
+++ b/content/renderer/media/audio_hardware.cc
@@ -11,6 +11,7 @@
static double output_sample_rate = 0.0;
static double input_sample_rate = 0.0;
static size_t output_buffer_size = 0;
+static uint32 input_channel_count = 0;
namespace audio_hardware {
@@ -47,12 +48,26 @@ size_t GetOutputBufferSize() {
return output_buffer_size;
}
+uint32 GetInputChannelCount() {
+ DCHECK(RenderThreadImpl::current() != NULL);
+
+ if (!input_channel_count) {
+ uint32 channels = 0;
+ RenderThreadImpl::current()->Send(
+ new ViewHostMsg_GetHardwareInputChannelCount(&channels));
+ input_channel_count = channels;
+ }
+
+ return input_channel_count;
+}
+
void ResetCache() {
DCHECK(RenderThreadImpl::current() != NULL);
output_sample_rate = 0.0;
input_sample_rate = 0.0;
output_buffer_size = 0;
+ input_channel_count = 0;
}
} // namespace audio_hardware
diff --git a/content/renderer/media/audio_hardware.h b/content/renderer/media/audio_hardware.h
index c603073..ea9a28a 100644
--- a/content/renderer/media/audio_hardware.h
+++ b/content/renderer/media/audio_hardware.h
@@ -26,6 +26,10 @@ CONTENT_EXPORT double GetInputSampleRate();
// Must be called from RenderThreadImpl::current().
CONTENT_EXPORT size_t GetOutputBufferSize();
+// Fetch the number of audio channels for the default input device.
+// Must be called from RenderThreadImpl::current().
+CONTENT_EXPORT uint32 GetInputChannelCount();
+
// Forces the next call to any of the Get functions to query the hardware
// and repopulate the cache.
CONTENT_EXPORT void ResetCache();
diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
index 300439d..f05beb3 100644
--- a/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/content/renderer/media/webrtc_audio_device_impl.cc
@@ -300,7 +300,11 @@ int32_t WebRtcAudioDeviceImpl::Init() {
static_cast<int>(audio_hardware::GetInputSampleRate());
DVLOG(1) << "Audio input hardware sample rate: " << input_sample_rate;
- int input_channels = 0;
+ // Ask the browser for the default number of audio input channels.
+ // This request is based on a synchronous IPC message.
+ int input_channels = audio_hardware::GetInputChannelCount();
+ DVLOG(1) << "Audio input hardware channels: " << input_channels;
+
int output_channels = 0;
size_t input_buffer_size = 0;
@@ -308,21 +312,17 @@ int32_t WebRtcAudioDeviceImpl::Init() {
// Windows
#if defined(OS_WIN)
- if (input_sample_rate != 48000 && input_sample_rate != 44100) {
- DLOG(ERROR) << "Only 48 and 44.1kHz input rates are supported on Windows.";
+ if (input_sample_rate != 48000 && input_sample_rate != 44100 &&
+ input_sample_rate != 32000 && input_sample_rate != 16000) {
+ DLOG(ERROR) << "Only 48, 44.1, 32 and 16kHz input rates are supported.";
return -1;
}
if (output_sample_rate != 48000 && output_sample_rate != 44100) {
- DLOG(ERROR) << "Only 48 and 44.1kHz output rates are supported on Windows.";
+ DLOG(ERROR) << "Only 48 and 44.1kHz output rates are supported.";
return -1;
}
- // Use stereo recording on Windows since low-latency Core Audio (WASAPI)
- // does not support mono.
- input_channels = 2;
-
- // Use stereo rendering on Windows to make input and output sides
- // symmetric. WASAPI supports both stereo and mono.
+ // Always use stereo rendering on Windows.
output_channels = 2;
// Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI)
@@ -331,12 +331,12 @@ int32_t WebRtcAudioDeviceImpl::Init() {
// 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 {
+ if (input_sample_rate == 44100) {
// 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;
+ } else {
+ input_buffer_size = (input_sample_rate / 100);
}
// Render side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI)
@@ -357,7 +357,7 @@ int32_t WebRtcAudioDeviceImpl::Init() {
// Windows XP and lower can't cope with 10 ms output buffer size.
// It must be extended to 30 ms (60 ms will be used internally by WaveOut).
- if (base::win::GetVersion() <= base::win::VERSION_XP) {
+ if (!media::IsWASAPISupported()) {
output_buffer_size = 3 * output_buffer_size;
DLOG(WARNING) << "Extending the output buffer size by a factor of three "
<< "since Windows XP has been detected.";
@@ -365,8 +365,9 @@ int32_t WebRtcAudioDeviceImpl::Init() {
// Mac OS X
#elif defined(OS_MACOSX)
- if (input_sample_rate != 48000 && input_sample_rate != 44100) {
- DLOG(ERROR) << "Only 48 and 44.1kHz input rates are supported on Mac OSX.";
+ if (input_sample_rate != 48000 && input_sample_rate != 44100 &&
+ input_sample_rate != 32000 && input_sample_rate != 16000) {
+ DLOG(ERROR) << "Only 48, 44.1, 32 and 16kHz input rates are supported.";
return -1;
}
if (output_sample_rate != 48000 && output_sample_rate != 44100) {
@@ -374,7 +375,6 @@ int32_t WebRtcAudioDeviceImpl::Init() {
return -1;
}
- input_channels = 1;
output_channels = 1;
// Capture side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback-
@@ -382,12 +382,12 @@ int32_t WebRtcAudioDeviceImpl::Init() {
// frame size to use, both for 48kHz and 44.1kHz.
// Use different buffer sizes depending on the current hardware sample rate.
- if (input_sample_rate == 48000) {
- input_buffer_size = 480;
- } else {
+ if (input_sample_rate == 44100) {
// 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;
+ } else {
+ input_buffer_size = (input_sample_rate / 100);
}
// Render side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback-
@@ -618,9 +618,6 @@ bool WebRtcAudioDeviceImpl::Playing() const {
int32_t WebRtcAudioDeviceImpl::StartRecording() {
DVLOG(1) << "StartRecording()";
-#if defined(OS_MACOSX)
- DLOG(WARNING) << "Real-time recording is not yet fully supported on Mac OS X";
-#endif
LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing";
if (!audio_transport_callback_) {
LOG(ERROR) << "Audio transport is missing";
diff --git a/content/renderer/media/webrtc_audio_device_unittest.cc b/content/renderer/media/webrtc_audio_device_unittest.cc
index 14bbcde..8908e47 100644
--- a/content/renderer/media/webrtc_audio_device_unittest.cc
+++ b/content/renderer/media/webrtc_audio_device_unittest.cc
@@ -38,14 +38,20 @@ class AudioUtil : public AudioUtilInterface {
virtual double GetAudioInputHardwareSampleRate() OVERRIDE {
return media::GetAudioInputHardwareSampleRate();
}
+ virtual uint32 GetAudioInputHardwareChannelCount() OVERRIDE {
+ return media::GetAudioInputHardwareChannelCount();
+ }
private:
DISALLOW_COPY_AND_ASSIGN(AudioUtil);
};
class AudioUtilNoHardware : public AudioUtilInterface {
public:
- AudioUtilNoHardware(double output_rate, double input_rate)
- : output_rate_(output_rate), input_rate_(input_rate) {
+ AudioUtilNoHardware(double output_rate, double input_rate,
+ uint32 input_channels)
+ : output_rate_(output_rate),
+ input_rate_(input_rate),
+ input_channels_(input_channels) {
}
virtual double GetAudioHardwareSampleRate() OVERRIDE {
@@ -54,10 +60,14 @@ class AudioUtilNoHardware : public AudioUtilInterface {
virtual double GetAudioInputHardwareSampleRate() OVERRIDE {
return input_rate_;
}
+ virtual uint32 GetAudioInputHardwareChannelCount() OVERRIDE {
+ return input_channels_;
+ }
private:
double output_rate_;
double input_rate_;
+ uint32 input_channels_;
DISALLOW_COPY_AND_ASSIGN(AudioUtilNoHardware);
};
@@ -82,7 +92,8 @@ bool HardwareSampleRatesAreValid() {
static_cast<int>(audio_hardware::GetInputSampleRate());
bool rates_are_valid =
((output_sample_rate == 44100 || output_sample_rate == 48000) &&
- (input_sample_rate == 44100 || input_sample_rate == 48000));
+ (input_sample_rate == 44100 || input_sample_rate == 48000 ||
+ input_sample_rate == 16000 || input_sample_rate == 32000));
DLOG_IF(WARNING, !rates_are_valid) << "Non-supported sample rate detected.";
return rates_are_valid;
}
@@ -160,10 +171,11 @@ class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess {
// Basic test that instantiates and initializes an instance of
// WebRtcAudioDeviceImpl.
TEST_F(WebRTCAudioDeviceTest, Construct) {
- AudioUtilNoHardware audio_util(48000.0, 48000.0);
+ AudioUtilNoHardware audio_util(48000.0, 48000.0, 1);
SetAudioUtilCallback(&audio_util);
scoped_refptr<WebRtcAudioDeviceImpl> audio_device(
new WebRtcAudioDeviceImpl());
+
audio_device->SetSessionId(1);
WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc
index 94c155b..35e13c4 100644
--- a/content/test/webrtc_audio_device_test.cc
+++ b/content/test/webrtc_audio_device_test.cc
@@ -235,6 +235,12 @@ void WebRTCAudioDeviceTest::OnGetHardwareInputSampleRate(double* sample_rate) {
audio_util_callback_->GetAudioInputHardwareSampleRate() : 0.0;
}
+void WebRTCAudioDeviceTest::OnGetHardwareInputChannelCount(uint32* channels) {
+ EXPECT_TRUE(audio_util_callback_);
+ *channels = audio_util_callback_ ?
+ audio_util_callback_->GetAudioInputHardwareChannelCount() : 0;
+}
+
// IPC::Channel::Listener implementation.
bool WebRTCAudioDeviceTest::OnMessageReceived(const IPC::Message& message) {
if (render_thread_) {
@@ -267,6 +273,8 @@ bool WebRTCAudioDeviceTest::OnMessageReceived(const IPC::Message& message) {
OnGetHardwareSampleRate)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareInputSampleRate,
OnGetHardwareInputSampleRate)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareInputChannelCount,
+ OnGetHardwareInputChannelCount)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
diff --git a/content/test/webrtc_audio_device_test.h b/content/test/webrtc_audio_device_test.h
index f821ad6..d02ef2c 100644
--- a/content/test/webrtc_audio_device_test.h
+++ b/content/test/webrtc_audio_device_test.h
@@ -109,6 +109,7 @@ class AudioUtilInterface {
virtual ~AudioUtilInterface() {}
virtual double GetAudioHardwareSampleRate() = 0;
virtual double GetAudioInputHardwareSampleRate() = 0;
+ virtual uint32 GetAudioInputHardwareChannelCount() = 0;
};
// Implemented and defined in the cc file.
@@ -137,6 +138,7 @@ class WebRTCAudioDeviceTest
void OnGetHardwareSampleRate(double* sample_rate);
void OnGetHardwareInputSampleRate(double* sample_rate);
+ void OnGetHardwareInputChannelCount(uint32* channels);
// IPC::Channel::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
diff --git a/media/audio/audio_util.cc b/media/audio/audio_util.cc
index 8989eb9..b4b87518 100644
--- a/media/audio/audio_util.cc
+++ b/media/audio/audio_util.cc
@@ -337,6 +337,22 @@ size_t GetAudioHardwareBufferSize() {
#endif
}
+uint32 GetAudioInputHardwareChannelCount() {
+ enum channel_layout { MONO = 1, STEREO = 2 };
+#if defined(OS_MACOSX)
+ return MONO;
+#elif defined(OS_WIN)
+ if (!IsWASAPISupported()) {
+ // Fall back to Windows Wave implementation on Windows XP or lower and
+ // use stereo by default.
+ return STEREO;
+ }
+ return WASAPIAudioInputStream::HardwareChannelCount(eConsole);
+#else
+ return STEREO;
+#endif
+}
+
// When transferring data in the shared memory, first word is size of data
// in bytes. Actual data starts immediately after it.
diff --git a/media/audio/audio_util.h b/media/audio/audio_util.h
index 278779a..d8de479 100644
--- a/media/audio/audio_util.h
+++ b/media/audio/audio_util.h
@@ -90,6 +90,9 @@ MEDIA_EXPORT double GetAudioInputHardwareSampleRate();
// at without glitches. The buffer size is in sample-frames.
MEDIA_EXPORT size_t GetAudioHardwareBufferSize();
+// Returns the default number of channels for the audio input hardware.
+MEDIA_EXPORT uint32 GetAudioInputHardwareChannelCount();
+
// Functions that handle data buffer passed between processes in the shared
// memory. Called on both IPC sides.
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index c6bb0ed..95dd425 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -184,6 +184,31 @@ void WASAPIAudioInputStream::Close() {
// static
double WASAPIAudioInputStream::HardwareSampleRate(ERole device_role) {
+ base::win::ScopedCoMem<WAVEFORMATEX> audio_engine_mix_format;
+ HRESULT hr = GetMixFormat(device_role, &audio_engine_mix_format);
+ if (FAILED(hr)) {
+ NOTREACHED() << "error code: " << hr;
+ return 0.0;
+ }
+
+ return static_cast<double>(audio_engine_mix_format->nSamplesPerSec);
+}
+
+// static
+uint32 WASAPIAudioInputStream::HardwareChannelCount(ERole device_role) {
+ base::win::ScopedCoMem<WAVEFORMATEX> audio_engine_mix_format;
+ HRESULT hr = GetMixFormat(device_role, &audio_engine_mix_format);
+ if (FAILED(hr)) {
+ NOTREACHED() << "error code: " << hr;
+ return 0;
+ }
+
+ return static_cast<uint32>(audio_engine_mix_format->nChannels);
+}
+
+// static
+HRESULT WASAPIAudioInputStream::GetMixFormat(ERole device_role,
+ WAVEFORMATEX** device_format) {
// It is assumed that this static method is called from a COM thread, i.e.,
// CoInitializeEx() is not called here to avoid STA/MTA conflicts.
ScopedComPtr<IMMDeviceEnumerator> enumerator;
@@ -192,10 +217,8 @@ double WASAPIAudioInputStream::HardwareSampleRate(ERole device_role) {
CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
enumerator.ReceiveVoid());
- if (FAILED(hr)) {
- NOTREACHED() << "error code: " << hr;
- return 0.0;
- }
+ if (FAILED(hr))
+ return hr;
ScopedComPtr<IMMDevice> endpoint_device;
hr = enumerator->GetDefaultAudioEndpoint(eCapture,
@@ -206,7 +229,7 @@ double WASAPIAudioInputStream::HardwareSampleRate(ERole device_role) {
// (e.g. some audio cards that have inputs will still report them as
// "not found" when no mic is plugged into the input jack).
LOG(WARNING) << "No audio end point: " << std::hex << hr;
- return 0.0;
+ return hr;
}
ScopedComPtr<IAudioClient> audio_client;
@@ -214,19 +237,10 @@ double WASAPIAudioInputStream::HardwareSampleRate(ERole device_role) {
CLSCTX_INPROC_SERVER,
NULL,
audio_client.ReceiveVoid());
- if (FAILED(hr)) {
- NOTREACHED() << "error code: " << hr;
- return 0.0;
- }
+ if (SUCCEEDED(hr))
+ hr = audio_client->GetMixFormat(device_format);
- base::win::ScopedCoMem<WAVEFORMATEX> audio_engine_mix_format;
- hr = audio_client->GetMixFormat(&audio_engine_mix_format);
- if (FAILED(hr)) {
- NOTREACHED() << "error code: " << hr;
- return 0.0;
- }
-
- return static_cast<double>(audio_engine_mix_format->nSamplesPerSec);
+ return hr;
}
void WASAPIAudioInputStream::Run() {
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h
index ebaab93..e236e44 100644
--- a/media/audio/win/audio_low_latency_input_win.h
+++ b/media/audio/win/audio_low_latency_input_win.h
@@ -89,10 +89,14 @@ class MEDIA_EXPORT WASAPIAudioInputStream
virtual void Stop() OVERRIDE;
virtual void Close() OVERRIDE;
- // Retrieves the stream format that the audio engine uses for its internal
+ // Retrieves the sample rate used by the audio engine for its internal
// processing/mixing of shared-mode streams.
static double HardwareSampleRate(ERole device_role);
+ // Retrieves the number of audio channels used by the audio engine for its
+ // internal processing/mixing of shared-mode streams.
+ static uint32 HardwareChannelCount(ERole device_role);
+
bool started() const { return started_; }
private:
@@ -109,6 +113,10 @@ class MEDIA_EXPORT WASAPIAudioInputStream
bool DesiredFormatIsSupported();
HRESULT InitializeAudioEngine();
+ // Retrieves the stream format that the audio engine uses for its internal
+ // processing/mixing of shared-mode streams.
+ static HRESULT GetMixFormat(ERole device_role, WAVEFORMATEX** device_format);
+
// Initializes the COM library for use by the calling thread and set the
// thread's concurrency model to multi-threaded.
base::win::ScopedCOMInitializer com_init_;