From 18f72b33afd451b25896ce527195c1a9ce468749 Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Mon, 3 Oct 2011 15:14:32 +1300 Subject: [PATCH] Bug 669556 - Calculate OS X sydneyaudio buffer sizes by time, and shrink buffers to 1000ms. Remove buffer refill wait from nsBuiltinDecoderStateMachine::AudioLoop as the buffer fullness estimation is inaccurate. r=cpearce --- .../media/nsBuiltinDecoderStateMachine.cpp | 18 ------- media/libsydneyaudio/src/sydney_audio_mac.c | 51 +++++++++++-------- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/content/media/nsBuiltinDecoderStateMachine.cpp b/content/media/nsBuiltinDecoderStateMachine.cpp index c2a0fc12d833..aef55f61e196 100644 --- a/content/media/nsBuiltinDecoderStateMachine.cpp +++ b/content/media/nsBuiltinDecoderStateMachine.cpp @@ -635,24 +635,6 @@ void nsBuiltinDecoderStateMachine::AudioLoop() NS_WARNING("Int overflow calculating audio end time"); break; } - - PRInt64 audioAhead = mAudioEndTime - GetMediaTime(); - if (audioAhead > AMPLE_AUDIO_USECS && - framesWritten > minWriteFrames) - { - // We've pushed enough audio onto the hardware that we've queued up a - // significant amount ahead of the playback position. The decode - // thread will be going to sleep, so we won't get any new audio - // anyway, so sleep until we need to push to the hardware again. - Wait(AMPLE_AUDIO_USECS / 2); - // Kick the decode thread; since above we only do a NotifyAll when - // we pop an audio chunk of the queue, the decoder won't wake up if - // we've got no more decoded chunks to push to the hardware. We can - // hit this condition if the last frame in the stream doesn't have - // it's EOS flag set, and the decode thread sleeps just after decoding - // that packet, but before realising there's no more packets. - mon.NotifyAll(); - } } } if (mReader->mAudioQueue.AtEndOfStream() && diff --git a/media/libsydneyaudio/src/sydney_audio_mac.c b/media/libsydneyaudio/src/sydney_audio_mac.c index 8d2c179915c2..7e93f3228eb4 100644 --- a/media/libsydneyaudio/src/sydney_audio_mac.c +++ b/media/libsydneyaudio/src/sydney_audio_mac.c @@ -82,15 +82,15 @@ struct sa_stream { sa_buf * bl_head; sa_buf * bl_tail; int n_bufs; + + size_t buffer_size; }; /* - * Use a default buffer size with enough room for one second of audio, - * assuming stereo data at 44.1kHz with 32 bits per channel, and impose - * a generous limit on the number of buffers. + * Allow up to a second of audio to be buffered. */ -#define BUF_SIZE (2 * 44100 * 4) +#define BUF_SIZE_MS 200 #define BUF_LIMIT 5 #if BUF_LIMIT < 2 @@ -101,7 +101,7 @@ struct sa_stream { static OSStatus audio_callback(void *arg, AudioUnitRenderActionFlags *action_flags, const AudioTimeStamp *time_stamp, UInt32 bus_num, UInt32 n_frames, AudioBufferList *data); -static sa_buf *new_buffer(void); +static sa_buf *new_buffer(size_t bufsz); /* @@ -143,15 +143,6 @@ sa_stream_create_pcm( if ((s = malloc(sizeof(sa_stream_t))) == NULL) { return SA_ERROR_OOM; } - if ((s->bl_head = new_buffer()) == NULL) { - free(s); - return SA_ERROR_OOM; - } - if (pthread_mutex_init(&s->mutex, NULL) != 0) { - free(s->bl_head); - free(s); - return SA_ERROR_SYSTEM; - } s->output_unit = NULL; s->playing = FALSE; @@ -160,9 +151,29 @@ sa_stream_create_pcm( s->rate = rate; s->n_channels = n_channels; s->bytes_per_ch = 2; + s->buffer_size = s->bytes_per_ch * + ((rate * n_channels * BUF_SIZE_MS) / 1000); + + /* round buffer_size up to ensure it's divisible by the number of bytes per frame. */ + if (s->buffer_size % (s->bytes_per_ch * n_channels) != 0) { + s->buffer_size += (s->bytes_per_ch * n_channels) - (s->buffer_size % (s->bytes_per_ch * n_channels)); + } + + if ((s->bl_head = new_buffer(s->buffer_size)) == NULL) { + free(s); + return SA_ERROR_OOM; + + } + s->bl_tail = s->bl_head; s->n_bufs = 1; + if (pthread_mutex_init(&s->mutex, NULL) != 0) { + free(s->bl_head); + free(s); + return SA_ERROR_SYSTEM; + } + *_s = s; return SA_SUCCESS; } @@ -367,7 +378,7 @@ sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) { if (!s->playing) { /* * We haven't even started playing yet! That means the - * BUF_SIZE/BUF_LIMIT values are too low... Not much we can + * BUF_SIZE_MS/BUF_LIMIT values are too low... Not much we can * do here; spinning won't help because the audio callback * hasn't been enabled yet. Oh well, error time. */ @@ -387,7 +398,7 @@ sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) { /* * Allocate a new tail buffer, and go 'round again to fill it up. */ - if ((s->bl_tail->next = new_buffer()) == NULL) { + if ((s->bl_tail->next = new_buffer(s->buffer_size)) == NULL) { result = SA_ERROR_OOM; break; } @@ -530,7 +541,7 @@ sa_stream_get_write_size(sa_stream_t *s, size_t *size) { * buffers represents the write space available before blocking. */ avail = s->bl_tail->size - s->bl_tail->end; - avail += (BUF_LIMIT - s->n_bufs) * BUF_SIZE; + avail += (BUF_LIMIT - s->n_bufs) * s->buffer_size; *size = avail; pthread_mutex_unlock(&s->mutex); @@ -602,10 +613,10 @@ sa_stream_resume(sa_stream_t *s) { static sa_buf * -new_buffer(void) { - sa_buf * b = malloc(sizeof(sa_buf) + BUF_SIZE); +new_buffer(size_t bufsz) { + sa_buf * b = malloc(sizeof(sa_buf) + bufsz); if (b != NULL) { - b->size = BUF_SIZE; + b->size = bufsz; b->start = 0; b->end = 0; b->next = NULL;