ao_coreaudio: report hardware latency to ao_read_data

Commit a6a4cd2c88 added reporting of playout latency, this commit also adds
support for reporting hardware and constant audio unit latency.
This commit is contained in:
Stefano Pigozzi 2014-07-03 19:05:22 +02:00
parent 29b047da6f
commit 97f6d7f4ec
2 changed files with 43 additions and 3 deletions

View File

@ -32,6 +32,8 @@ struct priv {
AudioDeviceID device;
AudioUnit audio_unit;
uint64_t hw_latency_us;
// options
int opt_device_id;
int opt_list;
@ -40,6 +42,41 @@ struct priv {
bool ca_layout_to_mp_chmap(struct ao *ao, AudioChannelLayout *layout,
struct mp_chmap *chmap);
static int64_t ca_frames_to_us(struct ao *ao, uint32_t frames)
{
return frames / (float) ao->samplerate * 1e6;
}
static int64_t ca_get_hardware_latency(struct ao *ao) {
struct priv *p = ao->priv;
double audiounit_latency_sec = 0.0;
uint32_t size = sizeof(audiounit_latency_sec);
OSStatus err = AudioUnitGetProperty(
p->audio_unit,
kAudioUnitProperty_Latency,
kAudioUnitScope_Global,
0,
&audiounit_latency_sec,
&size);
CHECK_CA_ERROR("cannot get audio unit latency");
uint32_t frames = 0;
err = CA_GET_O(p->device, kAudioDevicePropertyLatency, &frames);
CHECK_CA_ERROR("cannot get device latency");
uint64_t audiounit_latency_us = audiounit_latency_sec * 1e6;
uint64_t device_latency_us = ca_frames_to_us(ao, frames);
MP_VERBOSE(ao, "audiounit latency [us]: %lld\n", audiounit_latency_us);
MP_VERBOSE(ao, "device latency [us]: %lld\n", device_latency_us);
return audiounit_latency_us + device_latency_us;
coreaudio_error:
return 0;
}
static int64_t ca_get_latency(const AudioTimeStamp *ts)
{
uint64_t out = AudioConvertHostTimeToNanos(ts->mHostTime);
@ -56,12 +93,12 @@ static OSStatus render_cb_lpcm(void *ctx, AudioUnitRenderActionFlags *aflags,
UInt32 frames, AudioBufferList *buffer_list)
{
struct ao *ao = ctx;
struct priv *p = ao->priv;
AudioBuffer buf = buffer_list->mBuffers[0];
const int64_t playback_us = frames / (float) ao->samplerate * 1e6;
const int64_t latency_us = ca_get_latency(ts);
int64_t end = mp_time_us();
end += p->hw_latency_us + ca_get_latency(ts) + ca_frames_to_us(ao, frames);
const int64_t end = mp_time_us() + playback_us + latency_us;
ao_read_data(ao, &buf.mData, frames, end);
return noErr;
}
@ -219,6 +256,8 @@ static bool init_audiounit(struct ao *ao, AudioStreamBasicDescription asbd)
CHECK_CA_ERROR_L(coreaudio_error_audiounit,
"can't link audio unit to selected device");
p->hw_latency_us = ca_get_hardware_latency(ao);
AURenderCallbackStruct render_cb = (AURenderCallbackStruct) {
.inputProc = render_cb_lpcm,
.inputProcRefCon = ao,

View File

@ -37,6 +37,7 @@ OSStatus ca_set(AudioObjectID id, ca_scope scope, ca_sel selector,
#define CA_GET(id, sel, data) ca_get(id, CA_GLOBAL, sel, sizeof(*(data)), data)
#define CA_SET(id, sel, data) ca_set(id, CA_GLOBAL, sel, sizeof(*(data)), data)
#define CA_GET_O(id, sel, data) ca_get(id, CA_OUTPUT, sel, sizeof(*(data)), data)
OSStatus ca_get_ary(AudioObjectID id, ca_scope scope, ca_sel selector,
uint32_t element_size, void **data, size_t *elements);