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/browser/renderer_host/media/audio_input_device_manager.h" | 5 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "content/browser/renderer_host/media/audio_input_device_manager_event_h andler.h" | |
| 10 #include "content/public/browser/browser_thread.h" | 9 #include "content/public/browser/browser_thread.h" |
| 11 #include "content/public/common/media_stream_request.h" | 10 #include "content/public/common/media_stream_request.h" |
| 12 #include "media/audio/audio_device_name.h" | 11 #include "media/audio/audio_device_name.h" |
| 13 #include "media/audio/audio_input_ipc.h" | 12 #include "media/audio/audio_input_ipc.h" |
| 14 #include "media/audio/audio_manager_base.h" | 13 #include "media/audio/audio_manager_base.h" |
| 15 #include "media/audio/audio_parameters.h" | 14 #include "media/audio/audio_parameters.h" |
| 16 #include "media/base/channel_layout.h" | 15 #include "media/base/channel_layout.h" |
| 17 | 16 |
| 18 namespace content { | 17 namespace content { |
| 19 | 18 |
| 20 const int AudioInputDeviceManager::kFakeOpenSessionId = 1; | 19 const int AudioInputDeviceManager::kFakeOpenSessionId = 1; |
| 21 | 20 |
| 22 namespace { | 21 namespace { |
| 23 // Starting id for the first capture session. | 22 // Starting id for the first capture session. |
| 24 const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; | 23 const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; |
| 25 } | 24 } |
| 26 | 25 |
| 27 AudioInputDeviceManager::AudioInputDeviceManager( | 26 AudioInputDeviceManager::AudioInputDeviceManager( |
| 28 media::AudioManager* audio_manager) | 27 media::AudioManager* audio_manager) |
| 29 : listener_(NULL), | 28 : listener_(NULL), |
| 30 next_capture_session_id_(kFirstSessionId), | 29 next_capture_session_id_(kFirstSessionId), |
| 31 use_fake_device_(false), | 30 use_fake_device_(false), |
| 32 audio_manager_(audio_manager) { | 31 audio_manager_(audio_manager) { |
| 33 } | 32 } |
| 34 | 33 |
| 35 AudioInputDeviceManager::~AudioInputDeviceManager() { | 34 AudioInputDeviceManager::~AudioInputDeviceManager() { |
| 36 } | 35 } |
| 37 | 36 |
| 37 StreamDeviceInfo AudioInputDeviceManager::GetOpenedDeviceInfoById( | |
| 38 int session_id) { | |
| 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 40 StreamDeviceList::iterator device = GetDevice(session_id); | |
| 41 if (device == devices_.end()) | |
| 42 return StreamDeviceInfo(); | |
| 43 | |
| 44 return *device; | |
| 45 } | |
| 46 | |
| 38 void AudioInputDeviceManager::Register( | 47 void AudioInputDeviceManager::Register( |
| 39 MediaStreamProviderListener* listener, | 48 MediaStreamProviderListener* listener, |
| 40 base::MessageLoopProxy* device_thread_loop) { | 49 base::MessageLoopProxy* device_thread_loop) { |
| 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 42 DCHECK(!listener_); | 51 DCHECK(!listener_); |
| 43 DCHECK(!device_loop_); | 52 DCHECK(!device_loop_); |
| 44 listener_ = listener; | 53 listener_ = listener; |
| 45 device_loop_ = device_thread_loop; | 54 device_loop_ = device_thread_loop; |
| 46 } | 55 } |
| 47 | 56 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 68 FROM_HERE, | 77 FROM_HERE, |
| 69 base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread, | 78 base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread, |
| 70 this, session_id, device)); | 79 this, session_id, device)); |
| 71 | 80 |
| 72 return session_id; | 81 return session_id; |
| 73 } | 82 } |
| 74 | 83 |
| 75 void AudioInputDeviceManager::Close(int session_id) { | 84 void AudioInputDeviceManager::Close(int session_id) { |
| 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 77 DCHECK(listener_); | 86 DCHECK(listener_); |
| 78 // Check if the device has been stopped, if not, send stop signal. | 87 StreamDeviceList::iterator device = GetDevice(session_id); |
| 79 EventHandlerMap::iterator it = event_handlers_.find(session_id); | 88 if (device == devices_.end()) |
| 80 if (it != event_handlers_.end()) { | 89 return; |
| 81 it->second->OnDeviceStopped(session_id); | 90 const MediaStreamType stream_type = device->device.type; |
| 82 event_handlers_.erase(it); | 91 devices_.erase(device); |
| 83 } | |
| 84 | 92 |
| 85 device_loop_->PostTask( | 93 // Post a callback through the listener on IO thread since |
| 86 FROM_HERE, | 94 // MediaStreamManager is expecting the callback asynchronously. |
| 87 base::Bind(&AudioInputDeviceManager::CloseOnDeviceThread, | 95 BrowserThread::PostTask(BrowserThread::IO, |
| 88 this, session_id)); | 96 FROM_HERE, |
| 89 } | 97 base::Bind(&AudioInputDeviceManager::ClosedOnIOThread, |
| 90 | 98 this, stream_type, session_id)); |
| 91 void AudioInputDeviceManager::Start( | |
| 92 int session_id, AudioInputDeviceManagerEventHandler* handler) { | |
| 93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 94 DCHECK(handler); | |
| 95 | |
| 96 // Solution for not using MediaStreamManager. This is needed when Start() is | |
| 97 // called without using Open(), we post default device for test purpose. | |
| 98 // And we do not store the info for the kFakeOpenSessionId but return | |
| 99 // the callback immediately. | |
| 100 if (session_id == kFakeOpenSessionId) { | |
| 101 handler->OnDeviceStarted(session_id, | |
| 102 media::AudioManagerBase::kDefaultDeviceId); | |
| 103 return; | |
| 104 } | |
| 105 | |
| 106 // Look up the device_id of the session so we can notify the renderer that | |
| 107 // the device has started. If the session has not been started, | |
| 108 // use the empty device_id to indicate that Start() failed. | |
| 109 std::string device_id; | |
| 110 if (event_handlers_.insert(std::make_pair(session_id, handler)).second) { | |
| 111 StreamDeviceMap::const_iterator it = devices_.find(session_id); | |
| 112 if (it != devices_.end()) | |
| 113 device_id = it->second.device.id; | |
| 114 } | |
| 115 | |
| 116 // Post a callback through the AudioInputRendererHost to notify the renderer | |
| 117 // that the device has started. | |
| 118 handler->OnDeviceStarted(session_id, device_id); | |
| 119 } | |
| 120 | |
| 121 void AudioInputDeviceManager::Stop(int session_id) { | |
| 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 123 | |
| 124 // Erase the event handler referenced by the session_id. | |
| 125 event_handlers_.erase(session_id); | |
| 126 } | 99 } |
| 127 | 100 |
| 128 void AudioInputDeviceManager::UseFakeDevice() { | 101 void AudioInputDeviceManager::UseFakeDevice() { |
| 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 130 use_fake_device_ = true; | 103 use_fake_device_ = true; |
| 131 } | 104 } |
| 132 | 105 |
| 133 bool AudioInputDeviceManager::ShouldUseFakeDevice() const { | 106 bool AudioInputDeviceManager::ShouldUseFakeDevice() const { |
| 134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 135 return use_fake_device_; | 108 return use_fake_device_; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 149 break; | 122 break; |
| 150 | 123 |
| 151 default: | 124 default: |
| 152 NOTREACHED(); | 125 NOTREACHED(); |
| 153 break; | 126 break; |
| 154 } | 127 } |
| 155 | 128 |
| 156 scoped_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray()); | 129 scoped_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray()); |
| 157 for (media::AudioDeviceNames::iterator it = device_names.begin(); | 130 for (media::AudioDeviceNames::iterator it = device_names.begin(); |
| 158 it != device_names.end(); ++it) { | 131 it != device_names.end(); ++it) { |
| 159 // Get the preferred sample rate and channel configuration for the | |
| 160 // current audio device. | |
| 161 media::AudioParameters default_params = | |
| 162 audio_manager_->GetInputStreamParameters(it->unique_id); | |
| 163 | |
| 164 // Add device information to device vector. | 132 // Add device information to device vector. |
| 165 devices->push_back(StreamDeviceInfo( | 133 devices->push_back(StreamDeviceInfo( |
| 166 stream_type, it->device_name, it->unique_id, | 134 stream_type, it->device_name, it->unique_id, false)); |
| 167 default_params.sample_rate(), default_params.channel_layout(), false)); | |
| 168 } | 135 } |
| 169 | 136 |
| 170 // Return the device list through the listener by posting a task on | 137 // Return the device list through the listener by posting a task on |
| 171 // IO thread since MediaStreamManager handles the callback asynchronously. | 138 // IO thread since MediaStreamManager handles the callback asynchronously. |
| 172 BrowserThread::PostTask( | 139 BrowserThread::PostTask( |
| 173 BrowserThread::IO, | 140 BrowserThread::IO, |
| 174 FROM_HERE, | 141 FROM_HERE, |
| 175 base::Bind(&AudioInputDeviceManager::DevicesEnumeratedOnIOThread, | 142 base::Bind(&AudioInputDeviceManager::DevicesEnumeratedOnIOThread, |
| 176 this, stream_type, base::Passed(&devices))); | 143 this, stream_type, base::Passed(&devices))); |
| 177 } | 144 } |
| 178 | 145 |
| 179 void AudioInputDeviceManager::OpenOnDeviceThread( | 146 void AudioInputDeviceManager::OpenOnDeviceThread( |
| 180 int session_id, const StreamDeviceInfo& device) { | 147 int session_id, const StreamDeviceInfo& info) { |
| 181 DCHECK(IsOnDeviceThread()); | 148 DCHECK(IsOnDeviceThread()); |
| 182 | 149 |
| 183 // Add the session_id and device to the map. | 150 // Get the preferred sample rate and channel configuration for the |
| 184 if (!devices_.insert(std::make_pair(session_id, device)).second) { | 151 // audio device. |
| 185 NOTREACHED(); | 152 media::AudioParameters params = |
| 186 devices_[session_id] = device; | 153 audio_manager_->GetInputStreamParameters(info.device.id); |
| 187 } | 154 |
| 155 StreamDeviceInfo out(info.device.type, info.device.name, info.device.id, | |
| 156 params.sample_rate(), params.channel_layout(), false); | |
| 157 out.session_id = session_id; | |
| 188 | 158 |
| 189 // Return the |session_id| through the listener by posting a task on | 159 // Return the |session_id| through the listener by posting a task on |
| 190 // IO thread since MediaStreamManager handles the callback asynchronously. | 160 // IO thread since MediaStreamManager handles the callback asynchronously. |
| 191 BrowserThread::PostTask(BrowserThread::IO, | 161 BrowserThread::PostTask(BrowserThread::IO, |
| 192 FROM_HERE, | 162 FROM_HERE, |
| 193 base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, | 163 base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, |
| 194 this, device.device.type, session_id)); | 164 this, session_id, out)); |
| 195 } | |
| 196 | |
| 197 void AudioInputDeviceManager::CloseOnDeviceThread(int session_id) { | |
| 198 DCHECK(IsOnDeviceThread()); | |
| 199 | |
| 200 StreamDeviceMap::iterator it = devices_.find(session_id); | |
| 201 if (it == devices_.end()) | |
| 202 return; | |
| 203 const MediaStreamType stream_type = it->second.device.type; | |
| 204 devices_.erase(it); | |
| 205 | |
| 206 // Post a callback through the listener on IO thread since | |
| 207 // MediaStreamManager handles the callback asynchronously. | |
| 208 BrowserThread::PostTask(BrowserThread::IO, | |
| 209 FROM_HERE, | |
| 210 base::Bind(&AudioInputDeviceManager::ClosedOnIOThread, | |
| 211 this, stream_type, session_id)); | |
| 212 } | 165 } |
| 213 | 166 |
| 214 void AudioInputDeviceManager::DevicesEnumeratedOnIOThread( | 167 void AudioInputDeviceManager::DevicesEnumeratedOnIOThread( |
| 215 MediaStreamType stream_type, | 168 MediaStreamType stream_type, |
| 216 scoped_ptr<StreamDeviceInfoArray> devices) { | 169 scoped_ptr<StreamDeviceInfoArray> devices) { |
| 217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 218 // Ensure that |devices| gets deleted on exit. | 171 // Ensure that |devices| gets deleted on exit. |
| 219 if (listener_) | 172 if (listener_) |
| 220 listener_->DevicesEnumerated(stream_type, *devices); | 173 listener_->DevicesEnumerated(stream_type, *devices); |
| 221 } | 174 } |
| 222 | 175 |
| 223 void AudioInputDeviceManager::OpenedOnIOThread(MediaStreamType stream_type, | 176 void AudioInputDeviceManager::OpenedOnIOThread(int session_id, |
| 224 int session_id) { | 177 const StreamDeviceInfo& info) { |
| 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 179 DCHECK_EQ(session_id, info.session_id); | |
| 180 DCHECK(GetDevice(session_id) == devices_.end()); | |
| 181 devices_.push_back(info); | |
| 182 | |
| 226 if (listener_) | 183 if (listener_) |
| 227 listener_->Opened(stream_type, session_id); | 184 listener_->Opened(info.device.type, session_id); |
| 228 } | 185 } |
| 229 | 186 |
| 230 void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type, | 187 void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type, |
| 231 int session_id) { | 188 int session_id) { |
| 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 233 if (listener_) | 190 if (listener_) |
| 234 listener_->Closed(stream_type, session_id); | 191 listener_->Closed(stream_type, session_id); |
| 235 } | 192 } |
| 236 | 193 |
| 237 bool AudioInputDeviceManager::IsOnDeviceThread() const { | 194 bool AudioInputDeviceManager::IsOnDeviceThread() const { |
| 238 return device_loop_->BelongsToCurrentThread(); | 195 return device_loop_->BelongsToCurrentThread(); |
| 239 } | 196 } |
| 240 | 197 |
| 198 AudioInputDeviceManager::StreamDeviceList::iterator | |
| 199 AudioInputDeviceManager::GetDevice(int session_id) { | |
| 200 for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end(); | |
|
palmer
2013/03/14 21:05:14
Why do a linear search through a vector? Why not j
no longer working on chromium
2013/03/15 14:52:11
As discussed offline, the session_id_ can't be use
| |
| 201 ++i) { | |
| 202 if (i->session_id == session_id) | |
| 203 return i; | |
| 204 } | |
| 205 | |
| 206 return devices_.end(); | |
| 207 } | |
| 208 | |
| 241 } // namespace content | 209 } // namespace content |
| OLD | NEW |