summaryrefslogtreecommitdiffstats
path: root/audio/out
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2013-04-19 23:04:11 +0200
committerStefano Pigozzi <stefano.pigozzi@gmail.com>2013-06-16 18:20:38 +0200
commit680790617704b294476f27f265fd4041f06ae5a9 (patch)
tree5cedaf28d49618ecd54e9c32447416e3b372b7d1 /audio/out
parent74eb98279a7ed94804bad683fdbdad7abcad1835 (diff)
downloadmpv-680790617704b294476f27f265fd4041f06ae5a9.tar.bz2
mpv-680790617704b294476f27f265fd4041f06ae5a9.tar.xz
ao_coreaudio: move to new libao API
This is just a first pass and the bare minimum to make it compile and work. SPDIF is untested for lack of hardware.
Diffstat (limited to 'audio/out')
-rw-r--r--audio/out/ao_coreaudio.c649
1 files changed, 339 insertions, 310 deletions
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index 6389cbec6f..bd2bc34377 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -30,9 +30,6 @@
* simpler frameworks do. This is due to the fact that CoreAudio pulls
* audio samples rather than having them pushed at it (which is nice
* when you are wanting to do good buffering of audio).
- *
- * AC-3 and MPEG audio passthrough is possible, but has never been tested
- * due to lack of a soundcard that supports it.
*/
#include <CoreServices/CoreServices.h>
@@ -49,41 +46,25 @@
#include "core/mp_msg.h"
#include "ao.h"
-#include "audio_out_internal.h"
#include "audio/format.h"
#include "osdep/timer.h"
#include "libavutil/fifo.h"
#include "core/subopt-helper.h"
-static const ao_info_t info =
-{
- "Darwin/Mac OS X native audio output",
- "coreaudio",
- "Timothy J. Wood & Dan Christiansen & Chris Roccati",
- ""
-};
-
-LIBAO_EXTERN(coreaudio)
+#define ca_msg(a, b, c ...) mp_msg(a, b, "AO: [coreaudio] " c)
-/* Prefix for all mp_msg() calls */
-#define ao_msg(a, b, c ...) mp_msg(a, b, "AO: [coreaudio] " c)
+static void audio_pause(struct ao *ao);
+static void audio_resume(struct ao *ao);
+static void reset(struct ao *ao);
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1040
-/* AudioDeviceIOProcID does not exist in Mac OS X 10.4. We can emulate
- * this by using AudioDeviceAddIOProc() and AudioDeviceRemoveIOProc(). */
-#define AudioDeviceIOProcID AudioDeviceIOProc
-#define AudioDeviceDestroyIOProcID AudioDeviceRemoveIOProc
-static OSStatus AudioDeviceCreateIOProcID(AudioDeviceID dev,
- AudioDeviceIOProc proc,
- void *data,
- AudioDeviceIOProcID *procid)
-{
- *procid = proc;
- return AudioDeviceAddIOProc(dev, proc, data);
-}
-#endif
+struct ca_ringbuffer {
+ AVFifoBuffer *fifo;
+ int len;
+ int chunks;
+ int chunk_size;
+};
-typedef struct ao_coreaudio_s
+struct priv
{
AudioDeviceID i_selected_dev; /* Keeps DeviceID of the selected device. */
int b_supports_digital; /* Does the currently selected device support digital mode? */
@@ -109,79 +90,103 @@ typedef struct ao_coreaudio_s
int packetSize;
int paused;
- /* Ring-buffer */
- AVFifoBuffer *buffer;
- unsigned int buffer_len; ///< must always be num_chunks * chunk_size
- unsigned int num_chunks;
- unsigned int chunk_size;
-} ao_coreaudio_t;
+ struct ca_ringbuffer *buffer;
+};
-static ao_coreaudio_t *ao = NULL;
+static struct ca_ringbuffer *new_ca_ringbuffer(void *talloc_ctx, size_t chunks,
+ size_t chunk_size)
+{
+ struct ca_ringbuffer *buffer =
+ talloc_zero(talloc_ctx, struct ca_ringbuffer);
+
+ *buffer = (struct ca_ringbuffer) {
+ .fifo = av_fifo_alloc(chunks * chunk_size),
+ .len = chunks * chunk_size,
+ .chunks = chunks,
+ .chunk_size = chunk_size,
+ };
-/**
- * \brief add data to ringbuffer
- */
-static int write_buffer(unsigned char *data, int len)
+ return buffer;
+}
+
+static int ca_ringbuffer_buffered(struct ca_ringbuffer *buffer)
{
- int free = ao->buffer_len - av_fifo_size(ao->buffer);
- if (len > free)
- len = free;
- return av_fifo_generic_write(ao->buffer, data, len, NULL);
+ return av_fifo_size(buffer->fifo);
}
-/**
- * \brief remove data from ringbuffer
- */
-static int read_buffer(unsigned char *data, int len)
+static void ca_ringbuffer_reset(struct ca_ringbuffer *buffer)
+{
+ av_fifo_reset(buffer->fifo);
+}
+
+static int ca_ringbuffer_read(struct ca_ringbuffer *buffer,
+ unsigned char *data, int len)
{
- int buffered = av_fifo_size(ao->buffer);
+ int buffered = ca_ringbuffer_buffered(buffer);
if (len > buffered)
len = buffered;
if (data)
- av_fifo_generic_read(ao->buffer, data, len, NULL);
+ av_fifo_generic_read(buffer->fifo, data, len, NULL);
else
- av_fifo_drain(ao->buffer, len);
+ av_fifo_drain(buffer->fifo, len);
return len;
}
+static int ca_ringbuffer_write(struct ca_ringbuffer *buffer,
+ unsigned char *data, int len)
+{
+ int free = buffer->len - av_fifo_size(buffer->fifo);
+ if (len > free)
+ len = free;
+ return av_fifo_generic_write(buffer->fifo, data, len, NULL);
+}
+
static OSStatus theRenderProc(void *inRefCon,
AudioUnitRenderActionFlags *inActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber, UInt32 inNumFrames,
AudioBufferList *ioData)
{
- int amt = av_fifo_size(ao->buffer);
- int req = (inNumFrames) * ao->packetSize;
+ struct ao *ao = inRefCon;
+ struct priv *p = ao->priv;
- if (amt > req)
- amt = req;
+ int buffered = ca_ringbuffer_buffered(p->buffer);
+ int requested = inNumFrames * p->packetSize;
- if (amt)
- read_buffer((unsigned char *)ioData->mBuffers[0].mData, amt);
- else
- audio_pause();
- ioData->mBuffers[0].mDataByteSize = amt;
+ if (buffered > requested)
+ buffered = requested;
+
+ if (buffered) {
+ ca_ringbuffer_read(p->buffer,
+ (unsigned char *)ioData->mBuffers[0].mData,
+ buffered);
+ } else {
+ audio_pause(ao);
+ }
+
+ ioData->mBuffers[0].mDataByteSize = buffered;
return noErr;
}
-static int control(int cmd, void *arg)
+static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
+ struct priv *p = ao->priv;
ao_control_vol_t *control_vol;
OSStatus err;
Float32 vol;
switch (cmd) {
case AOCONTROL_GET_VOLUME:
control_vol = (ao_control_vol_t *)arg;
- if (ao->b_digital) {
+ if (p->b_digital) {
// Digital output has no volume adjust.
- int vol = ao->b_muted ? 0 : 100;
+ int vol = p->b_muted ? 0 : 100;
*control_vol = (ao_control_vol_t) {
.left = vol, .right = vol,
};
return CONTROL_TRUE;
}
- err = AudioUnitGetParameter(ao->theOutputUnit, kHALOutputParam_Volume,
+ err = AudioUnitGetParameter(p->theOutputUnit, kHALOutputParam_Volume,
kAudioUnitScope_Global, 0, &vol);
if (err == 0) {
@@ -189,7 +194,7 @@ static int control(int cmd, void *arg)
control_vol->left = control_vol->right = vol * 100.0 / 4.0;
return CONTROL_TRUE;
} else {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"could not get HAL output volume: [%4.4s]\n", (char *)&err);
return CONTROL_FALSE;
}
@@ -197,7 +202,7 @@ static int control(int cmd, void *arg)
case AOCONTROL_SET_VOLUME:
control_vol = (ao_control_vol_t *)arg;
- if (ao->b_digital) {
+ if (p->b_digital) {
// Digital output can not set volume. Here we have to return true
// to make mixer forget it. Else mixer will add a soft filter,
// that's not we expected and the filter not support ac3 stream
@@ -206,20 +211,20 @@ static int control(int cmd, void *arg)
// Although not support set volume, but at least we support mute.
// MPlayer set mute by set volume to zero, we handle it.
if (control_vol->left == 0 && control_vol->right == 0)
- ao->b_muted = 1;
+ p->b_muted = 1;
else
- ao->b_muted = 0;
+ p->b_muted = 0;
return CONTROL_TRUE;
}
vol = (control_vol->left + control_vol->right) * 4.0 / 200.0;
- err = AudioUnitSetParameter(ao->theOutputUnit, kHALOutputParam_Volume,
+ err = AudioUnitSetParameter(p->theOutputUnit, kHALOutputParam_Volume,
kAudioUnitScope_Global, 0, vol, 0);
if (err == 0) {
// printf("SET VOL=%f\n", vol);
return CONTROL_TRUE;
} else {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"could not set HAL output volume: [%4.4s]\n", (char *)&err);
return CONTROL_FALSE;
}
@@ -235,7 +240,7 @@ static void print_format(int lev, const char *str,
const AudioStreamBasicDescription *f)
{
uint32_t flags = (uint32_t) f->mFormatFlags;
- ao_msg(MSGT_AO, lev,
+ ca_msg(MSGT_AO, lev,
"%s %7.1fHz %" PRIu32 "bit [%c%c%c%c][%" PRIu32 "][%" PRIu32 "][%" PRIu32 "][%" PRIu32 "][%" PRIu32 "] %s %s %s%s%s%s\n",
str, f->mSampleRate, f->mBitsPerChannel,
(int)(f->mFormatID & 0xff000000) >> 24,
@@ -368,7 +373,7 @@ static Boolean IsAudioPropertySettable(AudioObjectID id,
static int AudioDeviceSupportsDigital(AudioDeviceID i_dev_id);
static int AudioStreamSupportsDigital(AudioStreamID i_stream_id);
-static int OpenSPDIF(void);
+static int OpenSPDIF(struct ao *ao);
static int AudioStreamChangeFormat(AudioStreamID i_stream_id,
AudioStreamBasicDescription change_format);
static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice,
@@ -436,8 +441,12 @@ static void print_help(void)
free(devids);
}
-static int init(int rate, const struct mp_chmap *channels, int format, int flags)
+static int init(struct ao *ao, char *params)
{
+ // int rate, int channels, int format, int flags)
+ struct priv *p = talloc_zero(ao, struct priv);
+ ao->priv = p;
+
AudioStreamBasicDescription inDesc;
AudioComponentDescription desc;
AudioComponent comp;
@@ -463,24 +472,22 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
return 0;
}
- ao_msg(MSGT_AO,MSGL_V, "init([%dHz][%dch][%s][%d])\n",
- rate, ao_data.channels.num, af_fmt2str_short(format), flags);
+ ca_msg(MSGT_AO, MSGL_V, "init([%dHz][%dch][%s][%d])\n",
+ ao->samplerate, ao->channels.num, af_fmt2str_short(ao->format), 0);
- ao = calloc(1, sizeof(ao_coreaudio_t));
+ p->i_selected_dev = 0;
+ p->b_supports_digital = 0;
+ p->b_digital = 0;
+ p->b_muted = 0;
+ p->b_stream_format_changed = 0;
+ p->i_hog_pid = -1;
+ p->i_stream_id = 0;
+ p->i_stream_index = -1;
+ p->b_revert = 0;
+ p->b_changed_mixing = 0;
- ao->i_selected_dev = 0;
- ao->b_supports_digital = 0;
- ao->b_digital = 0;
- ao->b_muted = 0;
- ao->b_stream_format_changed = 0;
- ao->i_hog_pid = -1;
- ao->i_stream_id = 0;
- ao->i_stream_index = -1;
- ao->b_revert = 0;
- ao->b_changed_mixing = 0;
-
- global_ao->per_application_mixer = true;
- global_ao->no_persistent_volume = true;
+ ao->per_application_mixer = true;
+ ao->no_persistent_volume = true;
if (device_id == 0) {
/* Find the ID of the default Device. */
@@ -488,60 +495,61 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
kAudioHardwarePropertyDefaultOutputDevice,
sizeof(UInt32), &devid_def);
if (err != noErr) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"could not get default audio device: [%4.4s]\n",
(char *)&err);
goto err_out;
}
- } else
+ } else {
devid_def = device_id;
+ }
/* Retrieve the name of the device. */
err = GetAudioPropertyString(devid_def,
kAudioObjectPropertyName,
&psz_name);
if (err != noErr) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"could not get default audio device name: [%4.4s]\n",
(char *)&err);
goto err_out;
}
- ao_msg(MSGT_AO, MSGL_V,
+ ca_msg(MSGT_AO, MSGL_V,
"got audio output device ID: %" PRIu32 " Name: %s\n", devid_def,
psz_name);
/* Probe whether device support S/PDIF stream output if input is AC3 stream. */
- if (AF_FORMAT_IS_AC3(format)) {
+ if (AF_FORMAT_IS_AC3(ao->format)) {
if (AudioDeviceSupportsDigital(devid_def))
- ao->b_supports_digital = 1;
- ao_msg(MSGT_AO, MSGL_V,
+ p->b_supports_digital = 1;
+ ca_msg(MSGT_AO, MSGL_V,
"probe default audio output device about support for digital s/pdif output: %d\n",
- ao->b_supports_digital);
+ p->b_supports_digital);
}
free(psz_name);
// Save selected device id
- ao->i_selected_dev = devid_def;
+ p->i_selected_dev = devid_def;
struct mp_chmap_sel chmap_sel = {0};
mp_chmap_sel_add_waveext(&chmap_sel);
- if (!ao_chmap_sel_adjust(&ao_data, &chmap_sel, &ao_data.channels))
+ if (!ao_chmap_sel_adjust(ao, &chmap_sel, &ao->channels))
goto err_out;
// Build Description for the input format
- inDesc.mSampleRate = rate;
+ inDesc.mSampleRate = ao->samplerate;
inDesc.mFormatID =
- ao->b_supports_digital ? kAudioFormat60958AC3 : kAudioFormatLinearPCM;
- inDesc.mChannelsPerFrame = ao_data.channels.num;
- inDesc.mBitsPerChannel = af_fmt2bits(format);
+ p->b_supports_digital ? kAudioFormat60958AC3 : kAudioFormatLinearPCM;
+ inDesc.mChannelsPerFrame = ao->channels.num;
+ inDesc.mBitsPerChannel = af_fmt2bits(ao->format);
- if ((format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) {
+ if ((ao->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) {
// float
inDesc.mFormatFlags = kAudioFormatFlagIsFloat |
kAudioFormatFlagIsPacked;
- } else if ((format & AF_FORMAT_SIGN_MASK) == AF_FORMAT_SI) {
+ } else if ((ao->format & AF_FORMAT_SIGN_MASK) == AF_FORMAT_SI) {
// signed int
inDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagIsPacked;
@@ -549,47 +557,47 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
// unsigned int
inDesc.mFormatFlags = kAudioFormatFlagIsPacked;
}
- if ((format & AF_FORMAT_END_MASK) == AF_FORMAT_BE)
+ if ((ao->format & AF_FORMAT_END_MASK) == AF_FORMAT_BE)
inDesc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
inDesc.mFramesPerPacket = 1;
- ao->packetSize = inDesc.mBytesPerPacket = inDesc.mBytesPerFrame =
+ p->packetSize = inDesc.mBytesPerPacket = inDesc.mBytesPerFrame =
inDesc.mFramesPerPacket *
- ao_data.channels.num *
+ ao->channels.num *
(inDesc.mBitsPerChannel / 8);
print_format(MSGL_V, "source:", &inDesc);
- if (ao->b_supports_digital) {
+ if (p->b_supports_digital) {
b_alive = 1;
- err = GetAudioProperty(ao->i_selected_dev,
+ err = GetAudioProperty(p->i_selected_dev,
kAudioDevicePropertyDeviceIsAlive,
sizeof(UInt32), &b_alive);
if (err != noErr)
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"could not check whether device is alive: [%4.4s]\n",
(char *)&err);
if (!b_alive)
- ao_msg(MSGT_AO, MSGL_WARN, "device is not alive\n");
+ ca_msg(MSGT_AO, MSGL_WARN, "device is not alive\n");
/* S/PDIF output need device in HogMode. */
- err = GetAudioProperty(ao->i_selected_dev,
+ err = GetAudioProperty(p->i_selected_dev,
kAudioDevicePropertyHogMode,
- sizeof(pid_t), &ao->i_hog_pid);
+ sizeof(pid_t), &p->i_hog_pid);
if (err != noErr) {
/* This is not a fatal error. Some drivers simply don't support this property. */
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"could not check whether device is hogged: [%4.4s]\n",
(char *)&err);
- ao->i_hog_pid = -1;
+ p->i_hog_pid = -1;
}
- if (ao->i_hog_pid != -1 && ao->i_hog_pid != getpid()) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ if (p->i_hog_pid != -1 && p->i_hog_pid != getpid()) {
+ ca_msg(MSGT_AO, MSGL_WARN,
"Selected audio device is exclusively in use by another program.\n");
goto err_out;
}
- ao->stream_format = inDesc;
- return OpenSPDIF();
+ p->stream_format = inDesc;
+ return OpenSPDIF(ao);
}
/* original analog output code */
@@ -603,106 +611,102 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
comp = AudioComponentFindNext(NULL, &desc); //Finds an component that meets the desc spec's
if (comp == NULL) {
- ao_msg(MSGT_AO, MSGL_WARN, "Unable to find Output Unit component\n");
+ ca_msg(MSGT_AO, MSGL_WARN, "Unable to find Output Unit component\n");
goto err_out;
}
- err = AudioComponentInstanceNew(comp, &(ao->theOutputUnit)); //gains access to the services provided by the component
+ err = AudioComponentInstanceNew(comp, &(p->theOutputUnit)); //gains access to the services provided by the component
if (err) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"Unable to open Output Unit component: [%4.4s]\n", (char *)&err);
goto err_out;
}
// Initialize AudioUnit
- err = AudioUnitInitialize(ao->theOutputUnit);
+ err = AudioUnitInitialize(p->theOutputUnit);
if (err) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"Unable to initialize Output Unit component: [%4.4s]\n",
(char *)&err);
goto err_out1;
}
size = sizeof(AudioStreamBasicDescription);
- err = AudioUnitSetProperty(ao->theOutputUnit,
+ err = AudioUnitSetProperty(p->theOutputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &inDesc, size);
if (err) {
- ao_msg(MSGT_AO, MSGL_WARN, "Unable to set the input format: [%4.4s]\n",
+ ca_msg(MSGT_AO, MSGL_WARN, "Unable to set the input format: [%4.4s]\n",
(char *)&err);
goto err_out2;
}
size = sizeof(UInt32);
- err = AudioUnitGetProperty(ao->theOutputUnit,
+ err = AudioUnitGetProperty(p->theOutputUnit,
kAudioDevicePropertyBufferSize,
kAudioUnitScope_Input, 0, &maxFrames, &size);
if (err) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"AudioUnitGetProperty returned [%4.4s] when getting kAudioDevicePropertyBufferSize\n",
(char *)&err);
goto err_out2;
}
//Set the Current Device to the Default Output Unit.
- err = AudioUnitSetProperty(ao->theOutputUnit,
+ err = AudioUnitSetProperty(p->theOutputUnit,
kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, 0, &ao->i_selected_dev,
- sizeof(ao->i_selected_dev));
+ kAudioUnitScope_Global, 0, &p->i_selected_dev,
+ sizeof(p->i_selected_dev));
- ao->chunk_size = maxFrames; //*inDesc.mBytesPerFrame;
+ ao->samplerate = inDesc.mSampleRate;
- ao_data.samplerate = inDesc.mSampleRate;
- if (!ao_chmap_sel_get_def(&ao_data, &chmap_sel, &ao_data.channels,
+ if (!ao_chmap_sel_get_def(ao, &chmap_sel, &ao->channels,
inDesc.mChannelsPerFrame))
goto err_out2;
- ao_data.channels.num = inDesc.mChannelsPerFrame;
- ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
- ao_data.outburst = ao->chunk_size;
- ao_data.buffersize = ao_data.bps;
- ao->num_chunks = (ao_data.bps + ao->chunk_size - 1) / ao->chunk_size;
- ao->buffer_len = ao->num_chunks * ao->chunk_size;
- ao->buffer = av_fifo_alloc(ao->buffer_len);
+ ao->bps = ao->samplerate * inDesc.mBytesPerFrame;
+ ao->buffersize = ao->bps;
+ int chunk_size = maxFrames; //*inDesc.mBytesPerFrame;
+ int chunks = (ao->bps + chunk_size - 1) / chunk_size;
+ p->buffer = new_ca_ringbuffer(p, chunks, chunk_size);
+ ao->outburst = chunk_size;
- ao_msg(MSGT_AO, MSGL_V,
- "using %5d chunks of %d bytes (buffer len %d bytes)\n",
- (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
+ ca_msg(MSGT_AO, MSGL_V,
+ "using %d chunks of %d bytes (buffer len %d bytes)\n",
+ p->buffer->chunks, p->buffer->chunk_size, p->buffer->len);
renderCallback.inputProc = theRenderProc;
- renderCallback.inputProcRefCon = 0;
- err = AudioUnitSetProperty(ao->theOutputUnit,
+ renderCallback.inputProcRefCon = ao;
+ err = AudioUnitSetProperty(p->theOutputUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &renderCallback,
sizeof(AURenderCallbackStruct));
if (err) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"Unable to set the render callback: [%4.4s]\n", (char *)&err);
goto err_out2;
}
- reset();
+ reset(ao);
return CONTROL_OK;
err_out2:
- AudioUnitUninitialize(ao->theOutputUnit);
+ AudioUnitUninitialize(p->theOutputUnit);
err_out1:
- AudioComponentInstanceDispose(ao->theOutputUnit);
+ AudioComponentInstanceDispose(p->theOutputUnit);
err_out:
- av_fifo_free(ao->buffer);
- free(ao);
- ao = NULL;
return CONTROL_FALSE;
}
/*****************************************************************************
* Setup a encoded digital stream (SPDIF)
*****************************************************************************/
-static int OpenSPDIF(void)
+static int OpenSPDIF(struct ao *ao)
{
+ struct priv *p = ao->priv;
OSStatus err = noErr;
UInt32 i_param_size, b_mix = 0;
Boolean b_writeable = 0;
@@ -711,18 +715,18 @@ static int OpenSPDIF(void)
AudioObjectPropertyAddress property_address;
/* Start doing the SPDIF setup process. */
- ao->b_digital = 1;
+ p->b_digital = 1;
/* Hog the device. */
- ao->i_hog_pid = getpid();
+ p->i_hog_pid = getpid();
- err = SetAudioProperty(ao->i_selected_dev,
+ err = SetAudioProperty(p->i_selected_dev,
kAudioDevicePropertyHogMode,
- sizeof(ao->i_hog_pid), &ao->i_hog_pid);
+ sizeof(p->i_hog_pid), &p->i_hog_pid);
if (err != noErr) {
- ao_msg(MSGT_AO, MSGL_WARN, "failed to set hogmode: [%4.4s]\n",
+ ca_msg(MSGT_AO, MSGL_WARN, "failed to set hogmode: [%4.4s]\n",
(char *)&err);
- ao->i_hog_pid = -1;
+ p->i_hog_pid = -1;
goto err_out;
}
@@ -731,44 +735,44 @@ static int OpenSPDIF(void)
property_address.mElement = kAudioObjectPropertyElementMaster;
/* Set mixable to false if we are allowed to. */
- if (AudioObjectHasProperty(ao->i_selected_dev, &property_address)) {
+ if (AudioObjectHasProperty(p->i_selected_dev, &property_address)) {
/* Set mixable to false if we are allowed to. */
- err = IsAudioPropertySettable(ao->i_selected_dev,
+ err = IsAudioPropertySettable(p->i_selected_dev,
kAudioDevicePropertySupportsMixing,
&b_writeable);
- err = GetAudioProperty(ao->i_selected_dev,
+ err = GetAudioProperty(p->i_selected_dev,
kAudioDevicePropertySupportsMixing,
sizeof(UInt32), &b_mix);
if (err == noErr && b_writeable) {
b_mix = 0;
- err = SetAudioProperty(ao->i_selected_dev,
+ err = SetAudioProperty(p->i_selected_dev,
kAudioDevicePropertySupportsMixing,
sizeof(UInt32), &b_mix);
- ao->b_changed_mixing = 1;
+ p->b_changed_mixing = 1;
}
if (err != noErr) {
- ao_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n",
+ ca_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n",
(char *)&err);
goto err_out;
}
}
/* Get a list of all the streams on this device. */
- i_param_size = GetAudioPropertyArray(ao->i_selected_dev,
+ i_param_size = GetAudioPropertyArray(p->i_selected_dev,
kAudioDevicePropertyStreams,
kAudioDevicePropertyScopeOutput,
(void **)&p_streams);
if (!i_param_size) {
- ao_msg(MSGT_AO, MSGL_WARN, "could not get number of streams.\n");
+ ca_msg(MSGT_AO, MSGL_WARN, "could not get number of streams.\n");
goto err_out;
}
i_streams = i_param_size / sizeof(AudioStreamID);
- ao_msg(MSGT_AO, MSGL_V, "current device stream number: %d\n", i_streams);
+ ca_msg(MSGT_AO, MSGL_V, "current device stream number: %d\n", i_streams);
- for (i = 0; i < i_streams && ao->i_stream_index < 0; ++i) {
+ for (i = 0; i < i_streams && p->i_stream_index < 0; ++i) {
/* Find a stream with a cac3 stream. */
AudioStreamRangedDescription *p_format_list = NULL;
int i_formats = 0, j = 0, b_digital = 0;
@@ -778,7 +782,7 @@ static int OpenSPDIF(void)
(void **)&p_format_list);
if (!i_param_size) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"Could not get number of stream formats.\n");
continue;
}
@@ -802,23 +806,23 @@ static int OpenSPDIF(void)
int i_current_rate_format = -1;
int i_backup_rate_format = -1;
- ao->i_stream_id = p_streams[i];
- ao->i_stream_index = i;
+ p->i_stream_id = p_streams[i];
+ p->i_stream_index = i;
- if (ao->b_revert == 0) {
+ if (p->b_revert == 0) {
/* Retrieve the original format of this stream first if not done so already. */
- err = GetAudioProperty(ao->i_stream_id,
+ err = GetAudioProperty(p->i_stream_id,
kAudioStreamPropertyPhysicalFormat,
- sizeof(ao->sfmt_revert),
- &ao->sfmt_revert);
+ sizeof(p->sfmt_revert),
+ &p->sfmt_revert);
if (err != noErr) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"Could not retrieve the original stream format: [%4.4s]\n",
(char *)&err);
free(p_format_list);
continue;
}
- ao->b_revert = 1;
+ p->b_revert = 1;
}
for (j = 0; j < i_formats; ++j)
@@ -828,12 +832,12 @@ static int OpenSPDIF(void)
kAudioFormat60958AC3 ||
p_format_list[j].mFormat.mFormatID == kAudioFormatAC3) {
if (p_format_list[j].mFormat.mSampleRate ==
- ao->stream_format.mSampleRate) {
+ p->stream_format.mSampleRate) {
i_requested_rate_format = j;
break;
}
if (p_format_list[j].mFormat.mSampleRate ==
- ao->sfmt_revert.mSampleRate)
+ p->sfmt_revert.mSampleRate)
i_current_rate_format = j;
else if (i_backup_rate_format < 0 ||
p_format_list[j].mFormat.mSampleRate >
@@ -843,40 +847,40 @@ static int OpenSPDIF(void)
}
if (i_requested_rate_format >= 0) /* We prefer to output at the samplerate of the original audio. */
- ao->stream_format =
+ p->stream_format =
p_format_list[i_requested_rate_format].mFormat;
else if (i_current_rate_format >= 0) /* If not possible, we will try to use the current samplerate of the device. */
- ao->stream_format =
+ p->stream_format =
p_format_list[i_current_rate_format].mFormat;
else
- ao->stream_format = p_format_list[i_backup_rate_format].mFormat;
+ p->stream_format = p_format_list[i_backup_rate_format].mFormat;
/* And if we have to, any digital format will be just fine (highest rate possible). */
}
free(p_format_list);
}
free(p_streams);
- if (ao->i_stream_index < 0) {
- ao_msg(MSGT_AO, MSGL_WARN,
+ if (p->i_stream_index < 0) {
+ ca_msg(MSGT_AO, MSGL_WARN,
"Cannot find any digital output stream format when OpenSPDIF().\n");
goto err_out;
}
- print_format(MSGL_V, "original stream format:", &ao->sfmt_revert);
+ print_format(MSGL_V, "original stream format:", &p->sfmt_revert);
- if (!AudioStreamChangeFormat(ao->i_stream_id, ao->stream_format))
+ if (!AudioStreamChangeFormat(p->i_stream_id, p->stream_format))
goto err_out;
property_address.mSelector = kAudioDevicePropertyDeviceHasChanged;
property_address.mScope = kAudioObjectPropertyScopeGlobal;
property_address.mElement = kAudioObjectPropertyElementMaster;
- err = AudioObjectAddPropertyListener(ao->i_selected_dev,
+ err = AudioObjectAddPropertyListener(p->i_selected_dev,
&property_address,
DeviceListener,
NULL);
if (err != noErr)
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"AudioDeviceAddPropertyListener for kAudioDevicePropertyDeviceHasChanged failed: [%4.4s]\n",
(char *)&err);
@@ -884,80 +888,78 @@ static int OpenSPDIF(void)
/* FIXME: If output stream is not native byte-order, we need change endian somewhere. */
/* Although there's no such case reported. */
#if BYTE_ORDER == BIG_ENDIAN
- if (!(ao->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian))
+ if (!(p->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian))
#else
/* tell mplayer that we need a byteswap on AC3 streams, */
- if (ao->stream_format.mFormatID & kAudioFormat60958AC3)
- ao_data.format = AF_FORMAT_AC3_LE;
+ if (p->stream_format.mFormatID & kAudioFormat60958AC3)
+ ao->format = AF_FORMAT_AC3_LE;
- if (ao->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
+ if (p->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
#endif
- ao_msg(MSGT_AO, MSGL_WARN,
+ ca_msg(MSGT_AO, MSGL_WARN,
"Output stream has non-native byte order, digital output may fail.\n");
- /* For ac3/dts, just use packet size 6144 bytes as chunk size. */
- ao->chunk_size = ao->stream_format.mBytesPerPacket;
+ ao->samplerate = p->stream_format.mSampleRate;
+ mp_chmap_from_channels(&ao->channels, p->stream_format.mChannelsPerFrame);
+ ao->bps = ao->samplerate *
+ (p->stream_format.mBytesPerPacket /
+ p->stream_format.mFramesPerPacket);
- ao_data.samplerate = ao->stream_format.mSampleRate;
- mp_chmap_from_channels(&ao_data.channels, ao->stream_format.mChannelsPerFrame);
- ao_data.bps = ao_data.samplerate *
- (ao->stream_format.mBytesPerPacket /
- ao->stream_format.mFramesPerPacket);
- ao_data.outburst = ao->chunk_size;
- ao_data.buffersize = ao_data.bps;
+ /* For ac3/dts, just use packet size 6144 bytes as chunk size. */
+ int chunk_size = p->stream_format.mBytesPerPacket;
+ int chunks = (ao->bps + chunk_size - 1) / chunk_size;
+ ao->outburst = chunk_size;
+ ao->buffersize = ao->bps;
- ao->num_chunks = (ao_data.bps + ao->chunk_size - 1) / ao->chunk_size;
- ao->buffer_len = ao->num_chunks * ao->chunk_size;
- ao->buffer = av_fifo_alloc(ao->buffer_len);
+ p->buffer->chunks = (ao->bps + p->buffer->chunk_size - 1) / p->buffer->chunk_size;
+ p->buffer->len = p->buffer->chunks * p->buffer->chunk_size;
+ p->buffer = new_ca_ringbuffer(p, chunks, chunk_size);
- ao_msg(MSGT_AO, MSGL_V,
+ ca_msg(MSGT_AO, MSGL_V,
"using %5d chunks of %d bytes (buffer len %d bytes)\n",
- (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
+ p->buffer->chunks, p->buffer->chunk_size, p->buffer->len);
/* Create IOProc callback. */
- err = AudioDeviceCreateIOProcID(ao->i_selected_dev,
+ err = AudioDeviceCreateIOProcID(p->i_selected_dev,
(AudioDeviceIOProc)RenderCallbackSPDIF,
(void *)ao,
- &ao->renderCallback);
+ &p->renderCallback);
- if (err != noErr || ao->renderCallback == NULL) {
- ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceAddIOProc failed: [%4.4s]\n",
+ if (err != noErr || p->renderCallback == NULL) {
+ ca_msg(MSGT_AO, MSGL_WARN, "AudioDeviceAddIOProc failed: [%4.4s]\n",
(char *)&err);
goto err_out1;
}
- reset();
+ reset(ao);
return CONTROL_TRUE;
err_out1:
- if (ao->b_revert)
- AudioStreamChangeFormat(ao->i_stream_id, ao->sfmt_revert);
+ if (p->b_revert)
+ AudioStreamChangeFormat(p->i_stream_id, p->sfmt_revert);
err_out:
- if (ao->b_changed_mixing && ao->sfmt_revert.mFormatID !=
+ if (p->b_changed_mixing && p->sfmt_revert.mFormatID !=
kAudioFormat60958AC3) {
int b_mix = 1;
- err = SetAudioProperty(ao->i_selected_dev,
+ err = SetAudioProperty(p->i_selected_dev,
kAudioDevicePropertySupportsMixing,
sizeof(int), &b_mix);
if (err != noErr)
- ao_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n",
+ ca_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n",
(char *)&err);
}
- if (ao->i_hog_pid == getpid()) {
- ao->i_hog_pid = -1;
- err = SetAudioProperty(ao->i_selected_dev,
+ if (p->i_hog_pid == getpid()) {
+ p->i_hog_pid = -1;
+ err = SetAudioProperty(p->i_selected_dev,
kAudioDevicePropertyHogMode,
- sizeof(ao->i_hog_pid), &ao->i_hog_pid);
+