[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