Chromium Code Reviews| 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::CreateDefault())); | |
| 25 } | |
| 26 | |
| 27 AudioRendererMixerManager::AudioRendererMixerManager( | |
| 28 std::unique_ptr<AudioRendererSinkCache> sink_cache) | |
| 29 : sink_cache_(std::move(sink_cache)) {} | |
|
miu
2016/05/12 21:53:06
nit: Looks like all the code assumes |sink_cache_|
o1ka
2016/05/17 17:17:23
Done.
| |
| 21 | 30 |
| 22 AudioRendererMixerManager::~AudioRendererMixerManager() { | 31 AudioRendererMixerManager::~AudioRendererMixerManager() { |
| 23 // References to AudioRendererMixers may be owned by garbage collected | 32 // References to AudioRendererMixers may be owned by garbage collected |
| 24 // objects. During process shutdown they may be leaked, so, transitively, | 33 // 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. | 34 // |mixers_| may leak (i.e., may be non-empty at this time) as well. |
| 26 } | 35 } |
| 27 | 36 |
| 28 media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput( | 37 media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput( |
| 29 int source_render_frame_id, | 38 int source_render_frame_id, |
| 30 int session_id, | 39 int session_id, |
| 31 const std::string& device_id, | 40 const std::string& device_id, |
| 32 const url::Origin& security_origin) { | 41 const url::Origin& security_origin) { |
| 33 // base::Unretained() is safe since AudioRendererMixerManager lives on the | 42 // base::Unretained() is safe since AudioRendererMixerManager lives on the |
| 34 // renderer thread and is destroyed on renderer thread destruction. | 43 // renderer thread and is destroyed on renderer thread destruction. |
| 35 return new media::AudioRendererMixerInput( | 44 return new media::AudioRendererMixerInput( |
| 36 base::Bind(&AudioRendererMixerManager::GetMixer, base::Unretained(this), | 45 base::Bind(&AudioRendererMixerManager::GetMixer, base::Unretained(this), |
| 37 source_render_frame_id), | 46 source_render_frame_id), |
| 38 base::Bind(&AudioRendererMixerManager::RemoveMixer, | 47 base::Bind(&AudioRendererMixerManager::RemoveMixer, |
| 39 base::Unretained(this), source_render_frame_id), | 48 base::Unretained(this), source_render_frame_id), |
| 49 base::Bind(&AudioRendererMixerManager::GetOutputDeviceInfo, | |
| 50 base::Unretained(this), source_render_frame_id, 0 /*sink id*/), | |
| 40 media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, | 51 media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, |
| 41 device_id) | 52 device_id) |
| 42 ? AudioDeviceFactory::GetOutputDeviceInfo( | 53 ? sink_cache_ |
|
chcunningham
2016/05/12 19:56:31
Can you make this call AudioRendererMixerManager::
o1ka
2016/05/17 17:17:23
Done.
| |
| 43 source_render_frame_id, session_id, device_id, security_origin) | 54 ->GetSinkInfo(source_render_frame_id, session_id, device_id, |
| 55 security_origin) | |
| 44 .device_id() | 56 .device_id() |
| 45 : device_id, | 57 : device_id, |
| 46 security_origin); | 58 security_origin); |
| 47 } | 59 } |
| 48 | 60 |
| 49 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( | 61 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( |
| 50 int source_render_frame_id, | 62 int source_render_frame_id, |
| 51 const media::AudioParameters& params, | 63 const media::AudioParameters& params, |
| 52 const std::string& device_id, | 64 const std::string& device_id, |
| 53 const url::Origin& security_origin, | 65 const url::Origin& security_origin, |
| 54 media::OutputDeviceStatus* device_status) { | 66 media::OutputDeviceStatus* device_status) { |
| 55 // Effects are not passed through to output creation, so ensure none are set. | 67 // Effects are not passed through to output creation, so ensure none are set. |
| 56 DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS); | 68 DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS); |
| 57 | 69 |
| 58 const MixerKey key(source_render_frame_id, params, device_id, | 70 const MixerKey key(source_render_frame_id, params, device_id, |
| 59 security_origin); | 71 security_origin); |
| 60 base::AutoLock auto_lock(mixers_lock_); | 72 base::AutoLock auto_lock(mixers_lock_); |
| 61 | 73 |
| 62 AudioRendererMixerMap::iterator it = mixers_.find(key); | 74 AudioRendererMixerMap::iterator it = mixers_.find(key); |
| 63 if (it != mixers_.end()) { | 75 if (it != mixers_.end()) { |
| 64 if (device_status) | 76 if (device_status) |
| 65 *device_status = media::OUTPUT_DEVICE_STATUS_OK; | 77 *device_status = media::OUTPUT_DEVICE_STATUS_OK; |
| 66 | 78 |
| 67 it->second.ref_count++; | 79 it->second.ref_count++; |
| 68 return it->second.mixer; | 80 return it->second.mixer; |
| 69 } | 81 } |
| 70 | 82 |
| 71 scoped_refptr<media::AudioRendererSink> sink = | 83 media::AudioRendererSink* sink = |
| 72 AudioDeviceFactory::NewAudioRendererMixerSink(source_render_frame_id, 0, | 84 sink_cache_->GetSink(source_render_frame_id, device_id, security_origin); |
| 73 device_id, security_origin); | |
| 74 | 85 |
| 75 const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo(); | 86 const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo(); |
| 76 if (device_status) | 87 if (device_status) |
| 77 *device_status = device_info.device_status(); | 88 *device_status = device_info.device_status(); |
| 78 if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) { | 89 if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) { |
| 79 sink->Stop(); | 90 sink_cache_->ReleaseSink(sink); |
| 80 return nullptr; | 91 return nullptr; |
| 81 } | 92 } |
| 82 | 93 |
| 83 // On ChromeOS as well as when a fake device is used, we can rely on the | 94 // 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. | 95 // playback device to handle resampling, so don't waste cycles on it here. |
| 85 int sample_rate = params.sample_rate(); | 96 int sample_rate = params.sample_rate(); |
| 86 int buffer_size = | 97 int buffer_size = |
| 87 media::AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, 0); | 98 media::AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, 0); |
| 88 | 99 |
| 89 #if !defined(OS_CHROMEOS) | 100 #if !defined(OS_CHROMEOS) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 100 #endif | 111 #endif |
| 101 | 112 |
| 102 // Create output parameters based on the audio hardware configuration for | 113 // Create output parameters based on the audio hardware configuration for |
| 103 // passing on to the output sink. Force to 16-bit output for now since we | 114 // passing on to the output sink. Force to 16-bit output for now since we |
| 104 // know that works everywhere; ChromeOS does not support other bit depths. | 115 // know that works everywhere; ChromeOS does not support other bit depths. |
| 105 media::AudioParameters output_params( | 116 media::AudioParameters output_params( |
| 106 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(), | 117 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(), |
| 107 sample_rate, 16, buffer_size); | 118 sample_rate, 16, buffer_size); |
| 108 DCHECK(output_params.IsValid()); | 119 DCHECK(output_params.IsValid()); |
| 109 | 120 |
| 110 media::AudioRendererMixer* mixer = | 121 // |sink_cache_| will outlive any mixers, so it's fine to use Unretained(). |
|
chcunningham
2016/05/12 19:56:31
I'm not sure sink_cache_ really will outlive mixer
o1ka
2016/05/17 17:17:23
I made some changes around that, mostly because if
| |
| 111 new media::AudioRendererMixer(output_params, sink); | 122 media::AudioRendererMixer* mixer = new media::AudioRendererMixer( |
| 123 output_params, sink, base::Bind(&AudioRendererSinkCache::ReleaseSink, | |
| 124 base::Unretained(sink_cache_.get()))); | |
| 112 AudioRendererMixerReference mixer_reference = { mixer, 1 }; | 125 AudioRendererMixerReference mixer_reference = { mixer, 1 }; |
| 113 mixers_[key] = mixer_reference; | 126 mixers_[key] = mixer_reference; |
| 114 return mixer; | 127 return mixer; |
| 115 } | 128 } |
| 116 | 129 |
| 117 void AudioRendererMixerManager::RemoveMixer( | 130 void AudioRendererMixerManager::RemoveMixer( |
| 118 int source_render_frame_id, | 131 int source_render_frame_id, |
| 119 const media::AudioParameters& params, | 132 const media::AudioParameters& params, |
| 120 const std::string& device_id, | 133 const std::string& device_id, |
| 121 const url::Origin& security_origin) { | 134 const url::Origin& security_origin) { |
| 122 const MixerKey key(source_render_frame_id, params, device_id, | 135 const MixerKey key(source_render_frame_id, params, device_id, |
| 123 security_origin); | 136 security_origin); |
| 124 base::AutoLock auto_lock(mixers_lock_); | 137 base::AutoLock auto_lock(mixers_lock_); |
| 125 | 138 |
| 126 AudioRendererMixerMap::iterator it = mixers_.find(key); | 139 AudioRendererMixerMap::iterator it = mixers_.find(key); |
| 127 DCHECK(it != mixers_.end()); | 140 DCHECK(it != mixers_.end()); |
| 128 | 141 |
| 129 // Only remove the mixer if AudioRendererMixerManager is the last owner. | 142 // Only remove the mixer if AudioRendererMixerManager is the last owner. |
| 130 it->second.ref_count--; | 143 it->second.ref_count--; |
| 131 if (it->second.ref_count == 0) { | 144 if (it->second.ref_count == 0) { |
| 132 delete it->second.mixer; | 145 delete it->second.mixer; |
| 133 mixers_.erase(it); | 146 mixers_.erase(it); |
| 134 } | 147 } |
| 135 } | 148 } |
| 136 | 149 |
| 150 media::OutputDeviceInfo AudioRendererMixerManager::GetOutputDeviceInfo( | |
| 151 int source_render_frame_id, | |
| 152 int session_id, | |
| 153 const std::string& device_id, | |
| 154 const url::Origin& security_origin) { | |
| 155 return sink_cache_->GetSinkInfo(source_render_frame_id, session_id, device_id, | |
| 156 security_origin); | |
| 157 } | |
| 158 | |
| 137 AudioRendererMixerManager::MixerKey::MixerKey( | 159 AudioRendererMixerManager::MixerKey::MixerKey( |
| 138 int source_render_frame_id, | 160 int source_render_frame_id, |
| 139 const media::AudioParameters& params, | 161 const media::AudioParameters& params, |
| 140 const std::string& device_id, | 162 const std::string& device_id, |
| 141 const url::Origin& security_origin) | 163 const url::Origin& security_origin) |
| 142 : source_render_frame_id(source_render_frame_id), | 164 : source_render_frame_id(source_render_frame_id), |
| 143 params(params), | 165 params(params), |
| 144 device_id(device_id), | 166 device_id(device_id), |
| 145 security_origin(security_origin) {} | 167 security_origin(security_origin) {} |
| 146 | 168 |
| 147 AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default; | 169 AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default; |
| 148 | 170 |
| 149 } // namespace content | 171 } // namespace content |
| OLD | NEW |