 Chromium Code Reviews
 Chromium Code Reviews Issue 2763383002:
  Switching AudioInputDeviceManager from using AudioManager interface to AudioSystem one.  (Closed)
    
  
    Issue 2763383002:
  Switching AudioInputDeviceManager from using AudioManager interface to AudioSystem one.  (Closed) 
  | 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 <memory> | 7 #include <memory> | 
| 8 | 8 | 
| 9 #include "base/bind.h" | 9 #include "base/bind.h" | 
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" | 
| 11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" | 
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" | 
| 13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" | 
| 14 #include "content/public/common/media_stream_request.h" | 14 #include "content/public/common/media_stream_request.h" | 
| 15 #include "media/audio/audio_input_ipc.h" | 15 #include "media/audio/audio_input_ipc.h" | 
| 16 #include "media/audio/audio_manager_base.h" | 16 #include "media/audio/audio_system.h" | 
| 17 #include "media/base/audio_parameters.h" | 17 #include "media/base/audio_parameters.h" | 
| 18 #include "media/base/channel_layout.h" | 18 #include "media/base/channel_layout.h" | 
| 19 #include "media/base/media_switches.h" | 19 #include "media/base/media_switches.h" | 
| 20 | 20 | 
| 21 #if defined(OS_CHROMEOS) | 21 #if defined(OS_CHROMEOS) | 
| 22 #include "chromeos/audio/cras_audio_handler.h" | 22 #include "chromeos/audio/cras_audio_handler.h" | 
| 23 #endif | 23 #endif | 
| 24 | 24 | 
| 25 namespace content { | 25 namespace content { | 
| 26 | 26 | 
| 27 const int AudioInputDeviceManager::kFakeOpenSessionId = 1; | 27 const int AudioInputDeviceManager::kFakeOpenSessionId = 1; | 
| 28 | 28 | 
| 29 namespace { | 29 namespace { | 
| 30 // Starting id for the first capture session. | 30 // Starting id for the first capture session. | 
| 31 const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; | 31 const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1; | 
| 32 } | 32 } | 
| 33 | 33 | 
| 34 AudioInputDeviceManager::AudioInputDeviceManager( | 34 AudioInputDeviceManager::AudioInputDeviceManager( | 
| 35 media::AudioManager* audio_manager) | 35 media::AudioSystem* audio_system) | 
| 36 : next_capture_session_id_(kFirstSessionId), | 36 : next_capture_session_id_(kFirstSessionId), | 
| 37 #if defined(OS_CHROMEOS) | 37 #if defined(OS_CHROMEOS) | 
| 38 keyboard_mic_streams_count_(0), | 38 keyboard_mic_streams_count_(0), | 
| 39 #endif | 39 #endif | 
| 40 audio_manager_(audio_manager), | 40 audio_system_(audio_system) { | 
| 41 device_task_runner_(audio_manager_->GetTaskRunner()) { | |
| 42 } | 41 } | 
| 43 | 42 | 
| 44 AudioInputDeviceManager::~AudioInputDeviceManager() { | 43 AudioInputDeviceManager::~AudioInputDeviceManager() { | 
| 45 } | 44 } | 
| 46 | 45 | 
| 47 const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById( | 46 const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById( | 
| 48 int session_id) { | 47 int session_id) { | 
| 49 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 48 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 50 StreamDeviceList::iterator device = GetDevice(session_id); | 49 StreamDeviceList::iterator device = GetDevice(session_id); | 
| 51 if (device == devices_.end()) | 50 if (device == devices_.end()) | 
| 52 return nullptr; | 51 return nullptr; | 
| 53 | 52 | 
| 54 return &(*device); | 53 return &(*device); | 
| 55 } | 54 } | 
| 56 | 55 | 
| 57 void AudioInputDeviceManager::RegisterListener( | 56 void AudioInputDeviceManager::RegisterListener( | 
| 58 MediaStreamProviderListener* listener) { | 57 MediaStreamProviderListener* listener) { | 
| 59 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 58 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 60 DCHECK(listener); | 59 DCHECK(listener); | 
| 61 DCHECK(device_task_runner_); | |
| 62 listeners_.AddObserver(listener); | 60 listeners_.AddObserver(listener); | 
| 63 } | 61 } | 
| 64 | 62 | 
| 65 void AudioInputDeviceManager::UnregisterListener( | 63 void AudioInputDeviceManager::UnregisterListener( | 
| 66 MediaStreamProviderListener* listener) { | 64 MediaStreamProviderListener* listener) { | 
| 67 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 65 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 68 DCHECK(listener); | 66 DCHECK(listener); | 
| 69 listeners_.RemoveObserver(listener); | 67 listeners_.RemoveObserver(listener); | 
| 70 } | 68 } | 
| 71 | 69 | 
| 72 int AudioInputDeviceManager::Open(const MediaStreamDevice& device) { | 70 int AudioInputDeviceManager::Open(const MediaStreamDevice& device) { | 
| 73 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 71 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 74 // Generate a new id for this device. | 72 // Generate a new id for this device. | 
| 75 int session_id = next_capture_session_id_++; | 73 int session_id = next_capture_session_id_++; | 
| 76 device_task_runner_->PostTask( | 74 | 
| 77 FROM_HERE, | 75 // base::Unretained(this) is safe, because the IO thread is stopped before | 
| 78 base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread, | 76 // AudioInputDeviceManager destruction on the main thread. | 
| 
Guido Urdaneta
2017/04/06 14:26:41
Update the comment: AIDM is not destroyed on the m
 
o1ka
2017/04/07 12:22:17
Done.
 | |
| 79 this, session_id, device)); | 77 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 
| 78 switches::kUseFakeDeviceForMediaStream)) { | |
| 79 audio_system_->GetAssociatedOutputDeviceID( | |
| 
Guido Urdaneta
2017/04/06 14:26:41
Why get associated output device ID of a fake devi
 
o1ka
2017/04/07 12:22:17
This is how the code works now (https://cs.chromiu
 
Guido Urdaneta
2017/04/11 09:44:55
Acknowledged.
 | |
| 80 device.id, | |
| 81 base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, | |
| 82 base::Unretained(this), session_id, device, | |
| 83 base::TimeTicks::Now(), | |
| 84 media::AudioParameters::UnavailableDeviceParams(), | |
| 85 media::AudioParameters::UnavailableDeviceParams())); | |
| 86 } else { | |
| 87 // TODO(tommi): As is, we hit this code path when device.type is | |
| 88 // MEDIA_TAB_AUDIO_CAPTURE and the device id is not a device that | |
| 89 // the AudioManager can know about. This currently does not fail because | |
| 90 // the implementation of GetInputStreamParameters returns valid parameters | |
| 91 // by default for invalid devices. That behavior is problematic because it | |
| 92 // causes other parts of the code to attempt to open truly invalid or | |
| 93 // missing devices and falling back on alternate devices (and likely fail | |
| 94 // twice in a row). Tab audio capture should not pass through here and | |
| 95 // GetInputStreamParameters should return invalid parameters for invalid | |
| 96 // devices. | |
| 97 | |
| 98 audio_system_->GetInputDeviceInfo( | |
| 99 device.id, base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, | |
| 100 base::Unretained(this), session_id, device, | |
| 101 base::TimeTicks::Now())); | |
| 102 } | |
| 80 | 103 | 
| 81 return session_id; | 104 return session_id; | 
| 82 } | 105 } | 
| 83 | 106 | 
| 84 void AudioInputDeviceManager::Close(int session_id) { | 107 void AudioInputDeviceManager::Close(int session_id) { | 
| 85 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 108 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 86 StreamDeviceList::iterator device = GetDevice(session_id); | 109 StreamDeviceList::iterator device = GetDevice(session_id); | 
| 87 if (device == devices_.end()) | 110 if (device == devices_.end()) | 
| 88 return; | 111 return; | 
| 89 const MediaStreamType stream_type = device->device.type; | 112 const MediaStreamType stream_type = device->device.type; | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 128 BrowserThread::UI, | 151 BrowserThread::UI, | 
| 129 FROM_HERE, | 152 FROM_HERE, | 
| 130 base::Bind( | 153 base::Bind( | 
| 131 &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread, | 154 &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread, | 
| 132 this, | 155 this, | 
| 133 false)); | 156 false)); | 
| 134 } | 157 } | 
| 135 } | 158 } | 
| 136 #endif | 159 #endif | 
| 137 | 160 | 
| 138 void AudioInputDeviceManager::OpenOnDeviceThread( | 161 void AudioInputDeviceManager::OpenedOnIOThread( | 
| 139 int session_id, | 162 int session_id, | 
| 140 const MediaStreamDevice& device) { | 163 const MediaStreamDevice& device, | 
| 141 SCOPED_UMA_HISTOGRAM_TIMER( | 164 base::TimeTicks start_time, | 
| 142 "Media.AudioInputDeviceManager.OpenOnDeviceThreadTime"); | 165 const media::AudioParameters& input_params, | 
| 143 DCHECK(IsOnDeviceThread()); | 166 const media::AudioParameters& matched_output_params, | 
| 167 const std::string& matched_output_device_id) { | |
| 168 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 169 DCHECK(GetDevice(session_id) == devices_.end()); | |
| 144 | 170 | 
| 145 StreamDeviceInfo out(device.type, device.name, device.id, 0, 0, 0); | 171 UMA_HISTOGRAM_TIMES("Media.AudioInputDeviceManager.OpenOnDeviceThreadTime", | 
| 146 out.session_id = session_id; | 172 base::TimeTicks::Now() - start_time); | 
| 147 | 173 | 
| 148 MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input; | 174 StreamDeviceInfo info(device.type, device.name, device.id); | 
| 149 | 175 info.session_id = session_id; | 
| 150 // Add preferred output device information if a matching output device | 176 info.device.input.sample_rate = input_params.sample_rate(); | 
| 
DaleCurtis
2017/04/06 18:37:17
We have the copy constructor enabled for AudioPara
 
o1ka
2017/04/07 12:22:17
These are not AudioParameters :(
(https://cs.chrom
 | |
| 151 // exists. | 177 info.device.input.channel_layout = input_params.channel_layout(); | 
| 152 out.device.matched_output_device_id = | 178 info.device.input.frames_per_buffer = input_params.frames_per_buffer(); | 
| 153 audio_manager_->GetAssociatedOutputDeviceID(device.id); | 179 info.device.input.effects = input_params.effects(); | 
| 154 | 180 info.device.input.mic_positions = input_params.mic_positions(); | 
| 155 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 181 info.device.matched_output_device_id = matched_output_device_id; | 
| 156 switches::kUseFakeDeviceForMediaStream)) { | 182 info.device.matched_output.sample_rate = matched_output_params.sample_rate(); | 
| 157 // Don't need to query the hardware information if using fake device. | 183 info.device.matched_output.channel_layout = | 
| 158 input_params.sample_rate = 44100; | 184 matched_output_params.channel_layout(); | 
| 159 input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO; | 185 info.device.matched_output.frames_per_buffer = | 
| 160 if (!out.device.matched_output_device_id.empty()) { | 186 matched_output_params.frames_per_buffer(); | 
| 161 out.device.matched_output.sample_rate = 44100; | 187 info.device.matched_output.effects = matched_output_params.effects(); | 
| 162 out.device.matched_output.channel_layout = media::CHANNEL_LAYOUT_STEREO; | |
| 163 } | |
| 164 } else { | |
| 165 // TODO(tommi): As is, we hit this code path when device.type is | |
| 166 // MEDIA_TAB_AUDIO_CAPTURE and the device id is not a device that | |
| 167 // the AudioManager can know about. This currently does not fail because | |
| 168 // the implementation of GetInputStreamParameters returns valid parameters | |
| 169 // by default for invalid devices. That behavior is problematic because it | |
| 170 // causes other parts of the code to attempt to open truly invalid or | |
| 171 // missing devices and falling back on alternate devices (and likely fail | |
| 172 // twice in a row). Tab audio capture should not pass through here and | |
| 173 // GetInputStreamParameters should return invalid parameters for invalid | |
| 174 // devices. | |
| 175 | |
| 176 // Get the preferred sample rate and channel configuration for the | |
| 177 // audio device. | |
| 178 media::AudioParameters params = | |
| 179 audio_manager_->GetInputStreamParameters(device.id); | |
| 180 input_params.sample_rate = params.sample_rate(); | |
| 181 input_params.channel_layout = params.channel_layout(); | |
| 182 input_params.frames_per_buffer = params.frames_per_buffer(); | |
| 183 input_params.effects = params.effects(); | |
| 184 input_params.mic_positions = params.mic_positions(); | |
| 185 if (!out.device.matched_output_device_id.empty()) { | |
| 186 params = audio_manager_->GetOutputStreamParameters( | |
| 187 out.device.matched_output_device_id); | |
| 188 MediaStreamDevice::AudioDeviceParameters& matched_output_params = | |
| 189 out.device.matched_output; | |
| 190 matched_output_params.sample_rate = params.sample_rate(); | |
| 191 matched_output_params.channel_layout = params.channel_layout(); | |
| 192 matched_output_params.frames_per_buffer = params.frames_per_buffer(); | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 // Return the |session_id| through the listener by posting a task on | |
| 197 // IO thread since MediaStreamManager handles the callback asynchronously. | |
| 198 BrowserThread::PostTask(BrowserThread::IO, | |
| 199 FROM_HERE, | |
| 200 base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, | |
| 201 this, session_id, out)); | |
| 202 } | |
| 203 | |
| 204 void AudioInputDeviceManager::OpenedOnIOThread(int session_id, | |
| 205 const StreamDeviceInfo& info) { | |
| 206 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 207 DCHECK_EQ(session_id, info.session_id); | |
| 208 DCHECK(GetDevice(session_id) == devices_.end()); | |
| 209 | 188 | 
| 210 devices_.push_back(info); | 189 devices_.push_back(info); | 
| 211 | 190 | 
| 212 for (auto& listener : listeners_) | 191 for (auto& listener : listeners_) | 
| 213 listener.Opened(info.device.type, session_id); | 192 listener.Opened(info.device.type, session_id); | 
| 214 } | 193 } | 
| 215 | 194 | 
| 216 void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type, | 195 void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type, | 
| 217 int session_id) { | 196 int session_id) { | 
| 218 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 197 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 219 for (auto& listener : listeners_) | 198 for (auto& listener : listeners_) | 
| 220 listener.Closed(stream_type, session_id); | 199 listener.Closed(stream_type, session_id); | 
| 221 } | 200 } | 
| 222 | 201 | 
| 223 bool AudioInputDeviceManager::IsOnDeviceThread() const { | |
| 224 return device_task_runner_->BelongsToCurrentThread(); | |
| 225 } | |
| 226 | 202 | 
| 227 AudioInputDeviceManager::StreamDeviceList::iterator | 203 AudioInputDeviceManager::StreamDeviceList::iterator | 
| 228 AudioInputDeviceManager::GetDevice(int session_id) { | 204 AudioInputDeviceManager::GetDevice(int session_id) { | 
| 229 for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end(); | 205 for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end(); | 
| 230 ++i) { | 206 ++i) { | 
| 231 if (i->session_id == session_id) | 207 if (i->session_id == session_id) | 
| 232 return i; | 208 return i; | 
| 233 } | 209 } | 
| 234 | 210 | 
| 235 return devices_.end(); | 211 return devices_.end(); | 
| 236 } | 212 } | 
| 237 | 213 | 
| 238 #if defined(OS_CHROMEOS) | 214 #if defined(OS_CHROMEOS) | 
| 239 void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread( | 215 void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread( | 
| 240 bool active) { | 216 bool active) { | 
| 241 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 217 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 242 chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active); | 218 chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active); | 
| 243 } | 219 } | 
| 244 #endif | 220 #endif | 
| 245 | 221 | 
| 246 | |
| 247 } // namespace content | 222 } // namespace content | 
| OLD | NEW |