diff --git a/audio/out/ao_avfoundation.m b/audio/out/ao_avfoundation.m index 887ec7ce33b91..c6faf65a05896 100644 --- a/audio/out/ao_avfoundation.m +++ b/audio/out/ao_avfoundation.m @@ -61,16 +61,16 @@ static CMTime CMTimeFromNanoseconds(int64_t time) static void feed(struct ao *ao) { struct priv *p = ao->priv; + int samplerate = ao->samplerate; + int sstride = ao->sstride; + CMBlockBufferRef block_buffer = NULL; CMSampleBufferRef sample_buffer = NULL; + OSStatus err; - int64_t cur_time_av = CMTimeGetNanoseconds([p->synchronizer currentTime]); - int64_t cur_time_mp = mp_time_ns(); - p->end_time_av = MPMAX(p->end_time_av, cur_time_av); - - int request_sample_count = ao->samplerate / 10; // 1/10 samplerate may be a good number - int buffer_size = request_sample_count * ao->sstride; - if (CMBlockBufferCreateWithMemoryBlock( + int request_sample_count = samplerate / 10; + int buffer_size = request_sample_count * sstride; + if ((err = CMBlockBufferCreateWithMemoryBlock( kCFAllocatorDefault, NULL, buffer_size, @@ -80,30 +80,36 @@ static void feed(struct ao *ao) buffer_size, kCMBlockBufferAssureMemoryNowFlag, &block_buffer - ) != noErr) { - MP_FATAL(ao, "failed to create CMBlockBuffer\n"); + )) != noErr) { + MP_FATAL(ao, "failed to create block buffer\n"); + MP_VERBOSE(ao, "CMBlockBufferCreateWithMemoryBlock returned %d\n", err); goto error; } void* data[1]; - if (CMBlockBufferGetDataPointer(block_buffer, 0, NULL, NULL, (char**)data) != noErr) { - MP_FATAL(ao, "CMBlockBufferGetDataPointer failed\n"); + if ((err = CMBlockBufferGetDataPointer(block_buffer, 0, NULL, NULL, (char**)data)) != noErr) { + MP_FATAL(ao, "failed to get data pointer from block buffer\n"); + MP_VERBOSE(ao, "CMBlockBufferGetDataPointer returned %d\n", err); goto error; } - int64_t delta = CMTimeGetNanoseconds(CMTimeMake(request_sample_count, ao->samplerate)); - int real_sample_count = ao_read_data_nonblocking(ao, data, request_sample_count, p->end_time_av - cur_time_av + cur_time_mp + delta); + int64_t cur_time_av = CMTimeGetNanoseconds([p->synchronizer currentTime]); + int64_t cur_time_mp = mp_time_ns(); + int64_t end_time_av = MPMAX(p->end_time_av, cur_time_av); + int64_t time_delta = CMTimeGetNanoseconds(CMTimeMake(request_sample_count, samplerate)); + int real_sample_count = ao_read_data_nonblocking(ao, data, request_sample_count, end_time_av - cur_time_av + cur_time_mp + time_delta); if (real_sample_count == 0) { - mp_sleep_ns(1000000); // avoid spinning + // avoid spinning by blocking the thread. + mp_sleep_ns(1000000); goto finish; } CMSampleTimingInfo sample_timing_into[] = {(CMSampleTimingInfo) { - .duration = CMTimeMake(1, ao->samplerate), - .presentationTimeStamp = CMTimeFromNanoseconds(p->end_time_av), + .duration = CMTimeMake(1, samplerate), + .presentationTimeStamp = CMTimeFromNanoseconds(end_time_av), .decodeTimeStamp = kCMTimeInvalid }}; - size_t sample_size_array[] = {ao->sstride}; - if (CMSampleBufferCreateReady( + size_t sample_size_array[] = {sstride}; + if ((err = CMSampleBufferCreateReady( kCFAllocatorDefault, block_buffer, p->format_description, @@ -113,15 +119,16 @@ static void feed(struct ao *ao) 1, sample_size_array, &sample_buffer - ) != noErr) { - MP_FATAL(ao, "failed to create CMSampleBuffe\n"); + )) != noErr) { + MP_FATAL(ao, "failed to create sample buffer\n"); + MP_VERBOSE(ao, "CMSampleBufferCreateReady returned %d\n", err); goto error; } [p->renderer enqueueSampleBuffer:sample_buffer]; - delta = CMTimeGetNanoseconds(CMTimeMake(real_sample_count, ao->samplerate)); - p->end_time_av += delta; + time_delta = CMTimeGetNanoseconds(CMTimeMake(real_sample_count, samplerate)); + p->end_time_av = end_time_av + time_delta; goto finish; @@ -162,21 +169,16 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) case AOCONTROL_GET_MUTE: *(bool*)arg = [p->renderer isMuted]; return CONTROL_OK; - case AOCONTROL_GET_VOLUME: *(float*)arg = [p->renderer volume] * 100; return CONTROL_OK; - case AOCONTROL_SET_MUTE: [p->renderer setMuted:*(bool*)arg]; return CONTROL_OK; - case AOCONTROL_SET_VOLUME: [p->renderer setVolume:*(float*)arg / 100]; return CONTROL_OK; - default: - // AOCONTROL_UPDATE_STREAM_TITLE should be handled by remote_command_center.swift return CONTROL_UNKNOWN; } } @@ -211,11 +213,13 @@ static int init(struct ao *ao) #endif if ((p->renderer = [[AVSampleBufferAudioRenderer alloc] init]) == nil) { - MP_FATAL(ao, "failed to create AVSampleBufferAudioRenderer\n"); + MP_FATAL(ao, "failed to create audio renderer\n"); + MP_VERBOSE(ao, "AVSampleBufferAudioRenderer failed to initialize\n"); goto error; } if ((p->synchronizer = [[AVSampleBufferRenderSynchronizer alloc] init]) == nil) { - MP_FATAL(ao, "failed to create AVSampleBufferRenderSynchronizer\n"); + MP_FATAL(ao, "failed to create rendering synchronizer\n"); + MP_VERBOSE(ao, "AVSampleBufferRenderSynchronizer failed to initialize\n"); goto error; } if ((p->queue = dispatch_queue_create( @@ -223,6 +227,7 @@ static int init(struct ao *ao) dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, 0) )) == NULL) { MP_FATAL(ao, "failed to create dispatch queue\n"); + MP_VERBOSE(ao, "dispatch_queue_create failed\n"); goto error; } @@ -269,7 +274,8 @@ static int init(struct ao *ao) talloc_free(talloc_ctx); ca_log_layout(ao, MSGL_V, layout); - if (CMAudioFormatDescriptionCreate( + OSStatus err; + if ((err = CMAudioFormatDescriptionCreate( kCFAllocatorDefault, &asbd, layout_size, @@ -278,8 +284,9 @@ static int init(struct ao *ao) NULL, NULL, &p->format_description - ) != noErr) { - MP_FATAL(ao, "failed to create CMAudioFormatDescription\n"); + )) != noErr) { + MP_FATAL(ao, "failed to create audio format description\n"); + MP_VERBOSE(ao, "CMAudioFormatDescriptionCreate returned %d\n", err); goto error; } talloc_free(layout);