[vlc-devel] [PATCH] opensles: protect buffer array with a spinlock
Rafaël Carré
funman at videolan.org
Sat Jan 21 13:45:25 CET 2012
Le 2012-01-21 07:40, Rafaël Carré a écrit :
> 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;
> }
I still see problems with this patch, e.g.
in logcat:
W/libOpenSLES(13045): Leaving BufferQueue::Enqueue
(SL_RESULT_BUFFER_INSUFFICIENT)
E/vlc (13045): buffer insufficient
W/libOpenSLES(13045): Leaving BufferQueue::Enqueue
(SL_RESULT_PARAMETER_INVALID)
W/vlc (13045): Error 2, dropping buffer
in gdb:
Program received signal SIGSEGV, Segmentation fault.
(gdb) frame 0
#0 0x00000000 in ?? ()
(gdb) frame 1
#1 0x463e2cb8 in block_Release (p_block=0x42bec8) at
../../../extras/package/android/../../../include/vlc_block.h:161
161 p_block->pf_release( p_block );
(gdb) print *p_block
$2 = {p_next = 0x458880, p_buffer = 0x458880 "", i_buffer = 0, i_flags =
0, i_nb_samples = 716142024, i_pts = 47244640259, i_dts = 1101004800,
i_length = 4740038608952164352, pf_release = 0x1}
(gdb) frame 2
#2 0x463e3f30 in Play (p_aout=0x3eae78, p_buffer=0x42bec8) at
../../../extras/package/android/../../../include/vlc_block.h:234
234 p_list = p_list->p_next;
amem works fine though
More information about the vlc-devel
mailing list