diff options
Diffstat (limited to 'audio/out/ao_coreaudio_utils.c')
-rw-r--r-- | audio/out/ao_coreaudio_utils.c | 92 |
1 files changed, 42 insertions, 50 deletions
diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index b55bf1c0df..78cdcad393 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -28,29 +28,14 @@ #include "osdep/semaphore.h" #include "audio/format.h" -#if HAVE_COREAUDIO +#if HAVE_COREAUDIO || HAVE_AVFOUNDATION #include "audio/out/ao_coreaudio_properties.h" #include <CoreAudio/HostTime.h> #else #include <mach/mach_time.h> #endif -CFStringRef cfstr_from_cstr(char *str) -{ - return CFStringCreateWithCString(NULL, str, CA_CFSTR_ENCODING); -} - -char *cfstr_get_cstr(CFStringRef cfstr) -{ - CFIndex size = - CFStringGetMaximumSizeForEncoding( - CFStringGetLength(cfstr), CA_CFSTR_ENCODING) + 1; - char *buffer = talloc_zero_size(NULL, size); - CFStringGetCString(cfstr, buffer, size, CA_CFSTR_ENCODING); - return buffer; -} - -#if HAVE_COREAUDIO +#if HAVE_COREAUDIO || HAVE_AVFOUNDATION static bool ca_is_output_device(struct ao *ao, AudioDeviceID dev) { size_t n_buffers; @@ -153,7 +138,8 @@ bool check_ca_st(struct ao *ao, int level, OSStatus code, const char *message) { if (code == noErr) return true; - mp_msg(ao->log, level, "%s (%s/%d)\n", message, mp_tag_str(code), (int)code); + if (ao) + mp_msg(ao->log, level, "%s (%s/%d)\n", message, mp_tag_str(code), (int)code); return false; } @@ -250,20 +236,20 @@ void ca_print_asbd(struct ao *ao, const char *description, int mpfmt = ca_asbd_to_mp_format(asbd); MP_VERBOSE(ao, - "%s %7.1fHz %" PRIu32 "bit %s " - "[%" PRIu32 "][%" PRIu32 "bpp][%" PRIu32 "fbp]" - "[%" PRIu32 "bpf][%" PRIu32 "ch] " - "%s %s %s%s%s%s (%s)\n", - description, asbd->mSampleRate, asbd->mBitsPerChannel, format, - asbd->mFormatFlags, asbd->mBytesPerPacket, asbd->mFramesPerPacket, - asbd->mBytesPerFrame, asbd->mChannelsPerFrame, - (flags & kAudioFormatFlagIsFloat) ? "float" : "int", - (flags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE", - (flags & kAudioFormatFlagIsSignedInteger) ? "S" : "U", - (flags & kAudioFormatFlagIsPacked) ? " packed" : "", - (flags & kAudioFormatFlagIsAlignedHigh) ? " aligned" : "", - (flags & kAudioFormatFlagIsNonInterleaved) ? " P" : "", - mpfmt ? af_fmt_to_str(mpfmt) : "-"); + "%s %7.1fHz %" PRIu32 "bit %s " + "[%" PRIu32 "][%" PRIu32 "bpp][%" PRIu32 "fbp]" + "[%" PRIu32 "bpf][%" PRIu32 "ch] " + "%s %s %s%s%s%s (%s)\n", + description, asbd->mSampleRate, asbd->mBitsPerChannel, format, + asbd->mFormatFlags, asbd->mBytesPerPacket, asbd->mFramesPerPacket, + asbd->mBytesPerFrame, asbd->mChannelsPerFrame, + (flags & kAudioFormatFlagIsFloat) ? "float" : "int", + (flags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE", + (flags & kAudioFormatFlagIsSignedInteger) ? "S" : "U", + (flags & kAudioFormatFlagIsPacked) ? " packed" : "", + (flags & kAudioFormatFlagIsAlignedHigh) ? " aligned" : "", + (flags & kAudioFormatFlagIsNonInterleaved) ? " P" : "", + mpfmt ? af_fmt_to_str(mpfmt) : "-"); } // Return whether new is an improvement over old. Assume a higher value means @@ -307,21 +293,21 @@ bool ca_asbd_is_better(AudioStreamBasicDescription *req, return true; } -int64_t ca_frames_to_us(struct ao *ao, uint32_t frames) +int64_t ca_frames_to_ns(struct ao *ao, uint32_t frames) { - return frames / (float) ao->samplerate * 1e6; + return MP_TIME_S_TO_NS(frames / (double)ao->samplerate); } int64_t ca_get_latency(const AudioTimeStamp *ts) { -#if HAVE_COREAUDIO +#if HAVE_COREAUDIO || HAVE_AVFOUNDATION uint64_t out = AudioConvertHostTimeToNanos(ts->mHostTime); uint64_t now = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()); if (now > out) return 0; - return (out - now) * 1e-3; + return out - now; #else static mach_timebase_info_data_t timebase; if (timebase.denom == 0) @@ -333,11 +319,11 @@ int64_t ca_get_latency(const AudioTimeStamp *ts) if (now > out) return 0; - return (out - now) * timebase.numer / timebase.denom / 1e3; + return (out - now) * timebase.numer / timebase.denom; #endif } -#if HAVE_COREAUDIO +#if HAVE_COREAUDIO || HAVE_AVFOUNDATION bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream) { AudioStreamRangedDescription *formats = NULL; @@ -437,7 +423,7 @@ OSStatus ca_enable_mixing(struct ao *ao, AudioDeviceID device, bool changed) return noErr; } -int64_t ca_get_device_latency_us(struct ao *ao, AudioDeviceID device) +int64_t ca_get_device_latency_ns(struct ao *ao, AudioDeviceID device) { uint32_t latency_frames = 0; uint32_t latency_properties[] = { @@ -456,7 +442,15 @@ int64_t ca_get_device_latency_us(struct ao *ao, AudioDeviceID device) } } - return ca_frames_to_us(ao, latency_frames); + double sample_rate = ao->samplerate; + OSStatus err = CA_GET_O(device, kAudioDevicePropertyNominalSampleRate, + &sample_rate); + CHECK_CA_WARN("cannot get device sample rate, falling back to AO sample rate!"); + if (err == noErr) { + MP_VERBOSE(ao, "Device sample rate: %f\n", sample_rate); + } + + return MP_TIME_S_TO_NS(latency_frames / sample_rate); } static OSStatus ca_change_format_listener( @@ -464,8 +458,8 @@ static OSStatus ca_change_format_listener( const AudioObjectPropertyAddress addresses[], void *data) { - sem_t *sem = data; - sem_post(sem); + mp_sem_t *sem = data; + mp_sem_post(sem); return noErr; } @@ -477,11 +471,9 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, ca_print_asbd(ao, "setting stream physical format:", &change_format); - sem_t wakeup; - if (sem_init(&wakeup, 0, 0)) { - MP_WARN(ao, "OOM\n"); - return false; - } + mp_sem_t wakeup; + if (mp_sem_init(&wakeup, 0, 0)) + MP_HANDLE_OOM(0); AudioStreamBasicDescription prev_format; err = CA_GET(stream, kAudioStreamPropertyPhysicalFormat, &prev_format); @@ -507,7 +499,7 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, /* The AudioStreamSetProperty is not only asynchronous, * it is also not Atomic, in its behaviour. */ - struct timespec timeout = mp_rel_time_to_timespec(2.0); + int64_t wait_until = mp_time_ns() + MP_TIME_S_TO_NS(2); AudioStreamBasicDescription actual_format = {0}; while (1) { err = CA_GET(stream, kAudioStreamPropertyPhysicalFormat, &actual_format); @@ -518,7 +510,7 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, if (format_set) break; - if (sem_timedwait(&wakeup, &timeout)) { + if (mp_sem_timedwait(&wakeup, wait_until)) { MP_VERBOSE(ao, "reached timeout\n"); break; } @@ -540,7 +532,7 @@ bool ca_change_physical_format_sync(struct ao *ao, AudioStreamID stream, CHECK_CA_ERROR("can't remove property listener"); coreaudio_error: - sem_destroy(&wakeup); + mp_sem_destroy(&wakeup); return format_set; } #endif |