android: remove get_android_opaque_mutex()
authorThomas Guillem <thomas@gllm.fr>
Tue, 8 Sep 2015 14:17:47 +0000 (16:17 +0200)
committerThomas Guillem <thomas@gllm.fr>
Tue, 8 Sep 2015 14:19:52 +0000 (16:19 +0200)
Replace it with a mutex per picture_sys_t. When doing direct rendering, the
picture_sys_t is refcounted between the vout and the decoder.

modules/codec/Makefile.am
modules/codec/omxil/android_opaque.c [deleted file]
modules/codec/omxil/android_opaque.h [deleted file]
modules/codec/omxil/mediacodec.c
modules/codec/omxil/omxil.c
modules/codec/omxil/omxil.h
modules/video_output/android/android_window.c
modules/video_output/android/android_window.h

index 4ae29ac..3b01dde 100644 (file)
@@ -417,7 +417,7 @@ libiomx_plugin_la_LIBADD = $(libomxil_plugin_la_LIBADD)
 libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
 libmediacodec_plugin_la_SOURCES = codec/omxil/mediacodec.c codec/omxil/mediacodec.h \
        codec/omxil/mediacodec_jni.c codec/omxil/mediacodec_ndk.c codec/omxil/utils.c \
-       video_chroma/copy.c codec/omxil/android_opaque.c codec/omxil/android_opaque.h \
+       video_chroma/copy.c
        video_output/android/utils.c video_output/android/utils.h
        packetizer/h264_nal.c packetizer/h264_nal.h
        packetizer/hevc_nal.c packetizer/hevc_nal.h
diff --git a/modules/codec/omxil/android_opaque.c b/modules/codec/omxil/android_opaque.c
deleted file mode 100644 (file)
index 7a06842..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*****************************************************************************
- * android_opaque.c: shared structures between MediaCodec decoder
- * and MediaCodec video output
- *****************************************************************************
- * Copyright (C) 2013 Felix Abecassis
- *
- * Authors: Felix Abecassis <felix.abecassis@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#include "android_opaque.h"
-
-vlc_mutex_t* get_android_opaque_mutex()
-{
-    static vlc_mutex_t s_mutex = VLC_STATIC_MUTEX;
-    return &s_mutex;
-}
diff --git a/modules/codec/omxil/android_opaque.h b/modules/codec/omxil/android_opaque.h
deleted file mode 100644 (file)
index 5d8b1e6..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*****************************************************************************
- * android_opaque.h: shared structures between MediaCodec decoder
- * and MediaCodec video output
- *****************************************************************************
- * Copyright (C) 2013 Felix Abecassis
- *
- * Authors: Felix Abecassis <felix.abecassis@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifndef ANDROID_OPAQUE_H_
-#define ANDROID_OPAQUE_H_
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <vlc_common.h>
-
-vlc_mutex_t* get_android_opaque_mutex(void);
-
-#endif
index 62987f6..c37924d 100644 (file)
@@ -46,7 +46,6 @@
 #include <OMX_Core.h>
 #include <OMX_Component.h>
 #include "omxil_utils.h"
-#include "android_opaque.h"
 #include "../../video_output/android/android_window.h"
 
 /* JNI functions to get/set an Android Surface object. */
@@ -117,7 +116,7 @@ struct decoder_sys_t
             size_t i_h264_profile;
             ArchitectureSpecificCopyData ascd;
             /* stores the inflight picture for each output buffer or NULL */
-            picture_t** pp_inflight_pictures;
+            picture_sys_t** pp_inflight_pictures;
             unsigned int i_inflight_pictures;
             timestamp_fifo_t *timestamp_fifo;
         } video;
