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

Side by Side Diff: media/audio/mac/audio_output_mac.cc

Issue 194112: Fixing audio in mac (Closed)
Patch Set: Created 11 years, 3 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
« no previous file with comments | « media/audio/mac/audio_output_mac.h ('k') | media/audio/mac/audio_output_mac_unittest.cc » ('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) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/mac/audio_manager_mac.h" 5 #include "media/audio/mac/audio_manager_mac.h"
6 #include "media/audio/mac/audio_output_mac.h" 6 #include "media/audio/mac/audio_output_mac.h"
7 7
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 10
(...skipping 19 matching lines...) Expand all
30 kAudioQueueErr_EnqueueDuringReset = -66632 30 kAudioQueueErr_EnqueueDuringReset = -66632
31 }; 31 };
32 32
33 PCMQueueOutAudioOutputStream::PCMQueueOutAudioOutputStream( 33 PCMQueueOutAudioOutputStream::PCMQueueOutAudioOutputStream(
34 AudioManagerMac* manager, int channels, int sampling_rate, 34 AudioManagerMac* manager, int channels, int sampling_rate,
35 char bits_per_sample) 35 char bits_per_sample)
36 : format_(), 36 : format_(),
37 audio_queue_(NULL), 37 audio_queue_(NULL),
38 buffer_(), 38 buffer_(),
39 source_(NULL), 39 source_(NULL),
40 manager_(manager) { 40 manager_(manager),
41 silence_bytes_(0),
42 pending_bytes_(0) {
41 // We must have a manager. 43 // We must have a manager.
42 DCHECK(manager_); 44 DCHECK(manager_);
43 // A frame is one sample across all channels. In interleaved audio the per 45 // A frame is one sample across all channels. In interleaved audio the per
44 // frame fields identify the set of n |channels|. In uncompressed audio, a 46 // frame fields identify the set of n |channels|. In uncompressed audio, a
45 // packet is always one frame. 47 // packet is always one frame.
46 format_.mSampleRate = sampling_rate; 48 format_.mSampleRate = sampling_rate;
47 format_.mFormatID = kAudioFormatLinearPCM; 49 format_.mFormatID = kAudioFormatLinearPCM;
48 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | 50 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked |
49 kLinearPCMFormatFlagIsSignedInteger; 51 kLinearPCMFormatFlagIsSignedInteger;
50 format_.mBitsPerChannel = bits_per_sample; 52 format_.mBitsPerChannel = bits_per_sample;
51 format_.mChannelsPerFrame = channels; 53 format_.mChannelsPerFrame = channels;
52 format_.mFramesPerPacket = 1; 54 format_.mFramesPerPacket = 1;
53 format_.mBytesPerPacket = (format_.mBitsPerChannel * channels) / 8; 55 format_.mBytesPerPacket = (format_.mBitsPerChannel * channels) / 8;
54 format_.mBytesPerFrame = format_.mBytesPerPacket; 56 format_.mBytesPerFrame = format_.mBytesPerPacket;
57
58 // Silence buffer has a duration of 6ms to simulate the behavior of Windows.
59 // This value is choosen by experiments and macs cannot keep up with
60 // anything less than 6ms.
61 silence_bytes_ = format_.mBytesPerFrame * sampling_rate * 6 / 1000;
55 } 62 }
56 63
57 PCMQueueOutAudioOutputStream::~PCMQueueOutAudioOutputStream() { 64 PCMQueueOutAudioOutputStream::~PCMQueueOutAudioOutputStream() {
58 } 65 }
59 66
60 void PCMQueueOutAudioOutputStream::HandleError(OSStatus err) { 67 void PCMQueueOutAudioOutputStream::HandleError(OSStatus err) {
61 // source_ can be set to NULL from another thread. We need to cache its 68 // source_ can be set to NULL from another thread. We need to cache its
62 // pointer while we operate here. Note that does not mean that the source 69 // pointer while we operate here. Note that does not mean that the source
63 // has been destroyed. 70 // has been destroyed.
64 AudioSourceCallback* source = source_; 71 AudioSourceCallback* source = source_;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this, 159 void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this,
153 AudioQueueRef queue, 160 AudioQueueRef queue,
154 AudioQueueBufferRef buffer) { 161 AudioQueueBufferRef buffer) {
155 PCMQueueOutAudioOutputStream* audio_stream = 162 PCMQueueOutAudioOutputStream* audio_stream =
156 static_cast<PCMQueueOutAudioOutputStream*>(p_this); 163 static_cast<PCMQueueOutAudioOutputStream*>(p_this);
157 // Call the audio source to fill the free buffer with data. Not having a 164 // Call the audio source to fill the free buffer with data. Not having a
158 // source means that the queue has been closed. This is not an error. 165 // source means that the queue has been closed. This is not an error.
159 AudioSourceCallback* source = audio_stream->source_; 166 AudioSourceCallback* source = audio_stream->source_;
160 if (!source) 167 if (!source)
161 return; 168 return;
169
170 // Adjust the number of pending bytes by subtracting the amount played.
171 audio_stream->pending_bytes_ -= buffer->mAudioDataByteSize;
162 size_t capacity = buffer->mAudioDataBytesCapacity; 172 size_t capacity = buffer->mAudioDataBytesCapacity;
163 // TODO(hclam): Provide pending bytes.
164 size_t filled = source->OnMoreData(audio_stream, buffer->mAudioData, 173 size_t filled = source->OnMoreData(audio_stream, buffer->mAudioData,
165 capacity, 0); 174 capacity, audio_stream->pending_bytes_);
175
176 // In order to keep the callback running, we need to provide a positive amount
177 // of data to the audio queue. To simulate the behavior of Windows, we write
178 // a buffer of silence.
179 if (!filled) {
180 CHECK(audio_stream->silence_bytes_ <= static_cast<int>(capacity));
181 filled = audio_stream->silence_bytes_;
182 memset(buffer->mAudioData, 0, filled);
183 }
184
cpu_(ooo_6.6-7.5) 2009/09/16 18:06:26 Won't it be much easier we just simply don't call
Alpha Left Google 2009/09/16 18:25:34 AudioQueue works as a circular buffer, if we don't
166 if (filled > capacity) { 185 if (filled > capacity) {
167 // User probably overran our buffer. 186 // User probably overran our buffer.
168 audio_stream->HandleError(0); 187 audio_stream->HandleError(0);
169 return; 188 return;
170 } 189 }
171 buffer->mAudioDataByteSize = filled; 190 buffer->mAudioDataByteSize = filled;
191 // Incremnet bytes by amount filled into audio buffer.
192 audio_stream->pending_bytes_ += filled;
172 if (NULL == queue) 193 if (NULL == queue)
173 return; 194 return;
174 // Queue the audio data to the audio driver. 195 // Queue the audio data to the audio driver.
175 OSStatus err = AudioQueueEnqueueBuffer(queue, buffer, 0, NULL); 196 OSStatus err = AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
176 if (err != noErr) { 197 if (err != noErr) {
177 if (err == kAudioQueueErr_EnqueueDuringReset) { 198 if (err == kAudioQueueErr_EnqueueDuringReset) {
178 // This is the error you get if you try to enqueue a buffer and the 199 // This is the error you get if you try to enqueue a buffer and the
179 // queue has been closed. Not really a problem if indeed the queue 200 // queue has been closed. Not really a problem if indeed the queue
180 // has been closed. 201 // has been closed.
181 if (!audio_stream->source_) 202 if (!audio_stream->source_)
182 return; 203 return;
183 } 204 }
184 audio_stream->HandleError(err); 205 audio_stream->HandleError(err);
185 } 206 }
186 } 207 }
187 208
188 void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) { 209 void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) {
189 DCHECK(callback); 210 DCHECK(callback);
190 OSStatus err = AudioQueueStart(audio_queue_, NULL); 211 OSStatus err = noErr;
191 if (err != noErr) {
192 HandleError(err);
193 return;
194 }
195 source_ = callback; 212 source_ = callback;
213 pending_bytes_ = 0;
196 // Ask the source to pre-fill all our buffers before playing. 214 // Ask the source to pre-fill all our buffers before playing.
197 for(size_t ix = 0; ix != kNumBuffers; ++ix) { 215 for(size_t ix = 0; ix != kNumBuffers; ++ix) {
216 buffer_[ix]->mAudioDataByteSize = 0;
198 RenderCallback(this, NULL, buffer_[ix]); 217 RenderCallback(this, NULL, buffer_[ix]);
199 } 218 }
200 // Queue the buffers to the audio driver, sounds starts now. 219 // Queue the buffers to the audio driver, sounds starts now.
201 for(size_t ix = 0; ix != kNumBuffers; ++ix) { 220 for(size_t ix = 0; ix != kNumBuffers; ++ix) {
202 err = AudioQueueEnqueueBuffer(audio_queue_, buffer_[ix], 0, NULL); 221 err = AudioQueueEnqueueBuffer(audio_queue_, buffer_[ix], 0, NULL);
203 if (err != noErr) { 222 if (err != noErr) {
204 HandleError(err); 223 HandleError(err);
205 return; 224 return;
206 } 225 }
207 } 226 }
227 err = AudioQueueStart(audio_queue_, NULL);
228 if (err != noErr) {
229 HandleError(err);
230 return;
231 }
208 } 232 }
209 233
OLDNEW
« no previous file with comments | « media/audio/mac/audio_output_mac.h ('k') | media/audio/mac/audio_output_mac_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698