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 |