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 AudioRendererMixerManager::AudioRendererMixerManager( |
| 22 std::unique_ptr<AudioRendererSinkCache> sink_cache) |
| 23 : sink_cache_(std::move(sink_cache)) { |
| 24 DCHECK(sink_cache_); |
| 25 } |
21 | 26 |
22 AudioRendererMixerManager::~AudioRendererMixerManager() { | 27 AudioRendererMixerManager::~AudioRendererMixerManager() { |
23 // References to AudioRendererMixers may be owned by garbage collected | 28 // References to AudioRendererMixers may be owned by garbage collected |
24 // objects. During process shutdown they may be leaked, so, transitively, | 29 // 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. | 30 // |mixers_| may leak (i.e., may be non-empty at this time) as well. |
26 } | 31 } |
27 | 32 |
| 33 // static |
| 34 std::unique_ptr<AudioRendererMixerManager> AudioRendererMixerManager::Create() { |
| 35 return base::WrapUnique( |
| 36 new AudioRendererMixerManager(AudioRendererSinkCache::Create())); |
| 37 } |
| 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 // AudioRendererMixerManager lives on the renderer thread and is destroyed on |
34 // renderer thread and is destroyed on renderer thread destruction. | 45 // renderer thread destruction, so it's safe to pass its pointer to a mixer |
| 46 // input. |
35 return new media::AudioRendererMixerInput( | 47 return new media::AudioRendererMixerInput( |
36 base::Bind(&AudioRendererMixerManager::GetMixer, base::Unretained(this), | 48 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, | 49 media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, |
41 device_id) | 50 device_id) |
42 ? AudioDeviceFactory::GetOutputDeviceInfo( | 51 ? GetOutputDeviceInfo(source_render_frame_id, session_id, device_id, |
43 source_render_frame_id, session_id, device_id, security_origin) | 52 security_origin) |
44 .device_id() | 53 .device_id() |
45 : device_id, | 54 : device_id, |
46 security_origin); | 55 security_origin); |
47 } | 56 } |
48 | 57 |
49 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( | 58 media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( |
50 int source_render_frame_id, | 59 int source_render_frame_id, |
51 const media::AudioParameters& params, | 60 const media::AudioParameters& params, |
52 const std::string& device_id, | 61 const std::string& device_id, |
53 const url::Origin& security_origin, | 62 const url::Origin& security_origin, |
54 media::OutputDeviceStatus* device_status) { | 63 media::OutputDeviceStatus* device_status) { |
55 // Effects are not passed through to output creation, so ensure none are set. | 64 // Effects are not passed through to output creation, so ensure none are set. |
56 DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS); | 65 DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS); |
57 | 66 |
58 const MixerKey key(source_render_frame_id, params, device_id, | 67 const MixerKey key(source_render_frame_id, params, device_id, |
59 security_origin); | 68 security_origin); |
60 base::AutoLock auto_lock(mixers_lock_); | 69 base::AutoLock auto_lock(mixers_lock_); |
61 | 70 |
62 AudioRendererMixerMap::iterator it = mixers_.find(key); | 71 AudioRendererMixerMap::iterator it = mixers_.find(key); |
63 if (it != mixers_.end()) { | 72 if (it != mixers_.end()) { |
64 if (device_status) | 73 if (device_status) |
65 *device_status = media::OUTPUT_DEVICE_STATUS_OK; | 74 *device_status = media::OUTPUT_DEVICE_STATUS_OK; |
66 | 75 |
67 it->second.ref_count++; | 76 it->second.ref_count++; |
68 return it->second.mixer; | 77 return it->second.mixer; |
69 } | 78 } |
70 | 79 |
71 scoped_refptr<media::AudioRendererSink> sink = | 80 scoped_refptr<media::AudioRendererSink> sink = |
72 AudioDeviceFactory::NewAudioRendererMixerSink(source_render_frame_id, 0, | 81 sink_cache_->GetSink(source_render_frame_id, device_id, security_origin); |
73 device_id, security_origin); | |
74 | 82 |
75 const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo(); | 83 const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo(); |
76 if (device_status) | 84 if (device_status) |
77 *device_status = device_info.device_status(); | 85 *device_status = device_info.device_status(); |
78 if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) { | 86 if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) { |
| 87 sink_cache_->ReleaseSink(sink.get()); |
79 sink->Stop(); | 88 sink->Stop(); |
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 |
(...skipping 18 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(it->second.mixer->sink_ptr()); |
132 delete it->second.mixer; | 143 delete it->second.mixer; |
133 mixers_.erase(it); | 144 mixers_.erase(it); |
134 } | 145 } |
135 } | 146 } |
136 | 147 |
| 148 media::OutputDeviceInfo AudioRendererMixerManager::GetOutputDeviceInfo( |
| 149 int source_render_frame_id, |
| 150 int session_id, |
| 151 const std::string& device_id, |
| 152 const url::Origin& security_origin) { |
| 153 return sink_cache_->GetSinkInfo(source_render_frame_id, session_id, device_id, |
| 154 security_origin); |
| 155 } |
| 156 |
137 AudioRendererMixerManager::MixerKey::MixerKey( | 157 AudioRendererMixerManager::MixerKey::MixerKey( |
138 int source_render_frame_id, | 158 int source_render_frame_id, |
139 const media::AudioParameters& params, | 159 const media::AudioParameters& params, |
140 const std::string& device_id, | 160 const std::string& device_id, |
141 const url::Origin& security_origin) | 161 const url::Origin& security_origin) |
142 : source_render_frame_id(source_render_frame_id), | 162 : source_render_frame_id(source_render_frame_id), |
143 params(params), | 163 params(params), |
144 device_id(device_id), | 164 device_id(device_id), |
145 security_origin(security_origin) {} | 165 security_origin(security_origin) {} |
146 | 166 |
147 AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default; | 167 AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default; |
148 | 168 |
149 } // namespace content | 169 } // namespace content |
OLD | NEW |