[vlc-devel] [PATCH] opensles: protect buffer array with a spinlock

Rafaël Carré funman at videolan.org
Sat Jan 21 13:40:43 CET 2012


Append buffer to array before playing it back.

The callback might fire after Enqueue() returned, but before we append
the buffer.

We could lock the whole call to Enqueue but it is simpler to just
increment the array index after the function succeeded.
If it failed, callback will not be called anyway.
---
 modules/audio_output/opensles_android.c |   17 +++++++++++++++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/modules/audio_output/opensles_android.c b/modules/audio_output/opensles_android.c
index 906b6bb..0afb6cb 100644
--- a/modules/audio_output/opensles_android.c
+++ b/modules/audio_output/opensles_android.c
@@ -64,6 +64,7 @@ struct aout_sys_t
     SLInterfaceID                 * SL_IID_VOLUME;
     SLInterfaceID                 * SL_IID_PLAY;
     void                          * p_so_handle;
+    vlc_spinlock_t                  lock;
 };
 
 typedef SLresult (*slCreateEngine_t)(
@@ -249,6 +250,8 @@ static int Open( vlc_object_t *p_this )
                                                  SL_PLAYSTATE_PLAYING );
     CHECK_OPENSL_ERROR( result, "Failed to switch to playing state" );
 
+    vlc_spin_init(&p_sys->lock);
+
     // we want 16bit signed data little endian.
     p_aout->format.i_format              = VLC_CODEC_S16L;
     p_aout->format.i_physical_channels   = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
@@ -278,6 +281,9 @@ static void Close( vlc_object_t *p_this )
     //Flush remaining buffers if any.
     if( p_sys->playerBufferQueue != NULL )
         (*p_sys->playerBufferQueue)->Clear( p_sys->playerBufferQueue );
+
+    vlc_spin_destroy(&p_sys->lock);
+
     Clear( p_sys );
 }
 
@@ -289,6 +295,9 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
     aout_sys_t *p_sys = p_aout->sys;
     int tries = 5;
 
+    vlc_spin_lock(&p_sys->lock);
+    p_sys->p_buffer_array[p_sys->i_toappend_buffer] = p_buffer;
+    vlc_spin_unlock(&p_sys->lock);
     for (;;)
     {
         SLresult result = (*p_sys->playerBufferQueue)->Enqueue(
@@ -298,7 +307,6 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
         switch (result)
         {
         case SL_RESULT_SUCCESS:
-            p_sys->p_buffer_array[p_sys->i_toappend_buffer] = p_buffer;
             if( ++p_sys->i_toappend_buffer == BUFF_QUEUE )
                 p_sys->i_toappend_buffer = 0;
             return;
@@ -324,10 +332,15 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
 static void PlayedCallback (SLAndroidSimpleBufferQueueItf caller, void *pContext )
 {
     aout_sys_t *p_sys = pContext;
+    block_t *p_buffer;
 
     assert (caller == p_sys->playerBufferQueue);
 
-    aout_BufferFree( p_sys->p_buffer_array[p_sys->i_toclean_buffer] );
+    vlc_spin_lock(&p_sys->lock);
+    p_buffer =  p_sys->p_buffer_array[p_sys->i_toclean_buffer];
+    vlc_spin_unlock(&p_sys->lock);
+
+    aout_BufferFree( p_buffer );
     if( ++p_sys->i_toclean_buffer == BUFF_QUEUE )
         p_sys->i_toclean_buffer = 0;
 }
-- 
1.7.8.3



More information about the vlc-devel mailing list