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 "media/audio/win/core_audio_util_win.h" | 5 #include "media/audio/win/core_audio_util_win.h" |
6 | 6 |
7 #include <audioclient.h> | 7 #include <audioclient.h> |
8 #include <devicetopology.h> | 8 #include <devicetopology.h> |
9 #include <functiondiscoverykeys_devpkey.h> | 9 #include <functiondiscoverykeys_devpkey.h> |
10 | 10 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 // issues. See http://crbug.com/378465 for details. | 180 // issues. See http://crbug.com/378465 for details. |
181 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); | 181 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); |
182 if (SUCCEEDED(hr)) { | 182 if (SUCCEEDED(hr)) { |
183 hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), | 183 hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), |
184 NULL, CLSCTX_INPROC_SERVER); | 184 NULL, CLSCTX_INPROC_SERVER); |
185 } | 185 } |
186 } | 186 } |
187 return device_enumerator; | 187 return device_enumerator; |
188 } | 188 } |
189 | 189 |
190 static bool IsRemoteSession() { | |
191 return !!GetSystemMetrics(SM_REMOTESESSION); | |
192 } | |
193 | |
194 static bool IsRemoteDeviceInternal(IMMDevice* device) { | |
195 DCHECK(IsRemoteSession()); | |
196 | |
197 std::string device_name; | |
198 HRESULT hr = GetDeviceFriendlyNameInternal(device, &device_name); | |
199 | |
200 // This method should only be called if IsRemoteSession() is true, so assume | |
201 // we have a remote audio device if we can't tell. | |
202 if (FAILED(hr)) | |
203 return true; | |
204 | |
205 return device_name == "Remote Audio"; | |
206 } | |
207 | |
208 static bool IsSupportedInternal() { | 190 static bool IsSupportedInternal() { |
209 // It is possible to force usage of WaveXxx APIs by using a command line flag. | 191 // It is possible to force usage of WaveXxx APIs by using a command line flag. |
210 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 192 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
211 if (cmd_line->HasSwitch(switches::kForceWaveAudio)) { | 193 if (cmd_line->HasSwitch(switches::kForceWaveAudio)) { |
212 DVLOG(1) << "Forcing usage of Windows WaveXxx APIs"; | 194 DVLOG(1) << "Forcing usage of Windows WaveXxx APIs"; |
213 return false; | 195 return false; |
214 } | 196 } |
215 | 197 |
216 // Microsoft does not plan to make the Core Audio APIs available for use | 198 // Microsoft does not plan to make the Core Audio APIs available for use |
217 // with earlier versions of Windows, including Microsoft Windows Server 2003, | 199 // with earlier versions of Windows, including Microsoft Windows Server 2003, |
(...skipping 16 matching lines...) Expand all Loading... |
234 // works as well we should be home free. | 216 // works as well we should be home free. |
235 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = | 217 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = |
236 CreateDeviceEnumeratorInternal(); | 218 CreateDeviceEnumeratorInternal(); |
237 if (!device_enumerator) { | 219 if (!device_enumerator) { |
238 LOG(ERROR) | 220 LOG(ERROR) |
239 << "Failed to create Core Audio device enumerator on thread with ID " | 221 << "Failed to create Core Audio device enumerator on thread with ID " |
240 << GetCurrentThreadId(); | 222 << GetCurrentThreadId(); |
241 return false; | 223 return false; |
242 } | 224 } |
243 | 225 |
244 // Don't use CoreAudio when a remote desktop session with remote audio is | 226 return true; |
245 // present; several users report only WaveAudio working for them and crash | |
246 // reports show hangs when calling into the OS for CoreAudio API calls. See | |
247 // http://crbug.com/422522 and http://crbug.com/180591. | |
248 // | |
249 // Note: There's another check in WASAPIAudioOutputStream::Open() for the case | |
250 // where a remote session is created after Chrome has been started. Graceful | |
251 // fallback to WaveOut will occur in this case via AudioOutputResampler. | |
252 if (!IsRemoteSession()) | |
253 return true; | |
254 | |
255 ScopedComPtr<IMMDevice> device; | |
256 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint(eRender, eConsole, | |
257 device.Receive()); | |
258 | |
259 // Assume remote audio playback if we can't tell. | |
260 if (FAILED(hr)) | |
261 return false; | |
262 | |
263 return !IsRemoteDeviceInternal(device.get()); | |
264 } | 227 } |
265 | 228 |
266 bool CoreAudioUtil::IsSupported() { | 229 bool CoreAudioUtil::IsSupported() { |
267 static bool g_is_supported = IsSupportedInternal(); | 230 static bool g_is_supported = IsSupportedInternal(); |
268 return g_is_supported; | 231 return g_is_supported; |
269 } | 232 } |
270 | 233 |
271 base::TimeDelta CoreAudioUtil::RefererenceTimeToTimeDelta(REFERENCE_TIME time) { | 234 base::TimeDelta CoreAudioUtil::RefererenceTimeToTimeDelta(REFERENCE_TIME time) { |
272 // Each unit of reference time is 100 nanoseconds <=> 0.1 microsecond. | 235 // Each unit of reference time is 100 nanoseconds <=> 0.1 microsecond. |
273 return base::TimeDelta::FromMicroseconds(0.1 * time + 0.5); | 236 return base::TimeDelta::FromMicroseconds(0.1 * time + 0.5); |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 if (FAILED(render_client->GetBuffer(num_frames_to_fill, &data))) | 862 if (FAILED(render_client->GetBuffer(num_frames_to_fill, &data))) |
900 return false; | 863 return false; |
901 | 864 |
902 // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to | 865 // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to |
903 // explicitly write silence data to the rendering buffer. | 866 // explicitly write silence data to the rendering buffer. |
904 DVLOG(2) << "filling up " << num_frames_to_fill << " frames with silence"; | 867 DVLOG(2) << "filling up " << num_frames_to_fill << " frames with silence"; |
905 return SUCCEEDED(render_client->ReleaseBuffer(num_frames_to_fill, | 868 return SUCCEEDED(render_client->ReleaseBuffer(num_frames_to_fill, |
906 AUDCLNT_BUFFERFLAGS_SILENT)); | 869 AUDCLNT_BUFFERFLAGS_SILENT)); |
907 } | 870 } |
908 | 871 |
909 bool CoreAudioUtil::IsRemoteOutputDevice(const std::string& device_id) { | |
910 DCHECK(IsSupported()); | |
911 if (!IsRemoteSession()) | |
912 return false; | |
913 ScopedComPtr<IMMDevice> device(device_id.empty() | |
914 ? CreateDefaultDevice(eRender, eConsole) | |
915 : CreateDevice(device_id)); | |
916 // Assume remote audio if we can't tell. | |
917 return device ? IsRemoteDeviceInternal(device.get()) : true; | |
918 } | |
919 | |
920 } // namespace media | 872 } // namespace media |
OLD | NEW |