[vlc-devel] [PATCH 30/39] directx_va: rework the picture picking algorithm

Steve Lhomme robux4 at videolabs.io
Fri Jun 2 16:46:33 CEST 2017


Just rely on an available atomic value to find a usable picture or wait for
the vout to release some pictures.
Similar to the algorithm found in avcodec/VDPAU.
---
 modules/codec/avcodec/directx_va.c | 58 ++++++++++++++++----------------------
 modules/codec/avcodec/directx_va.h |  2 --
 2 files changed, 25 insertions(+), 35 deletions(-)

diff --git a/modules/codec/avcodec/directx_va.c b/modules/codec/avcodec/directx_va.c
index b83e4c38ab..9996470ccb 100644
--- a/modules/codec/avcodec/directx_va.c
+++ b/modules/codec/avcodec/directx_va.c
@@ -350,7 +350,6 @@ int directx_va_Setup(vlc_va_t *va, directx_sys_t *dx_sys, AVCodecContext *avctx)
             return VLC_ENOMEM;
         }
         atomic_init(&surface->refcount, 1);
-        surface->order = 0;
         surface->p_lock = &dx_sys->surface_lock;
         surface->p_pic = dx_sys->pf_alloc_surface_pic(va, &fmt, i);
         dx_sys->surface[i] = surface;
@@ -383,57 +382,50 @@ void DestroyVideoDecoder(vlc_va_t *va, directx_sys_t *dx_sys)
     dx_sys->surface_count = 0;
 }
 
-/* FIXME it is nearly common with VAAPI */
+static vlc_va_surface_t *GetSurface(directx_sys_t *dx_sys)
+{
+    for (int i = 0; i < dx_sys->surface_count; i++) {
+        vlc_va_surface_t *surface = dx_sys->surface[i];
+        uintptr_t expected = 1;
+
+        if (atomic_compare_exchange_strong(&surface->refcount, &expected, 2))
+        {
+            /* TODO do a copy to allow releasing locally and keep forward alive atomic_fetch_sub(&surface->refs, 1);*/
+            surface->decoderSurface = dx_sys->hw_surface[i];
+            return surface;
+        }
+    }
+    return NULL;
+}
+
 vlc_va_surface_t *directx_va_Get(vlc_va_t *va, directx_sys_t *dx_sys)
 {
     /* Check the device */
     if (dx_sys->pf_check_device(va)!=VLC_SUCCESS)
         return NULL;
 
-    vlc_mutex_lock( &dx_sys->surface_lock );
-
-    /* Grab the oldest unused surface, in case none are, use the oldest used one
-     * XXX using the used one is a workaround in case a problem happens with libavcodec */
-    int i, old = -1, old_used = -1;
+    unsigned tries = (CLOCK_FREQ + VOUT_OUTMEM_SLEEP) / VOUT_OUTMEM_SLEEP;
+    vlc_va_surface_t *field;
 
-    for (i = 0; i < dx_sys->surface_count; i++) {
-        vlc_va_surface_t *surface = dx_sys->surface[i];
-        if (((old == -1 || surface->order < dx_sys->surface[old]->order)) && atomic_load(&surface->refcount))
-            old = i;
-        if (old_used == -1 || surface->order < dx_sys->surface[old_used]->order)
-            old_used = i;
-    }
-    if (old >= 0)
-        i = old;
-    else if (old_used >= 0)
+    while ((field = GetSurface(dx_sys)) == NULL)
     {
-        msg_Warn(va, "couldn't find a free decoding buffer, using index %d", old_used);
-        i = old_used;
+        if (--tries == 0)
+            return NULL;
+        /* Pool empty. Wait for some time as in src/input/decoder.c.
+         * XXX: Both this and the core should use a semaphore or a CV. */
+        msleep(VOUT_OUTMEM_SLEEP);
     }
-
-    vlc_va_surface_t *surface = dx_sys->surface[i];
-
-    atomic_store(&surface->refcount,1);
-    surface->order = ++dx_sys->surface_order;
-    surface->decoderSurface = dx_sys->hw_surface[i];
-
-    vlc_mutex_unlock( &dx_sys->surface_lock );
-
-    return surface;
+    return field;
 }
 
 void directx_va_AddRef(vlc_va_surface_t *surface)
 {
-    vlc_mutex_lock( surface->p_lock );
     atomic_fetch_add(&surface->refcount, 1);
-    vlc_mutex_unlock( surface->p_lock );
 }
 
 void directx_va_Release(vlc_va_surface_t *surface)
 {
-    vlc_mutex_lock( surface->p_lock );
     atomic_fetch_sub(&surface->refcount, 1);
-    vlc_mutex_unlock( surface->p_lock );
 }
 
 void directx_va_Close(vlc_va_t *va, directx_sys_t *dx_sys)
diff --git a/modules/codec/avcodec/directx_va.h b/modules/codec/avcodec/directx_va.h
index 858b01705b..b5512b25c7 100644
--- a/modules/codec/avcodec/directx_va.h
+++ b/modules/codec/avcodec/directx_va.h
@@ -45,7 +45,6 @@
 /* */
 typedef struct {
     atomic_uintptr_t     refcount;
-    unsigned int       order;
     vlc_mutex_t        *p_lock;
     picture_t          *p_pic;
     AVVA_DecoderSurface  *decoderSurface;
@@ -80,7 +79,6 @@ typedef struct
 
     /* */
     int          surface_count;
-    int          surface_order;
     int          surface_width;
     int          surface_height;
 
-- 
2.12.1



More information about the vlc-devel mailing list