1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/renderer/media/audio_renderer_mixer_manager.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "content/renderer/media/audio_device_factory.h" 10#include "media/audio/audio_output_device.h" 11#include "media/base/audio_hardware_config.h" 12#include "media/base/audio_renderer_mixer.h" 13#include "media/base/audio_renderer_mixer_input.h" 14 15namespace content { 16 17AudioRendererMixerManager::AudioRendererMixerManager( 18 media::AudioHardwareConfig* hardware_config) 19 : hardware_config_(hardware_config), 20 sink_for_testing_(NULL) { 21} 22 23AudioRendererMixerManager::~AudioRendererMixerManager() { 24 DCHECK(mixers_.empty()); 25} 26 27media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput( 28 int source_render_view_id, int source_render_frame_id) { 29 return new media::AudioRendererMixerInput( 30 base::Bind( 31 &AudioRendererMixerManager::GetMixer, base::Unretained(this), 32 source_render_view_id, 33 source_render_frame_id), 34 base::Bind( 35 &AudioRendererMixerManager::RemoveMixer, base::Unretained(this), 36 source_render_view_id)); 37} 38 39void AudioRendererMixerManager::SetAudioRendererSinkForTesting( 40 media::AudioRendererSink* sink) { 41 sink_for_testing_ = sink; 42} 43 44media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( 45 int source_render_view_id, 46 int source_render_frame_id, 47 const media::AudioParameters& params) { 48 const MixerKey key(source_render_view_id, params); 49 base::AutoLock auto_lock(mixers_lock_); 50 51 AudioRendererMixerMap::iterator it = mixers_.find(key); 52 if (it != mixers_.end()) { 53 it->second.ref_count++; 54 return it->second.mixer; 55 } 56 57 // On ChromeOS and Linux we can rely on the playback device to handle 58 // resampling, so don't waste cycles on it here. 59#if defined(OS_CHROMEOS) || defined(OS_LINUX) 60 int sample_rate = params.sample_rate(); 61#else 62 int sample_rate = hardware_config_->GetOutputSampleRate(); 63#endif 64 65 // Create output parameters based on the audio hardware configuration for 66 // passing on to the output sink. Force to 16-bit output for now since we 67 // know that works well for WebAudio and WebRTC. 68 media::AudioParameters output_params( 69 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(), 70 sample_rate, 16, hardware_config_->GetHighLatencyBufferSize()); 71 72 // If we've created invalid output parameters, simply pass on the input params 73 // and let the browser side handle automatic fallback. 74 if (!output_params.IsValid()) 75 output_params = params; 76 77 media::AudioRendererMixer* mixer; 78 if (sink_for_testing_) { 79 mixer = new media::AudioRendererMixer( 80 params, output_params, sink_for_testing_); 81 } else { 82 mixer = new media::AudioRendererMixer( 83 params, output_params, AudioDeviceFactory::NewOutputDevice( 84 source_render_view_id, source_render_frame_id)); 85 } 86 87 AudioRendererMixerReference mixer_reference = { mixer, 1 }; 88 mixers_[key] = mixer_reference; 89 return mixer; 90} 91 92void AudioRendererMixerManager::RemoveMixer( 93 int source_render_view_id, 94 const media::AudioParameters& params) { 95 const MixerKey key(source_render_view_id, params); 96 base::AutoLock auto_lock(mixers_lock_); 97 98 AudioRendererMixerMap::iterator it = mixers_.find(key); 99 DCHECK(it != mixers_.end()); 100 101 // Only remove the mixer if AudioRendererMixerManager is the last owner. 102 it->second.ref_count--; 103 if (it->second.ref_count == 0) { 104 delete it->second.mixer; 105 mixers_.erase(it); 106 } 107} 108 109} // namespace content 110