Commit 01951465 authored by Felix Paul Kühne's avatar Felix Paul Kühne

AudioQueue: re-written to make use of the 2.1 aout API

TimeGet is left as an exercise for tomorrow
parent 727dbceb
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright (C) 2010 VideoLAN and AUTHORS * Copyright (C) 2010 VideoLAN and AUTHORS
* *
* Authors: Romain Goyet <romain.goyet@likid.org> * Authors: Romain Goyet <romain.goyet@likid.org>
* Felix Paul Kühne <fkuehne@videolan.org>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -23,8 +24,6 @@ ...@@ -23,8 +24,6 @@
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
#include <unistd.h> /* write(), close() */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
...@@ -35,7 +34,6 @@ ...@@ -35,7 +34,6 @@
#include <AudioToolBox/AudioToolBox.h> #include <AudioToolBox/AudioToolBox.h>
#define NUMBER_OF_BUFFERS 3
#define FRAME_SIZE 2048 #define FRAME_SIZE 2048
/***************************************************************************** /*****************************************************************************
...@@ -46,10 +44,7 @@ ...@@ -46,10 +44,7 @@
*****************************************************************************/ *****************************************************************************/
struct aout_sys_t struct aout_sys_t
{ {
aout_packet_t packet;
AudioQueueRef audioQueue; AudioQueueRef audioQueue;
float soft_gain;
bool soft_mute;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -57,32 +52,32 @@ struct aout_sys_t ...@@ -57,32 +52,32 @@ struct aout_sys_t
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static void Play ( audio_output_t *, block_t *, mtime_t * ); static void Play ( audio_output_t *, block_t * );
static void Pause ( audio_output_t *p_aout, bool pause, mtime_t date );
static void Flush ( audio_output_t *p_aout, bool wait );
static int TimeGet ( audio_output_t *aout, mtime_t * );
static void AudioQueueCallback (void *, AudioQueueRef, AudioQueueBufferRef); static void AudioQueueCallback (void *, AudioQueueRef, AudioQueueBufferRef);
#include "volume.h"
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
vlc_module_begin () vlc_module_begin ()
set_shortname( "AudioQueue" ) set_shortname( "AudioQueue" )
set_description( N_("AudioQueue (iOS / Mac OS) audio output") ) set_description( N_("AudioQueue (iOS / Mac OS) audio output") )
set_capability( "audio output", 40 ) set_capability( "audio output", 40 )
set_category( CAT_AUDIO ) set_category( CAT_AUDIO )
set_subcategory( SUBCAT_AUDIO_AOUT ) set_subcategory( SUBCAT_AUDIO_AOUT )
add_shortcut( "audioqueue" ) add_shortcut( "audioqueue" )
set_callbacks( Open, Close ) set_callbacks( Open, Close )
vlc_module_end () vlc_module_end ()
/***************************************************************************** /*****************************************************************************
* Open: open the audio device * Start: open the audio device
*****************************************************************************/ *****************************************************************************/
static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt ) static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
OSStatus status = 0; OSStatus status = 0;
// Setup the audio device. // Setup the audio device.
...@@ -100,97 +95,114 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt ) ...@@ -100,97 +95,114 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
// Create a new output AudioQueue for the device. // Create a new output AudioQueue for the device.
status = AudioQueueNewOutput(&deviceFormat, // Format status = AudioQueueNewOutput(&deviceFormat, // Format
AudioQueueCallback, // Callback AudioQueueCallback, // Callback
p_aout, // User data, passed to the callback NULL, // User data, passed to the callback
CFRunLoopGetMain(), // RunLoop CFRunLoopGetMain(), // RunLoop
kCFRunLoopDefaultMode, // RunLoop mode kCFRunLoopDefaultMode, // RunLoop mode
0, // Flags ; must be zero (per documentation)... 0, // Flags ; must be zero (per documentation)...
&(p_sys->audioQueue)); // Output &(p_sys->audioQueue)); // Output
// This will be used for boosting the audio without the need of a mixer (floating-point conversion is expensive on ARM) msg_Dbg(p_aout, "New AudioQueue output created (status = %i)", status);
// AudioQueueSetParameter(p_sys->audioQueue, kAudioQueueParam_Volume, 12.0); // Defaults to 1.0 if (status != noErr)
return VLC_EGENERIC;
msg_Dbg(p_aout, "New AudioQueue output created (status = %li)", status);
// Allocate buffers for the AudioQueue, and pre-fill them.
for (int i = 0; i < NUMBER_OF_BUFFERS; ++i) {
AudioQueueBufferRef buffer = NULL;
status = AudioQueueAllocateBuffer(p_sys->audioQueue, FRAME_SIZE * 4, &buffer);
AudioQueueCallback(NULL, p_sys->audioQueue, buffer);
}
fmt->i_format = VLC_CODEC_S16L; fmt->i_format = VLC_CODEC_S16L;
fmt->i_physical_channels = AOUT_CHANS_STEREO; fmt->i_physical_channels = AOUT_CHANS_STEREO;
fmt->i_rate = 44100; fmt->i_rate = 44100;
aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE, fmt); aout_FormatPrepare(fmt);
p_aout->time_get = aout_PacketTimeGet;
p_aout->play = aout_PacketPlay;
p_aout->pause = NULL;
p_aout->flush = aout_PacketFlush;
aout_SoftVolumeStart(p_aout);
msg_Dbg(p_aout, "Starting AudioQueue (status = %li)", status);
status = AudioQueueStart(p_sys->audioQueue, NULL); status = AudioQueueStart(p_sys->audioQueue, NULL);
msg_Dbg(p_aout, "Starting AudioQueue (status = %i)", status);
p_aout->time_get = TimeGet;
p_aout->play = Play;
p_aout->pause = Pause;
p_aout->flush = Flush;
if (status != noErr)
return VLC_EGENERIC;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* aout_FifoPop : get the next buffer out of the FIFO * Stop: close the audio device
*****************************************************************************/ *****************************************************************************/
static block_t *aout_FifoPop2( aout_fifo_t * p_fifo )
{
block_t *p_buffer = p_fifo->p_first;
if( p_buffer != NULL )
{
p_fifo->p_first = p_buffer->p_next;
if( p_fifo->p_first == NULL )
p_fifo->pp_last = &p_fifo->p_first;
}
return p_buffer;
}
/*****************************************************************************
* Close: close the audio device
*****************************************************************************/
static void Stop ( audio_output_t *p_aout ) static void Stop ( audio_output_t *p_aout )
{ {
struct aout_sys_t * p_sys = p_aout->sys; struct aout_sys_t * p_sys = p_aout->sys;
msg_Dbg(p_aout, "Stopping AudioQueue"); msg_Dbg(p_aout, "Stopping AudioQueue");
AudioQueueStop(p_sys->audioQueue, false); AudioQueueStop(p_sys->audioQueue, false);
msg_Dbg(p_aout, "Disposing of AudioQueue"); msg_Dbg(p_aout, "Disposing AudioQueue");
AudioQueueDispose(p_sys->audioQueue, false); AudioQueueDispose(p_sys->audioQueue, false);
aout_PacketDestroy(p_aout);
} }
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { /*****************************************************************************
audio_output_t * p_aout = (audio_output_t *)inUserData; * actual playback
block_t * p_buffer = NULL; *****************************************************************************/
if (p_aout) {
struct aout_sys_t * p_sys = p_aout->sys;
aout_packet_t * packet = &p_sys->packet;
if (packet) static void Play (audio_output_t *p_aout, block_t *p_block)
{ {
vlc_mutex_lock( &packet->lock ); if ( p_block != NULL ) {
p_buffer = aout_FifoPop2( &packet->fifo ); AudioQueueBufferRef inBuffer = NULL;
vlc_mutex_unlock( &packet->lock ); OSStatus status;
}
status = AudioQueueAllocateBuffer(p_aout->sys->audioQueue, FRAME_SIZE * 2, &inBuffer);
if (status != noErr) {
msg_Err( p_aout, "buffer alloction failed (%i)", status);
return;
} }
if ( p_buffer != NULL ) { memcpy( inBuffer->mAudioData, p_block->p_buffer, p_block->i_buffer );
memcpy( inBuffer->mAudioData, p_buffer->p_buffer, p_buffer->i_buffer ); inBuffer->mAudioDataByteSize = p_block->i_buffer;
inBuffer->mAudioDataByteSize = p_buffer->i_buffer; block_Release( p_block );
block_Release( p_buffer );
} else { status = AudioQueueEnqueueBuffer(p_aout->sys->audioQueue, inBuffer, 0, NULL);
memset( inBuffer->mAudioData, 0, inBuffer->mAudioDataBytesCapacity ); if (status != noErr)
inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity; msg_Err( p_aout, "enqueuing buffer failed (%i)", status);
} }
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
} }
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
/* this function does nothing, but needs to be here to make the AudioQueue API happy.
* without a callback, it will refuse to create an AudioQueue instance. */
VLC_UNUSED(inUserData);
VLC_UNUSED(inAQ);
VLC_UNUSED(inBuffer);
}
static void Pause (audio_output_t *p_aout, bool pause, mtime_t date)
{
VLC_UNUSED( date );
if (pause)
AudioQueuePause( p_aout->sys->audioQueue );
else
AudioQueueStart( p_aout->sys->audioQueue, NULL );
}
static void Flush (audio_output_t *p_aout, bool wait)
{
VLC_UNUSED( wait );
AudioQueueFlush( p_aout->sys->audioQueue );
}
static int TimeGet (audio_output_t *p_aout, mtime_t *restrict delay)
{
// TODO
VLC_UNUSED( p_aout );
VLC_UNUSED( delay );
return -1;
}
/*****************************************************************************
* Module management
*****************************************************************************/
static int Open(vlc_object_t *obj) static int Open(vlc_object_t *obj)
{ {
audio_output_t *aout = (audio_output_t *)obj; audio_output_t *aout = (audio_output_t *)obj;
...@@ -198,10 +210,12 @@ static int Open(vlc_object_t *obj) ...@@ -198,10 +210,12 @@ static int Open(vlc_object_t *obj)
if (unlikely(sys == NULL)) if (unlikely(sys == NULL))
return VLC_ENOMEM; return VLC_ENOMEM;
aout->sys = sys; aout->sys = sys;
aout->start = Start; aout->start = Start;
aout->stop = Stop; aout->stop = Stop;
aout_SoftVolumeInit(aout); aout->play = Play;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment