summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_coreaudio_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_coreaudio_utils.c')
-rw-r--r--audio/out/ao_coreaudio_utils.c64
1 files changed, 28 insertions, 36 deletions
diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c
index b55bf1c0df..44604e6df2 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;
}
@@ -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