static int TimeGet (audio_output_t *, mtime_t *);
static OSStatus RenderCallback (vlc_object_t *, AudioUnitRenderActionFlags *, const AudioTimeStamp *,
UInt32 , UInt32, AudioBufferList *);
+
vlc_module_begin ()
set_shortname("audiounit_ios")
set_description(N_("AudioUnit output for iOS"))
status = AudioComponentInstanceNew(p_sys->au_component, &p_sys->au_unit);
if (status != noErr) {
- msg_Warn(p_aout, "we cannot open our audio component (%li)", status);
+ msg_Warn(p_aout, "we cannot open our audio component (%i)", (int)status);
return false;
}
&flag,
sizeof(flag));
if (status != noErr)
- msg_Warn(p_aout, "failed to set IO mode (%li)", status);
+ msg_Warn(p_aout, "failed to set IO mode (%i)", (int)status);
/* Get the current format */
AudioStreamBasicDescription streamDescription;
streamDescription.mSampleRate = fmt->i_rate;
fmt->i_format = VLC_CODEC_FL32;
- fmt->i_physical_channels = AOUT_CHANS_STEREO;
+ fmt->i_physical_channels = fmt->i_original_channels = AOUT_CHANS_STEREO;
streamDescription.mFormatID = kAudioFormatLinearPCM;
streamDescription.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; // FL32
streamDescription.mChannelsPerFrame = aout_FormatNbChannels(fmt);
&streamDescription,
i_param_size);
if (status != noErr) {
- msg_Err(p_aout, "failed to set stream format (%li)", status);
+ msg_Err(p_aout, "failed to set stream format (%i)", (int)status);
return false;
}
msg_Dbg(p_aout, STREAM_FORMAT_MSG("we set the AU format: " , streamDescription));
&streamDescription,
&i_param_size);
if (status != noErr)
- msg_Warn(p_aout, "failed to verify stream format (%li)", status);
+ msg_Warn(p_aout, "failed to verify stream format (%i)", (int)status);
msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is " , streamDescription));
/* Do the last VLC aout setups */
kAudioUnitScope_Input,
0, &callback, sizeof(callback));
if (status != noErr) {
- msg_Err(p_aout, "render callback setup failed (%li)", status);
+ msg_Err(p_aout, "render callback setup failed (%i)", (int)status);
return false;
}
/* AU init */
status = AudioUnitInitialize(p_sys->au_unit);
if (status != noErr) {
- msg_Err(p_aout, "failed to init AudioUnit (%li)", status);
+ msg_Err(p_aout, "failed to init AudioUnit (%i)", (int)status);
return false;
}
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory),&sessionCategory);
AudioSessionSetActive(true);
+ /* start the unit */
status = AudioOutputUnitStart(p_sys->au_unit);
- msg_Dbg(p_aout, "audio output unit started: %li", status);
+ msg_Dbg(p_aout, "audio output unit started: %i", (int)status);
return true;
}
if (p_sys->au_unit) {
status = AudioOutputUnitStop(p_sys->au_unit);
if (status != noErr)
- msg_Warn(p_aout, "failed to stop AudioUnit (%li)", status);
+ msg_Warn(p_aout, "failed to stop AudioUnit (%i)", (int)status);
status = AudioComponentInstanceDispose(p_sys->au_unit);
if (status != noErr)
- msg_Warn(p_aout, "failed to dispose Audio Component instance (%li)", status);
+ msg_Warn(p_aout, "failed to dispose Audio Component instance (%i)", (int)status);
}
p_sys->i_bytes_per_sample = 0;
p_sys->b_paused = pause;
vlc_mutex_unlock(&p_sys->lock);
- if (pause)
+ /* we need to start / stop the audio unit here because otherwise
+ * the OS won't believe us that we stopped the audio output
+ * so in case of an interruption, our unit would be permanently
+ * silenced.
+ * in case of multi-tasking, the multi-tasking view would still
+ * show a playing state despite we are paused, same for lock screen */
+ if (pause) {
+ AudioOutputUnitStop(p_sys->au_unit);
AudioSessionSetActive(false);
- else
+ } else {
+ AudioOutputUnitStart(p_sys->au_unit);
+ UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
+ AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory),&sessionCategory);
AudioSessionSetActive(true);
+ }
}
static void Flush(audio_output_t *p_aout, bool wait)
{
- struct aout_sys_t * p_sys = p_aout->sys;
+ struct aout_sys_t *p_sys = p_aout->sys;
+
+ int32_t availableBytes;
+ vlc_mutex_lock(&p_sys->lock);
+ TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes);
if (wait) {
- int32_t availableBytes;
- vlc_mutex_lock(&p_sys->lock);
- TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes);
while (availableBytes > 0) {
vlc_cond_wait(&p_sys->cond, &p_sys->lock);
TPCircularBufferTail(&p_sys->circular_buffer, &availableBytes);
}
- vlc_mutex_unlock(&p_sys->lock);
- } else
- /* flush circular buffer */
- TPCircularBufferClear(&p_aout->sys->circular_buffer);
+ } else {
+ /* flush circular buffer if data is left */
+ if (availableBytes > 0)
+ TPCircularBufferClear(&p_aout->sys->circular_buffer);
+ }
+
+ vlc_mutex_unlock(&p_sys->lock);
}
static int TimeGet(audio_output_t *p_aout, mtime_t *delay)
} else {
int32_t bytesToCopy = __MIN(bytesRequested, availableBytes);
- memcpy(targetBuffer, buffer, bytesToCopy);
- TPCircularBufferConsume(&p_sys->circular_buffer, bytesToCopy);
- ioData->mBuffers[0].mDataByteSize = bytesToCopy;
+ if (likely(bytesToCopy > 0)) {
+ memcpy(targetBuffer, buffer, bytesToCopy);
+ TPCircularBufferConsume(&p_sys->circular_buffer, bytesToCopy);
+ ioData->mBuffers[0].mDataByteSize = bytesToCopy;
+ }
}
vlc_cond_signal(&p_sys->cond);