diff options
35 files changed, 462 insertions, 166 deletions
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 18b7e70..ea05dc5 100644 --- a/content/browser/renderer_host/media/audio_input_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc @@ -232,7 +232,8 @@ void AudioInputRendererHost::OnCreateStream( if (media_stream_manager_->audio_input_device_manager()-> ShouldUseFakeDevice()) { audio_params.Reset(media::AudioParameters::AUDIO_FAKE, - params.channel_layout(), 0, params.sample_rate(), + params.channel_layout(), params.channels(), 0, + params.sample_rate(), params.bits_per_sample(), params.frames_per_buffer()); } diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 608c7ed..fc216a1 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -33,6 +33,7 @@ #include "content/common/child_process_host_impl.h" #include "content/common/child_process_messages.h" #include "content/common/desktop_notification_messages.h" +#include "content/common/media/media_param_traits.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -778,22 +779,18 @@ void RenderMessageFilter::OnGetCPUUsage(int* cpu_usage) { *cpu_usage = cpu_usage_; } -// TODO(xians): refactor the API to return input and output AudioParameters. void RenderMessageFilter::OnGetAudioHardwareConfig( - int* output_buffer_size, int* output_sample_rate, int* input_sample_rate, - media::ChannelLayout* input_channel_layout) { + media::AudioParameters* input_params, + media::AudioParameters* output_params) { + DCHECK(input_params); + DCHECK(output_params); media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager(); - const media::AudioParameters output_parameters = - audio_manager->GetDefaultOutputStreamParameters(); - *output_buffer_size = output_parameters.frames_per_buffer(); - *output_sample_rate = output_parameters.sample_rate(); + *output_params = audio_manager->GetDefaultOutputStreamParameters(); // TODO(henrika): add support for all available input devices. - const media::AudioParameters input_parameters = + *input_params = audio_manager->GetInputStreamParameters( media::AudioManagerBase::kDefaultDeviceId); - *input_sample_rate = input_parameters.sample_rate(); - *input_channel_layout = input_parameters.channel_layout(); } void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) { diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 6f19c33..689b3f6 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -22,6 +22,7 @@ #include "content/common/pepper_renderer_instance_data.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/common/three_d_api_types.h" +#include "media/audio/audio_parameters.h" #include "media/base/channel_layout.h" #include "net/cookies/canonical_cookie.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h" @@ -190,9 +191,8 @@ class RenderMessageFilter : public BrowserMessageFilter { void OnGetCPUUsage(int* cpu_usage); - void OnGetAudioHardwareConfig(int* output_buffer_size, - int* output_sample_rate, int* input_sample_rate, - media::ChannelLayout* input_channel_layout); + void OnGetAudioHardwareConfig(media::AudioParameters* input_params, + media::AudioParameters* output_params); // Used to look up the monitor color profile. void OnGetMonitorColorProfile(std::vector<char>* profile); diff --git a/content/common/DEPS b/content/common/DEPS index bd4bed3..e09f27a 100644 --- a/content/common/DEPS +++ b/content/common/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+cc", "+components/tracing", + "+media/audio", "+media/base", "+sandbox/linux/seccomp-legacy", ] diff --git a/content/common/media/media_param_traits.cc b/content/common/media/media_param_traits.cc index 31ba948..f833ea0 100644 --- a/content/common/media/media_param_traits.cc +++ b/content/common/media/media_param_traits.cc @@ -42,8 +42,8 @@ bool ParamTraits<AudioParameters>::Read(const Message* m, !m->ReadInt(iter, &input_channels)) return false; r->Reset(static_cast<AudioParameters::Format>(format), - static_cast<ChannelLayout>(channel_layout), input_channels, - sample_rate, bits_per_sample, frames_per_buffer); + static_cast<ChannelLayout>(channel_layout), channels, + input_channels, sample_rate, bits_per_sample, frames_per_buffer); if (!r->IsValid()) return false; return true; diff --git a/content/common/media/media_param_traits.h b/content/common/media/media_param_traits.h index 94ce9ca..90d7258 100644 --- a/content/common/media/media_param_traits.h +++ b/content/common/media/media_param_traits.h @@ -5,6 +5,7 @@ #ifndef CONTENT_COMMON_MEDIA_MEDIA_PARAM_TRAITS_H_ #define CONTENT_COMMON_MEDIA_MEDIA_PARAM_TRAITS_H_ +#include "content/common/content_export.h" #include "ipc/ipc_message.h" #include "ipc/ipc_param_traits.h" @@ -16,7 +17,7 @@ struct VideoCaptureParams; namespace IPC { template <> -struct ParamTraits<media::AudioParameters> { +struct CONTENT_EXPORT ParamTraits<media::AudioParameters> { typedef media::AudioParameters param_type; static void Write(Message* m, const param_type& p); static bool Read(const Message* m, PickleIterator* iter, param_type* r); @@ -24,7 +25,7 @@ struct ParamTraits<media::AudioParameters> { }; template <> -struct ParamTraits<media::VideoCaptureParams> { +struct CONTENT_EXPORT ParamTraits<media::VideoCaptureParams> { typedef media::VideoCaptureParams param_type; static void Write(Message* m, const param_type& p); static bool Read(const Message* m, PickleIterator* iter, param_type* r); diff --git a/content/common/view_messages.h b/content/common/view_messages.h index c10f4aa..c186f21 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -31,6 +31,7 @@ #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_platform_file.h" +#include "media/audio/audio_parameters.h" #include "media/base/channel_layout.h" #include "media/base/media_log_event.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -1417,12 +1418,10 @@ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_CreateFullscreenWidget, IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GenerateRoutingID, int /* routing_id */) -// Asks the browser for the default audio hardware buffer-size. -IPC_SYNC_MESSAGE_CONTROL0_4(ViewHostMsg_GetAudioHardwareConfig, - int /* output_buffer_size */, - int /* output_sample_rate */, - int /* input_sample_rate */, - media::ChannelLayout /* input_channel_layout */) +// Asks the browser for the default audio hardware configuration. +IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_GetAudioHardwareConfig, + media::AudioParameters /* input parameters */, + media::AudioParameters /* output parameters */) // Asks the browser for CPU usage of the renderer process in percents. IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetCPUUsage, diff --git a/content/renderer/media/audio_message_filter.cc b/content/renderer/media/audio_message_filter.cc index 377c770..11de086 100644 --- a/content/renderer/media/audio_message_filter.cc +++ b/content/renderer/media/audio_message_filter.cc @@ -172,7 +172,22 @@ void AudioMessageFilter::OnOutputDeviceChanged(int stream_id, if (!audio_hardware_config_) return; - audio_hardware_config_->UpdateOutputConfig(new_buffer_size, new_sample_rate); + // TODO(crogers): fix OnOutputDeviceChanged() to pass AudioParameters. + media::ChannelLayout channel_layout = + audio_hardware_config_->GetOutputChannelLayout(); + int channels = audio_hardware_config_->GetOutputChannels(); + + media::AudioParameters output_params; + output_params.Reset( + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + channel_layout, + channels, + 0, + new_sample_rate, + 16, + new_buffer_size); + + audio_hardware_config_->UpdateOutputConfig(output_params); } void AudioMessageFilter::SetAudioHardwareConfig( diff --git a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc index 0d00942..900162f 100644 --- a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc +++ b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc @@ -6,6 +6,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "content/renderer/media/audio_renderer_mixer_manager.h" +#include "media/audio/audio_parameters.h" #include "media/base/audio_hardware_config.h" #include "media/base/audio_renderer_mixer.h" #include "media/base/audio_renderer_mixer_input.h" @@ -24,10 +25,20 @@ static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; static const int kRenderViewId = 123; static const int kAnotherRenderViewId = 456; +using media::AudioParameters; + class AudioRendererMixerManagerTest : public testing::Test { public: AudioRendererMixerManagerTest() - : fake_config_(kBufferSize, kSampleRate, 0, media::CHANNEL_LAYOUT_NONE) { + : fake_config_(AudioParameters(), AudioParameters()) { + AudioParameters output_params( + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, + kSampleRate, + 16, + kBufferSize); + fake_config_.UpdateOutputConfig(output_params); + manager_.reset(new AudioRendererMixerManager(&fake_config_)); // We don't want to deal with instantiating a real AudioOutputDevice since diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc index 1217458..b1eebba 100644 --- a/content/renderer/media/webrtc_audio_capturer.cc +++ b/content/renderer/media/webrtc_audio_capturer.cc @@ -85,9 +85,9 @@ class WebRtcAudioCapturer::ConfiguredBuffer : // bits_per_sample is always 16 for now. int bits_per_sample = 16; - - params_.Reset(format, channel_layout, 0, sample_rate, bits_per_sample, - buffer_size); + int channels = ChannelLayoutToChannelCount(channel_layout); + params_.Reset(format, channel_layout, channels, 0, + sample_rate, bits_per_sample, buffer_size); buffer_.reset(new int16[params_.frames_per_buffer() * params_.channels()]); return true; diff --git a/content/renderer/media/webrtc_audio_device_unittest.cc b/content/renderer/media/webrtc_audio_device_unittest.cc index e04eafc..e039ae4 100644 --- a/content/renderer/media/webrtc_audio_device_unittest.cc +++ b/content/renderer/media/webrtc_audio_device_unittest.cc @@ -18,6 +18,7 @@ #include "third_party/webrtc/voice_engine/include/voe_file.h" #include "third_party/webrtc/voice_engine/include/voe_network.h" +using media::AudioParameters; using testing::_; using testing::AnyNumber; using testing::InvokeWithoutArgs; @@ -32,14 +33,13 @@ const int kRenderViewId = 1; scoped_ptr<media::AudioHardwareConfig> CreateRealHardwareConfig( media::AudioManager* manager) { - const media::AudioParameters output_parameters = + const AudioParameters output_parameters = manager->GetDefaultOutputStreamParameters(); - const media::AudioParameters input_parameters = + const AudioParameters input_parameters = manager->GetInputStreamParameters( media::AudioManagerBase::kDefaultDeviceId); return make_scoped_ptr(new media::AudioHardwareConfig( - output_parameters.frames_per_buffer(), output_parameters.sample_rate(), - input_parameters.sample_rate(), input_parameters.channel_layout())); + input_parameters, output_parameters)); } // Return true if at least one element in the array matches |value|. @@ -218,8 +218,21 @@ TEST_F(WebRTCAudioDeviceTest, TestValidOutputRates) { // Basic test that instantiates and initializes an instance of // WebRtcAudioDeviceImpl. TEST_F(WebRTCAudioDeviceTest, Construct) { - media::AudioHardwareConfig audio_config( - 480, 48000, 48000, media::CHANNEL_LAYOUT_MONO); + AudioParameters input_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_MONO, + 48000, + 16, + 480); + + AudioParameters output_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, + 48000, + 16, + 480); + + media::AudioHardwareConfig audio_config(input_params, output_params); SetAudioHardwareConfig(&audio_config); scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc index b668f80..c30f265 100644 --- a/content/renderer/media/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc_audio_renderer.cc @@ -158,8 +158,10 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { return false; } + int channels = ChannelLayoutToChannelCount(channel_layout); source_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - channel_layout, 0, sample_rate, 16, buffer_size); + channel_layout, channels, 0, + sample_rate, 16, buffer_size); // Set up audio parameters for the sink, i.e., the native audio output stream. // We strive to open up using native parameters to achieve best possible @@ -171,7 +173,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { buffer_size = hardware_config->GetOutputBufferSize(); sink_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - channel_layout, 0, sample_rate, 16, buffer_size); + channel_layout, channels, 0, sample_rate, 16, buffer_size); // Create a FIFO if re-buffering is required to match the source input with // the sink request. The source acts as provider here and the sink as diff --git a/content/renderer/pepper/pepper_platform_audio_input_impl.cc b/content/renderer/pepper/pepper_platform_audio_input_impl.cc index 6351768..4534f33 100644 --- a/content/renderer/pepper/pepper_platform_audio_input_impl.cc +++ b/content/renderer/pepper/pepper_platform_audio_input_impl.cc @@ -165,7 +165,7 @@ bool PepperPlatformAudioInputImpl::Initialize( client_ = client; params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR, - media::CHANNEL_LAYOUT_MONO, 0, + media::CHANNEL_LAYOUT_MONO, 1, 0, sample_rate, 16, frames_per_buffer); if (device_id.empty()) { diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 58cd3f7..8879aa0 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -980,18 +980,13 @@ AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() { media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() { if (!audio_hardware_config_) { - int output_buffer_size; - int output_sample_rate; - int input_sample_rate; - media::ChannelLayout input_channel_layout; - + media::AudioParameters input_params; + media::AudioParameters output_params; Send(new ViewHostMsg_GetAudioHardwareConfig( - &output_buffer_size, &output_sample_rate, - &input_sample_rate, &input_channel_layout)); + &input_params, &output_params)); audio_hardware_config_.reset(new media::AudioHardwareConfig( - output_buffer_size, output_sample_rate, input_sample_rate, - input_channel_layout)); + input_params, output_params)); audio_message_filter_->SetAudioHardwareConfig(audio_hardware_config_.get()); } diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc index 1368005..addb397 100644 --- a/content/renderer/renderer_webkitplatformsupport_impl.cc +++ b/content/renderer/renderer_webkitplatformsupport_impl.cc @@ -633,6 +633,11 @@ size_t RendererWebKitPlatformSupportImpl::audioHardwareBufferSize() { return thread->GetAudioHardwareConfig()->GetOutputBufferSize(); } +unsigned RendererWebKitPlatformSupportImpl::audioHardwareOutputChannels() { + RenderThreadImpl* thread = RenderThreadImpl::current(); + return thread->GetAudioHardwareConfig()->GetOutputChannels(); +} + // TODO(crogers): remove deprecated API as soon as WebKit calls new API. WebAudioDevice* RendererWebKitPlatformSupportImpl::createAudioDevice( diff --git a/content/renderer/renderer_webkitplatformsupport_impl.h b/content/renderer/renderer_webkitplatformsupport_impl.h index 10210e9..03d2df7 100644 --- a/content/renderer/renderer_webkitplatformsupport_impl.h +++ b/content/renderer/renderer_webkitplatformsupport_impl.h @@ -79,6 +79,7 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl virtual bool isThreadedCompositingEnabled(); virtual double audioHardwareSampleRate(); virtual size_t audioHardwareBufferSize(); + virtual unsigned audioHardwareOutputChannels(); // TODO(crogers): remove deprecated API as soon as WebKit calls new API. virtual WebKit::WebAudioDevice* createAudioDevice( diff --git a/content/test/DEPS b/content/test/DEPS index ebd2714..95f1d48 100644 --- a/content/test/DEPS +++ b/content/test/DEPS @@ -1,6 +1,7 @@ include_rules = [ # Testing utilities can access anything in content/ "+content", + "+media/audio", # For AudioParameters in WebRTC tests. "+media/base", # For ChannelLayout in WebRTC tests. "+ui/aura/test/test_aura_initializer.h", "+ui/base/resource/data_pack.h", diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc index e9a3c48..562c308 100644 --- a/content/test/webrtc_audio_device_test.cc +++ b/content/test/webrtc_audio_device_test.cc @@ -16,6 +16,7 @@ #include "content/browser/renderer_host/media/audio_renderer_host.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/browser/renderer_host/media/mock_media_observer.h" +#include "content/common/media/media_param_traits.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_paths.h" @@ -27,6 +28,7 @@ #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" +#include "media/audio/audio_parameters.h" #include "media/base/audio_hardware_config.h" #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -40,6 +42,8 @@ #include "base/win/scoped_com_initializer.h" #endif +using media::AudioParameters; +using media::ChannelLayout; using testing::_; using testing::InvokeWithoutArgs; using testing::Return; @@ -262,16 +266,10 @@ void WebRTCAudioDeviceTest::DestroyChannel() { } void WebRTCAudioDeviceTest::OnGetAudioHardwareConfig( - int* output_buffer_size, int* output_sample_rate, int* input_sample_rate, - media::ChannelLayout* input_channel_layout) { + AudioParameters* input_params, AudioParameters* output_params) { ASSERT_TRUE(audio_hardware_config_); - - *output_buffer_size = audio_hardware_config_->GetOutputBufferSize(); - *output_sample_rate = audio_hardware_config_->GetOutputSampleRate(); - - // TODO(henrika): add support for all available input devices. - *input_sample_rate = audio_hardware_config_->GetInputSampleRate(); - *input_channel_layout = audio_hardware_config_->GetInputChannelLayout(); + *input_params = audio_hardware_config_->GetInputConfig(); + *output_params = audio_hardware_config_->GetOutputConfig(); } // IPC::Listener implementation. diff --git a/content/test/webrtc_audio_device_test.h b/content/test/webrtc_audio_device_test.h index 71327b6..ed9760d 100644 --- a/content/test/webrtc_audio_device_test.h +++ b/content/test/webrtc_audio_device_test.h @@ -132,9 +132,8 @@ class WebRTCAudioDeviceTest : public ::testing::Test, public IPC::Listener { void CreateChannel(const char* name); void DestroyChannel(); - void OnGetAudioHardwareConfig(int* output_buffer_size, - int* output_sample_rate, int* input_sample_rate, - media::ChannelLayout* input_channel_layout); + void OnGetAudioHardwareConfig(media::AudioParameters* input_params, + media::AudioParameters* output_params); // IPC::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc index 5628f66..5668687 100644 --- a/media/audio/audio_output_device_unittest.cc +++ b/media/audio/audio_output_device_unittest.cc @@ -152,7 +152,7 @@ AudioOutputDeviceTest::AudioOutputDeviceTest() input_channels_(synchronized_io_ ? 2 : 0) { default_audio_parameters_.Reset( AudioParameters::AUDIO_PCM_LINEAR, - CHANNEL_LAYOUT_STEREO, input_channels_, + CHANNEL_LAYOUT_STEREO, 2, input_channels_, 48000, 16, 1024); audio_device_ = new AudioOutputDevice( diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc index 9993096..089c083 100644 --- a/media/audio/audio_output_resampler.cc +++ b/media/audio/audio_output_resampler.cc @@ -221,7 +221,7 @@ bool AudioOutputResampler::OpenStream() { // Finally fall back to a fake audio output device. output_params_.Reset( AudioParameters::AUDIO_FAKE, params_.channel_layout(), - params_.input_channels(), params_.sample_rate(), + params_.channels(), params_.input_channels(), params_.sample_rate(), params_.bits_per_sample(), params_.frames_per_buffer()); Initialize(); if (dispatcher_->OpenStream()) { diff --git a/media/audio/audio_parameters.cc b/media/audio/audio_parameters.cc index 721dea0a..5e77c60 100644 --- a/media/audio/audio_parameters.cc +++ b/media/audio/audio_parameters.cc @@ -4,6 +4,7 @@ #include "media/audio/audio_parameters.h" +#include "base/logging.h" #include "media/base/limits.h" namespace media { @@ -44,16 +45,19 @@ AudioParameters::AudioParameters(Format format, ChannelLayout channel_layout, } void AudioParameters::Reset(Format format, ChannelLayout channel_layout, - int input_channels, + int channels, int input_channels, int sample_rate, int bits_per_sample, int frames_per_buffer) { + if (channel_layout != CHANNEL_LAYOUT_DISCRETE) + DCHECK_EQ(channels, ChannelLayoutToChannelCount(channel_layout)); + format_ = format; channel_layout_ = channel_layout; + channels_ = channels; input_channels_ = input_channels; sample_rate_ = sample_rate; bits_per_sample_ = bits_per_sample; frames_per_buffer_ = frames_per_buffer; - channels_ = ChannelLayoutToChannelCount(channel_layout); } bool AudioParameters::IsValid() const { @@ -85,4 +89,9 @@ int AudioParameters::GetBytesPerFrame() const { return channels_ * bits_per_sample_ / 8; } +void AudioParameters::SetDiscreteChannels(int channels) { + channel_layout_ = CHANNEL_LAYOUT_DISCRETE; + channels_ = channels; +} + } // namespace media diff --git a/media/audio/audio_parameters.h b/media/audio/audio_parameters.h index 498fe2e..dcc9eae 100644 --- a/media/audio/audio_parameters.h +++ b/media/audio/audio_parameters.h @@ -51,7 +51,7 @@ class MEDIA_EXPORT AudioParameters { int sample_rate, int bits_per_sample, int frames_per_buffer); void Reset(Format format, ChannelLayout channel_layout, - int input_channels, + int channels, int input_channels, int sample_rate, int bits_per_sample, int frames_per_buffer); @@ -76,6 +76,9 @@ class MEDIA_EXPORT AudioParameters { int channels() const { return channels_; } int input_channels() const { return input_channels_; } + // Set to CHANNEL_LAYOUT_DISCRETE with given number of channels. + void SetDiscreteChannels(int channels); + private: Format format_; // Format of the stream. ChannelLayout channel_layout_; // Order of surround sound channels. diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index 2184e12..ec6a79a 100644 --- a/media/audio/mac/audio_manager_mac.cc +++ b/media/audio/mac/audio_manager_mac.cc @@ -264,6 +264,97 @@ bool AudioManagerMac::HasAudioInputDevices() { return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice); } +// TODO(crogers): There are several places on the OSX specific code which +// could benefit from this helper function. +bool AudioManagerMac::GetDefaultOutputDevice( + AudioDeviceID* device) { + CHECK(device); + + // Obtain the current output device selected by the user. + static const AudioObjectPropertyAddress kAddress = { + kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + + UInt32 size = sizeof(*device); + + OSStatus result = AudioObjectGetPropertyData( + kAudioObjectSystemObject, + &kAddress, + 0, + 0, + &size, + device); + + if ((result != kAudioHardwareNoError) || (*device == kAudioDeviceUnknown)) { + DLOG(ERROR) << "Error getting default output AudioDevice."; + return false; + } + + return true; +} + +bool AudioManagerMac::GetDefaultOutputChannels( + int* channels, int* channels_per_frame) { + AudioDeviceID device; + if (!GetDefaultOutputDevice(&device)) + return false; + + return GetDeviceChannels(device, + kAudioDevicePropertyScopeOutput, + channels, + channels_per_frame); +} + +bool AudioManagerMac::GetDeviceChannels( + AudioDeviceID device, + AudioObjectPropertyScope scope, + int* channels, + int* channels_per_frame) { + CHECK(channels); + CHECK(channels_per_frame); + + // Get stream configuration. + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyStreamConfiguration; + pa.mScope = scope; + pa.mElement = kAudioObjectPropertyElementMaster; + + UInt32 size; + OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size); + if (result != noErr || !size) + return false; + + // Allocate storage. + scoped_array<uint8> list_storage(new uint8[size]); + AudioBufferList& buffer_list = + *reinterpret_cast<AudioBufferList*>(list_storage.get()); + + result = AudioObjectGetPropertyData( + device, + &pa, + 0, + 0, + &size, + &buffer_list); + if (result != noErr) + return false; + + // Determine number of input channels. + *channels_per_frame = buffer_list.mNumberBuffers > 0 ? + buffer_list.mBuffers[0].mNumberChannels : 0; + if (*channels_per_frame == 1 && buffer_list.mNumberBuffers > 1) { + // Non-interleaved. + *channels = buffer_list.mNumberBuffers; + } else { + // Interleaved. + *channels = *channels_per_frame; + } + + return true; +} + void AudioManagerMac::GetAudioInputDeviceNames( media::AudioDeviceNames* device_names) { GetAudioDeviceInfo(true, device_names); @@ -333,11 +424,23 @@ AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream( AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters( const AudioParameters& input_params) { - ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; + int hardware_channels = 2; + int hardware_channels_per_frame = 1; + if (!GetDefaultOutputChannels(&hardware_channels, + &hardware_channels_per_frame)) { + // Fallback to stereo. + hardware_channels = 2; + } + + ChannelLayout channel_layout = GuessChannelLayout(hardware_channels); + int buffer_size = kDefaultLowLatencyBufferSize; + int user_buffer_size = GetUserBufferSize(); + if (user_buffer_size) + buffer_size = user_buffer_size; + int input_channels = 0; if (input_params.IsValid()) { - channel_layout = input_params.channel_layout(); input_channels = input_params.input_channels(); if (input_channels > 0) { @@ -349,13 +452,18 @@ AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters( } } - int user_buffer_size = GetUserBufferSize(); - if (user_buffer_size) - buffer_size = user_buffer_size; + AudioParameters params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + channel_layout, + input_channels, + AUAudioOutputStream::HardwareSampleRate(), + 16, + buffer_size); - return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, - AUAudioOutputStream::HardwareSampleRate(), 16, buffer_size); + if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) + params.SetDiscreteChannels(hardware_channels); + + return params; } void AudioManagerMac::CreateDeviceListener() { diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h index 5eba595..6ebac06 100644 --- a/media/audio/mac/audio_manager_mac.h +++ b/media/audio/mac/audio_manager_mac.h @@ -38,6 +38,16 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase { virtual AudioInputStream* MakeLowLatencyInputStream( const AudioParameters& params, const std::string& device_id) OVERRIDE; + static bool GetDefaultOutputDevice(AudioDeviceID* device); + + static bool GetDefaultOutputChannels(int* channels, + int* channels_per_frame); + + static bool GetDeviceChannels(AudioDeviceID device, + AudioObjectPropertyScope scope, + int* channels, + int* channels_per_frame); + protected: virtual ~AudioManagerMac(); diff --git a/media/base/audio_converter.cc b/media/base/audio_converter.cc index 1b66b03..5fda460 100644 --- a/media/base/audio_converter.cc +++ b/media/base/audio_converter.cc @@ -30,8 +30,7 @@ AudioConverter::AudioConverter(const AudioParameters& input_params, << " to " << output_params.channel_layout() << "; from " << input_params.channels() << " channels to " << output_params.channels() << " channels."; - channel_mixer_.reset(new ChannelMixer( - input_params.channel_layout(), output_params.channel_layout())); + channel_mixer_.reset(new ChannelMixer(input_params, output_params)); // Pare off data as early as we can for efficiency. downmix_early_ = input_params.channels() > output_params.channels(); diff --git a/media/base/audio_hardware_config.cc b/media/base/audio_hardware_config.cc index eaacc69..d72fce7 100644 --- a/media/base/audio_hardware_config.cc +++ b/media/base/audio_hardware_config.cc @@ -4,50 +4,77 @@ #include "media/base/audio_hardware_config.h" +using base::AutoLock; +using media::AudioParameters; + namespace media { AudioHardwareConfig::AudioHardwareConfig( - int output_buffer_size, int output_sample_rate, - int input_sample_rate, ChannelLayout input_channel_layout) - : output_buffer_size_(output_buffer_size), - output_sample_rate_(output_sample_rate), - input_sample_rate_(input_sample_rate), - input_channel_layout_(input_channel_layout) { + const AudioParameters& input_params, + const AudioParameters& output_params) + : input_params_(input_params), + output_params_(output_params) { } AudioHardwareConfig::~AudioHardwareConfig() {} -int AudioHardwareConfig::GetOutputBufferSize() { - base::AutoLock auto_lock(config_lock_); - return output_buffer_size_; +int AudioHardwareConfig::GetOutputBufferSize() const { + AutoLock auto_lock(config_lock_); + return output_params_.frames_per_buffer(); +} + +int AudioHardwareConfig::GetOutputSampleRate() const { + AutoLock auto_lock(config_lock_); + return output_params_.sample_rate(); +} + +ChannelLayout AudioHardwareConfig::GetOutputChannelLayout() const { + AutoLock auto_lock(config_lock_); + return output_params_.channel_layout(); +} + +int AudioHardwareConfig::GetOutputChannels() const { + AutoLock auto_lock(config_lock_); + return output_params_.channels(); +} + +int AudioHardwareConfig::GetInputSampleRate() const { + AutoLock auto_lock(config_lock_); + return input_params_.sample_rate(); +} + +ChannelLayout AudioHardwareConfig::GetInputChannelLayout() const { + AutoLock auto_lock(config_lock_); + return input_params_.channel_layout(); } -int AudioHardwareConfig::GetOutputSampleRate() { - base::AutoLock auto_lock(config_lock_); - return output_sample_rate_; +int AudioHardwareConfig::GetInputChannels() const { + AutoLock auto_lock(config_lock_); + return input_params_.channels(); } -int AudioHardwareConfig::GetInputSampleRate() { - base::AutoLock auto_lock(config_lock_); - return input_sample_rate_; +media::AudioParameters +AudioHardwareConfig::GetInputConfig() const { + AutoLock auto_lock(config_lock_); + return input_params_; } -ChannelLayout AudioHardwareConfig::GetInputChannelLayout() { - base::AutoLock auto_lock(config_lock_); - return input_channel_layout_; +media::AudioParameters +AudioHardwareConfig::GetOutputConfig() const { + AutoLock auto_lock(config_lock_); + return output_params_; } void AudioHardwareConfig::UpdateInputConfig( - int sample_rate, media::ChannelLayout channel_layout) { - base::AutoLock auto_lock(config_lock_); - input_sample_rate_ = sample_rate; - input_channel_layout_ = channel_layout; + const AudioParameters& input_params) { + AutoLock auto_lock(config_lock_); + input_params_ = input_params; } -void AudioHardwareConfig::UpdateOutputConfig(int buffer_size, int sample_rate) { - base::AutoLock auto_lock(config_lock_); - output_buffer_size_ = buffer_size; - output_sample_rate_ = sample_rate; +void AudioHardwareConfig::UpdateOutputConfig( + const AudioParameters& output_params) { + AutoLock auto_lock(config_lock_); + output_params_ = output_params; } } // namespace media diff --git a/media/base/audio_hardware_config.h b/media/base/audio_hardware_config.h index e61d9ba..d1621b98 100644 --- a/media/base/audio_hardware_config.h +++ b/media/base/audio_hardware_config.h @@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "base/synchronization/lock.h" +#include "media/audio/audio_parameters.h" #include "media/base/channel_layout.h" #include "media/base/media_export.h" @@ -15,32 +16,36 @@ namespace media { // Provides thread safe access to the audio hardware configuration. class MEDIA_EXPORT AudioHardwareConfig { public: - AudioHardwareConfig(int output_buffer_size, int output_sample_rate, - int input_sample_rate, - ChannelLayout input_channel_layout); + AudioHardwareConfig(const media::AudioParameters& input_params, + const media::AudioParameters& output_params); virtual ~AudioHardwareConfig(); // Accessors for the currently cached hardware configuration. Safe to call // from any thread. - int GetOutputBufferSize(); - int GetOutputSampleRate(); - int GetInputSampleRate(); - ChannelLayout GetInputChannelLayout(); + int GetOutputBufferSize() const; + int GetOutputSampleRate() const; + ChannelLayout GetOutputChannelLayout() const; + int GetOutputChannels() const; + + int GetInputSampleRate() const; + ChannelLayout GetInputChannelLayout() const; + int GetInputChannels() const; + + media::AudioParameters GetInputConfig() const; + media::AudioParameters GetOutputConfig() const; // Allows callers to update the cached values for either input or output. The // values are paired under the assumption that these values will only be set // after an input or output device change respectively. Safe to call from // any thread. - void UpdateInputConfig(int sample_rate, media::ChannelLayout channel_layout); - void UpdateOutputConfig(int buffer_size, int sample_rate); + void UpdateInputConfig(const media::AudioParameters& input_params); + void UpdateOutputConfig(const media::AudioParameters& output_params); private: // Cached values; access is protected by |config_lock_|. - base::Lock config_lock_; - int output_buffer_size_; - int output_sample_rate_; - int input_sample_rate_; - ChannelLayout input_channel_layout_; + mutable base::Lock config_lock_; + media::AudioParameters input_params_; + media::AudioParameters output_params_; DISALLOW_COPY_AND_ASSIGN(AudioHardwareConfig); }; diff --git a/media/base/audio_hardware_config_unittest.cc b/media/base/audio_hardware_config_unittest.cc index afa2e0d..4a742bf 100644 --- a/media/base/audio_hardware_config_unittest.cc +++ b/media/base/audio_hardware_config_unittest.cc @@ -3,19 +3,33 @@ // found in the LICENSE file. #include "media/base/audio_hardware_config.h" +#include "media/audio/audio_parameters.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { static const int kOutputBufferSize = 2048; static const int kOutputSampleRate = 48000; +static const ChannelLayout kOutputChannelLayout = CHANNEL_LAYOUT_STEREO; static const int kInputSampleRate = 44100; static const ChannelLayout kInputChannelLayout = CHANNEL_LAYOUT_STEREO; TEST(AudioHardwareConfig, Getters) { - AudioHardwareConfig fake_config( - kOutputBufferSize, kOutputSampleRate, kInputSampleRate, - kInputChannelLayout); + AudioParameters input_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + kInputChannelLayout, + kInputSampleRate, + 16, + kOutputBufferSize); + + AudioParameters output_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + kOutputChannelLayout, + kOutputSampleRate, + 16, + kOutputBufferSize); + + AudioHardwareConfig fake_config(input_params, output_params); EXPECT_EQ(kOutputBufferSize, fake_config.GetOutputBufferSize()); EXPECT_EQ(kOutputSampleRate, fake_config.GetOutputSampleRate()); @@ -24,16 +38,35 @@ TEST(AudioHardwareConfig, Getters) { } TEST(AudioHardwareConfig, Setters) { - AudioHardwareConfig fake_config( - kOutputBufferSize, kOutputSampleRate, kInputSampleRate, - kInputChannelLayout); + AudioParameters input_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + kInputChannelLayout, + kInputSampleRate, + 16, + kOutputBufferSize); + + AudioParameters output_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + kOutputChannelLayout, + kOutputSampleRate, + 16, + kOutputBufferSize); + + AudioHardwareConfig fake_config(input_params, output_params); // Verify output parameters. const int kNewOutputBufferSize = kOutputBufferSize * 2; const int kNewOutputSampleRate = kOutputSampleRate * 2; EXPECT_NE(kNewOutputBufferSize, fake_config.GetOutputBufferSize()); EXPECT_NE(kNewOutputSampleRate, fake_config.GetOutputSampleRate()); - fake_config.UpdateOutputConfig(kNewOutputBufferSize, kNewOutputSampleRate); + + AudioParameters new_output_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + kOutputChannelLayout, + kNewOutputSampleRate, + 16, + kNewOutputBufferSize); + fake_config.UpdateOutputConfig(new_output_params); EXPECT_EQ(kNewOutputBufferSize, fake_config.GetOutputBufferSize()); EXPECT_EQ(kNewOutputSampleRate, fake_config.GetOutputSampleRate()); @@ -42,7 +75,14 @@ TEST(AudioHardwareConfig, Setters) { const ChannelLayout kNewInputChannelLayout = CHANNEL_LAYOUT_MONO; EXPECT_NE(kNewInputSampleRate, fake_config.GetInputSampleRate()); EXPECT_NE(kNewInputChannelLayout, fake_config.GetInputChannelLayout()); - fake_config.UpdateInputConfig(kNewInputSampleRate, kNewInputChannelLayout); + + AudioParameters new_input_params( + AudioParameters::AUDIO_PCM_LOW_LATENCY, + kNewInputChannelLayout, + kNewInputSampleRate, + 16, + kOutputBufferSize); + fake_config.UpdateInputConfig(new_input_params); EXPECT_EQ(kNewInputSampleRate, fake_config.GetInputSampleRate()); EXPECT_EQ(kNewInputChannelLayout, fake_config.GetInputChannelLayout()); } diff --git a/media/base/channel_layout.cc b/media/base/channel_layout.cc index e622f91..927cd77 100644 --- a/media/base/channel_layout.cc +++ b/media/base/channel_layout.cc @@ -39,6 +39,7 @@ static const int kLayoutToChannels[] = { 7, // CHANNEL_LAYOUT_7_0_FRONT 8, // CHANNEL_LAYOUT_7_1_WIDE_BACK 8, // CHANNEL_LAYOUT_OCTAGONAL + 0, // CHANNEL_LAYOUT_DISCRETE }; // The channel orderings for each layout as specified by FFmpeg. Each value @@ -141,6 +142,9 @@ static const int kChannelOrderings[CHANNEL_LAYOUT_MAX][CHANNELS_MAX] = { // CHANNEL_LAYOUT_OCTAGONAL { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , 7 , 3 , 4 }, + // CHANNEL_LAYOUT_DISCRETE + { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, + // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR }; @@ -149,6 +153,31 @@ int ChannelLayoutToChannelCount(ChannelLayout layout) { return kLayoutToChannels[layout]; } +// Converts a channel count into a channel layout. +ChannelLayout GuessChannelLayout(int channels) { + switch (channels) { + case 1: + return CHANNEL_LAYOUT_MONO; + case 2: + return CHANNEL_LAYOUT_STEREO; + case 3: + return CHANNEL_LAYOUT_SURROUND; + case 4: + return CHANNEL_LAYOUT_QUAD; + case 5: + return CHANNEL_LAYOUT_5_0; + case 6: + return CHANNEL_LAYOUT_5_1; + case 7: + return CHANNEL_LAYOUT_6_1; + case 8: + return CHANNEL_LAYOUT_7_1; + default: + DVLOG(1) << "Unsupported channel count: " << channels; + } + return CHANNEL_LAYOUT_UNSUPPORTED; +} + int ChannelOrder(ChannelLayout layout, Channels channel) { DCHECK_LT(static_cast<size_t>(layout), arraysize(kChannelOrderings)); DCHECK_LT(static_cast<size_t>(channel), arraysize(kChannelOrderings[0])); diff --git a/media/base/channel_layout.h b/media/base/channel_layout.h index 8153ca6..4c96ca5 100644 --- a/media/base/channel_layout.h +++ b/media/base/channel_layout.h @@ -96,6 +96,9 @@ enum ChannelLayout { // Front L, Front R, Front C, Side L, Side R, Rear C, Back L, Back R. CHANNEL_LAYOUT_OCTAGONAL = 28, + // Channels are not explicitly mapped to speakers. + CHANNEL_LAYOUT_DISCRETE = 29, + // Total number of layouts. CHANNEL_LAYOUT_MAX // Must always be last! }; @@ -123,6 +126,10 @@ MEDIA_EXPORT int ChannelOrder(ChannelLayout layout, Channels channel); // Returns the number of channels in a given ChannelLayout. MEDIA_EXPORT int ChannelLayoutToChannelCount(ChannelLayout layout); +// Given the number of channels, return the best layout, +// or return CHANNEL_LAYOUT_UNSUPPORTED if there is no good match. +MEDIA_EXPORT ChannelLayout GuessChannelLayout(int channels); + } // namespace media #endif // MEDIA_BASE_CHANNEL_LAYOUT_H_ diff --git a/media/base/channel_mixer.cc b/media/base/channel_mixer.cc index fa4cbb6..420ecda 100644 --- a/media/base/channel_mixer.cc +++ b/media/base/channel_mixer.cc @@ -11,6 +11,7 @@ #include <cmath> #include "base/logging.h" +#include "media/audio/audio_parameters.h" #include "media/base/audio_bus.h" #include "media/base/vector_math.h" @@ -20,14 +21,11 @@ namespace media { // value for stereo -> mono and mono -> stereo mixes. static const float kEqualPowerScale = static_cast<float>(M_SQRT1_2); -static int ValidateLayout(ChannelLayout layout) { +static void ValidateLayout(ChannelLayout layout) { CHECK_NE(layout, CHANNEL_LAYOUT_NONE); CHECK_NE(layout, CHANNEL_LAYOUT_MAX); - - // TODO(dalecurtis, crogers): We will eventually handle unsupported layouts by - // simply copying the input channels to the output channels, similar to if the - // user requests identical input and output layouts today. CHECK_NE(layout, CHANNEL_LAYOUT_UNSUPPORTED); + CHECK_NE(layout, CHANNEL_LAYOUT_DISCRETE); // Verify there's at least one channel. Should always be true here by virtue // of not being one of the invalid layouts, but lets double check to be sure. @@ -52,24 +50,60 @@ static int ValidateLayout(ChannelLayout layout) { DCHECK_EQ(layout, CHANNEL_LAYOUT_MONO); } - return channel_count; + return; +} + +ChannelMixer::ChannelMixer(ChannelLayout input_layout, + ChannelLayout output_layout) { + Initialize(input_layout, + ChannelLayoutToChannelCount(input_layout), + output_layout, + ChannelLayoutToChannelCount(output_layout)); } -ChannelMixer::ChannelMixer(ChannelLayout input, ChannelLayout output) - : input_layout_(input), - output_layout_(output), - remapping_(false) { +ChannelMixer::ChannelMixer( + const AudioParameters& input, const AudioParameters& output) { + Initialize(input.channel_layout(), + input.channels(), + output.channel_layout(), + output.channels()); +} + +void ChannelMixer::Initialize( + ChannelLayout input_layout, int input_channels, + ChannelLayout output_layout, int output_channels) { + input_layout_ = input_layout; + output_layout_ = output_layout; + remapping_ = false; + // Stereo down mix should never be the output layout. CHECK_NE(output_layout_, CHANNEL_LAYOUT_STEREO_DOWNMIX); - int input_channels = ValidateLayout(input_layout_); - int output_channels = ValidateLayout(output_layout_); + if (input_layout_ != CHANNEL_LAYOUT_DISCRETE) + ValidateLayout(input_layout_); + if (output_layout_ != CHANNEL_LAYOUT_DISCRETE) + ValidateLayout(output_layout_); // Size out the initial matrix. matrix_.reserve(output_channels); for (int output_ch = 0; output_ch < output_channels; ++output_ch) matrix_.push_back(std::vector<float>(input_channels, 0)); + // First check for discrete case. + if (input_layout_ == CHANNEL_LAYOUT_DISCRETE || + output_layout_ == CHANNEL_LAYOUT_DISCRETE) { + // If the number of input channels is more than output channels, then + // copy as many as we can then drop the remaining input channels. + // If the number of input channels is less than output channels, then + // copy them all, then zero out the remaining output channels. + int passthrough_channels = std::min(input_channels, output_channels); + for (int i = 0; i < passthrough_channels; ++i) + matrix_[i][i] = 1; + + remapping_ = true; + return; + } + // Route matching channels and figure out which ones aren't accounted for. for (Channels ch = LEFT; ch < CHANNELS_MAX; ch = static_cast<Channels>(ch + 1)) { @@ -102,7 +136,8 @@ ChannelMixer::ChannelMixer(ChannelLayout input, ChannelLayout output) // When down mixing to mono from stereo, we need to be careful of full scale // stereo mixes. Scaling by 1 / sqrt(2) here will likely lead to clipping // so we use 1 / 2 instead. - float scale = (output == CHANNEL_LAYOUT_MONO && input_channels == 2) ? + float scale = + (output_layout_ == CHANNEL_LAYOUT_MONO && input_channels == 2) ? 0.5 : kEqualPowerScale; Mix(LEFT, CENTER, scale); Mix(RIGHT, CENTER, scale); @@ -111,7 +146,8 @@ ChannelMixer::ChannelMixer(ChannelLayout input, ChannelLayout output) // Mix center into front LR. if (IsUnaccounted(CENTER)) { // When up mixing from mono, just do a copy to front LR. - float scale = (input == CHANNEL_LAYOUT_MONO) ? 1 : kEqualPowerScale; + float scale = + (input_layout_ == CHANNEL_LAYOUT_MONO) ? 1 : kEqualPowerScale; MixWithoutAccounting(CENTER, LEFT, scale); Mix(CENTER, RIGHT, scale); } @@ -128,7 +164,7 @@ ChannelMixer::ChannelMixer(ChannelLayout input, ChannelLayout output) // Mix back LR into back center. Mix(BACK_LEFT, BACK_CENTER, kEqualPowerScale); Mix(BACK_RIGHT, BACK_CENTER, kEqualPowerScale); - } else if (output > CHANNEL_LAYOUT_MONO) { + } else if (output_layout_ > CHANNEL_LAYOUT_MONO) { // Mix back LR into front LR. Mix(BACK_LEFT, LEFT, kEqualPowerScale); Mix(BACK_RIGHT, RIGHT, kEqualPowerScale); @@ -151,7 +187,7 @@ ChannelMixer::ChannelMixer(ChannelLayout input, ChannelLayout output) // Mix side LR into back center. Mix(SIDE_LEFT, BACK_CENTER, kEqualPowerScale); Mix(SIDE_RIGHT, BACK_CENTER, kEqualPowerScale); - } else if (output > CHANNEL_LAYOUT_MONO) { + } else if (output_layout_ > CHANNEL_LAYOUT_MONO) { // Mix side LR into front LR. Mix(SIDE_LEFT, LEFT, kEqualPowerScale); Mix(SIDE_RIGHT, RIGHT, kEqualPowerScale); @@ -172,7 +208,7 @@ ChannelMixer::ChannelMixer(ChannelLayout input, ChannelLayout output) // Mix back center into side LR. MixWithoutAccounting(BACK_CENTER, SIDE_LEFT, kEqualPowerScale); Mix(BACK_CENTER, SIDE_RIGHT, kEqualPowerScale); - } else if (output > CHANNEL_LAYOUT_MONO) { + } else if (output_layout_ > CHANNEL_LAYOUT_MONO) { // Mix back center into front LR. // TODO(dalecurtis): Not sure about these values? MixWithoutAccounting(BACK_CENTER, LEFT, kEqualPowerScale); diff --git a/media/base/channel_mixer.h b/media/base/channel_mixer.h index 0fdcc18..c88669d 100644 --- a/media/base/channel_mixer.h +++ b/media/base/channel_mixer.h @@ -14,6 +14,7 @@ namespace media { class AudioBus; +class AudioParameters; // ChannelMixer is for converting audio between channel layouts. The conversion // matrix is built upon construction and used during each Transform() call. The @@ -23,9 +24,13 @@ class AudioBus; // input channels as defined in the matrix. class MEDIA_EXPORT ChannelMixer { public: - ChannelMixer(ChannelLayout input, ChannelLayout output); + ChannelMixer(ChannelLayout input_layout, ChannelLayout output_layout); + ChannelMixer(const AudioParameters& input, const AudioParameters& output); ~ChannelMixer(); + void Initialize(ChannelLayout input_layout, int input_channels, + ChannelLayout output_layout, int output_channels); + // Transforms all channels from |input| into |output| channels. void Transform(const AudioBus* input, AudioBus* output); diff --git a/media/base/channel_mixer_unittest.cc b/media/base/channel_mixer_unittest.cc index a71f86b..3e44409 100644 --- a/media/base/channel_mixer_unittest.cc +++ b/media/base/channel_mixer_unittest.cc @@ -25,6 +25,11 @@ TEST(ChannelMixerTest, ConstructAllPossibleLayouts) { for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO; output_layout < CHANNEL_LAYOUT_STEREO_DOWNMIX; output_layout = static_cast<ChannelLayout>(output_layout + 1)) { + // DISCRETE can't be tested here based on the current approach. + if (input_layout == CHANNEL_LAYOUT_DISCRETE || + output_layout == CHANNEL_LAYOUT_DISCRETE) + continue; + SCOPED_TRACE(base::StringPrintf( "Input Layout: %d, Output Layout: %d", input_layout, output_layout)); ChannelMixer mixer(input_layout, output_layout); diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index bf23430..a2c4efd 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc @@ -269,32 +269,6 @@ static AVSampleFormat SampleFormatToAVSampleFormat(SampleFormat sample_format) { return AV_SAMPLE_FMT_NONE; } -// Converts a channel count into a channel layout. Layouts chosen based on the -// Vorbis / Opus channel layout. -static ChannelLayout GuessChannelLayout(int channels) { - switch (channels) { - case 1: - return CHANNEL_LAYOUT_MONO; - case 2: - return CHANNEL_LAYOUT_STEREO; - case 3: - return CHANNEL_LAYOUT_SURROUND; - case 4: - return CHANNEL_LAYOUT_QUAD; - case 5: - return CHANNEL_LAYOUT_5_0; - case 6: - return CHANNEL_LAYOUT_5_1; - case 7: - return CHANNEL_LAYOUT_6_1; - case 8: - return CHANNEL_LAYOUT_7_1; - default: - DVLOG(1) << "Unsupported channel count: " << channels; - } - return CHANNEL_LAYOUT_UNSUPPORTED; -} - void AVCodecContextToAudioDecoderConfig( const AVCodecContext* codec_context, AudioDecoderConfig* config) { |