summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_coreaudio_common.c
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2013-06-26 08:16:34 +0200
committerStefano Pigozzi <stefano.pigozzi@gmail.com>2013-07-22 21:53:17 +0200
commit838fa07376e3b6c34c2a75535d9f29b9eb1b0db5 (patch)
tree9a71d06d3a2ccfdfcb0800c1b413b6b2cbb1008b /audio/out/ao_coreaudio_common.c
parent40f6e2e041b7c0d690b1a22d4bb706feef991022 (diff)
downloadmpv-838fa07376e3b6c34c2a75535d9f29b9eb1b0db5.tar.bz2
mpv-838fa07376e3b6c34c2a75535d9f29b9eb1b0db5.tar.xz
ao_coreaudio: move AudioStreamChangeFormat to common file and refactor
Diffstat (limited to 'audio/out/ao_coreaudio_common.c')
-rw-r--r--audio/out/ao_coreaudio_common.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/audio/out/ao_coreaudio_common.c b/audio/out/ao_coreaudio_common.c
index 289fa93b64..c6c56c0323 100644
--- a/audio/out/ao_coreaudio_common.c
+++ b/audio/out/ao_coreaudio_common.c
@@ -26,6 +26,7 @@
#include <AudioUnit/AudioUnit.h>
#include <inttypes.h>
#include <stdbool.h>
+#include "osdep/timer.h"
#include "core/mp_msg.h"
#define ca_msg(a, b ...) mp_msg(MSGT_AO, a, "AO: [coreaudio] " b)
@@ -329,3 +330,76 @@ static OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid) {
}
return noErr;
}
+
+static int AudioStreamChangeFormat(AudioStreamID i_stream_id,
+ AudioStreamBasicDescription change_format)
+{
+ OSStatus err = noErr;
+ AudioObjectPropertyAddress p_addr;
+ volatile int stream_format_changed = 0;
+
+ ca_print_asbd("setting stream format:", &change_format);
+
+ /* Install the callback. */
+ p_addr = (AudioObjectPropertyAddress) {
+ .mSelector = kAudioStreamPropertyPhysicalFormat,
+ .mScope = kAudioObjectPropertyScopeGlobal,
+ .mElement = kAudioObjectPropertyElementMaster,
+ };
+
+ err = AudioObjectAddPropertyListener(i_stream_id,
+ &p_addr,
+ ca_stream_listener,
+ (void *)&stream_format_changed);
+ if (!CHECK_CA_WARN("can't add property listener during format change")) {
+ return CONTROL_FALSE;
+ }
+
+ /* Change the format. */
+ err = SetAudioProperty(i_stream_id,
+ kAudioStreamPropertyPhysicalFormat,
+ sizeof(AudioStreamBasicDescription), &change_format);
+ if (!CHECK_CA_WARN("error changing physical format")) {
+ return CONTROL_FALSE;
+ }
+
+ /* The AudioStreamSetProperty is not only asynchronious,
+ * it is also not Atomic, in its behaviour.
+ * Therefore we check 5 times before we really give up. */
+ bool format_set = CONTROL_FALSE;
+ for (int i = 0; !format_set && i < 5; ++i) {
+ for (int j = 0; !stream_format_changed && j < 50; ++j)
+ mp_sleep_us(10000);
+
+ if (stream_format_changed) {
+ stream_format_changed = 0;
+ } else {
+ ca_msg(MSGL_V, "reached timeout\n");
+ }
+
+ AudioStreamBasicDescription actual_format;
+ err = GetAudioProperty(i_stream_id,
+ kAudioStreamPropertyPhysicalFormat,
+ sizeof(AudioStreamBasicDescription),
+ &actual_format);
+
+ ca_print_asbd("actual format in use:", &actual_format);
+ if (actual_format.mSampleRate == change_format.mSampleRate &&
+ actual_format.mFormatID == change_format.mFormatID &&
+ actual_format.mFramesPerPacket == change_format.mFramesPerPacket) {
+ format_set = CONTROL_TRUE;
+ }
+ }
+
+ err = AudioObjectRemovePropertyListener(i_stream_id,
+ &p_addr,
+ ca_stream_listener,
+ (void *)&stream_format_changed);
+
+ if (!CHECK_CA_WARN("can't remove property listener")) {
+ return CONTROL_FALSE;
+ }
+
+ return format_set;
+}
+