diff options
43 files changed, 195 insertions, 44 deletions
diff --git a/components/copresence/mediums/audio/audio_recorder.cc b/components/copresence/mediums/audio/audio_recorder.cc index 0946ba8..7430b27 100644 --- a/components/copresence/mediums/audio/audio_recorder.cc +++ b/components/copresence/mediums/audio/audio_recorder.cc @@ -104,6 +104,8 @@ void AudioRecorder::InitializeOnAudioThread() { const media::AudioParameters dest_params(params.format(), kDefaultChannelLayout, + kDefaultChannels, + params.input_channels(), kDefaultSampleRate, kDefaultBitsPerSample, params.frames_per_buffer(), diff --git a/components/copresence/mediums/audio/audio_recorder_unittest.cc b/components/copresence/mediums/audio/audio_recorder_unittest.cc index 4f0e6c8..69c856a 100644 --- a/components/copresence/mediums/audio/audio_recorder_unittest.cc +++ b/components/copresence/mediums/audio/audio_recorder_unittest.cc @@ -97,6 +97,7 @@ class AudioRecorderTest : public testing::Test { params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, kDefaultChannelLayout, channels, + 2, sample_rate, bits_per_sample, 4096); diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc index 06c51e6..1d3f4b4 100644 --- a/content/browser/media/media_internals.cc +++ b/content/browser/media/media_internals.cc @@ -110,6 +110,7 @@ void AudioLogImpl::OnCreated(int component_id, dict.SetString(kAudioLogStatusKey, "created"); dict.SetString("device_id", device_id); + dict.SetInteger("input_channels", params.input_channels()); dict.SetInteger("frames_per_buffer", params.frames_per_buffer()); dict.SetInteger("sample_rate", params.sample_rate()); dict.SetInteger("channels", params.channels()); diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc index 3dd2181..b9208c8 100644 --- a/content/browser/media/media_internals_unittest.cc +++ b/content/browser/media/media_internals_unittest.cc @@ -30,6 +30,7 @@ class MediaInternalsTest base::Unretained(this))), test_params_(media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_MONO, + 0, 48000, 16, 128, @@ -96,6 +97,7 @@ TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) { ExpectInt("sample_rate", test_params_.sample_rate()); ExpectInt("frames_per_buffer", test_params_.frames_per_buffer()); ExpectInt("channels", test_params_.channels()); + ExpectInt("input_channels", test_params_.input_channels()); ExpectString("effects", "ECHO_CANCELLER | DUCKING"); ExpectString("device_id", kTestDeviceID); ExpectInt("component_id", kTestComponentID); 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 87eed7e..2dcc56d 100644 --- a/content/browser/renderer_host/media/audio_input_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc @@ -267,7 +267,7 @@ void AudioInputRendererHost::OnCreateStream( ShouldUseFakeDevice()) { audio_params.Reset( media::AudioParameters::AUDIO_FAKE, - config.params.channel_layout(), config.params.channels(), + config.params.channel_layout(), config.params.channels(), 0, config.params.sample_rate(), config.params.bits_per_sample(), config.params.frames_per_buffer()); } diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index 91cea83..7b07fd9 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc @@ -357,6 +357,8 @@ void AudioRendererHost::OnCreateStream( output_device_id = info->device.matched_output_device_id; // Create the shared memory and share with the renderer process. + // For synchronized I/O (if input_channels > 0) then we allocate + // extra memory after the output data for the input data. uint32 shared_memory_size = AudioBus::CalculateMemorySize(params); scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc index e87b825..9dc99f2 100644 --- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc +++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc @@ -199,6 +199,7 @@ class AudioRendererHostTest : public testing::Test { params = media::AudioParameters( media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, + 2, media::AudioParameters::kAudioCDSampleRate, 16, media::AudioParameters::kAudioCDSampleRate / 10, media::AudioParameters::NO_EFFECTS); diff --git a/content/browser/speech/speech_recognizer_impl.cc b/content/browser/speech/speech_recognizer_impl.cc index 8824bf0..a4b004a 100644 --- a/content/browser/speech/speech_recognizer_impl.cc +++ b/content/browser/speech/speech_recognizer_impl.cc @@ -556,6 +556,7 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) { input_parameters.Reset(in_params.format(), in_params.channel_layout(), in_params.channels(), + in_params.input_channels(), in_params.sample_rate(), in_params.bits_per_sample(), frames_per_buffer); diff --git a/content/common/media/media_param_traits.cc b/content/common/media/media_param_traits.cc index 405e89d..345f838 100644 --- a/content/common/media/media_param_traits.cc +++ b/content/common/media/media_param_traits.cc @@ -24,6 +24,7 @@ void ParamTraits<AudioParameters>::Write(Message* m, m->WriteInt(p.bits_per_sample()); m->WriteInt(p.frames_per_buffer()); m->WriteInt(p.channels()); + m->WriteInt(p.input_channels()); m->WriteInt(p.effects()); } @@ -31,7 +32,7 @@ bool ParamTraits<AudioParameters>::Read(const Message* m, PickleIterator* iter, AudioParameters* r) { int format, channel_layout, sample_rate, bits_per_sample, - frames_per_buffer, channels, effects; + frames_per_buffer, channels, input_channels, effects; if (!m->ReadInt(iter, &format) || !m->ReadInt(iter, &channel_layout) || @@ -39,12 +40,13 @@ bool ParamTraits<AudioParameters>::Read(const Message* m, !m->ReadInt(iter, &bits_per_sample) || !m->ReadInt(iter, &frames_per_buffer) || !m->ReadInt(iter, &channels) || + !m->ReadInt(iter, &input_channels) || !m->ReadInt(iter, &effects)) return false; - AudioParameters params(static_cast<AudioParameters::Format>(format), static_cast<ChannelLayout>(channel_layout), channels, - sample_rate, bits_per_sample, frames_per_buffer, effects); + input_channels, sample_rate, bits_per_sample, frames_per_buffer, + effects); *r = params; if (!r->IsValid()) return false; diff --git a/content/renderer/media/audio_message_filter.cc b/content/renderer/media/audio_message_filter.cc index 2f852b7..fde42fb 100644 --- a/content/renderer/media/audio_message_filter.cc +++ b/content/renderer/media/audio_message_filter.cc @@ -234,6 +234,7 @@ void AudioMessageFilter::OnOutputDeviceChanged(int stream_id, media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, channels, + 0, new_sample_rate, 16, new_buffer_size); diff --git a/content/renderer/media/webaudio_capturer_source.cc b/content/renderer/media/webaudio_capturer_source.cc index 2095ac6..7076c24 100644 --- a/content/renderer/media/webaudio_capturer_source.cc +++ b/content/renderer/media/webaudio_capturer_source.cc @@ -48,7 +48,7 @@ void WebAudioCapturerSource::setFormat( // as buffer size since that is the native buffer size of WebRtc packet // running on. params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - channel_layout, number_of_channels, sample_rate, 16, + channel_layout, number_of_channels, 0, sample_rate, 16, sample_rate / 100); audio_format_changed_ = true; diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc index d5e7045..301fc21 100644 --- a/content/renderer/media/webrtc_audio_capturer.cc +++ b/content/renderer/media/webrtc_audio_capturer.cc @@ -327,7 +327,7 @@ void WebRtcAudioCapturer::SetCapturerSource( // bits_per_sample is always 16 for now. int buffer_size = GetBufferSize(sample_rate); media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - channel_layout, sample_rate, + channel_layout, 0, sample_rate, 16, buffer_size, device_info_.device.input.effects); diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc index 8976ca6..006f12f 100644 --- a/content/renderer/media/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc_audio_renderer.cc @@ -218,7 +218,7 @@ WebRtcAudioRenderer::WebRtcAudioRenderer( audio_delay_milliseconds_(0), fifo_delay_milliseconds_(0), sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::CHANNEL_LAYOUT_STEREO, sample_rate, 16, + media::CHANNEL_LAYOUT_STEREO, 0, sample_rate, 16, frames_per_buffer, GetCurrentDuckingFlag(source_render_frame_id)) { WebRtcLogMessage(base::StringPrintf( @@ -285,7 +285,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { DVLOG(1) << "Using WebRTC output buffer size: " << frames_per_10ms; source_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - sink_params_.channel_layout(), sink_params_.channels(), + sink_params_.channel_layout(), sink_params_.channels(), 0, sample_rate, 16, frames_per_10ms); // Update audio parameters for the sink, i.e., the native audio output stream. @@ -312,7 +312,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { DVLOG(1) << "Using sink output buffer size: " << frames_per_buffer; sink_params_.Reset(sink_params_.format(), sink_params_.channel_layout(), - sink_params_.channels(), sample_rate, 16, + sink_params_.channels(), 0, sample_rate, 16, frames_per_buffer); // Create a FIFO if re-buffering is required to match the source input with diff --git a/content/renderer/media/webrtc_local_audio_renderer.cc b/content/renderer/media/webrtc_local_audio_renderer.cc index 1de32d0..ac44a21 100644 --- a/content/renderer/media/webrtc_local_audio_renderer.cc +++ b/content/renderer/media/webrtc_local_audio_renderer.cc @@ -282,7 +282,8 @@ void WebRtcLocalAudioRenderer::ReconfigureSink( source_params_ = params; sink_params_ = media::AudioParameters(source_params_.format(), - source_params_.channel_layout(), source_params_.sample_rate(), + source_params_.channel_layout(), source_params_.channels(), + source_params_.input_channels(), source_params_.sample_rate(), source_params_.bits_per_sample(), #if defined(OS_ANDROID) // On Android, input and output use the same sample rate. In order to diff --git a/content/renderer/media/webrtc_local_audio_source_provider.cc b/content/renderer/media/webrtc_local_audio_source_provider.cc index 9253984..10ee943f 100644 --- a/content/renderer/media/webrtc_local_audio_source_provider.cc +++ b/content/renderer/media/webrtc_local_audio_source_provider.cc @@ -36,7 +36,7 @@ WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider( int sample_rate = hardware_config->GetOutputSampleRate(); sink_params_.Reset( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::CHANNEL_LAYOUT_STEREO, 2, sample_rate, 16, + media::CHANNEL_LAYOUT_STEREO, 2, 0, sample_rate, 16, kWebAudioRenderBufferSize); } diff --git a/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc b/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc index 6c7bb64..bd2bb74 100644 --- a/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc +++ b/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc @@ -20,10 +20,10 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test { protected: virtual void SetUp() OVERRIDE { source_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::CHANNEL_LAYOUT_MONO, 1, 48000, 16, 480); + media::CHANNEL_LAYOUT_MONO, 1, 0, 48000, 16, 480); sink_params_.Reset( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::CHANNEL_LAYOUT_STEREO, 2, 44100, 16, + media::CHANNEL_LAYOUT_STEREO, 2, 0, 44100, 16, WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize); const int length = source_params_.frames_per_buffer() * source_params_.channels(); diff --git a/content/renderer/media/webrtc_local_audio_track_unittest.cc b/content/renderer/media/webrtc_local_audio_track_unittest.cc index 20c462e..e77660e 100644 --- a/content/renderer/media/webrtc_local_audio_track_unittest.cc +++ b/content/renderer/media/webrtc_local_audio_track_unittest.cc @@ -169,7 +169,7 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test { protected: virtual void SetUp() OVERRIDE { params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::CHANNEL_LAYOUT_STEREO, 2, 48000, 16, 480); + media::CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 480); MockMediaConstraintFactory constraint_factory; blink_source_.initialize("dummy", blink::WebMediaStreamSource::TypeAudio, "dummy"); diff --git a/content/renderer/pepper/pepper_platform_audio_input.cc b/content/renderer/pepper/pepper_platform_audio_input.cc index b1d62f0..fafff22 100644 --- a/content/renderer/pepper/pepper_platform_audio_input.cc +++ b/content/renderer/pepper/pepper_platform_audio_input.cc @@ -172,6 +172,7 @@ bool PepperPlatformAudioInput::Initialize( params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_MONO, ppapi::kAudioInputChannels, + 0, sample_rate, ppapi::kBitsPerAudioInputSample, frames_per_buffer); diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc index 2516000..dd0c3c1 100644 --- a/content/renderer/renderer_webkitplatformsupport_impl.cc +++ b/content/renderer/renderer_webkitplatformsupport_impl.cc @@ -739,7 +739,8 @@ RendererWebKitPlatformSupportImpl::createAudioDevice( media::AudioParameters params( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - layout, static_cast<int>(sample_rate), 16, buffer_size, + layout, input_channels, + static_cast<int>(sample_rate), 16, buffer_size, media::AudioParameters::NO_EFFECTS); return new RendererWebAudioDeviceImpl(params, callback, session_id); diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc index 7624834..beb60ba 100644 --- a/media/audio/alsa/audio_manager_alsa.cc +++ b/media/audio/alsa/audio_manager_alsa.cc @@ -311,6 +311,7 @@ AudioParameters AudioManagerAlsa::GetPreferredOutputStreamParameters( int sample_rate = kDefaultSampleRate; int buffer_size = kDefaultOutputBufferSize; int bits_per_sample = 16; + int input_channels = 0; if (input_params.IsValid()) { // Some clients, such as WebRTC, have a more limited use case and work // acceptably with a smaller buffer size. The check below allows clients @@ -320,6 +321,7 @@ AudioParameters AudioManagerAlsa::GetPreferredOutputStreamParameters( sample_rate = input_params.sample_rate(); bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); + input_channels = input_params.input_channels(); buffer_size = std::min(input_params.frames_per_buffer(), buffer_size); } @@ -328,7 +330,7 @@ AudioParameters AudioManagerAlsa::GetPreferredOutputStreamParameters( buffer_size = user_buffer_size; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); } diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc index 68e74a4..177953d 100644 --- a/media/audio/android/audio_android_unittest.cc +++ b/media/audio/android/audio_android_unittest.cc @@ -598,6 +598,7 @@ class AudioAndroidInputTest : public AudioAndroidOutputTest, AudioParameters::NO_EFFECTS; AudioParameters params(audio_input_parameters().format(), audio_input_parameters().channel_layout(), + audio_input_parameters().input_channels(), audio_input_parameters().sample_rate(), audio_input_parameters().bits_per_sample(), audio_input_parameters().frames_per_buffer(), @@ -804,6 +805,7 @@ TEST_P(AudioAndroidInputTest, AudioParameters native_params = GetInputStreamParameters(); AudioParameters params(native_params.format(), native_params.channel_layout(), + native_params.input_channels(), native_params.sample_rate(), native_params.bits_per_sample(), native_params.sample_rate() / 100, diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc index 090f853..48f203a 100644 --- a/media/audio/android/audio_manager_android.cc +++ b/media/audio/android/audio_manager_android.cc @@ -138,7 +138,7 @@ AudioParameters AudioManagerAndroid::GetInputStreamParameters( buffer_size = user_buffer_size; AudioParameters params( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, GetNativeOutputSampleRate(), 16, buffer_size, effects); return params; } @@ -274,11 +274,13 @@ AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters( int sample_rate = GetNativeOutputSampleRate(); int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2); int bits_per_sample = 16; + int input_channels = 0; if (input_params.IsValid()) { // Use the client's input parameters if they are valid. sample_rate = input_params.sample_rate(); bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); + input_channels = input_params.input_channels(); buffer_size = GetOptimalOutputFrameSize( sample_rate, ChannelLayoutToChannelCount(channel_layout)); } @@ -288,7 +290,7 @@ AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters( buffer_size = user_buffer_size; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); } diff --git a/media/audio/audio_output_device.h b/media/audio/audio_output_device.h index 0d53d8b..8449e9f 100644 --- a/media/audio/audio_output_device.h +++ b/media/audio/audio_output_device.h @@ -81,8 +81,11 @@ class MEDIA_EXPORT AudioOutputDevice scoped_ptr<AudioOutputIPC> ipc, const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner); - // Initialize the stream using |session_id|, which is used for the browser - // to select the correct input device. + // Initialize function for clients wishing to have unified input and + // output, |params| may specify |input_channels| > 0, representing a + // number of input channels which will be at the same sample-rate + // and buffer-size as the output as specified in |params|. |session_id| is + // used for the browser to select the correct input device. void InitializeWithSessionId(const AudioParameters& params, RenderCallback* callback, int session_id); diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc index 0e1fd1e5..92d9425 100644 --- a/media/audio/audio_output_device_unittest.cc +++ b/media/audio/audio_output_device_unittest.cc @@ -126,7 +126,7 @@ int AudioOutputDeviceTest::CalculateMemorySize() { AudioOutputDeviceTest::AudioOutputDeviceTest() { default_audio_parameters_.Reset( AudioParameters::AUDIO_PCM_LINEAR, - CHANNEL_LAYOUT_STEREO, 2, 48000, 16, 1024); + CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 1024); audio_output_ipc_ = new MockAudioOutputIPC(); audio_device_ = new AudioOutputDevice( diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc index cf966e0..15633bb 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_.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 7532f34..62b825f 100644 --- a/media/audio/audio_parameters.cc +++ b/media/audio/audio_parameters.cc @@ -16,6 +16,7 @@ AudioParameters::AudioParameters() bits_per_sample_(0), frames_per_buffer_(0), channels_(0), + input_channels_(0), effects_(NO_EFFECTS) { } @@ -28,10 +29,12 @@ AudioParameters::AudioParameters(Format format, ChannelLayout channel_layout, bits_per_sample_(bits_per_sample), frames_per_buffer_(frames_per_buffer), channels_(ChannelLayoutToChannelCount(channel_layout)), + input_channels_(0), effects_(NO_EFFECTS) { } AudioParameters::AudioParameters(Format format, ChannelLayout channel_layout, + int input_channels, int sample_rate, int bits_per_sample, int frames_per_buffer, int effects) : format_(format), @@ -40,33 +43,37 @@ AudioParameters::AudioParameters(Format format, ChannelLayout channel_layout, bits_per_sample_(bits_per_sample), frames_per_buffer_(frames_per_buffer), channels_(ChannelLayoutToChannelCount(channel_layout)), + input_channels_(input_channels), effects_(effects) { } AudioParameters::AudioParameters(Format format, ChannelLayout channel_layout, - int channels, int sample_rate, - int bits_per_sample, int frames_per_buffer, - int effects) + int channels, int input_channels, + int sample_rate, int bits_per_sample, + int frames_per_buffer, int effects) : format_(format), channel_layout_(channel_layout), sample_rate_(sample_rate), bits_per_sample_(bits_per_sample), frames_per_buffer_(frames_per_buffer), channels_(channels), + input_channels_(input_channels), effects_(effects) { if (channel_layout != CHANNEL_LAYOUT_DISCRETE) DCHECK_EQ(channels, ChannelLayoutToChannelCount(channel_layout)); } void AudioParameters::Reset(Format format, ChannelLayout channel_layout, - int channels, int sample_rate, - int bits_per_sample, int frames_per_buffer) { + 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; @@ -79,6 +86,8 @@ bool AudioParameters::IsValid() const { (channels_ <= media::limits::kMaxChannels) && (channel_layout_ > CHANNEL_LAYOUT_UNSUPPORTED) && (channel_layout_ <= CHANNEL_LAYOUT_MAX) && + (input_channels_ >= 0) && + (input_channels_ <= media::limits::kMaxChannels) && (sample_rate_ >= media::limits::kMinSampleRate) && (sample_rate_ <= media::limits::kMaxSampleRate) && (bits_per_sample_ > 0) && diff --git a/media/audio/audio_parameters.h b/media/audio/audio_parameters.h index 03fe043..b23d26f 100644 --- a/media/audio/audio_parameters.h +++ b/media/audio/audio_parameters.h @@ -58,14 +58,17 @@ class MEDIA_EXPORT AudioParameters { int sample_rate, int bits_per_sample, int frames_per_buffer); AudioParameters(Format format, ChannelLayout channel_layout, + int input_channels, int sample_rate, int bits_per_sample, int frames_per_buffer, int effects); AudioParameters(Format format, ChannelLayout channel_layout, - int channels, int sample_rate, int bits_per_sample, + int channels, int input_channels, + int sample_rate, int bits_per_sample, int frames_per_buffer, int effects); void Reset(Format format, ChannelLayout channel_layout, - int channels, int sample_rate, int bits_per_sample, + int channels, int input_channels, + int sample_rate, int bits_per_sample, int frames_per_buffer); // Checks that all values are in the expected range. All limits are specified @@ -91,6 +94,7 @@ class MEDIA_EXPORT AudioParameters { int bits_per_sample() const { return bits_per_sample_; } int frames_per_buffer() const { return frames_per_buffer_; } int channels() const { return channels_; } + int input_channels() const { return input_channels_; } int effects() const { return effects_; } // Comparison with other AudioParams. @@ -99,6 +103,7 @@ class MEDIA_EXPORT AudioParameters { sample_rate_ == other.sample_rate() && channel_layout_ == other.channel_layout() && channels_ == other.channels() && + input_channels_ == other.input_channels() && bits_per_sample_ == other.bits_per_sample() && frames_per_buffer_ == other.frames_per_buffer() && effects_ == other.effects(); @@ -115,6 +120,9 @@ class MEDIA_EXPORT AudioParameters { int channels_; // Number of channels. Value set based on // |channel_layout|. + int input_channels_; // Optional number of input channels. + // Normally 0, but can be set to specify + // synchronized I/O. int effects_; // Bitmask using PlatformEffectsMask. }; @@ -124,6 +132,8 @@ inline bool operator<(const AudioParameters& a, const AudioParameters& b) { return a.format() < b.format(); if (a.channels() != b.channels()) return a.channels() < b.channels(); + if (a.input_channels() != b.input_channels()) + return a.input_channels() < b.input_channels(); if (a.sample_rate() != b.sample_rate()) return a.sample_rate() < b.sample_rate(); if (a.bits_per_sample() != b.bits_per_sample()) diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index ef46176..abc78dd 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc @@ -124,10 +124,12 @@ AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters( int sample_rate = kDefaultSampleRate; int buffer_size = kMinimumOutputBufferSize; int bits_per_sample = 16; + int input_channels = 0; if (input_params.IsValid()) { sample_rate = input_params.sample_rate(); bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); + input_channels = input_params.input_channels(); buffer_size = std::min(kMaximumOutputBufferSize, std::max(buffer_size, input_params.frames_per_buffer())); @@ -138,7 +140,7 @@ AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters( buffer_size = user_buffer_size; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); } diff --git a/media/audio/cras/cras_unified.cc b/media/audio/cras/cras_unified.cc index 42d9222..25af383 100644 --- a/media/audio/cras/cras_unified.cc +++ b/media/audio/cras/cras_unified.cc @@ -21,6 +21,30 @@ namespace media { // 5) Finally Close() is called. It cleans up and notifies the audio manager, // which likely will destroy this object. // +// For output-only streams, a unified stream is created with 0 input channels. +// +// Simplified data flow for unified streams: +// +// +-------------+ +------------------+ +// | CRAS Server | | Chrome Client | +// +------+------+ Add Stream +---------+--------+ +// |<----------------------------------| +// | | +// | buffer_frames captured to shm | +// |---------------------------------->| +// | | UnifiedCallback() +// | | ReadWriteAudio() +// | | +// | buffer_frames written to shm | +// |<----------------------------------| +// | | +// ... Repeats for each block. ... +// | | +// | | +// | Remove stream | +// |<----------------------------------| +// | | +// // Simplified data flow for output only streams: // // +-------------+ +------------------+ @@ -62,6 +86,18 @@ CrasUnifiedStream::CrasUnifiedStream(const AudioParameters& params, DCHECK(manager_); DCHECK(params_.channels() > 0); + // Must have at least one input or output. If there are both they must be the + // same. + int input_channels = params_.input_channels(); + + if (input_channels) { + // A unified stream for input and output. + DCHECK(params_.channels() == input_channels); + stream_direction_ = CRAS_STREAM_UNIFIED; + input_bus_ = AudioBus::Create(input_channels, + params_.frames_per_buffer()); + } + output_bus_ = AudioBus::Create(params); } @@ -289,6 +325,9 @@ uint32 CrasUnifiedStream::DispatchCallback(size_t frames, case CRAS_STREAM_INPUT: NOTREACHED() << "CrasUnifiedStream doesn't support input streams."; return 0; + case CRAS_STREAM_UNIFIED: + return ReadWriteAudio(frames, input_samples, output_samples, + input_ts, output_ts); default: break; } @@ -296,6 +335,37 @@ uint32 CrasUnifiedStream::DispatchCallback(size_t frames, return 0; } +// Note these are run from a real time thread, so don't waste cycles here. +uint32 CrasUnifiedStream::ReadWriteAudio(size_t frames, + uint8* input_samples, + uint8* output_samples, + const timespec* input_ts, + const timespec* output_ts) { + DCHECK_EQ(frames, static_cast<size_t>(output_bus_->frames())); + DCHECK(source_callback_); + + uint32 bytes_per_sample = bytes_per_frame_ / params_.channels(); + input_bus_->FromInterleaved(input_samples, frames, bytes_per_sample); + + // Determine latency and pass that on to the source. We have the capture time + // of the first input sample and the playback time of the next audio sample + // passed from the audio server, add them together for total latency. + uint32 total_delay_bytes; + timespec latency_ts = {0, 0}; + cras_client_calc_capture_latency(input_ts, &latency_ts); + total_delay_bytes = GetBytesLatency(latency_ts); + cras_client_calc_playback_latency(output_ts, &latency_ts); + total_delay_bytes += GetBytesLatency(latency_ts); + + int frames_filled = source_callback_->OnMoreData( + output_bus_.get(), + AudioBuffersState(0, total_delay_bytes)); + + output_bus_->ToInterleaved(frames_filled, bytes_per_sample, output_samples); + + return frames_filled; +} + uint32 CrasUnifiedStream::WriteAudio(size_t frames, uint8* buffer, const timespec* sample_ts) { diff --git a/media/audio/cras/cras_unified.h b/media/audio/cras/cras_unified.h index 7e946e0..db1d9fe 100644 --- a/media/audio/cras/cras_unified.h +++ b/media/audio/cras/cras_unified.h @@ -70,6 +70,13 @@ class MEDIA_EXPORT CrasUnifiedStream : public AudioOutputStream { const timespec* input_ts, const timespec* output_ts); + // Receives input samples and write output samples for a unified I/O stream. + uint32 ReadWriteAudio(size_t frames, + uint8* input_samples, + uint8* output_samples, + const timespec* input_ts, + const timespec* output_ts); + // Writes audio for a playback stream. uint32 WriteAudio(size_t frames, uint8* buffer, const timespec* sample_ts); @@ -101,6 +108,7 @@ class MEDIA_EXPORT CrasUnifiedStream : public AudioOutputStream { AudioSourceCallback* source_callback_; // Container for exchanging data with AudioSourceCallback::OnMoreData(). + scoped_ptr<AudioBus> input_bus_; scoped_ptr<AudioBus> output_bus_; // Direciton of the stream. diff --git a/media/audio/fake_audio_manager.cc b/media/audio/fake_audio_manager.cc index a181a2f..e5d9bd4 100644 --- a/media/audio/fake_audio_manager.cc +++ b/media/audio/fake_audio_manager.cc @@ -58,15 +58,17 @@ AudioParameters FakeAudioManager::GetPreferredOutputStreamParameters( int sample_rate = kDefaultSampleRate; int buffer_size = kDefaultOutputBufferSize; int bits_per_sample = 16; + int input_channels = 0; if (input_params.IsValid()) { sample_rate = input_params.sample_rate(); bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); + input_channels = input_params.input_channels(); buffer_size = std::min(input_params.frames_per_buffer(), buffer_size); } return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); } diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index 336a8c4..eabce32 100644 --- a/media/audio/mac/audio_manager_mac.cc +++ b/media/audio/mac/audio_manager_mac.cc @@ -674,9 +674,20 @@ AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters( channel_layout = CHANNEL_LAYOUT_DISCRETE; } + const int input_channels = + has_valid_input_params ? input_params.input_channels() : 0; + if (input_channels > 0) { + // TODO(xians): given the limitations of the AudioOutputStream + // back-ends used with synchronized I/O, we hard-code to stereo. + // Specifically, this is a limitation of AudioSynchronizedStream which + // can be removed as part of the work to consolidate these back-ends. + channel_layout = CHANNEL_LAYOUT_STEREO; + } + return AudioParameters( AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, output_channels, - hardware_sample_rate, 16, buffer_size, AudioParameters::NO_EFFECTS); + input_channels, hardware_sample_rate, 16, buffer_size, + AudioParameters::NO_EFFECTS); } void AudioManagerMac::InitializeOnAudioThread() { diff --git a/media/audio/openbsd/audio_manager_openbsd.cc b/media/audio/openbsd/audio_manager_openbsd.cc index 618fb0c..ec482d8 100644 --- a/media/audio/openbsd/audio_manager_openbsd.cc +++ b/media/audio/openbsd/audio_manager_openbsd.cc @@ -127,10 +127,12 @@ AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters( int sample_rate = kDefaultSampleRate; int buffer_size = kDefaultOutputBufferSize; int bits_per_sample = 16; + int input_channels = 0; if (input_params.IsValid()) { sample_rate = input_params.sample_rate(); bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); + input_channels = input_params.input_channels(); buffer_size = std::min(buffer_size, input_params.frames_per_buffer()); } @@ -139,7 +141,7 @@ AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters( buffer_size = user_buffer_size; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); } diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc index c752a9e..03ff17d 100644 --- a/media/audio/pulse/audio_manager_pulse.cc +++ b/media/audio/pulse/audio_manager_pulse.cc @@ -176,10 +176,12 @@ AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters( ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; int buffer_size = kMinimumOutputBufferSize; int bits_per_sample = 16; + int input_channels = 0; int sample_rate = GetNativeSampleRate(); if (input_params.IsValid()) { bits_per_sample = input_params.bits_per_sample(); channel_layout = input_params.channel_layout(); + input_channels = input_params.input_channels(); buffer_size = std::min(kMaximumOutputBufferSize, std::max(buffer_size, input_params.frames_per_buffer())); @@ -190,7 +192,7 @@ AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters( buffer_size = user_buffer_size; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); } diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc index 29a2e7d..d29d1b4 100644 --- a/media/audio/win/audio_low_latency_input_win.cc +++ b/media/audio/win/audio_low_latency_input_win.cc @@ -282,7 +282,7 @@ AudioParameters WASAPIAudioInputStream::GetInputStreamParameters( // Use 10ms frame size as default. int frames_per_buffer = sample_rate / 100; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 0, sample_rate, 16, frames_per_buffer, effects); } diff --git a/media/audio/win/audio_low_latency_input_win_unittest.cc b/media/audio/win/audio_low_latency_input_win_unittest.cc index 9ce7acf..eee1887 100644 --- a/media/audio/win/audio_low_latency_input_win_unittest.cc +++ b/media/audio/win/audio_low_latency_input_win_unittest.cc @@ -208,6 +208,7 @@ class AudioInputStreamWrapper { AudioInputStream* CreateInputStream() { AudioInputStream* ais = audio_man_->MakeAudioInputStream( AudioParameters(format(), default_params_.channel_layout(), + default_params_.input_channels(), sample_rate(), bits_per_sample(), frames_per_buffer_, default_params_.effects()), AudioManagerBase::kDefaultDeviceId); diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index b4e5e77..eb05ca0 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc @@ -305,7 +305,7 @@ AudioParameters AudioManagerWin::GetInputStreamParameters( if (!core_audio_supported()) { // Windows Wave implementation is being used. parameters = AudioParameters( - AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 48000, + AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 0, 48000, 16, kFallbackBufferSize, AudioParameters::NO_EFFECTS); } else { parameters = WASAPIAudioInputStream::GetInputStreamParameters(device_id); @@ -314,8 +314,9 @@ AudioParameters AudioManagerWin::GetInputStreamParameters( int user_buffer_size = GetUserBufferSize(); if (user_buffer_size) { parameters.Reset(parameters.format(), parameters.channel_layout(), - parameters.channels(), parameters.sample_rate(), - parameters.bits_per_sample(), user_buffer_size); + parameters.channels(), parameters.input_channels(), + parameters.sample_rate(), parameters.bits_per_sample(), + user_buffer_size); } return parameters; @@ -421,6 +422,7 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( int sample_rate = 48000; int buffer_size = kFallbackBufferSize; int bits_per_sample = 16; + int input_channels = 0; int effects = AudioParameters::NO_EFFECTS; bool use_input_params = !core_audio_supported(); if (core_audio_supported()) { @@ -485,7 +487,7 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( } } } - + input_channels = input_params.input_channels(); effects |= input_params.effects(); if (use_input_params) { // If WASAPI isn't supported we'll fallback to WaveOut, which will take @@ -505,7 +507,7 @@ AudioParameters AudioManagerWin::GetPreferredOutputStreamParameters( buffer_size = user_buffer_size; return AudioParameters( - AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, + AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, sample_rate, bits_per_sample, buffer_size, effects); } diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index a01229c..29e955ef 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc @@ -698,8 +698,8 @@ HRESULT CoreAudioUtil::GetPreferredAudioParameters( if (role == eCommunications) { // Raise the 'DUCKING' flag for default communication devices. *params = AudioParameters(params->format(), params->channel_layout(), - params->channels(), params->sample_rate(), params->bits_per_sample(), - params->frames_per_buffer(), + params->channels(), params->input_channels(), params->sample_rate(), + params->bits_per_sample(), params->frames_per_buffer(), params->effects() | AudioParameters::DUCKING); } diff --git a/media/base/audio_buffer_converter.cc b/media/base/audio_buffer_converter.cc index 0297ff6..59c6681 100644 --- a/media/base/audio_buffer_converter.cc +++ b/media/base/audio_buffer_converter.cc @@ -142,6 +142,7 @@ void AudioBufferConverter::ResetConverter( input_params_.format(), buffer->channel_layout(), buffer->channel_count(), + 0, buffer->sample_rate(), input_params_.bits_per_sample(), // If resampling is needed and the FIFO disabled, the AudioConverter will diff --git a/media/base/audio_buffer_converter_unittest.cc b/media/base/audio_buffer_converter_unittest.cc index 7045b70..3445996 100644 --- a/media/base/audio_buffer_converter_unittest.cc +++ b/media/base/audio_buffer_converter_unittest.cc @@ -210,6 +210,7 @@ TEST_F(AudioBufferConverterTest, DiscreteChannelLayout) { output_params_ = AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_DISCRETE, 2, + 0, kOutSampleRate, 16, 512, diff --git a/media/base/channel_mixer_unittest.cc b/media/base/channel_mixer_unittest.cc index ac228e66..911866a 100644 --- a/media/base/channel_mixer_unittest.cc +++ b/media/base/channel_mixer_unittest.cc @@ -107,6 +107,7 @@ TEST_P(ChannelMixerTest, Mixing) { input_layout == CHANNEL_LAYOUT_DISCRETE ? input_channels : ChannelLayoutToChannelCount(input_layout), + 0, AudioParameters::kAudioCDSampleRate, 16, kFrames, AudioParameters::NO_EFFECTS); @@ -117,8 +118,9 @@ TEST_P(ChannelMixerTest, Mixing) { AudioParameters output_audio(AudioParameters::AUDIO_PCM_LINEAR, output_layout, output_layout == CHANNEL_LAYOUT_DISCRETE ? - output_channels : - ChannelLayoutToChannelCount(output_layout), + output_channels : + ChannelLayoutToChannelCount(output_layout), + 0, AudioParameters::kAudioCDSampleRate, 16, kFrames, AudioParameters::NO_EFFECTS); diff --git a/media/cast/test/fake_media_source.cc b/media/cast/test/fake_media_source.cc index 73b2493..96e22c6 100644 --- a/media/cast/test/fake_media_source.cc +++ b/media/cast/test/fake_media_source.cc @@ -147,6 +147,7 @@ void FakeMediaSource::SetSourceFile(const base::FilePath& video_file, AudioParameters::AUDIO_PCM_LINEAR, layout, av_codec_context->channels, + av_codec_context->channels, av_codec_context->sample_rate, 8 * av_get_bytes_per_sample(av_codec_context->sample_fmt), av_codec_context->sample_rate / kAudioPacketsPerSecond); diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc index f5f35a8..9387de9 100644 --- a/media/filters/audio_renderer_impl.cc +++ b/media/filters/audio_renderer_impl.cc @@ -277,6 +277,7 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream, stream->audio_decoder_config().channel_layout(), ChannelLayoutToChannelCount( stream->audio_decoder_config().channel_layout()), + 0, stream->audio_decoder_config().samples_per_second(), stream->audio_decoder_config().bits_per_channel(), buffer_size); @@ -293,6 +294,7 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream, stream->audio_decoder_config().channel_layout(), ChannelLayoutToChannelCount( stream->audio_decoder_config().channel_layout()), + hw_params.input_channels(), hw_params.sample_rate(), hw_params.bits_per_sample(), hardware_config_->GetHighLatencyBufferSize()); |