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

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
« no previous file with comments | « media/audio/win/waveout_output_win.h ('k') | media/base/limits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.GetPacketSize()),
91 volume_(1), 91 volume_(1),
92 channels_(params.channels), 92 channels_(params.channels),
93 pending_bytes_(0) { 93 pending_bytes_(0) {
94
94 format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 95 format_.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
95 format_.Format.nChannels = params.channels; 96 format_.Format.nChannels = params.channels;
96 format_.Format.nSamplesPerSec = params.sample_rate; 97 format_.Format.nSamplesPerSec = params.sample_rate;
97 format_.Format.wBitsPerSample = params.bits_per_sample; 98 format_.Format.wBitsPerSample = params.bits_per_sample;
98 format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX); 99 format_.Format.cbSize = sizeof(format_) - sizeof(WAVEFORMATEX);
99 // The next are computed from above. 100 // The next are computed from above.
100 format_.Format.nBlockAlign = (format_.Format.nChannels * 101 format_.Format.nBlockAlign = (format_.Format.nChannels *
101 format_.Format.wBitsPerSample) / 8; 102 format_.Format.wBitsPerSample) / 8;
102 format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign * 103 format_.Format.nAvgBytesPerSec = format_.Format.nBlockAlign *
103 format_.Format.nSamplesPerSec; 104 format_.Format.nSamplesPerSec;
104 if (params.channels > kMaxChannelsToMask) { 105 if (params.channels > kMaxChannelsToMask) {
105 format_.dwChannelMask = kChannelsToMask[kMaxChannelsToMask]; 106 format_.dwChannelMask = kChannelsToMask[kMaxChannelsToMask];
106 } else { 107 } else {
107 format_.dwChannelMask = kChannelsToMask[params.channels]; 108 format_.dwChannelMask = kChannelsToMask[params.channels];
108 } 109 }
109 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 110 format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
110 format_.Samples.wValidBitsPerSample = params.bits_per_sample; 111 format_.Samples.wValidBitsPerSample = params.bits_per_sample;
111 // The event is auto-reset. 112 // The event is auto-reset.
112 stopped_event_.Set(::CreateEventW(NULL, FALSE, FALSE, NULL)); 113 stopped_event_.Set(::CreateEventW(NULL, FALSE, FALSE, NULL));
113 } 114 }
114 115
115 PCMWaveOutAudioOutputStream::~PCMWaveOutAudioOutputStream() { 116 PCMWaveOutAudioOutputStream::~PCMWaveOutAudioOutputStream() {
116 DCHECK(NULL == waveout_); 117 DCHECK(NULL == waveout_);
117 } 118 }
118 119
119 bool PCMWaveOutAudioOutputStream::Open(uint32 buffer_size) { 120 bool PCMWaveOutAudioOutputStream::Open() {
120 if (state_ != PCMA_BRAND_NEW) 121 if (state_ != PCMA_BRAND_NEW)
121 return false; 122 return false;
122 if (buffer_size > kMaxOpenBufferSize)
123 return false;
124 if (num_buffers_ < 2 || num_buffers_ > 5) 123 if (num_buffers_ < 2 || num_buffers_ > 5)
125 return false; 124 return false;
126 // Open the device. We'll be getting callback in WaveCallback function. 125 // Open the device. We'll be getting callback in WaveCallback function.
127 // They occur in a magic, time-critical thread that windows creates. 126 // They occur in a magic, time-critical thread that windows creates.
128 MMRESULT result = ::waveOutOpen(&waveout_, device_id_, 127 MMRESULT result = ::waveOutOpen(&waveout_, device_id_,
129 reinterpret_cast<LPCWAVEFORMATEX>(&format_), 128 reinterpret_cast<LPCWAVEFORMATEX>(&format_),
130 reinterpret_cast<DWORD_PTR>(WaveCallback), 129 reinterpret_cast<DWORD_PTR>(WaveCallback),
131 reinterpret_cast<DWORD_PTR>(this), 130 reinterpret_cast<DWORD_PTR>(this),
132 CALLBACK_FUNCTION); 131 CALLBACK_FUNCTION);
133 if (result != MMSYSERR_NOERROR) 132 if (result != MMSYSERR_NOERROR)
134 return false; 133 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 134
139 SetupBuffers(buffer_size); 135 SetupBuffers();
140 buffer_size_ = buffer_size;
141 state_ = PCMA_READY; 136 state_ = PCMA_READY;
142 return true; 137 return true;
143 } 138 }
144 139
145 void PCMWaveOutAudioOutputStream::SetupBuffers(uint32 rq_size) { 140 void PCMWaveOutAudioOutputStream::SetupBuffers() {
146 WAVEHDR* last = NULL; 141 WAVEHDR* last = NULL;
147 WAVEHDR* first = NULL; 142 WAVEHDR* first = NULL;
148 for (int ix = 0; ix != num_buffers_; ++ix) { 143 for (int ix = 0; ix != num_buffers_; ++ix) {
149 uint32 sz = sizeof(WAVEHDR) + rq_size; 144 uint32 sz = sizeof(WAVEHDR) + buffer_size_;
150 buffer_ = reinterpret_cast<WAVEHDR*>(new char[sz]); 145 buffer_ = reinterpret_cast<WAVEHDR*>(new char[sz]);
151 buffer_->lpData = reinterpret_cast<char*>(buffer_) + sizeof(WAVEHDR); 146 buffer_->lpData = reinterpret_cast<char*>(buffer_) + sizeof(WAVEHDR);
152 buffer_->dwBufferLength = rq_size; 147 buffer_->dwBufferLength = buffer_size_;
153 buffer_->dwBytesRecorded = 0; 148 buffer_->dwBytesRecorded = 0;
154 buffer_->dwUser = reinterpret_cast<DWORD_PTR>(last); 149 buffer_->dwUser = reinterpret_cast<DWORD_PTR>(last);
155 buffer_->dwFlags = WHDR_DONE; 150 buffer_->dwFlags = WHDR_DONE;
156 buffer_->dwLoops = 0; 151 buffer_->dwLoops = 0;
157 if (ix == 0) 152 if (ix == 0)
158 first = buffer_; 153 first = buffer_;
159 last = buffer_; 154 last = buffer_;
160 // Tell windows sound drivers about our buffers. Not documented what 155 // 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 156 // 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. 157 // 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()); 223 HandleError(::GetLastError());
229 return; 224 return;
230 } 225 }
231 state_ = PCMA_STOPPED; 226 state_ = PCMA_STOPPED;
232 MMRESULT res = ::waveOutReset(waveout_); 227 MMRESULT res = ::waveOutReset(waveout_);
233 if (res != MMSYSERR_NOERROR) { 228 if (res != MMSYSERR_NOERROR) {
234 state_ = PCMA_PLAYING; 229 state_ = PCMA_PLAYING;
235 HandleError(res); 230 HandleError(res);
236 return; 231 return;
237 } 232 }
233
234 // Don't use callback after Stop().
235 callback_ = NULL;
236
238 state_ = PCMA_READY; 237 state_ = PCMA_READY;
239 } 238 }
240 239
241 // We can Close in any state except that trying to close a stream that is 240 // 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. 241 // playing Windows generates an error, which we propagate to the source.
243 void PCMWaveOutAudioOutputStream::Close() { 242 void PCMWaveOutAudioOutputStream::Close() {
244 if (waveout_) { 243 if (waveout_) {
245 // waveOutClose generates a callback with WOM_CLOSE id in the same thread. 244 // waveOutClose generates a callback with WOM_CLOSE id in the same thread.
246 MMRESULT res = ::waveOutClose(waveout_); 245 MMRESULT res = ::waveOutClose(waveout_);
247 if (res != MMSYSERR_NOERROR) { 246 if (res != MMSYSERR_NOERROR) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 obj->QueueNextPacket(buffer); 339 obj->QueueNextPacket(buffer);
341 340
342 // Time to send the buffer to the audio driver. Since we are reusing 341 // Time to send the buffer to the audio driver. Since we are reusing
343 // the same buffers we can get away without calling waveOutPrepareHeader. 342 // the same buffers we can get away without calling waveOutPrepareHeader.
344 MMRESULT result = ::waveOutWrite(hwo, buffer, sizeof(WAVEHDR)); 343 MMRESULT result = ::waveOutWrite(hwo, buffer, sizeof(WAVEHDR));
345 if (result != MMSYSERR_NOERROR) 344 if (result != MMSYSERR_NOERROR)
346 obj->HandleError(result); 345 obj->HandleError(result);
347 346
348 obj->pending_bytes_ += buffer->dwBufferLength; 347 obj->pending_bytes_ += buffer->dwBufferLength;
349 348
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 } 349 }
356 } 350 }
OLDNEW
« no previous file with comments | « media/audio/win/waveout_output_win.h ('k') | media/base/limits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698