Home | History | Annotate | Download | only in media
      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 
     15 namespace content {
     16 
     17 AudioRendererMixerManager::AudioRendererMixerManager(
     18     media::AudioHardwareConfig* hardware_config)
     19     : hardware_config_(hardware_config),
     20       sink_for_testing_(NULL) {
     21 }
     22 
     23 AudioRendererMixerManager::~AudioRendererMixerManager() {
     24   DCHECK(mixers_.empty());
     25 }
     26 
     27 media::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 
     39 void AudioRendererMixerManager::SetAudioRendererSinkForTesting(
     40     media::AudioRendererSink* sink) {
     41   sink_for_testing_ = sink;
     42 }
     43 
     44 media::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 
     92 void 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