Commit aa9ba2d5 authored by Romain Goyet's avatar Romain Goyet Committed by Jean-Baptiste Kempf

iOS: audio output module (Based on the AudioQueue API)

This audio output is still quite young, but works fine on existing iOS devices.
In theory this can also be used on Mac OS X as well, but for now it's not as powerful as the existing CoreAudio driver.
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent b2e1a820
......@@ -3588,6 +3588,17 @@ then
], [ AC_MSG_ERROR([cannot find CoreAudio headers]) ])
fi
dnl
dnl AudioQueue plugin
dnl
AC_ARG_ENABLE(audioqueue,
[ --enable-audioqueue AudioQueue audio module (default disabled)])
if test "${enable_audioqueue}" = "yes"
then
VLC_ADD_PLUGIN([audioqueue])
VLC_ADD_LDFLAGS([audioqueue], [-Wl,-framework,AudioToolbox,-framework,CoreFoundation])
fi
dnl
dnl Roku HD1000 audio
dnl
......
......@@ -8,6 +8,7 @@ SOURCES_portaudio = portaudio.c
SOURCES_auhal = auhal.c
SOURCES_jack = jack.c
SOURCES_pulse = pulse.c
SOURCES_audioqueue = audioqueue.c
libvlc_LTLIBRARIES += libaout_file_plugin.la
......
/*****************************************************************************
* audioqueue.c : AudioQueue audio output plugin for vlc
*****************************************************************************
* Copyright (C) 2010 VideoLAN and AUTHORS
*
* Authors: Romain Goyet <romain.goyet@likid.org>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <unistd.h> /* write(), close() */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <AudioToolBox/AudioToolBox.h>
#define FRAME_SIZE 2048
#define NUMBER_OF_BUFFERS 3
/*****************************************************************************
* aout_sys_t: AudioQueue audio output method descriptor
*****************************************************************************
* This structure is part of the audio output thread descriptor.
* It describes the specific properties of an audio device.
*****************************************************************************/
struct aout_sys_t
{
AudioQueueRef audioQueue;
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static void Play ( aout_instance_t * );
static void AudioQueueCallback (void *, AudioQueueRef, AudioQueueBufferRef);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin ()
set_shortname( "AudioQueue" )
set_description( N_("AudioQueue (iOS / Mac OS) audio output") )
set_capability( "audio output", 40 )
set_category( CAT_AUDIO )
set_subcategory( SUBCAT_AUDIO_AOUT )
add_shortcut( "audioqueue" )
set_callbacks( Open, Close )
vlc_module_end ()
/*****************************************************************************
* Open: open the audio device
*****************************************************************************/
static int Open ( vlc_object_t *p_this )
{
aout_instance_t *p_aout = (aout_instance_t *)p_this;
struct aout_sys_t *p_sys = malloc(sizeof(aout_sys_t));
p_aout->output.p_sys = p_sys;
OSStatus status = 0;
// Setup the audio device.
AudioStreamBasicDescription deviceFormat;
deviceFormat.mSampleRate = 44100;
deviceFormat.mFormatID = kAudioFormatLinearPCM;
deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; // Signed integer, little endian
deviceFormat.mBytesPerPacket = 4;
deviceFormat.mFramesPerPacket = 1;
deviceFormat.mBytesPerFrame = 4;
deviceFormat.mChannelsPerFrame = 2;
deviceFormat.mBitsPerChannel = 16;
deviceFormat.mReserved = 0;
// Create a new output AudioQueue for the device.
status = AudioQueueNewOutput(&deviceFormat, // Format
AudioQueueCallback, // Callback
p_aout, // User data, passed to the callback
CFRunLoopGetMain(), // RunLoop
kCFRunLoopDefaultMode, // RunLoop mode
0, // Flags ; must be zero (per documentation)...
&(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)
// AudioQueueSetParameter(p_sys->audioQueue, kAudioQueueParam_Volume, 12.0); // Defaults to 1.0
msg_Dbg(p_aout, "New AudioQueue output created (status = %ld)", 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);
}
/* Volume is entirely done in software. */
aout_VolumeSoftInit( p_aout );
p_aout->output.output.i_format = VLC_CODEC_S16L;
p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
p_aout->output.output.i_rate = 44100;
p_aout->output.i_nb_samples = FRAME_SIZE;
p_aout->output.pf_play = Play;
msg_Dbg(p_aout, "Starting AudioQueue (status = %ld)", status);
status = AudioQueueStart(p_sys->audioQueue, NULL);
return VLC_SUCCESS;
}
/*****************************************************************************
* Play: play a sound samples buffer
*****************************************************************************/
static void Play( aout_instance_t * p_aout )
{
VLC_UNUSED(p_aout);
}
/*****************************************************************************
* Close: close the audio device
*****************************************************************************/
static void Close ( vlc_object_t *p_this )
{
aout_instance_t *p_aout = (aout_instance_t *)p_this;
struct aout_sys_t * p_sys = p_aout->output.p_sys;
msg_Dbg(p_aout, "Stopping AudioQueue");
AudioQueueStop(p_sys->audioQueue, false);
msg_Dbg(p_aout, "Disposing of AudioQueue");
AudioQueueDispose(p_sys->audioQueue, false);
free (p_sys);
}
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
aout_instance_t * p_aout = (aout_instance_t *)inUserData;
aout_buffer_t * p_buffer = NULL;
if (p_aout) {
vlc_mutex_lock( &p_aout->output_fifo_lock );
p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
vlc_mutex_unlock( &p_aout->output_fifo_lock );
}
if ( p_buffer != NULL ) {
vlc_memcpy( inBuffer->mAudioData, p_buffer->p_buffer, p_buffer->i_buffer );
inBuffer->mAudioDataByteSize = p_buffer->i_buffer;
aout_BufferFree( p_buffer );
} else {
vlc_memset( inBuffer->mAudioData, 0, inBuffer->mAudioDataBytesCapacity );
inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
}
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}
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