Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Side by Side Diff: media/audio/win/audio_low_latency_output_win.h

Issue 10575017: Adding experimental exclusive-mode streaming to WASAPIAudioOutputStream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes based on review by Chris and Andrew Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 // by the AudioManager. 105 // by the AudioManager.
106 // - It is a requirement to call the following methods on the same audio 106 // - It is a requirement to call the following methods on the same audio
107 // thread: Open(), Start(), Stop(), and Close(). 107 // thread: Open(), Start(), Stop(), and Close().
108 // - Audio rendering is performed on the audio render thread, owned by this 108 // - Audio rendering is performed on the audio render thread, owned by this
109 // class, and the AudioSourceCallback::OnMoreData() method will be called 109 // class, and the AudioSourceCallback::OnMoreData() method will be called
110 // from this thread. Stream switching also takes place on the audio-render 110 // from this thread. Stream switching also takes place on the audio-render
111 // thread. 111 // thread.
112 // - All callback methods from the IMMNotificationClient interface will be 112 // - All callback methods from the IMMNotificationClient interface will be
113 // called on a Windows-internal MMDevice thread. 113 // called on a Windows-internal MMDevice thread.
114 // 114 //
115 // Experimental exclusive mode (DO NOT USE IN PRODUCTION CODE):
116 //
117 // - It is possible to open up a stream in exclusive mode by using the
118 // |share_mode| flag in the constructor. To try it out, set this flag to
119 // AUDCLNT_SHAREMODE_EXCLUSIVE.
120 // - The internal buffering scheme is less flexible for exclusive-mode streams.
121 // Hence, some manual tuning will be required before deciding what frame
122 // size to use. See the WinAudioOutputTest unit test for more details.
123 // - If an application opens a stream in exclusive mode, the application has
124 // exclusive use of the audio endpoint device that plays the stream.
125 // - Exclusive-mode access to an audio device can block crucial system sounds,
126 // prevent interoperability with other applications, and otherwise degrade
127 // the user experience.
128 // - Exclusive-mode should only be utilized when the lowest possible latency
129 // is important.
130 // - In exclusive mode, the client can choose to open the stream in any audio
131 // format that the endpoint device supports.
132 // - Initial measurements on Windows 7 have shown that the lowest possible
133 // latencies we can achieve are:
134 // o ~3.3333ms @ 48kHz <=> 160 audio frames per buffer.
135 // o ~3.6281ms @ 44.1kHz <=> 160 audio frames per buffer.
136 // - See msdn.microsoft.com/en-us/library/windows/desktop/dd370844(v=vs.85).aspx
137 // for more details.
138
115 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 139 #ifndef MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_
116 #define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 140 #define MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_
117 141
118 #include <Audioclient.h> 142 #include <Audioclient.h>
119 #include <audiopolicy.h> 143 #include <audiopolicy.h>
120 #include <MMDeviceAPI.h> 144 #include <MMDeviceAPI.h>
121 145
122 #include <string> 146 #include <string>
123 147
124 #include "base/compiler_specific.h" 148 #include "base/compiler_specific.h"
(...skipping 14 matching lines...) Expand all
139 // AudioOutputStream implementation using Windows Core Audio APIs. 163 // AudioOutputStream implementation using Windows Core Audio APIs.
140 // The IMMNotificationClient interface enables device event notifications 164 // The IMMNotificationClient interface enables device event notifications
141 // related to changes in the status of an audio endpoint device. 165 // related to changes in the status of an audio endpoint device.
142 class MEDIA_EXPORT WASAPIAudioOutputStream 166 class MEDIA_EXPORT WASAPIAudioOutputStream
143 : public IMMNotificationClient, 167 : public IMMNotificationClient,
144 public AudioOutputStream, 168 public AudioOutputStream,
145 public base::DelegateSimpleThread::Delegate { 169 public base::DelegateSimpleThread::Delegate {
146 public: 170 public:
147 // The ctor takes all the usual parameters, plus |manager| which is the 171 // The ctor takes all the usual parameters, plus |manager| which is the
148 // the audio manager who is creating this object. 172 // the audio manager who is creating this object.
173 // Note that, |share_mode| shall be set to AUDCLNT_SHAREMODE_SHARED in
174 // production code. AUDCLNT_SHAREMODE_EXCLUSIVE is also supported but must
175 // only be used behind a command-line flag.
149 WASAPIAudioOutputStream(AudioManagerWin* manager, 176 WASAPIAudioOutputStream(AudioManagerWin* manager,
150 const AudioParameters& params, 177 const AudioParameters& params,
151 ERole device_role); 178 ERole device_role,
179 AUDCLNT_SHAREMODE share_mode);
152 // The dtor is typically called by the AudioManager only and it is usually 180 // The dtor is typically called by the AudioManager only and it is usually
153 // triggered by calling AudioOutputStream::Close(). 181 // triggered by calling AudioOutputStream::Close().
154 virtual ~WASAPIAudioOutputStream(); 182 virtual ~WASAPIAudioOutputStream();
155 183
156 // Implementation of AudioOutputStream. 184 // Implementation of AudioOutputStream.
157 virtual bool Open() OVERRIDE; 185 virtual bool Open() OVERRIDE;
158 virtual void Start(AudioSourceCallback* callback) OVERRIDE; 186 virtual void Start(AudioSourceCallback* callback) OVERRIDE;
159 virtual void Stop() OVERRIDE; 187 virtual void Stop() OVERRIDE;
160 virtual void Close() OVERRIDE; 188 virtual void Close() OVERRIDE;
161 virtual void SetVolume(double volume) OVERRIDE; 189 virtual void SetVolume(double volume) OVERRIDE;
162 virtual void GetVolume(double* volume) OVERRIDE; 190 virtual void GetVolume(double* volume) OVERRIDE;
163 191
164 // Retrieves the stream format that the audio engine uses for its internal 192 // Retrieves the stream format that the audio engine uses for its internal
165 // processing/mixing of shared-mode streams. 193 // processing/mixing of shared-mode streams.
194 // This method should not be used in combination with exclusive-mode streams.
166 static int HardwareSampleRate(ERole device_role); 195 static int HardwareSampleRate(ERole device_role);
167 196
168 bool started() const { return started_; } 197 bool started() const { return started_; }
169 198
170 private: 199 private:
171 // Implementation of IUnknown (trivial in this case). See 200 // Implementation of IUnknown (trivial in this case). See
172 // msdn.microsoft.com/en-us/library/windows/desktop/dd371403(v=vs.85).aspx 201 // msdn.microsoft.com/en-us/library/windows/desktop/dd371403(v=vs.85).aspx
173 // for details regarding why proper implementations of AddRef(), Release() 202 // for details regarding why proper implementations of AddRef(), Release()
174 // and QueryInterface() are not needed here. 203 // and QueryInterface() are not needed here.
175 STDMETHOD_(ULONG, AddRef)(); 204 STDMETHOD_(ULONG, AddRef)();
(...skipping 23 matching lines...) Expand all
199 return S_OK; 228 return S_OK;
200 } 229 }
201 230
202 // DelegateSimpleThread::Delegate implementation. 231 // DelegateSimpleThread::Delegate implementation.
203 virtual void Run() OVERRIDE; 232 virtual void Run() OVERRIDE;
204 233
205 // Issues the OnError() callback to the |sink_|. 234 // Issues the OnError() callback to the |sink_|.
206 void HandleError(HRESULT err); 235 void HandleError(HRESULT err);
207 236
208 // The Open() method is divided into these sub methods. 237 // The Open() method is divided into these sub methods.
209 HRESULT SetRenderDevice(ERole device_role); 238 HRESULT SetRenderDevice();
210 HRESULT ActivateRenderDevice(); 239 HRESULT ActivateRenderDevice();
211 HRESULT GetAudioEngineStreamFormat(); 240 HRESULT GetAudioEngineStreamFormat();
212 bool DesiredFormatIsSupported(); 241 bool DesiredFormatIsSupported();
213 HRESULT InitializeAudioEngine(); 242 HRESULT InitializeAudioEngine();
214 243
215 // Converts unique endpoint ID to user-friendly device name. 244 // Converts unique endpoint ID to user-friendly device name.
216 std::string GetDeviceName(LPCWSTR device_id) const; 245 std::string GetDeviceName(LPCWSTR device_id) const;
217 246
218 // Called on the audio render thread when the current audio stream must 247 // Called on the audio render thread when the current audio stream must
219 // be re-initialized because the default audio device has changed. This 248 // be re-initialized because the default audio device has changed. This
220 // method: stops the current renderer, releases and re-creates all WASAPI 249 // method: stops the current renderer, releases and re-creates all WASAPI
221 // interfaces, creates a new IMMDevice and re-starts rendering using the 250 // interfaces, creates a new IMMDevice and re-starts rendering using the
222 // new default audio device. 251 // new default audio device.
223 bool RestartRenderingUsingNewDefaultDevice(); 252 bool RestartRenderingUsingNewDefaultDevice();
224 253
254 AUDCLNT_SHAREMODE share_mode() const { return share_mode_; }
255
225 // Initializes the COM library for use by the calling thread and sets the 256 // Initializes the COM library for use by the calling thread and sets the
226 // thread's concurrency model to multi-threaded. 257 // thread's concurrency model to multi-threaded.
227 base::win::ScopedCOMInitializer com_init_; 258 base::win::ScopedCOMInitializer com_init_;
228 259
229 // Contains the thread ID of the creating thread. 260 // Contains the thread ID of the creating thread.
230 base::PlatformThreadId creating_thread_id_; 261 base::PlatformThreadId creating_thread_id_;
231 262
232 // Our creator, the audio manager needs to be notified when we close. 263 // Our creator, the audio manager needs to be notified when we close.
233 AudioManagerWin* manager_; 264 AudioManagerWin* manager_;
234 265
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 300
270 // Size in milliseconds of each audio packet. 301 // Size in milliseconds of each audio packet.
271 float packet_size_ms_; 302 float packet_size_ms_;
272 303
273 // Length of the audio endpoint buffer. 304 // Length of the audio endpoint buffer.
274 size_t endpoint_buffer_size_frames_; 305 size_t endpoint_buffer_size_frames_;
275 306
276 // Defines the role that the system has assigned to an audio endpoint device. 307 // Defines the role that the system has assigned to an audio endpoint device.
277 ERole device_role_; 308 ERole device_role_;
278 309
310 // The sharing mode for the connection.
311 // Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE
312 // where AUDCLNT_SHAREMODE_SHARED is the default.
313 // This member is not modified (only read) after construction hence we don't
314 // have to pro
315 AUDCLNT_SHAREMODE share_mode_;
316
279 // Counts the number of audio frames written to the endpoint buffer. 317 // Counts the number of audio frames written to the endpoint buffer.
280 UINT64 num_written_frames_; 318 UINT64 num_written_frames_;
281 319
282 // Pointer to the client that will deliver audio samples to be played out. 320 // Pointer to the client that will deliver audio samples to be played out.
283 AudioSourceCallback* source_; 321 AudioSourceCallback* source_;
284 322
285 // An IMMDeviceEnumerator interface which represents a device enumerator. 323 // An IMMDeviceEnumerator interface which represents a device enumerator.
286 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_; 324 base::win::ScopedComPtr<IMMDeviceEnumerator> device_enumerator_;
287 325
288 // An IMMDevice interface which represents an audio endpoint device. 326 // An IMMDevice interface which represents an audio endpoint device.
(...skipping 16 matching lines...) Expand all
305 343
306 // This event will be signaled when stream switching shall take place. 344 // This event will be signaled when stream switching shall take place.
307 base::win::ScopedHandle stream_switch_event_; 345 base::win::ScopedHandle stream_switch_event_;
308 346
309 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); 347 DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream);
310 }; 348 };
311 349
312 } // namespace media 350 } // namespace media
313 351
314 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_ 352 #endif // MEDIA_AUDIO_WIN_AUDIO_LOW_LATENCY_OUTPUT_WIN_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698