[vlc-commits] [Git][videolan/vlc][master] 6 commits: coreaudio: add ca_MuteSet()
Jean-Baptiste Kempf
gitlab at videolan.org
Thu May 27 09:37:34 UTC 2021
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
09de6e91 by Thomas Guillem at 2021-05-27T08:59:51+00:00
coreaudio: add ca_MuteSet()
This will write 0s from the render callback without touching at the
playback buffer state.
- - - - -
33a04f1c by Thomas Guillem at 2021-05-27T08:59:51+00:00
coreaudio: notify when the output is silence
It can be used as a hint to whether the buffer needs to be processed or
not.
- - - - -
929ce490 by Thomas Guillem at 2021-05-27T08:59:51+00:00
audiounit_ios: use ca_MuteSet
Fix data race with au_init, leading to crashes, since the audiounit was
stopped from a different thread than the playback one. Indeed, mute
callback can be called from any threads.
- - - - -
f7c4d13f by Thomas Guillem at 2021-05-27T08:59:51+00:00
auhal: use ca_MuteSet
Fix data race with au_unit. Indeed, the aout can be muted from any
threads.
SPDIF playback can now be muted.
- - - - -
42937c98 by Thomas Guillem at 2021-05-27T08:59:51+00:00
auhal: reset au_unit in case of failure or when stopped
- - - - -
dcb42685 by Thomas Guillem at 2021-05-27T08:59:51+00:00
auhal: fix data race with VolumeSet
VolumeSet (called from any threads) was accessing the au_unit variable,
that is written and setup from the aout stream thread.
This also fixes possible crashes when changing the volume after a
failing Start().
- - - - -
4 changed files:
- modules/audio_output/audiounit_ios.m
- modules/audio_output/auhal.c
- modules/audio_output/coreaudio_common.c
- modules/audio_output/coreaudio_common.h
Changes:
=====================================
modules/audio_output/audiounit_ios.m
=====================================
@@ -408,15 +408,8 @@ Pause (audio_output_t *p_aout, bool pause, vlc_tick_t date)
static int
MuteSet(audio_output_t *p_aout, bool mute)
{
- aout_sys_t * p_sys = p_aout->sys;
-
- p_sys->b_muted = mute;
- if (p_sys->au_unit != NULL)
- {
- Pause(p_aout, mute, 0);
- if (mute)
- ca_Flush(p_aout);
- }
+ ca_MuteSet(p_aout, mute);
+ aout_MuteReport(p_aout, mute);
return VLC_SUCCESS;
}
=====================================
modules/audio_output/auhal.c
=====================================
@@ -118,8 +118,14 @@ typedef struct
* thread (start, stop, close) needs no protection. */
vlc_mutex_t selected_device_lock;
+ /* Synchronizes access to au_unit and f_volume. This is needed by the
+ * VolumeSet callback, that can be called from any threads. The au_unit
+ * variable is written in the start and stop callbacks from the aout
+ * thread. Streams callbacks (play, pause, flush...) doesn't need this lock
+ * to access au_unit since they are called from the aout thread. */
+ vlc_mutex_t volume_lock;
+
float f_volume;
- bool b_mute;
bool b_ignore_streams_changed_callback;
} aout_sys_t;
@@ -897,27 +903,25 @@ SwitchAudioDevice(audio_output_t *p_aout, const char *name)
}
static int
-VolumeSet(audio_output_t * p_aout, float volume)
+VolumeSetLocked(audio_output_t * p_aout, float volume)
{
aout_sys_t *p_sys = p_aout->sys;
- OSStatus err = noErr;
+ OSStatus err;
- if (p_sys->b_digital)
+ p_sys->f_volume = volume;
+
+ if (p_sys->au_unit == NULL)
return VLC_EGENERIC;
- p_sys->f_volume = volume;
aout_VolumeReport(p_aout, volume);
/* Set volume for output unit */
- if (!p_sys->b_mute)
- {
- err = AudioUnitSetParameter(p_sys->au_unit,
- kHALOutputParam_Volume,
- kAudioUnitScope_Global,
- 0,
- volume * volume * volume,
- 0);
- }
+ err = AudioUnitSetParameter(p_sys->au_unit,
+ kHALOutputParam_Volume,
+ kAudioUnitScope_Global,
+ 0,
+ volume * volume * volume,
+ 0);
if (var_InheritBool(p_aout, "volume-save"))
config_PutInt("auhal-volume", lroundf(volume * AOUT_VOLUME_DEFAULT));
@@ -926,26 +930,23 @@ VolumeSet(audio_output_t * p_aout, float volume)
}
static int
-MuteSet(audio_output_t * p_aout, bool mute)
+VolumeSet(audio_output_t * p_aout, float volume)
{
aout_sys_t *p_sys = p_aout->sys;
- if (p_sys->b_digital)
- return VLC_EGENERIC;
+ vlc_mutex_lock(&p_sys->volume_lock);
+ int ret = VolumeSetLocked(p_aout, volume);
+ vlc_mutex_unlock(&p_sys->volume_lock);
+ return ret;
+}
- p_sys->b_mute = mute;
+static int
+MuteSet(audio_output_t * p_aout, bool mute)
+{
+ ca_MuteSet(p_aout, mute);
aout_MuteReport(p_aout, mute);
- float volume = .0;
- if (!mute)
- volume = p_sys->f_volume;
-
- OSStatus err =
- AudioUnitSetParameter(p_sys->au_unit, kHALOutputParam_Volume,
- kAudioUnitScope_Global, 0,
- volume * volume * volume, 0);
-
- return (err == noErr) ? VLC_SUCCESS : VLC_EGENERIC;
+ return VLC_SUCCESS;
}
#pragma mark -
@@ -975,7 +976,7 @@ RenderCallbackSPDIF(AudioDeviceID inDevice, const AudioTimeStamp * inNow,
uint64_t i_host_time = (inOutputTime->mFlags & kAudioTimeStampHostTimeValid)
? inOutputTime->mHostTime : 0;
- ca_Render(p_aout, 0, i_host_time, p_output, i_size);
+ ca_Render(p_aout, 0, i_host_time, p_output, i_size, NULL);
return noErr;
}
@@ -1120,8 +1121,7 @@ StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
}
/* Set volume for output unit */
- VolumeSet(p_aout, p_sys->f_volume);
- MuteSet(p_aout, p_sys->b_mute);
+ VolumeSetLocked(p_aout, p_sys->f_volume);
free(layout);
@@ -1131,6 +1131,7 @@ StartAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
return VLC_SUCCESS;
error:
AudioComponentInstanceDispose(p_sys->au_unit);
+ p_sys->au_unit = NULL;
free(layout);
return VLC_EGENERIC;
}
@@ -1414,9 +1415,14 @@ Stop(audio_output_t *p_aout)
if (p_sys->au_unit)
{
+ vlc_mutex_lock(&p_sys->volume_lock);
+
AudioOutputUnitStop(p_sys->au_unit);
au_Uninitialize(p_aout, p_sys->au_unit);
AudioComponentInstanceDispose(p_sys->au_unit);
+ p_sys->au_unit = NULL;
+
+ vlc_mutex_unlock(&p_sys->volume_lock);
}
else
{
@@ -1504,8 +1510,6 @@ Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
return VLC_EGENERIC;
p_sys = p_aout->sys;
- p_sys->b_digital = false;
- p_sys->au_unit = NULL;
p_sys->i_stream_index = -1;
p_sys->b_revert = false;
p_sys->b_changed_mixing = false;
@@ -1614,7 +1618,11 @@ Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
}
else
{
- if (StartAnalog(p_aout, fmt) == VLC_SUCCESS)
+ vlc_mutex_lock(&p_sys->volume_lock);
+ int ret = StartAnalog(p_aout, fmt);
+ vlc_mutex_unlock(&p_sys->volume_lock);
+
+ if (ret == VLC_SUCCESS)
{
msg_Dbg(p_aout, "analog output successfully opened");
fmt->channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
@@ -1699,7 +1707,9 @@ static int Open(vlc_object_t *obj)
vlc_mutex_init(&p_sys->device_list_lock);
vlc_mutex_init(&p_sys->selected_device_lock);
+ vlc_mutex_init(&p_sys->volume_lock);
p_sys->b_digital = false;
+ p_sys->au_unit = NULL;
p_sys->b_ignore_streams_changed_callback = false;
p_sys->b_selected_dev_is_default = false;
memset(&p_sys->sfmt_revert, 0, sizeof(p_sys->sfmt_revert));
@@ -1764,8 +1774,7 @@ static int Open(vlc_object_t *obj)
p_sys->f_volume = var_InheritInteger(p_aout, "auhal-volume")
/ (float)AOUT_VOLUME_DEFAULT;
aout_VolumeReport(p_aout, p_sys->f_volume);
- p_sys->b_mute = var_InheritBool(p_aout, "mute");
- aout_MuteReport(p_aout, p_sys->b_mute);
+ MuteSet(p_aout, var_InheritBool(p_aout, "mute"));
return VLC_SUCCESS;
}
=====================================
modules/audio_output/coreaudio_common.c
=====================================
@@ -140,7 +140,7 @@ ca_Open(audio_output_t *p_aout)
/* Called from render callbacks. No lock, wait, and IO here */
void
ca_Render(audio_output_t *p_aout, uint32_t i_frames, uint64_t i_host_time,
- uint8_t *p_output, size_t i_requested)
+ uint8_t *p_output, size_t i_requested, bool *is_silence)
{
struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
@@ -203,7 +203,10 @@ ca_Render(audio_output_t *p_aout, uint32_t i_frames, uint64_t i_host_time,
while (p_block != NULL && i_requested != 0)
{
size_t i_tocopy = __MIN(i_requested, p_block->i_buffer);
- memcpy(p_output, p_block->p_buffer, i_tocopy);
+ if (unlikely(p_sys->b_muted))
+ memset(p_output, 0, i_tocopy);
+ else
+ memcpy(p_output, p_block->p_buffer, i_tocopy);
i_requested -= i_tocopy;
i_copied += i_tocopy;
p_output += i_tocopy;
@@ -235,11 +238,15 @@ ca_Render(audio_output_t *p_aout, uint32_t i_frames, uint64_t i_host_time,
memset(p_output, 0, i_requested);
}
+ if (is_silence != NULL)
+ *is_silence = p_sys->b_muted;
lock_unlock(p_sys);
return;
drop:
memset(p_output, 0, i_requested);
+ if (is_silence != NULL)
+ *is_silence = true;
lock_unlock(p_sys);
}
@@ -313,6 +320,16 @@ ca_Pause(audio_output_t * p_aout, bool pause, vlc_tick_t date)
lock_unlock(p_sys);
}
+void
+ca_MuteSet(audio_output_t * p_aout, bool muted)
+{
+ struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
+
+ lock_lock(p_sys);
+ p_sys->b_muted = muted;
+ lock_unlock(p_sys);
+}
+
void
ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
{
@@ -415,6 +432,7 @@ ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
p_sys->i_underrun_size = 0;
p_sys->b_paused = false;
+ p_sys->b_muted = false;
p_sys->i_render_host_time = p_sys->i_first_render_host_time = 0;
p_sys->i_render_frames = 0;
@@ -533,8 +551,11 @@ RenderCallback(void *p_data, AudioUnitRenderActionFlags *ioActionFlags,
uint64_t i_host_time = (inTimeStamp->mFlags & kAudioTimeStampHostTimeValid)
? inTimeStamp->mHostTime : 0;
+ bool is_silence;
ca_Render(p_data, inNumberFrames, i_host_time, ioData->mBuffers[0].mData,
- ioData->mBuffers[0].mDataByteSize);
+ ioData->mBuffers[0].mDataByteSize, &is_silence);
+ if (is_silence)
+ *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
return noErr;
}
=====================================
modules/audio_output/coreaudio_common.h
=====================================
@@ -53,6 +53,7 @@ struct aout_sys_common
size_t i_underrun_size;
bool b_paused;
+ bool b_muted;
bool b_do_flush;
size_t i_out_max_size;
@@ -87,7 +88,7 @@ struct aout_sys_common
int ca_Open(audio_output_t *p_aout);
void ca_Render(audio_output_t *p_aout, uint32_t i_nb_samples, uint64_t i_host_time,
- uint8_t *p_output, size_t i_requested);
+ uint8_t *p_output, size_t i_requested, bool *is_silence);
int ca_TimeGet(audio_output_t *p_aout, vlc_tick_t *delay);
@@ -95,6 +96,8 @@ void ca_Flush(audio_output_t *p_aout);
void ca_Pause(audio_output_t * p_aout, bool pause, vlc_tick_t date);
+void ca_MuteSet(audio_output_t * p_aout, bool mute);
+
void ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date);
int ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
@@ -114,3 +117,5 @@ int au_Initialize(audio_output_t *p_aout, AudioUnit au,
bool *warn_configuration);
void au_Uninitialize(audio_output_t *p_aout, AudioUnit au);
+
+void au_VolumeSet(audio_output_t *p_aout);
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/42bc3b3d8f32c6199015d6482454aaa90cabb404...dcb42685eb18e3f36c2e0e86429d38098f1c036c
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/42bc3b3d8f32c6199015d6482454aaa90cabb404...dcb42685eb18e3f36c2e0e86429d38098f1c036c
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list