 Chromium Code Reviews
 Chromium Code Reviews Issue 1942803002:
  Caching AudioOutputDevice instances in mixer manager  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1942803002:
  Caching AudioOutputDevice instances in mixer manager  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "content/renderer/media/audio_renderer_mixer_manager.h" | 5 #include "content/renderer/media/audio_renderer_mixer_manager.h" | 
| 6 | 6 | 
| 7 #include <string> | 7 #include <string> | 
| 8 | 8 | 
| 9 #include "base/bind.h" | 9 #include "base/bind.h" | 
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" | 
| 11 #include "base/memory/ptr_util.h" | |
| 11 #include "build/build_config.h" | 12 #include "build/build_config.h" | 
| 12 #include "content/renderer/media/audio_device_factory.h" | 13 #include "content/renderer/media/audio_renderer_sink_cache.h" | 
| 13 #include "media/audio/audio_device_description.h" | 14 #include "media/audio/audio_device_description.h" | 
| 14 #include "media/base/audio_hardware_config.h" | 15 #include "media/base/audio_hardware_config.h" | 
| 15 #include "media/base/audio_renderer_mixer.h" | 16 #include "media/base/audio_renderer_mixer.h" | 
| 16 #include "media/base/audio_renderer_mixer_input.h" | 17 #include "media/base/audio_renderer_mixer_input.h" | 
| 17 | 18 | 
| 18 namespace content { | 19 namespace content { | 
| 19 | 20 | 
| 20 AudioRendererMixerManager::AudioRendererMixerManager() {} | 21 // static | 
| 22 std::unique_ptr<AudioRendererMixerManager> AudioRendererMixerManager::Create() { | |
| 23 return base::WrapUnique( | |
| 24 new AudioRendererMixerManager(AudioRendererSinkCache::Create())); | |
| 25 } | |
| 26 | |
| 27 AudioRendererMixerManager::AudioRendererMixerManager( | |
| 28 std::unique_ptr<AudioRendererSinkCache> sink_cache) | |
| 29 : sink_cache_(std::move(sink_cache)) { | |
| 30 DCHECK(sink_cache_); | |
| 31 } | |
| 21 | 32 | 
| 22 AudioRendererMixerManager::~AudioRendererMixerManager() { | 33 AudioRendererMixerManager::~AudioRendererMixerManager() { | 
| 23 // References to AudioRendererMixers may be owned by garbage collected | 34 // References to AudioRendererMixers may be owned by garbage collected | 
| 24 // objects. During process shutdown they may be leaked, so, transitively, | 35 // objects. During process shutdown they may be leaked, so, transitively, | 
| 25 // |mixers_| may leak (i.e., may be non-empty at this time) as well. | 36 // |mixers_| may leak (i.e., may be non-empty at this time) as well. | 
| 26 } | 37 } | 
| 27 | 38 | 
| 28 media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput( | 39 media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput( | 
| 29 int source_render_frame_id, | 40 int source_render_frame_id, | 
| 30 int session_id, | 41 int session_id, | 
| 31 const std::string& device_id, | 42 const std::string& device_id, | 
| 32 const url::Origin& security_origin) { | 43 const url::Origin& security_origin) { | 
| 33 // base::Unretained() is safe since AudioRendererMixerManager lives on the | 44 // base::Unretained() is safe since AudioRendererMixerManager lives on the | 
| 
miu
2016/05/19 22:27:15
This comment is obsolete now.
 
o1ka
2016/05/23 16:16:54
Done.
 | |
| 34 // renderer thread and is destroyed on renderer thread destruction. | 45 // renderer thread and is destroyed on renderer thread destruction. | 
| 35 return new media::AudioRendererMixerInput( | 46 return new media::AudioRendererMixerInput( | 
| 36 base::Bind(&AudioRendererMixerManager::GetMixer, base::Unretained(this), | 47 this, source_render_frame_id, | 
| 37 source_render_frame_id), | |
| 38 base::Bind(&AudioRendererMixerManager::RemoveMixer, | |
| 39 base::Unretained(this), source_render_frame_id), | |
| 40 media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, | 48 media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, | 
| 41 device_id) | 49 device_id) | 
| 42 ? AudioDeviceFactory::GetOutputDeviceInfo( | 50 ? GetOutputDeviceInfo(source_render_frame_id, session_id, device_id, | 
| 43 source_render_frame_id, session_id, device_id, security_origin) | 51 security_origin) | 
| 44 .device_id() | 52 .device_id() | 
| 45 : device_id, | 53 : device_id, | 
| 46 security_origin); | 54 security_origin); | 
| 47 } | 55 } | 
| 48 | 56 | 
| 49 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( | 57 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( | 
| 50 int source_render_frame_id, | 58 int source_render_frame_id, | 
| 51 const media::AudioParameters& params, | 59 const media::AudioParameters& params, | 
| 52 const std::string& device_id, | 60 const std::string& device_id, | 
| 53 const url::Origin& security_origin, | 61 const url::Origin& security_origin, | 
| 54 media::OutputDeviceStatus* device_status) { | 62 media::OutputDeviceStatus* device_status) { | 
| 55 // Effects are not passed through to output creation, so ensure none are set. | 63 // Effects are not passed through to output creation, so ensure none are set. | 
| 56 DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS); | 64 DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS); | 
| 57 | 65 | 
| 58 const MixerKey key(source_render_frame_id, params, device_id, | 66 const MixerKey key(source_render_frame_id, params, device_id, | 
| 59 security_origin); | 67 security_origin); | 
| 60 base::AutoLock auto_lock(mixers_lock_); | 68 base::AutoLock auto_lock(mixers_lock_); | 
| 61 | 69 | 
| 62 AudioRendererMixerMap::iterator it = mixers_.find(key); | 70 AudioRendererMixerMap::iterator it = mixers_.find(key); | 
| 63 if (it != mixers_.end()) { | 71 if (it != mixers_.end()) { | 
| 64 if (device_status) | 72 if (device_status) | 
| 65 *device_status = media::OUTPUT_DEVICE_STATUS_OK; | 73 *device_status = media::OUTPUT_DEVICE_STATUS_OK; | 
| 66 | 74 | 
| 67 it->second.ref_count++; | 75 it->second.ref_count++; | 
| 68 return it->second.mixer; | 76 return it->second.mixer; | 
| 69 } | 77 } | 
| 70 | 78 | 
| 71 scoped_refptr<media::AudioRendererSink> sink = | 79 scoped_refptr<media::AudioRendererSink> sink = | 
| 72 AudioDeviceFactory::NewAudioRendererMixerSink(source_render_frame_id, 0, | 80 sink_cache_->GetSink(source_render_frame_id, device_id, security_origin); | 
| 73 device_id, security_origin); | |
| 74 | 81 | 
| 75 const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo(); | 82 const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo(); | 
| 76 if (device_status) | 83 if (device_status) | 
| 77 *device_status = device_info.device_status(); | 84 *device_status = device_info.device_status(); | 
| 78 if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) { | 85 if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) { | 
| 79 sink->Stop(); | 86 sink->Stop(); | 
| 87 sink_cache_->ReleaseSink(source_render_frame_id, device_id, security_origin, | |
| 88 sink.get()); | |
| 80 return nullptr; | 89 return nullptr; | 
| 81 } | 90 } | 
| 82 | 91 | 
| 83 // On ChromeOS as well as when a fake device is used, we can rely on the | 92 // On ChromeOS as well as when a fake device is used, we can rely on the | 
| 84 // playback device to handle resampling, so don't waste cycles on it here. | 93 // playback device to handle resampling, so don't waste cycles on it here. | 
| 85 int sample_rate = params.sample_rate(); | 94 int sample_rate = params.sample_rate(); | 
| 86 int buffer_size = | 95 int buffer_size = | 
| 87 media::AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, 0); | 96 media::AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, 0); | 
| 88 | 97 | 
| 89 #if !defined(OS_CHROMEOS) | 98 #if !defined(OS_CHROMEOS) | 
| (...skipping 17 matching lines...) Expand all Loading... | |
| 107 sample_rate, 16, buffer_size); | 116 sample_rate, 16, buffer_size); | 
| 108 DCHECK(output_params.IsValid()); | 117 DCHECK(output_params.IsValid()); | 
| 109 | 118 | 
| 110 media::AudioRendererMixer* mixer = | 119 media::AudioRendererMixer* mixer = | 
| 111 new media::AudioRendererMixer(output_params, sink); | 120 new media::AudioRendererMixer(output_params, sink); | 
| 112 AudioRendererMixerReference mixer_reference = { mixer, 1 }; | 121 AudioRendererMixerReference mixer_reference = { mixer, 1 }; | 
| 113 mixers_[key] = mixer_reference; | 122 mixers_[key] = mixer_reference; | 
| 114 return mixer; | 123 return mixer; | 
| 115 } | 124 } | 
| 116 | 125 | 
| 117 void AudioRendererMixerManager::RemoveMixer( | 126 void AudioRendererMixerManager::ReturnMixer( | 
| 118 int source_render_frame_id, | 127 int source_render_frame_id, | 
| 119 const media::AudioParameters& params, | 128 const media::AudioParameters& params, | 
| 120 const std::string& device_id, | 129 const std::string& device_id, | 
| 121 const url::Origin& security_origin) { | 130 const url::Origin& security_origin) { | 
| 122 const MixerKey key(source_render_frame_id, params, device_id, | 131 const MixerKey key(source_render_frame_id, params, device_id, | 
| 123 security_origin); | 132 security_origin); | 
| 124 base::AutoLock auto_lock(mixers_lock_); | 133 base::AutoLock auto_lock(mixers_lock_); | 
| 125 | 134 | 
| 126 AudioRendererMixerMap::iterator it = mixers_.find(key); | 135 AudioRendererMixerMap::iterator it = mixers_.find(key); | 
| 127 DCHECK(it != mixers_.end()); | 136 DCHECK(it != mixers_.end()); | 
| 128 | 137 | 
| 129 // Only remove the mixer if AudioRendererMixerManager is the last owner. | 138 // Only remove the mixer if AudioRendererMixerManager is the last owner. | 
| 130 it->second.ref_count--; | 139 it->second.ref_count--; | 
| 131 if (it->second.ref_count == 0) { | 140 if (it->second.ref_count == 0) { | 
| 141 // The mixer will be deleted now, so release the sink. | |
| 142 sink_cache_->ReleaseSink(source_render_frame_id, device_id, security_origin, | |
| 143 it->second.mixer->sink_ptr()); | |
| 132 delete it->second.mixer; | 144 delete it->second.mixer; | 
| 133 mixers_.erase(it); | 145 mixers_.erase(it); | 
| 134 } | 146 } | 
| 135 } | 147 } | 
| 136 | 148 | 
| 149 media::OutputDeviceInfo AudioRendererMixerManager::GetOutputDeviceInfo( | |
| 150 int source_render_frame_id, | |
| 151 int session_id, | |
| 152 const std::string& device_id, | |
| 153 const url::Origin& security_origin) { | |
| 154 return sink_cache_->GetSinkInfo(source_render_frame_id, session_id, device_id, | |
| 155 security_origin); | |
| 156 } | |
| 157 | |
| 137 AudioRendererMixerManager::MixerKey::MixerKey( | 158 AudioRendererMixerManager::MixerKey::MixerKey( | 
| 138 int source_render_frame_id, | 159 int source_render_frame_id, | 
| 139 const media::AudioParameters& params, | 160 const media::AudioParameters& params, | 
| 140 const std::string& device_id, | 161 const std::string& device_id, | 
| 141 const url::Origin& security_origin) | 162 const url::Origin& security_origin) | 
| 142 : source_render_frame_id(source_render_frame_id), | 163 : source_render_frame_id(source_render_frame_id), | 
| 143 params(params), | 164 params(params), | 
| 144 device_id(device_id), | 165 device_id(device_id), | 
| 145 security_origin(security_origin) {} | 166 security_origin(security_origin) {} | 
| 146 | 167 | 
| 147 AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default; | 168 AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default; | 
| 148 | 169 | 
| 149 } // namespace content | 170 } // namespace content | 
| OLD | NEW |