@@ -150,7 +149,7 @@ static int Audio_ProcessOutput(decoder_t *, mc_api_out *, picture_t **, block_t
 static block_t *DecodeAudio(decoder_t *, block_t **);
 
 static void InvalidateAllPictures(decoder_t *);
-static int InsertInflightPicture(decoder_t *, picture_t *, unsigned int );
+static void RemoveInflightPictures(decoder_t *);
 
 /*****************************************************************************
  * Module descriptor
@@ -453,10 +452,10 @@ static void StopMediaCodec(decoder_t *p_dec)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    /* Invalidate all pictures that are currently in flight in order
+    /* Remove all pictures that are currently in flight in order
      * to prevent the vout from using destroyed output buffers. */
     if (p_sys->api->b_direct_rendering)
-        InvalidateAllPictures(p_dec);
+        RemoveInflightPictures(p_dec);
 
     p_sys->api->stop(p_sys->api);
     if (p_dec->fmt_in.i_cat == VIDEO_ES && p_sys->u.video.p_awh)
@@ -576,6 +575,8 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
         p_sys->u.video.timestamp_fifo = timestamp_FifoNew(32);
         if (!p_sys->u.video.timestamp_fifo)
             goto bailout;
+        TAB_INIT( p_sys->u.video.i_inflight_pictures,
+                  p_sys->u.video.pp_inflight_pictures );
 
         if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
             h264_get_profile_level(&p_dec->fmt_in,
@@ -673,7 +674,6 @@ static void CloseDecoder(vlc_object_t *p_this)
     {
         ArchitectureSpecificCopyHooksDestroy(p_sys->u.video.i_pixel_format,
                                              &p_sys->u.video.ascd);
-        free(p_sys->u.video.pp_inflight_pictures);
         if (p_sys->u.video.timestamp_fifo)
             timestamp_FifoRelease(p_sys->u.video.timestamp_fifo);
         if (p_sys->u.video.p_awh)
@@ -687,73 +687,48 @@ static void CloseDecoder(vlc_object_t *p_this)
 /*****************************************************************************
  * vout callbacks
  *****************************************************************************/
-static void UnlockPicture(picture_t* p_pic, bool b_render)
+static void ReleasePicture(decoder_t *p_dec, unsigned i_index, bool b_render)
 {
-    picture_sys_t *p_picsys = p_pic->p_sys;
-    decoder_t *p_dec = p_picsys->priv.hw.p_dec;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if (!p_picsys->priv.hw.b_valid)
-        return;
-
-    vlc_mutex_lock(get_android_opaque_mutex());
-
-    /* Picture might have been invalidated while waiting on the mutex. */
-    if (!p_picsys->priv.hw.b_valid) {
-        vlc_mutex_unlock(get_android_opaque_mutex());
-        return;
-    }
-
-    uint32_t i_index = p_picsys->priv.hw.i_index;
-    InsertInflightPicture(p_dec, NULL, i_index);
-
-    /* Release the MediaCodec buffer. */
     p_sys->api->release_out(p_sys->api, i_index, b_render);
-    p_picsys->priv.hw.b_valid = false;
-
-    vlc_mutex_unlock(get_android_opaque_mutex());
 }
 
 static void InvalidateAllPictures(decoder_t *p_dec)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    vlc_mutex_lock(get_android_opaque_mutex());
-
-    for (unsigned int i = 0; i < p_sys->u.video.i_inflight_pictures; ++i) {
-        picture_t *p_pic = p_sys->u.video.pp_inflight_pictures[i];
-        if (p_pic) {
-            if (p_pic->p_sys->priv.hw.b_valid)
-            {
-                p_sys->api->release_out(p_sys->api, p_pic->p_sys->priv.hw.i_index, false);
-                p_pic->p_sys->priv.hw.b_valid = false;
-            }
-            p_sys->u.video.pp_inflight_pictures[i] = NULL;
-        }
-    }
-    vlc_mutex_unlock(get_android_opaque_mutex());
+    for (unsigned int i = 0; i < p_sys->u.video.i_inflight_pictures; ++i)
+        AndroidOpaquePicture_Release(p_sys->u.video.pp_inflight_pictures[i],
+                                     false);
 }
 
-static int InsertInflightPicture(decoder_t *p_dec, picture_t *p_pic,
-                                 unsigned int i_index)
+static int InsertInflightPicture(decoder_t *p_dec, picture_sys_t *p_picsys)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if (i_index >= p_sys->u.video.i_inflight_pictures) {
-        picture_t **pp_pics = realloc(p_sys->u.video.pp_inflight_pictures,
-                                      (i_index + 1) * sizeof (picture_t *));
-        if (!pp_pics)
-            return -1;
-        if (i_index - p_sys->u.video.i_inflight_pictures > 0)
-            memset(&pp_pics[p_sys->u.video.i_inflight_pictures], 0,
-                   (i_index - p_sys->u.video.i_inflight_pictures) * sizeof (picture_t *));
-        p_sys->u.video.pp_inflight_pictures = pp_pics;
-        p_sys->u.video.i_inflight_pictures = i_index + 1;
-    }
-    p_sys->u.video.pp_inflight_pictures[i_index] = p_pic;
+    if (!p_picsys->priv.hw.p_dec)
+    {
+        p_picsys->priv.hw.p_dec = p_dec;
+        p_picsys->priv.hw.pf_release = ReleasePicture;
+        TAB_APPEND_CAST((picture_sys_t **),
+                        p_sys->u.video.i_inflight_pictures,
+                        p_sys->u.video.pp_inflight_pictures,
+                        p_picsys);
+    } /* else already attached */
     return 0;
 }
 
+static void RemoveInflightPictures(decoder_t *p_dec)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    for (unsigned int i = 0; i < p_sys->u.video.i_inflight_pictures; ++i)
+        AndroidOpaquePicture_DetachDecoder(p_sys->u.video.pp_inflight_pictures[i]);
+    TAB_CLEAN(p_sys->u.video.i_inflight_pictures,
+              p_sys->u.video.pp_inflight_pictures);
+}
+
 static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
                                picture_t **pp_out_pic, block_t **pp_out_block)
 {
@@ -816,16 +791,8 @@ static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
 
         if (p_sys->api->b_direct_rendering)
         {
-            picture_sys_t *p_picsys = p_pic->p_sys;
-            p_picsys->pf_lock_pic = NULL;
-            p_picsys->pf_unlock_pic = UnlockPicture;
-            p_picsys->priv.hw.p_dec = p_dec;
-            p_picsys->priv.hw.i_index = p_out->u.buf.i_index;
-            p_picsys->priv.hw.b_valid = true;
-
-            vlc_mutex_lock(get_android_opaque_mutex());
-            InsertInflightPicture(p_dec, p_pic, p_out->u.buf.i_index);
-            vlc_mutex_unlock(get_android_opaque_mutex());
+            p_pic->p_sys->priv.hw.i_index = p_out->u.buf.i_index;
+            InsertInflightPicture(p_dec, p_pic->p_sys);
         } else {
             unsigned int chroma_div;
             GetVlcChromaSizes(p_dec->fmt_out.i_codec,
index a088f82..63470a5 100644 (file)
@@ -45,7 +45,6 @@
 #if defined(USE_IOMX)
 #include <dlfcn.h>
 #include <jni.h>
-#include "android_opaque.h"
 #include "../../video_output/android/android_window.h"
 #endif
 
@@ -91,7 +90,7 @@ static OMX_ERRORTYPE OmxFillBufferDone( OMX_HANDLETYPE, OMX_PTR,
 
 #if defined(USE_IOMX)
 static void *DequeueThread( void *data );
-static void UnlockPicture( picture_t* p_pic, bool b_render );
+static void ReleasePicture( decoder_t *p_dec, unsigned int i_index, bool b_render );
 static void HwBuffer_Init( decoder_t *p_dec, OmxPort *p_port );
 static void HwBuffer_Destroy( decoder_t *p_dec, OmxPort *p_port );
 static int  HwBuffer_AllocateBuffers( decoder_t *p_dec, OmxPort *p_port );
@@ -1611,11 +1610,8 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             if (invalid_picture) {
                 invalid_picture->date = VLC_TS_INVALID;
                 picture_sys_t *p_picsys = invalid_picture->p_sys;
-                p_picsys->pf_lock_pic = NULL;
-                p_picsys->pf_unlock_pic = NULL;
                 p_picsys->priv.hw.p_dec = NULL;
                 p_picsys->priv.hw.i_index = -1;
-                p_picsys->priv.hw.b_valid = false;
             } else {
                 /* If we cannot return a picture we must free the
                    block since the decoder will proceed with the
@@ -2240,7 +2236,7 @@ static int HwBuffer_AllocateBuffers( decoder_t *p_dec, OmxPort *p_port )
         goto error;
 
     p_port->p_hwbuf->inflight_picture = calloc( p_port->p_hwbuf->i_buffers,
-                                                sizeof(picture_t*) );
+                                                sizeof(picture_sys_t*) );
     if( !p_port->p_hwbuf->inflight_picture )
         goto error;
 
@@ -2375,19 +2371,10 @@ static int HwBuffer_Stop( decoder_t *p_dec, OmxPort *p_port )
     /* invalidate and release all inflight pictures */
     if( p_port->p_hwbuf->inflight_picture ) {
         for( unsigned int i = 0; i < p_port->i_buffers; ++i ) {
-            picture_t *p_pic = p_port->p_hwbuf->inflight_picture[i];
-            if( p_pic ) {
-                picture_sys_t *p_picsys = p_pic->p_sys;
-                if( p_picsys ) {
-                    void *p_handle = p_port->pp_buffers[p_picsys->priv.hw.i_index]->pBuffer;
-                    if( p_handle )
-                    {
-                        p_port->p_hwbuf->anwpriv->cancel( p_port->p_hwbuf->window_priv, p_handle );
-                        HwBuffer_ChangeState( p_dec, p_port, p_picsys->priv.hw.i_index,
-                                              BUF_STATE_NOT_OWNED );
-                    }
-                    p_picsys->priv.hw.b_valid = false;
-                }
+            picture_sys_t *p_picsys = p_port->p_hwbuf->inflight_picture[i];
+            if( p_picsys )
+            {
+                AndroidOpaquePicture_DetachDecoder(p_picsys);
                 p_port->p_hwbuf->inflight_picture[i] = NULL;
             }
         }
@@ -2454,13 +2441,11 @@ static int HwBuffer_GetPic( decoder_t *p_dec, OmxPort *p_port,
     p_pic->date = FromOmxTicks( p_header->nTimeStamp );
 
     p_picsys = p_pic->p_sys;
-    p_picsys->pf_lock_pic = NULL;
-    p_picsys->pf_unlock_pic = UnlockPicture;
-    p_picsys->priv.hw.p_dec = p_dec;
     p_picsys->priv.hw.i_index = i_index;
-    p_picsys->priv.hw.b_valid = true;
+    p_picsys->priv.hw.p_dec = p_dec;
+    p_picsys->priv.hw.pf_release = ReleasePicture;
 
-    p_port->p_hwbuf->inflight_picture[i_index] = p_pic;
+    p_port->p_hwbuf->inflight_picture[i_index] = p_picsys;
 
     *pp_pic = p_pic;
     OMX_FIFO_GET( &p_port->fifo, p_header );
@@ -2559,25 +2544,15 @@ static void *DequeueThread( void *data )
 /*****************************************************************************
  * vout callbacks
  *****************************************************************************/
-static void UnlockPicture( picture_t* p_pic, bool b_render )
+static void ReleasePicture( decoder_t *p_dec, unsigned int i_index,
+                            bool b_render )
 {
-    picture_sys_t *p_picsys = p_pic->p_sys;
-    decoder_t *p_dec = p_picsys->priv.hw.p_dec;
     decoder_sys_t *p_sys = p_dec->p_sys;
     OmxPort *p_port = &p_sys->out;
     void *p_handle;
 
     HWBUFFER_LOCK( p_port );
-    if( !p_picsys->priv.hw.b_valid ) return;
-
-
-    /* Picture might have been invalidated while waiting on the mutex. */
-    if (!p_picsys->priv.hw.b_valid) {
-        HWBUFFER_UNLOCK();
-        return;
-    }
-
-    p_handle = p_port->pp_buffers[p_picsys->priv.hw.i_index]->pBuffer;
+    p_handle = p_port->pp_buffers[i_index]->pBuffer;
 
     OMX_DBG( "DisplayBuffer: %s %p",
              b_render ? "render" : "cancel", p_handle );
@@ -2593,14 +2568,10 @@ static void UnlockPicture( picture_t* p_pic, bool b_render )
     else
         p_port->p_hwbuf->anwpriv->cancel( p_port->p_hwbuf->window_priv, p_handle );
 
-    HwBuffer_ChangeState( p_dec, p_port, p_picsys->priv.hw.i_index, BUF_STATE_NOT_OWNED );
+    HwBuffer_ChangeState( p_dec, p_port, i_index, BUF_STATE_NOT_OWNED );
     HWBUFFER_BROADCAST( p_port );
 
-    p_port->p_hwbuf->inflight_picture[p_picsys->priv.hw.i_index] = NULL;
-
 end:
-    p_picsys->priv.hw.b_valid = false;
-    p_picsys->priv.hw.i_index = -1;
 
     HWBUFFER_UNLOCK( p_port );
 }
index e5fd38a..1399c72 100644 (file)
@@ -67,7 +67,7 @@ typedef struct HwBuffer
     bool            b_run;
     vlc_mutex_t     lock;
     vlc_cond_t      wait;
-    picture_t**     inflight_picture; /**< stores the inflight picture for each output buffer or NULL */
+    picture_sys_t** inflight_picture; /**< stores the inflight picture for each output buffer or NULL */
 
     unsigned int    i_buffers;
     void            **pp_handles;
index e3cb300..5cbf00a 100644 (file)
@@ -176,7 +176,26 @@ static int UpdateWindowSize(vout_display_sys_t *sys, video_format_t *p_fmt,
     return 0;
 }
 
-static picture_t *PictureAlloc(vout_display_sys_t *sys, video_format_t *fmt)
+static void AndroidOpaquePicture_DetachVout(picture_t *p_pic)
+{
+    picture_sys_t *p_picsys = p_pic->p_sys;
+
+    vlc_mutex_lock(&p_picsys->priv.hw.lock);
+    p_pic->p_sys->p_vd_sys = NULL;
+    /* Release p_picsys if references from VOUT and from decoder are NULL */
+    if (!p_picsys->p_vd_sys && !p_picsys->priv.hw.p_dec)
+    {
+        vlc_mutex_unlock(&p_picsys->priv.hw.lock);
+        vlc_mutex_destroy(&p_picsys->priv.hw.lock);
+        free(p_picsys);
+    }
+    else
+        vlc_mutex_unlock(&p_picsys->priv.hw.lock);
+    free(p_pic);
+}
+
+static picture_t *PictureAlloc(vout_display_sys_t *sys, video_format_t *fmt,
+                               bool b_opaque)
 {
     picture_t *p_pic;
     picture_resource_t rsc;
@@ -188,7 +207,14 @@ static picture_t *PictureAlloc(vout_display_sys_t *sys, video_format_t *fmt)
     p_picsys->p_vd_sys = sys;
 
     memset(&rsc, 0, sizeof(picture_resource_t));
-    rsc.p_sys = p_picsys,
+    rsc.p_sys = p_picsys;
+
+    if (b_opaque)
+    {
+        p_picsys->priv.hw.i_index = -1;
+        vlc_mutex_init(&p_picsys->priv.hw.lock);
+        rsc.pf_destroy = AndroidOpaquePicture_DetachVout;
+    }
 
     p_pic = picture_NewFromResource(fmt, &rsc);
     if (!p_pic)
@@ -506,7 +532,7 @@ static int AndroidWindow_Setup(vout_display_sys_t *sys,
 
     if (!p_window->b_opaque) {
         int align_pixels;
-        picture_t *p_pic = PictureAlloc(sys, &p_window->fmt);
+        picture_t *p_pic = PictureAlloc(sys, &p_window->fmt, false);
 
         // For RGB (32 or 16) we need to align on 8 or 4 pixels, 16 pixels for YUV
         align_pixels = (16 / p_pic->p[0].i_pixel_pitch) - 1;
@@ -751,37 +777,30 @@ static void Close(vlc_object_t *p_this)
     free(sys);
 }
 
-static int DefaultLockPicture(picture_t *p_pic)
-{
-    picture_sys_t *p_picsys = p_pic->p_sys;
-    vout_display_sys_t *sys = p_picsys->p_vd_sys;
-
-    return AndroidWindow_LockPicture(sys, sys->p_window, p_pic);
-}
-
-static void DefaultUnlockPicture(picture_t *p_pic, bool b_render)
-{
-    picture_sys_t *p_picsys = p_pic->p_sys;
-    vout_display_sys_t *sys = p_picsys->p_vd_sys;
-
-    AndroidWindow_UnlockPicture(sys, sys->p_window, p_pic, b_render);
-}
-
 static void UnlockPicture(picture_t *p_pic, bool b_render)
 {
     picture_sys_t *p_picsys = p_pic->p_sys;
+    vout_display_sys_t *sys = p_picsys->p_vd_sys;
 
-    if (p_picsys->b_locked && p_picsys->pf_unlock_pic)
-        p_picsys->pf_unlock_pic(p_pic, b_render);
-    p_picsys->b_locked  = false;
+    if (p_picsys->b_locked)
+    {
+        if (sys->p_window->b_opaque)
+            AndroidOpaquePicture_Release(p_picsys, b_render);
+        else
+            AndroidWindow_UnlockPicture(sys, sys->p_window, p_pic, b_render);
+        p_picsys->b_locked  = false;
+    }
 }
 
 static int PoolLockPicture(picture_t *p_pic)
 {
     picture_sys_t *p_picsys = p_pic->p_sys;
+    vout_display_sys_t *sys = p_picsys->p_vd_sys;
 
-    if (p_picsys->pf_lock_pic && p_picsys->pf_lock_pic(p_pic) != 0)
+    if (!sys->p_window->b_opaque
+     && AndroidWindow_LockPicture(sys, sys->p_window, p_pic) != 0)
         return -1;
+
     p_picsys->b_locked = true;
     return 0;
 }
@@ -811,13 +830,10 @@ static picture_pool_t *PoolAlloc(vout_display_t *vd, unsigned requested_count)
 
     for (i = 0; i < requested_count; i++)
     {
-        picture_t *p_pic = PictureAlloc(sys, &sys->p_window->fmt);
+        picture_t *p_pic = PictureAlloc(sys, &sys->p_window->fmt,
+                                        sys->p_window->b_opaque);
         if (!p_pic)
             goto error;
-        if (!sys->p_window->b_opaque) {
-            p_pic->p_sys->pf_lock_pic = DefaultLockPicture;
-            p_pic->p_sys->pf_unlock_pic = DefaultUnlockPicture;
-        }
 
         pp_pics[i] = p_pic;
     }
@@ -990,7 +1006,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
 
         if (!sys->p_sub_pic
          && AndroidWindow_Setup(sys, sys->p_sub_window, 1) == 0)
-            sys->p_sub_pic = PictureAlloc(sys, &sys->p_sub_window->fmt);
+            sys->p_sub_pic = PictureAlloc(sys, &sys->p_sub_window->fmt, false);
         if (!sys->p_spu_blend && sys->p_sub_pic)
             sys->p_spu_blend = filter_NewBlend(VLC_OBJECT(vd),
                                                &sys->p_sub_pic->format);
index 3aa4921..aceb5cb 100644 (file)
@@ -31,6 +31,7 @@
 # include "config.h"
 #endif
 
+#include <assert.h>
 #include <vlc_common.h>
 #include <vlc_vout_display.h>
 #include <android/native_window.h>
@@ -39,14 +40,13 @@ struct picture_sys_t
 {
     vout_display_sys_t *p_vd_sys;
 
-    int (*pf_lock_pic)(picture_t *);
-    void (*pf_unlock_pic)(picture_t *, bool b_render);
-
     union {
         struct {
+            vlc_mutex_t lock;
             decoder_t *p_dec;
-            uint32_t i_index;
-            bool b_valid;
+            int i_index;
+            void (*pf_release)(decoder_t *p_dec, unsigned int i_index,
+                               bool b_render);
         } hw;
         struct {
             void *p_handle;
@@ -56,4 +56,44 @@ struct picture_sys_t
     bool b_locked;
 };
 
+static inline void
+AndroidOpaquePicture_DetachDecoder(picture_sys_t *p_picsys)
+{
+    vlc_mutex_lock(&p_picsys->priv.hw.lock);
+    if (p_picsys->priv.hw.i_index >= 0)
+    {
+        assert(p_picsys->priv.hw.pf_release && p_picsys->priv.hw.p_dec);
+        p_picsys->priv.hw.pf_release(p_picsys->priv.hw.p_dec,
+                                     (unsigned int) p_picsys->priv.hw.i_index,
+                                     false);
+        p_picsys->priv.hw.i_index = -1;
+    }
+    p_picsys->priv.hw.pf_release = NULL;
+    p_picsys->priv.hw.p_dec = NULL;
+    /* Release p_picsys if references from VOUT and from decoder are NULL */
+    if (!p_picsys->p_vd_sys && !p_picsys->priv.hw.p_dec)
+    {
+        vlc_mutex_unlock(&p_picsys->priv.hw.lock);
+        vlc_mutex_destroy(&p_picsys->priv.hw.lock);
+        free(p_picsys);
+    }
+    else
+        vlc_mutex_unlock(&p_picsys->priv.hw.lock);
+}
+
+static inline void
+AndroidOpaquePicture_Release(picture_sys_t *p_picsys, bool b_render)
+{
+    vlc_mutex_lock(&p_picsys->priv.hw.lock);
+    if (p_picsys->priv.hw.i_index >= 0)
+    {
+        assert(p_picsys->priv.hw.pf_release && p_picsys->priv.hw.p_dec);
+        p_picsys->priv.hw.pf_release(p_picsys->priv.hw.p_dec,
+                                     (unsigned int) p_picsys->priv.hw.i_index,
+                                     b_render);
+        p_picsys->priv.hw.i_index = -1;
+    }
+    vlc_mutex_unlock(&p_picsys->priv.hw.lock);
+}
+
 #endif