summaryrefslogtreecommitdiffstats
path: root/media/audio/mac/audio_output_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/audio/mac/audio_output_mac.cc')
-rw-r--r--media/audio/mac/audio_output_mac.cc40
1 files changed, 32 insertions, 8 deletions
diff --git a/media/audio/mac/audio_output_mac.cc b/media/audio/mac/audio_output_mac.cc
index f2446b4..7799f159 100644
--- a/media/audio/mac/audio_output_mac.cc
+++ b/media/audio/mac/audio_output_mac.cc
@@ -39,7 +39,9 @@ PCMQueueOutAudioOutputStream::PCMQueueOutAudioOutputStream(
audio_queue_(NULL),
buffer_(),
source_(NULL),
- manager_(manager) {
+ manager_(manager),
+ silence_bytes_(0),
+ pending_bytes_(0) {
// We must have a manager.
DCHECK(manager_);
// A frame is one sample across all channels. In interleaved audio the per
@@ -54,6 +56,11 @@ PCMQueueOutAudioOutputStream::PCMQueueOutAudioOutputStream(
format_.mFramesPerPacket = 1;
format_.mBytesPerPacket = (format_.mBitsPerChannel * channels) / 8;
format_.mBytesPerFrame = format_.mBytesPerPacket;
+
+ // Silence buffer has a duration of 6ms to simulate the behavior of Windows.
+ // This value is choosen by experiments and macs cannot keep up with
+ // anything less than 6ms.
+ silence_bytes_ = format_.mBytesPerFrame * sampling_rate * 6 / 1000;
}
PCMQueueOutAudioOutputStream::~PCMQueueOutAudioOutputStream() {
@@ -161,16 +168,30 @@ void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this,
AudioSourceCallback* source = audio_stream->source_;
if (!source)
return;
+
+ // Adjust the number of pending bytes by subtracting the amount played.
+ audio_stream->pending_bytes_ -= buffer->mAudioDataByteSize;
size_t capacity = buffer->mAudioDataBytesCapacity;
- // TODO(hclam): Provide pending bytes.
size_t filled = source->OnMoreData(audio_stream, buffer->mAudioData,
- capacity, 0);
+ capacity, audio_stream->pending_bytes_);
+
+ // In order to keep the callback running, we need to provide a positive amount
+ // of data to the audio queue. To simulate the behavior of Windows, we write
+ // a buffer of silence.
+ if (!filled) {
+ CHECK(audio_stream->silence_bytes_ <= static_cast<int>(capacity));
+ filled = audio_stream->silence_bytes_;
+ memset(buffer->mAudioData, 0, filled);
+ }
+
if (filled > capacity) {
// User probably overran our buffer.
audio_stream->HandleError(0);
return;
}
buffer->mAudioDataByteSize = filled;
+ // Incremnet bytes by amount filled into audio buffer.
+ audio_stream->pending_bytes_ += filled;
if (NULL == queue)
return;
// Queue the audio data to the audio driver.
@@ -189,14 +210,12 @@ void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this,
void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) {
DCHECK(callback);
- OSStatus err = AudioQueueStart(audio_queue_, NULL);
- if (err != noErr) {
- HandleError(err);
- return;
- }
+ OSStatus err = noErr;
source_ = callback;
+ pending_bytes_ = 0;
// Ask the source to pre-fill all our buffers before playing.
for(size_t ix = 0; ix != kNumBuffers; ++ix) {
+ buffer_[ix]->mAudioDataByteSize = 0;
RenderCallback(this, NULL, buffer_[ix]);
}
// Queue the buffers to the audio driver, sounds starts now.
@@ -207,5 +226,10 @@ void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) {
return;
}
}
+ err = AudioQueueStart(audio_queue_, NULL);
+ if (err != noErr) {
+ HandleError(err);
+ return;
+ }
}