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 // Implementation of AudioOutputStream for Windows using Windows Core Audio | 5 // Implementation of AudioOutputStream for Windows using Windows Core Audio |
| 6 // WASAPI for low latency rendering. | 6 // WASAPI for low latency rendering. |
| 7 // | 7 // |
| 8 // Overview of operation and performance: | 8 // Overview of operation and performance: |
| 9 // | 9 // |
| 10 // - An object of WASAPIAudioOutputStream is created by the AudioManager | 10 // - An object of WASAPIAudioOutputStream is created by the AudioManager |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 virtual ~WASAPIAudioOutputStream(); | 175 virtual ~WASAPIAudioOutputStream(); |
| 176 | 176 |
| 177 // Implementation of AudioOutputStream. | 177 // Implementation of AudioOutputStream. |
| 178 virtual bool Open() OVERRIDE; | 178 virtual bool Open() OVERRIDE; |
| 179 virtual void Start(AudioSourceCallback* callback) OVERRIDE; | 179 virtual void Start(AudioSourceCallback* callback) OVERRIDE; |
| 180 virtual void Stop() OVERRIDE; | 180 virtual void Stop() OVERRIDE; |
| 181 virtual void Close() OVERRIDE; | 181 virtual void Close() OVERRIDE; |
| 182 virtual void SetVolume(double volume) OVERRIDE; | 182 virtual void SetVolume(double volume) OVERRIDE; |
| 183 virtual void GetVolume(double* volume) OVERRIDE; | 183 virtual void GetVolume(double* volume) OVERRIDE; |
| 184 | 184 |
| 185 // Retrieves the stream format that the audio engine uses for its internal | 185 // Retrieves the number of channels the audio engine uses for its internal |
| 186 // processing/mixing of shared-mode streams. | 186 // processing/mixing of shared-mode streams for the default endpoint device. |
| 187 // This method should not be used in combination with exclusive-mode streams. | 187 static int HardwareChannelCount(); |
| 188 | |
| 189 // Retrieves the channel layout the audio engine uses for its internal | |
| 190 // processing/mixing of shared-mode streams for the default endpoint device. | |
| 191 // Note that we convert an internal channel layout mask (see ChannelMask()) | |
| 192 // into a Chrome-specific channel layout enumerator in this method, hence | |
| 193 // the match might not be perfect. | |
| 194 static ChannelLayout HardwareChannelLayout(); | |
| 195 | |
| 196 // Retrieves the sample rate the audio engine uses for its internal | |
| 197 // processing/mixing of shared-mode streams for the default endpoint device. | |
| 188 static int HardwareSampleRate(ERole device_role); | 198 static int HardwareSampleRate(ERole device_role); |
| 189 | 199 |
| 190 // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used | 200 // Returns AUDCLNT_SHAREMODE_EXCLUSIVE if --enable-exclusive-mode is used |
| 191 // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default). | 201 // as command-line flag and AUDCLNT_SHAREMODE_SHARED otherwise (default). |
| 192 static AUDCLNT_SHAREMODE GetShareMode(); | 202 static AUDCLNT_SHAREMODE GetShareMode(); |
| 193 | 203 |
| 194 bool started() const { return started_; } | 204 bool started() const { return started_; } |
| 195 | 205 |
| 196 private: | 206 private: |
| 197 // Implementation of IUnknown (trivial in this case). See | 207 // Implementation of IUnknown (trivial in this case). See |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 | 240 |
| 231 // Issues the OnError() callback to the |sink_|. | 241 // Issues the OnError() callback to the |sink_|. |
| 232 void HandleError(HRESULT err); | 242 void HandleError(HRESULT err); |
| 233 | 243 |
| 234 // The Open() method is divided into these sub methods. | 244 // The Open() method is divided into these sub methods. |
| 235 HRESULT SetRenderDevice(); | 245 HRESULT SetRenderDevice(); |
| 236 HRESULT ActivateRenderDevice(); | 246 HRESULT ActivateRenderDevice(); |
| 237 bool DesiredFormatIsSupported(); | 247 bool DesiredFormatIsSupported(); |
| 238 HRESULT InitializeAudioEngine(); | 248 HRESULT InitializeAudioEngine(); |
| 239 | 249 |
| 250 // Retrieves the stream format that the audio engine uses for its internal | |
| 251 // processing/mixing of shared-mode streams. | |
| 252 static HRESULT GetMixFormat(ERole device_role, WAVEFORMATEX** device_format); | |
|
scherkus (not reviewing)
2012/08/01 00:14:05
any reason static private methods need to be here?
henrika (OOO until Aug 14)
2012/08/01 16:11:09
Great input, thanks. I actually did use private me
scherkus (not reviewing)
2012/08/02 00:41:57
Above the function.
| |
| 253 | |
| 240 // Called when the device will be opened in shared mode and use the | 254 // Called when the device will be opened in shared mode and use the |
| 241 // internal audio engine's mix format. | 255 // internal audio engine's mix format. |
| 242 HRESULT SharedModeInitialization(); | 256 HRESULT SharedModeInitialization(); |
| 243 | 257 |
| 244 // Called when the device will be opened in exclusive mode and use the | 258 // Called when the device will be opened in exclusive mode and use the |
| 245 // application specified format. | 259 // application specified format. |
| 246 HRESULT ExclusiveModeInitialization(); | 260 HRESULT ExclusiveModeInitialization(); |
| 247 | 261 |
| 248 // Converts unique endpoint ID to user-friendly device name. | 262 // Converts unique endpoint ID to user-friendly device name. |
| 249 std::string GetDeviceName(LPCWSTR device_id) const; | 263 std::string GetDeviceName(LPCWSTR device_id) const; |
| 250 | 264 |
| 251 // Called on the audio render thread when the current audio stream must | 265 // Called on the audio render thread when the current audio stream must |
| 252 // be re-initialized because the default audio device has changed. This | 266 // be re-initialized because the default audio device has changed. This |
| 253 // method: stops the current renderer, releases and re-creates all WASAPI | 267 // method: stops the current renderer, releases and re-creates all WASAPI |
| 254 // interfaces, creates a new IMMDevice and re-starts rendering using the | 268 // interfaces, creates a new IMMDevice and re-starts rendering using the |
| 255 // new default audio device. | 269 // new default audio device. |
| 256 bool RestartRenderingUsingNewDefaultDevice(); | 270 bool RestartRenderingUsingNewDefaultDevice(); |
| 257 | 271 |
| 272 // Retrieves an integer mask which corresponds to the channel layout the | |
| 273 // audio engine uses for its internal processing/mixing of shared-mode | |
| 274 // streams. This mask indicates which channels are present in the multi- | |
| 275 // channel stream. The least significant bit corresponds with the Front Left | |
| 276 // speaker, the next least significant bit corresponds to the Front Right | |
| 277 // speaker, and so on, continuing in the order defined in KsMedia.h. | |
| 278 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs. 85).aspx | |
| 279 // for more details. | |
| 280 static uint32 ChannelConfig(); | |
|
tommi (sloooow) - chröme
2012/07/31 21:39:30
Maybe we could define our own type for channel con
henrika (OOO until Aug 14)
2012/08/01 16:11:09
Added typedef ChannelConfigMask in media. Got conf
| |
| 281 | |
| 282 // Converts Microsoft's channel configuration to Chrome's ChannelLayout. | |
| 283 // This mapping is not perfect but the best we can do given the current | |
| 284 // ChannelLayout enumerator and the Windows-specific speaker configurations | |
| 285 // defined in ksmedia.h. Don't assume that the channel ordering in | |
| 286 // ChannelLayout is exactly the same as the Windows specific configuration. | |
| 287 // As an example: KSAUDIO_SPEAKER_7POINT1_SURROUND is mapped to | |
| 288 // CHANNEL_LAYOUT_7_1 but the positions of Back L, Back R and Side L, Side R | |
| 289 // speakers are different in these two definitions. | |
| 290 static ChannelLayout ChannelConfigToChromeChannelLayout(uint32 layout); | |
| 291 | |
| 258 AUDCLNT_SHAREMODE share_mode() const { return share_mode_; } | 292 AUDCLNT_SHAREMODE share_mode() const { return share_mode_; } |
| 293 int endpoint_channel_count() const { return endpoint_channel_count_; } | |
|
scherkus (not reviewing)
2012/08/01 00:14:05
huh? these are all private methods -- why the acce
henrika (OOO until Aug 14)
2012/08/01 16:11:09
Got it. Will clean up.
| |
| 294 uint32 endpoint_channel_config() const { return endpoint_channel_config_; } | |
| 295 int client_channel_count() const { | |
| 296 return client_audio_parameters_.channels(); | |
| 297 } | |
| 259 | 298 |
| 260 // Initializes the COM library for use by the calling thread and sets the | 299 // Initializes the COM library for use by the calling thread and sets the |
| 261 // thread's concurrency model to multi-threaded. | 300 // thread's concurrency model to multi-threaded. |
| 262 base::win::ScopedCOMInitializer com_init_; | 301 base::win::ScopedCOMInitializer com_init_; |
| 263 | 302 |
| 264 // Contains the thread ID of the creating thread. | 303 // Contains the thread ID of the creating thread. |
| 265 base::PlatformThreadId creating_thread_id_; | 304 base::PlatformThreadId creating_thread_id_; |
| 266 | 305 |
| 267 // Our creator, the audio manager needs to be notified when we close. | 306 // Our creator, the audio manager needs to be notified when we close. |
| 268 AudioManagerWin* manager_; | 307 AudioManagerWin* manager_; |
| 269 | 308 |
| 309 AudioParameters client_audio_parameters_; | |
|
tommi (sloooow) - chröme
2012/07/31 21:39:30
are there any other audio parameters that this cla
henrika (OOO until Aug 14)
2012/08/01 16:11:09
I store this one to keep track of the parameters s
| |
| 310 | |
| 270 // Rendering is driven by this thread (which has no message loop). | 311 // Rendering is driven by this thread (which has no message loop). |
| 271 // All OnMoreData() callbacks will be called from this thread. | 312 // All OnMoreData() callbacks will be called from this thread. |
| 272 base::DelegateSimpleThread* render_thread_; | 313 base::DelegateSimpleThread* render_thread_; |
| 273 | 314 |
| 274 // Contains the desired audio format which is set up at construction. | 315 // Contains the desired audio format which is set up at construction. |
| 275 WAVEFORMATEX format_; | 316 // Extended PCM waveform format structure based on WAVEFORMATEXTENSIBLE. |
| 317 // Use this for multiple channel and hi-resolution PCM data. | |
| 318 WAVEFORMATPCMEX format_; | |
| 276 | 319 |
| 277 // Copy of the audio format which we know the audio engine supports. | 320 // Copy of the audio format which we know the audio engine supports. |
| 278 // It is recommended to ensure that the sample rate in |format_| is identical | 321 // It is recommended to ensure that the sample rate in |format_| is identical |
| 279 // to the sample rate in |audio_engine_mix_format_|. | 322 // to the sample rate in |audio_engine_mix_format_|. |
| 280 base::win::ScopedCoMem<WAVEFORMATEX> audio_engine_mix_format_; | 323 base::win::ScopedCoMem<WAVEFORMATPCMEX> audio_engine_mix_format_; |
| 281 | 324 |
| 282 bool opened_; | 325 bool opened_; |
| 283 bool started_; | 326 bool started_; |
| 284 | 327 |
| 285 // Set to true as soon as a new default device is detected, and cleared when | 328 // Set to true as soon as a new default device is detected, and cleared when |
| 286 // the streaming has switched from using the old device to the new device. | 329 // the streaming has switched from using the old device to the new device. |
| 287 // All additional device detections during an active state are ignored to | 330 // All additional device detections during an active state are ignored to |
| 288 // ensure that the ongoing switch can finalize without disruptions. | 331 // ensure that the ongoing switch can finalize without disruptions. |
| 289 bool restart_rendering_mode_; | 332 bool restart_rendering_mode_; |
| 290 | 333 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 309 size_t endpoint_buffer_size_frames_; | 352 size_t endpoint_buffer_size_frames_; |
| 310 | 353 |
| 311 // Defines the role that the system has assigned to an audio endpoint device. | 354 // Defines the role that the system has assigned to an audio endpoint device. |
| 312 ERole device_role_; | 355 ERole device_role_; |
| 313 | 356 |
| 314 // The sharing mode for the connection. | 357 // The sharing mode for the connection. |
| 315 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE | 358 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE |
| 316 // where AUDCLNT_SHAREMODE_SHARED is the default. | 359 // where AUDCLNT_SHAREMODE_SHARED is the default. |
| 317 AUDCLNT_SHAREMODE share_mode_; | 360 AUDCLNT_SHAREMODE share_mode_; |
| 318 | 361 |
| 362 // Contains the number of channels the audio engine uses for its internal | |
| 363 // processing/mixing of shared-mode streams for the default endpoint device. | |
| 364 const int endpoint_channel_count_; | |
| 365 | |
| 366 // Contains the channel configuration the audio engine uses for its internal | |
| 367 // processing/mixing of shared-mode streams for the default endpoint | |
| 368 // device. | |
| 369 const uint32 endpoint_channel_config_; | |
| 370 | |
| 371 // TODO(henrika): add comments.... | |
| 372 int channel_factor_; | |
| 373 | |
| 319 // Counts the number of audio frames written to the endpoint buffer. | 374 // Counts the number of audio frames written to the endpoint buffer. |
| 320 UINT64 num_written_frames_; | 375 UINT64 num_written_frames_; |
| 321 | 376 |
| 322 // Pointer to the client that will deliver audio samples to be played out. | 377 // Pointer to the client that will deliver audio samples to be played out. |
| 323 AudioSourceCallback* source_; | 378 AudioSourceCallback* source_; |
| 324 | 379 |
| 325 // An IMMDeviceEnumerator interface which represents a device enumerator. | 380 // An IMMDeviceEnumerator interface which represents a device enumerator. |
| 326 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; | 381 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; |
| 327 | 382 |
| 328 // An IMMDevice interface which represents an audio endpoint device. | 383 // An IMMDevice interface which represents an audio endpoint device. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 345 | 400 |
| 346 // This event will be signaled when stream switching shall take place. | 401 // This event will be signaled when stream switching shall take place. |
| 347 base::win::ScopedHandle stream_switch_event_; | 402 base::win::ScopedHandle stream_switch_event_; |
| 348 | 403 |
| 349 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); | 404 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); |
| 350 }; | 405 }; |
| 351 | 406 |
| 352 } // namespace media | 407 } // namespace media |
| 353 | 408 |
| 354 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ | 409 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ |
| OLD | NEW |