- add sources.
[platform/framework/web/crosswalk.git] / src / media / audio / win / waveout_output_win.cc
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
3 // found in the LICENSE file.
4
5 #include "media/audio/win/waveout_output_win.h"
6
7 #include <windows.h>
8 #include <mmsystem.h>
9 #pragma comment(lib, "winmm.lib")
10
11 #include "base/atomicops.h"
12 #include "base/basictypes.h"
13 #include "base/debug/trace_event.h"
14 #include "base/logging.h"
15 #include "media/audio/audio_io.h"
16 #include "media/audio/win/audio_manager_win.h"
17
18 namespace media {
19
20 // Some general thoughts about the waveOut API which is badly documented :
21 // - We use CALLBACK_EVENT mode in which XP signals events such as buffer
22 //   releases.
23 // - We use RegisterWaitForSingleObject() so one of threads in thread pool
24 //   automatically calls our callback that feeds more data to Windows.
25 // - Windows does not provide a way to query if the device is playing or paused
26 //   thus it forces you to maintain state, which naturally is not exactly
27 //   synchronized to the actual device state.
28
29 // Sixty four MB is the maximum buffer size per AudioOutputStream.
30 static const uint32 kMaxOpenBufferSize = 1024 * 1024 * 64;
31
32 // See Also
33 // http://www.thx.com/consumer/home-entertainment/home-theater/surround-sound-speaker-set-up/
34 // http://en.wikipedia.org/wiki/Surround_sound
35
36 static const int kMaxChannelsToMask = 8;
37 static const unsigned int kChannelsToMask[kMaxChannelsToMask + 1] = {
38   0,
39   // 1 = Mono
40   SPEAKER_FRONT_CENTER,
41   // 2 = Stereo
42   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT,
43   // 3 = Stereo + Center
44   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER,
45   // 4 = Quad
46   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
47   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
48   // 5 = 5.0
49   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
50   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
51   // 6 = 5.1
52   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
53   SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
54   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT,
55   // 7 = 6.1
56   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
57   SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
58   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
59   SPEAKER_BACK_CENTER,
60   // 8 = 7.1
61   SPEAKER_FRONT_LEFT  | SPEAKER_FRONT_RIGHT |
62   SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |
63   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |
64   SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
65   // TODO(fbarchard): Add additional masks for 7.2 and beyond.
66 };
67
68 inline size_t PCMWaveOutAudioOutputStream::BufferSize() const {
69   // Round size of buffer up to the nearest 16 bytes.
70   return (sizeof(WAVEHDR) + buffer_size_ + 15u) & static_cast<size_t>(~15);
71 }
72
73 inline WAVEHDR* PCMWaveOutAudioOutputStream::GetBuffer(int n) const {
74   DCHECK_GE(n, 0);
75   DCHECK_LT(n, num_buffers_);
76   return reinterpret_cast<WAVEHDR*>(&buffers_[n * BufferSize()]);
77 }
78
79 PCMWaveOutAudioOutputStream::PCMWaveOutAudioOutputStream(
80     AudioManagerWin* manager, const AudioParameters& params, int num_buffers,
81     UINT device_id)
82     : state_(PCMA_BRAND_NEW),
83       manager_(manager),
84       device_id_(device_id),
85       waveout_(NULL),
86       callback_(NULL),
87       num_buffers_(num_buffers),
88       buffer_size_(params.GetBytesPerBuffer()),
89       volume_(1),
90       channels_(params.channels()),
91       pending_bytes_(0),
92       waiting_handle_(NULL),
93       audio_bus_(AudioBus::Create(params)) {
94   format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
95   format_.Format.nChannels = params.channels();
96   format_.Format.nSamplesPerSec = params.sample_rate();
97   format_.Format.wBitsPerSample = params.bits_per_sample();
98   format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX);
99   // The next are computed from above.
100   format_.Format.nBlockAlign = (format_.Format.nChannels *
101                                 format_.Format.wBitsPerSample) / 8;
102   format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign *
103                                    format_.Format.nSamplesPerSec;
104   if (params.channels() > kMaxChannelsToMask) {
105     format_.dwChannelMask = kChannelsToMask[kMaxChannelsToMask];
106   } else {
107     format_.dwChannelMask = kChannelsToMask[params.channels()];
108   }
109   format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
110   format_.Samples.wValidBitsPerSample = params.bits_per_sample();
111 }
112
113 PCMWaveOutAudioOutputStream::~PCMWaveOutAudioOutputStream() {
114   DCHECK(NULL == waveout_);
115 }
116
117 bool PCMWaveOutAudioOutputStream::Open() {
118   if (state_ != PCMA_BRAND_NEW)
119     return false;
120   if (BufferSize() * num_buffers_ > kMaxOpenBufferSize)
121     return false;
122   if (num_buffers_ < 2 || num_buffers_ > 5)
123     return false;
124
125   // Create buffer event.
126   buffer_event_.Set(::CreateEvent(NULL,    // Security attributes.
127                                   FALSE,   // It will auto-reset.
128                                   FALSE,   // Initial state.
129                                   NULL));  // No name.
130   if (!buffer_event_.Get())
131     return false;
132
133   // Open the device.
134   // We'll be getting buffer_event_ events when it's time to refill the buffer.
135   MMRESULT result = ::waveOutOpen(
136       &waveout_,
137       device_id_,
138       reinterpret_cast<LPCWAVEFORMATEX>(&format_),
139       reinterpret_cast<DWORD_PTR>(buffer_event_.Get()),
140       NULL,
141       CALLBACK_EVENT);
142   if (result != MMSYSERR_NOERROR)
143     return false;
144
145   SetupBuffers();
146   state_ = PCMA_READY;
147   return true;
148 }
149
150 void PCMWaveOutAudioOutputStream::SetupBuffers() {
151   buffers_.reset(new char[BufferSize() * num_buffers_]);
152   for (int ix = 0; ix != num_buffers_; ++ix) {
153     WAVEHDR* buffer = GetBuffer(ix);
154     buffer->lpData = reinterpret_cast<char*>(buffer) + sizeof(WAVEHDR);
155     buffer->dwBufferLength = buffer_size_;
156     buffer->dwBytesRecorded = 0;
157     buffer->dwFlags = WHDR_DONE;
158     buffer->dwLoops = 0;
159     // Tell windows sound drivers about our buffers. Not documented what
160     // this does but we can guess that causes the OS to keep a reference to
161     // the memory pages so the driver can use them without worries.
162     ::waveOutPrepareHeader(waveout_, buffer, sizeof(WAVEHDR));
163   }
164 }
165
166 void PCMWaveOutAudioOutputStream::FreeBuffers() {
167   for (int ix = 0; ix != num_buffers_; ++ix) {
168     ::waveOutUnprepareHeader(waveout_, GetBuffer(ix), sizeof(WAVEHDR));
169   }
170   buffers_.reset();
171 }
172
173 // Initially we ask the source to fill up all audio buffers. If we don't do
174 // this then we would always get the driver callback when it is about to run
175 // samples and that would leave too little time to react.
176 void PCMWaveOutAudioOutputStream::Start(AudioSourceCallback* callback) {
177   if (state_ != PCMA_READY)
178     return;
179   callback_ = callback;
180
181   // Reset buffer event, it can be left in the arbitrary state if we
182   // previously stopped the stream. Can happen because we are stopping
183   // callbacks before stopping playback itself.
184   if (!::ResetEvent(buffer_event_.Get())) {
185     HandleError(MMSYSERR_ERROR);
186     return;
187   }
188
189   // Start watching for buffer events.
190   if (!::RegisterWaitForSingleObject(&waiting_handle_,
191                                      buffer_event_.Get(),
192                                      &BufferCallback,
193                                      this,
194                                      INFINITE,
195                                      WT_EXECUTEDEFAULT)) {
196     HandleError(MMSYSERR_ERROR);
197     waiting_handle_ = NULL;
198     return;
199   }
200
201   state_ = PCMA_PLAYING;
202
203   // Queue the buffers.
204   pending_bytes_ = 0;
205   for (int ix = 0; ix != num_buffers_; ++ix) {
206     WAVEHDR* buffer = GetBuffer(ix);
207     QueueNextPacket(buffer);  // Read more data.
208     pending_bytes_ += buffer->dwBufferLength;
209   }
210
211   // From now on |pending_bytes_| would be accessed by callback thread.
212   // Most likely waveOutPause() or waveOutRestart() has its own memory barrier,
213   // but issuing our own is safer.
214   base::subtle::MemoryBarrier();
215
216   MMRESULT result = ::waveOutPause(waveout_);
217   if (result != MMSYSERR_NOERROR) {
218     HandleError(result);
219     return;
220   }
221
222   // Send the buffers to the audio driver. Note that the device is paused
223   // so we avoid entering the callback method while still here.
224   for (int ix = 0; ix != num_buffers_; ++ix) {
225     result = ::waveOutWrite(waveout_, GetBuffer(ix), sizeof(WAVEHDR));
226     if (result != MMSYSERR_NOERROR) {
227       HandleError(result);
228       break;
229     }
230   }
231   result = ::waveOutRestart(waveout_);
232   if (result != MMSYSERR_NOERROR) {
233     HandleError(result);
234     return;
235   }
236 }
237
238 // Stopping is tricky if we want it be fast.
239 // For now just do it synchronously and avoid all the complexities.
240 // TODO(enal): if we want faster Stop() we can create singleton that keeps track
241 //             of all currently playing streams. Then you don't have to wait
242 //             till all callbacks are completed. Of course access to singleton
243 //             should be under its own lock, and checking the liveness and
244 //             acquiring the lock on stream should be done atomically.
245 void PCMWaveOutAudioOutputStream::Stop() {
246   if (state_ != PCMA_PLAYING)
247     return;
248   state_ = PCMA_STOPPING;
249   base::subtle::MemoryBarrier();
250
251   // Stop watching for buffer event, wait till all the callbacks are complete.
252   // Should be done before ::waveOutReset() call to avoid race condition when
253   // callback that is currently active and already checked that stream is still
254   // being played calls ::waveOutWrite() after ::waveOutReset() returns, later
255   // causing ::waveOutClose() to fail with WAVERR_STILLPLAYING.
256   // TODO(enal): that delays actual stopping of playback. Alternative can be
257   //             to call ::waveOutReset() twice, once before
258   //             ::UnregisterWaitEx() and once after.
259   if (waiting_handle_) {
260     if (!::UnregisterWaitEx(waiting_handle_, INVALID_HANDLE_VALUE)) {
261       state_ = PCMA_PLAYING;
262       HandleError(MMSYSERR_ERROR);
263       return;
264     }
265     waiting_handle_ = NULL;
266   }
267
268   // Stop playback.
269   MMRESULT res = ::waveOutReset(waveout_);
270   if (res != MMSYSERR_NOERROR) {
271     state_ = PCMA_PLAYING;
272     HandleError(res);
273     return;
274   }
275
276   // Wait for lock to ensure all outstanding callbacks have completed.
277   base::AutoLock auto_lock(lock_);
278
279   // waveOutReset() leaves buffers in the unpredictable state, causing
280   // problems if we want to close, release, or reuse them. Fix the states.
281   for (int ix = 0; ix != num_buffers_; ++ix) {
282     GetBuffer(ix)->dwFlags = WHDR_PREPARED;
283   }
284
285   // Don't use callback after Stop().
286   callback_ = NULL;
287
288   state_ = PCMA_READY;
289 }
290
291 // We can Close in any state except that trying to close a stream that is
292 // playing Windows generates an error. We cannot propagate it to the source,
293 // as callback_ is set to NULL. Just print it and hope somebody somehow
294 // will find it...
295 void PCMWaveOutAudioOutputStream::Close() {
296   // Force Stop() to ensure it's safe to release buffers and free the stream.
297   Stop();
298
299   if (waveout_) {
300     FreeBuffers();
301
302     // waveOutClose() generates a WIM_CLOSE callback.  In case Start() was never
303     // called, force a reset to ensure close succeeds.
304     MMRESULT res = ::waveOutReset(waveout_);
305     DCHECK_EQ(res, static_cast<MMRESULT>(MMSYSERR_NOERROR));
306     res = ::waveOutClose(waveout_);
307     DCHECK_EQ(res, static_cast<MMRESULT>(MMSYSERR_NOERROR));
308     state_ = PCMA_CLOSED;
309     waveout_ = NULL;
310   }
311
312   // Tell the audio manager that we have been released. This can result in
313   // the manager destroying us in-place so this needs to be the last thing
314   // we do on this function.
315   manager_->ReleaseOutputStream(this);
316 }
317
318 void PCMWaveOutAudioOutputStream::SetVolume(double volume) {
319   if (!waveout_)
320     return;
321   volume_ = static_cast<float>(volume);
322 }
323
324 void PCMWaveOutAudioOutputStream::GetVolume(double* volume) {
325   if (!waveout_)
326     return;
327   *volume = volume_;
328 }
329
330 void PCMWaveOutAudioOutputStream::HandleError(MMRESULT error) {
331   DLOG(WARNING) << "PCMWaveOutAudio error " << error;
332   if (callback_)
333     callback_->OnError(this);
334 }
335
336 void PCMWaveOutAudioOutputStream::QueueNextPacket(WAVEHDR *buffer) {
337   DCHECK_EQ(channels_, format_.Format.nChannels);
338   // Call the source which will fill our buffer with pleasant sounds and
339   // return to us how many bytes were used.
340   // TODO(fbarchard): Handle used 0 by queueing more.
341
342   // TODO(sergeyu): Specify correct hardware delay for AudioBuffersState.
343   int frames_filled = callback_->OnMoreData(
344       audio_bus_.get(), AudioBuffersState(pending_bytes_, 0));
345   uint32 used = frames_filled * audio_bus_->channels() *
346       format_.Format.wBitsPerSample / 8;
347
348   if (used <= buffer_size_) {
349     // Note: If this ever changes to output raw float the data must be clipped
350     // and sanitized since it may come from an untrusted source such as NaCl.
351     audio_bus_->Scale(volume_);
352     audio_bus_->ToInterleaved(
353         frames_filled, format_.Format.wBitsPerSample / 8, buffer->lpData);
354
355     buffer->dwBufferLength = used * format_.Format.nChannels / channels_;
356   } else {
357     HandleError(0);
358     return;
359   }
360   buffer->dwFlags = WHDR_PREPARED;
361 }
362
363 // One of the threads in our thread pool asynchronously calls this function when
364 // buffer_event_ is signalled. Search through all the buffers looking for freed
365 // ones, fills them with data, and "feed" the Windows.
366 // Note: by searching through all the buffers we guarantee that we fill all the
367 //       buffers, even when "event loss" happens, i.e. if Windows signals event
368 //       when it did not flip into unsignaled state from the previous signal.
369 void NTAPI PCMWaveOutAudioOutputStream::BufferCallback(PVOID lpParameter,
370                                                        BOOLEAN timer_fired) {
371   TRACE_EVENT0("audio", "PCMWaveOutAudioOutputStream::BufferCallback");
372
373   DCHECK(!timer_fired);
374   PCMWaveOutAudioOutputStream* stream =
375       reinterpret_cast<PCMWaveOutAudioOutputStream*>(lpParameter);
376
377   // Lock the stream so callbacks do not interfere with each other.
378   // Several callbacks can be called simultaneously by different threads in the
379   // thread pool if some of the callbacks are slow, or system is very busy and
380   // scheduled callbacks are not called on time.
381   base::AutoLock auto_lock(stream->lock_);
382   if (stream->state_ != PCMA_PLAYING)
383     return;
384
385   for (int ix = 0; ix != stream->num_buffers_; ++ix) {
386     WAVEHDR* buffer = stream->GetBuffer(ix);
387     if (buffer->dwFlags & WHDR_DONE) {
388       // Before we queue the next packet, we need to adjust the number of
389       // pending bytes since the last write to hardware.
390       stream->pending_bytes_ -= buffer->dwBufferLength;
391       stream->QueueNextPacket(buffer);
392
393       // QueueNextPacket() can take a long time, especially if several of them
394       // were called back-to-back. Check if we are stopping now.
395       if (stream->state_ != PCMA_PLAYING)
396         return;
397
398       // Time to send the buffer to the audio driver. Since we are reusing
399       // the same buffers we can get away without calling waveOutPrepareHeader.
400       MMRESULT result = ::waveOutWrite(stream->waveout_,
401                                        buffer,
402                                        sizeof(WAVEHDR));
403       if (result != MMSYSERR_NOERROR)
404         stream->HandleError(result);
405       stream->pending_bytes_ += buffer->dwBufferLength;
406     }
407   }
408 }
409
410 }  // namespace media