diff options
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 6 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter.h | 1 | ||||
-rw-r--r-- | content/common/view_messages.h | 4 | ||||
-rw-r--r-- | content/renderer/media/audio_hardware.cc | 15 | ||||
-rw-r--r-- | content/renderer/media/audio_hardware.h | 4 | ||||
-rw-r--r-- | content/renderer/media/webrtc_audio_device_impl.cc | 43 | ||||
-rw-r--r-- | content/renderer/media/webrtc_audio_device_unittest.cc | 20 | ||||
-rw-r--r-- | content/test/webrtc_audio_device_test.cc | 8 | ||||
-rw-r--r-- | content/test/webrtc_audio_device_test.h | 2 | ||||
-rw-r--r-- | media/audio/audio_util.cc | 16 | ||||
-rw-r--r-- | media/audio/audio_util.h | 3 | ||||
-rw-r--r-- | media/audio/win/audio_low_latency_input_win.cc | 48 | ||||
-rw-r--r-- | media/audio/win/audio_low_latency_input_win.h | 10 |
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_; |