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

Side by Side Diff: media/audio/win/waveout_output_win.cc

Issue 4661001: Simplified AudioOutputStream interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 10 years, 1 month 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/waveout_output_win.h" 5 #include "media/audio/win/waveout_output_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <mmsystem.h> 8 #include <mmsystem.h>
9 #pragma comment(lib, "winmm.lib") 9 #pragma comment(lib, "winmm.lib")
10 10
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 PCMWaveOutAudioOutputStream::PCMWaveOutAudioOutputStream( 80 PCMWaveOutAudioOutputStream::PCMWaveOutAudioOutputStream(
81 AudioManagerWin* manager, AudioParameters params, int num_buffers, 81 AudioManagerWin* manager, AudioParameters params, int num_buffers,
82 UINT device_id) 82 UINT device_id)
83 : state_(PCMA_BRAND_NEW), 83 : state_(PCMA_BRAND_NEW),
84 manager_(manager), 84 manager_(manager),
85 device_id_(device_id), 85 device_id_(device_id),
86 waveout_(NULL), 86 waveout_(NULL),
87 callback_(NULL), 87 callback_(NULL),
88 num_buffers_(num_buffers), 88 num_buffers_(num_buffers),
89 buffer_(NULL), 89 buffer_(NULL),
90 buffer_size_(0), 90 buffer_size_(params.samples_per_packet * params.channels *
91 params.bits_per_sample / 8),
91 volume_(1), 92 volume_(1),
92 channels_(params.channels), 93 channels_(params.channels),
93 pending_bytes_(0) { 94 pending_bytes_(0) {
95
94 format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 96 format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
95 format_.Format.nChannels = params.channels; 97 format_.Format.nChannels = params.channels;
96 format_.Format.nSamplesPerSec = params.sample_rate; 98 format_.Format.nSamplesPerSec = params.sample_rate;
97 format_.Format.wBitsPerSample = params.bits_per_sample; 99 format_.Format.wBitsPerSample = params.bits_per_sample;
98 format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX); 100 format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX);
99 // The next are computed from above. 101 // The next are computed from above.
100 format_.Format.nBlockAlign = (format_.Format.nChannels * 102 format_.Format.nBlockAlign = (format_.Format.nChannels *
101 format_.Format.wBitsPerSample) / 8; 103 format_.Format.wBitsPerSample) / 8;
102 format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign * 104 format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign *
103 format_.Format.nSamplesPerSec; 105 format_.Format.nSamplesPerSec;
104 if (params.channels > kMaxChannelsToMask) { 106 if (params.channels > kMaxChannelsToMask) {
105 format_.dwChannelMask = kChannelsToMask[kMaxChannelsToMask]; 107 format_.dwChannelMask = kChannelsToMask[kMaxChannelsToMask];
106 } else { 108 } else {
107 format_.dwChannelMask = kChannelsToMask[params.channels]; 109 format_.dwChannelMask = kChannelsToMask[params.channels];
108 } 110 }
109 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 111 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
110 format_.Samples.wValidBitsPerSample = params.bits_per_sample; 112 format_.Samples.wValidBitsPerSample = params.bits_per_sample;
111 // The event is auto-reset. 113 // The event is auto-reset.
112 stopped_event_.Set(::CreateEventW(NULL, FALSE, FALSE, NULL)); 114 stopped_event_.Set(::CreateEventW(NULL, FALSE, FALSE, NULL));
113 } 115 }
114 116
115 PCMWaveOutAudioOutputStream::~PCMWaveOutAudioOutputStream() { 117 PCMWaveOutAudioOutputStream::~PCMWaveOutAudioOutputStream() {
116 DCHECK(NULL == waveout_); 118 DCHECK(NULL == waveout_);
117 } 119 }
118 120
119 bool PCMWaveOutAudioOutputStream::Open(uint32 buffer_size) { 121 bool PCMWaveOutAudioOutputStream::Open() {
120 if (state_ != PCMA_BRAND_NEW) 122 if (state_ != PCMA_BRAND_NEW)
121 return false; 123 return false;
122 if (buffer_size > kMaxOpenBufferSize)
123 return false;
124 if (num_buffers_ < 2 || num_buffers_ > 5) 124 if (num_buffers_ < 2 || num_buffers_ > 5)
125 return false; 125 return false;
126 // Open the device. We'll be getting callback in WaveCallback function. 126 // Open the device. We'll be getting callback in WaveCallback function.
127 // They occur in a magic, time-critical thread that windows creates. 127 // They occur in a magic, time-critical thread that windows creates.
128 MMRESULT result = ::waveOutOpen(&waveout_, device_id_, 128 MMRESULT result = ::waveOutOpen(&waveout_, device_id_,
129 reinterpret_cast<LPCWAVEFORMATEX>(&format_), 129 reinterpret_cast<LPCWAVEFORMATEX>(&format_),
130 reinterpret_cast<DWORD_PTR>(WaveCallback), 130 reinterpret_cast<DWORD_PTR>(WaveCallback),
131 reinterpret_cast<DWORD_PTR>(this), 131 reinterpret_cast<DWORD_PTR>(this),
132 CALLBACK_FUNCTION); 132 CALLBACK_FUNCTION);
133 if (result != MMSYSERR_NOERROR) 133 if (result != MMSYSERR_NOERROR)
134 return false; 134 return false;
135 // If we don't have a packet size we use 100ms.
136 if (!buffer_size)
137 buffer_size = format_.Format.nAvgBytesPerSec / 10;
138 135
139 SetupBuffers(buffer_size); 136 SetupBuffers();
140 buffer_size_ = buffer_size;
141 state_ = PCMA_READY; 137 state_ = PCMA_READY;
142 return true; 138 return true;
143 } 139 }
144 140
145 void PCMWaveOutAudioOutputStream::SetupBuffers(uint32 rq_size) { 141 void PCMWaveOutAudioOutputStream::SetupBuffers() {
146 WAVEHDR* last = NULL; 142 WAVEHDR* last = NULL;
147 WAVEHDR* first = NULL; 143 WAVEHDR* first = NULL;
148 for (int ix = 0; ix != num_buffers_; ++ix) { 144 for (int ix = 0; ix != num_buffers_; ++ix) {
149 uint32 sz = sizeof(WAVEHDR) + rq_size; 145 uint32 sz = sizeof(WAVEHDR) + buffer_size_;
150 buffer_ = reinterpret_cast<WAVEHDR*>(new char[sz]); 146 buffer_ = reinterpret_cast<WAVEHDR*>(new char[sz]);
151 buffer_->lpData = reinterpret_cast<char*>(buffer_) + sizeof(WAVEHDR); 147 buffer_->lpData = reinterpret_cast<char*>(buffer_) + sizeof(WAVEHDR);
152 buffer_->dwBufferLength = rq_size; 148 buffer_->dwBufferLength = buffer_size_;
153 buffer_->dwBytesRecorded = 0; 149 buffer_->dwBytesRecorded = 0;
154 buffer_->dwUser = reinterpret_cast<DWORD_PTR>(last); 150 buffer_->dwUser = reinterpret_cast<DWORD_PTR>(last);
155 buffer_->dwFlags = WHDR_DONE; 151 buffer_->dwFlags = WHDR_DONE;
156 buffer_->dwLoops = 0; 152 buffer_->dwLoops = 0;
157 if (ix == 0) 153 if (ix == 0)
158 first = buffer_; 154 first = buffer_;
159 last = buffer_; 155 last = buffer_;
160 // Tell windows sound drivers about our buffers. Not documented what 156 // Tell windows sound drivers about our buffers. Not documented what
161 // this does but we can guess that causes the OS to keep a reference to 157 // this does but we can guess that causes the OS to keep a reference to
162 // the memory pages so the driver can use them without worries. 158 // the memory pages so the driver can use them without worries.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 HandleError(::GetLastError()); 224 HandleError(::GetLastError());
229 return; 225 return;
230 } 226 }
231 state_ = PCMA_STOPPED; 227 state_ = PCMA_STOPPED;
232 MMRESULT res = ::waveOutReset(waveout_); 228 MMRESULT res = ::waveOutReset(waveout_);
233 if (res != MMSYSERR_NOERROR) { 229 if (res != MMSYSERR_NOERROR) {
234 state_ = PCMA_PLAYING; 230 state_ = PCMA_PLAYING;
235 HandleError(res); 231 HandleError(res);
236 return; 232 return;
237 } 233 }
234
235 // Don't use callback after Stop().
236 callback_ = NULL;
237
238 state_ = PCMA_READY; 238 state_ = PCMA_READY;
239 } 239 }
240 240
241 // We can Close in any state except that trying to close a stream that is 241 // We can Close in any state except that trying to close a stream that is
242 // playing Windows generates an error, which we propagate to the source. 242 // playing Windows generates an error, which we propagate to the source.
243 void PCMWaveOutAudioOutputStream::Close() { 243 void PCMWaveOutAudioOutputStream::Close() {
244 if (waveout_) { 244 if (waveout_) {
245 // waveOutClose generates a callback with WOM_CLOSE id in the same thread. 245 // waveOutClose generates a callback with WOM_CLOSE id in the same thread.
246 MMRESULT res = ::waveOutClose(waveout_); 246 MMRESULT res = ::waveOutClose(waveout_);
247 if (res != MMSYSERR_NOERROR) { 247 if (res != MMSYSERR_NOERROR) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 obj->QueueNextPacket(buffer); 340 obj->QueueNextPacket(buffer);
341 341
342 // Time to send the buffer to the audio driver. Since we are reusing 342 // Time to send the buffer to the audio driver. Since we are reusing
343 // the same buffers we can get away without calling waveOutPrepareHeader. 343 // the same buffers we can get away without calling waveOutPrepareHeader.
344 MMRESULT result = ::waveOutWrite(hwo, buffer, sizeof(WAVEHDR)); 344 MMRESULT result = ::waveOutWrite(hwo, buffer, sizeof(WAVEHDR));
345 if (result != MMSYSERR_NOERROR) 345 if (result != MMSYSERR_NOERROR)
346 obj->HandleError(result); 346 obj->HandleError(result);
347 347
348 obj->pending_bytes_ += buffer->dwBufferLength; 348 obj->pending_bytes_ += buffer->dwBufferLength;
349 349
350 } else if (msg == WOM_CLOSE) {
351 // We can be closed before calling Start, so it is possible to have a
352 // null callback at this point.
353 if (obj->callback_)
354 obj->callback_->OnClose(obj);
355 } 350 }
356 } 351 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698