[vlc-commits] nvdec: separate the nvdec_pool code from nvdec specific code

Steve Lhomme git at videolan.org
Fri Sep 4 13:49:13 CEST 2020


vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Fri Sep  4 10:21:34 2020 +0200| [5e6ca37942fb743e136ab2012830e92b4c6f16a5] | committer: Steve Lhomme

nvdec: separate the nvdec_pool code from nvdec specific code

The pool can be reused to manage the lifecycle of a picture pool with (hardware)
surfaces that can be released easily in push.

The pictures coming out of the pool no longer have p_sys filled. They only
carry a video context with the relevant data.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5e6ca37942fb743e136ab2012830e92b4c6f16a5
---

 modules/hw/nvdec/nvdec.c | 94 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 62 insertions(+), 32 deletions(-)

diff --git a/modules/hw/nvdec/nvdec.c b/modules/hw/nvdec/nvdec.c
index e255c8a4fb..658a7e0099 100644
--- a/modules/hw/nvdec/nvdec.c
+++ b/modules/hw/nvdec/nvdec.c
@@ -79,17 +79,28 @@ vlc_module_end ()
 #define OUTPUT_WIDTH_ALIGN   16
 
 typedef struct nvdec_ctx  nvdec_ctx_t;
+typedef struct nvdec_pool_owner  nvdec_pool_owner_t;
 
 typedef struct nvdec_pool_t {
     vlc_video_context           *vctx;
-    nvdec_ctx_t                 *p_sys;
 
-    CUdeviceptr                 outputDevicePtr[MAX_POOL_SIZE];
+    nvdec_pool_owner_t          *owner;
+
+    void                        *res[64];
+    size_t                      pool_size;
+
     picture_pool_t              *picture_pool;
 
     vlc_atomic_rc_t             rc;
 } nvdec_pool_t;
 
+struct nvdec_pool_owner
+{
+    void *sys;
+    void (*release_resources)(nvdec_pool_owner_t *, void *buffers[], size_t pics_count);
+    picture_context_t * (*attach_picture)(nvdec_pool_owner_t *, nvdec_pool_t *, void *surface);
+};
+
 typedef struct pic_pool_context_nvdec_t {
   pic_context_nvdec_t ctx;
   nvdec_pool_t        *pool;
@@ -116,6 +127,7 @@ struct nvdec_ctx {
 
     unsigned int                outputPitch;
     nvdec_pool_t                *out_pool;
+    nvdec_pool_owner_t          pool_owner;
 
     vlc_video_context           *vctx_out;
 };
@@ -127,10 +139,11 @@ struct nvdec_ctx {
 #define NVDEC_PICPOOLCTX_FROM_PICCTX(pic_ctx)  \
     container_of(NVDEC_PICCONTEXT_FROM_PICCTX(pic_ctx), pic_pool_context_nvdec_t, ctx)
 
-static void PoolRelease(nvdec_ctx_t *p_sys, CUdeviceptr buffers[], size_t pics_count)
+static void PoolRelease(nvdec_pool_owner_t *owner, void *buffers[], size_t pics_count)
 {
+    nvdec_ctx_t *p_sys = container_of(owner, nvdec_ctx_t, pool_owner);
     for (size_t i=0; i < pics_count; i++)
-        p_sys->devsys->cudaFunctions->cuMemFree( buffers[i] );
+        p_sys->devsys->cudaFunctions->cuMemFree( (CUdeviceptr)buffers[i] );
     cuvid_free_functions(&p_sys->cuvidFunctions);
     free(p_sys);
 }
@@ -145,49 +158,55 @@ static void nvdec_pool_Release(nvdec_pool_t *pool)
     if (!vlc_atomic_rc_dec(&pool->rc))
         return;
 
-    PoolRelease(pool->p_sys, pool->outputDevicePtr, ARRAY_SIZE(pool->outputDevicePtr));
+    pool->owner->release_resources(pool->owner, pool->res, pool->pool_size);
 
     picture_pool_Release(pool->picture_pool);
     vlc_video_context_Release(pool->vctx);
 }
 
-static nvdec_pool_t* nvdec_pool_Create(vlc_video_context *vctx,
+static nvdec_pool_t* nvdec_pool_Create(nvdec_pool_owner_t *owner,
                                        const video_format_t *fmt,
-                                       CUdeviceptr outputDevicePtr[MAX_POOL_SIZE])
+                                       vlc_video_context *vctx,
+                                       void *buffers[], size_t pics_count)
 {
     nvdec_pool_t *pool = calloc(1, sizeof(*pool));
     if (unlikely(!pool))
-        goto error;
+        return NULL;
 
-    picture_t *pics[ARRAY_SIZE(pool->outputDevicePtr)] = {0};
-    for (size_t i=0; i < ARRAY_SIZE(pool->outputDevicePtr); i++)
+    picture_t *pics[pics_count];
+    for (size_t i=0; i < pics_count; i++)
     {
         pics[i] = picture_NewFromResource(fmt, &(picture_resource_t) { 0 });
         if (!pics[i])
-            goto free_pool;
-        pool->outputDevicePtr[i] = outputDevicePtr[i];
-        pics[i]->p_sys = (void*)(uintptr_t)pool->outputDevicePtr[i];
+        {
+            while (i--)
+                picture_Release(pics[i]);
+            goto error;
+        }
+        pool->res[i] = buffers[i];
+        pics[i]->p_sys = buffers[i];
     }
 
-    pool->picture_pool = picture_pool_New(ARRAY_SIZE(pool->outputDevicePtr), pics);
+    pool->picture_pool = picture_pool_New(pics_count, pics);
     if (!pool->picture_pool)
         goto free_pool;
 
+    pool->owner = owner;
     pool->vctx = vctx;
+    pool->pool_size = pics_count;
     vlc_video_context_Hold(pool->vctx);
 
     vlc_atomic_rc_init(&pool->rc);
     return pool;
 
 free_pool:
-    for (size_t i=0; i < ARRAY_SIZE(pool->outputDevicePtr); i++)
+    for (size_t i=0; i < pics_count; i++)
     {
         if (pics[i] != NULL)
             picture_Release(pics[i]);
     }
 error:
-    if (pool)
-        free(pool);
+    free(pool);
     return NULL;
 }
 
@@ -217,26 +236,35 @@ static picture_t* nvdec_pool_Wait(nvdec_pool_t *pool)
     if (!pic)
         return NULL;
 
+    void *surface = pic->p_sys;
+    pic->p_sys = NULL;
+    pic->context = pool->owner->attach_picture(pool->owner, pool, surface);
+    if (likely(pic->context != NULL))
+        return pic;
+
+    picture_Release(pic);
+    return NULL;
+}
+
+static picture_context_t * PoolAttachPicture(nvdec_pool_owner_t *owner, nvdec_pool_t *pool, void *surface)
+{
+    nvdec_ctx_t *p_sys = container_of(owner, nvdec_ctx_t, pool_owner);
     pic_pool_context_nvdec_t *picctx = malloc(sizeof(*picctx));
-    if (!picctx)
-        goto error;
+    if (unlikely(!picctx))
+        return NULL;
 
     picctx->ctx.ctx = (picture_context_t) {
         nvdec_picture_CtxDestroy,
         nvdec_picture_CtxClone,
-        pool->vctx,
+        p_sys->vctx_out,
     };
     vlc_video_context_Hold(picctx->ctx.ctx.vctx);
 
+    picctx->ctx.devicePtr = (CUdeviceptr)surface;
     picctx->pool = pool;
     nvdec_pool_AddRef(picctx->pool);
 
-    pic->context = &picctx->ctx.ctx;
-    return pic;
-
-error:
-    picture_Release(pic);
-    return NULL;
+    return &picctx->ctx.ctx;
 }
 
 static vlc_fourcc_t MapSurfaceChroma(cudaVideoChromaFormat chroma, unsigned bitDepth)
@@ -425,15 +453,18 @@ static int CUDAAPI HandleVideoSequence(void *p_opaque, CUVIDEOFORMAT *p_format)
         p_sys->out_pool = NULL;
         if (outputDevicePtr[0])
         {
+            p_sys->pool_owner = (nvdec_pool_owner_t) {
+                p_dec, PoolRelease, PoolAttachPicture,
+            };
+
             void *bufferPtr[ARRAY_SIZE(outputDevicePtr)];
             for (size_t i=0; i<ARRAY_SIZE(outputDevicePtr); i++)
                 bufferPtr[i] = (void*)(uintptr_t)outputDevicePtr[i];
-            p_sys->out_pool = nvdec_pool_Create(p_sys->vctx_out, &p_dec->fmt_out.video,
-                                                outputDevicePtr);
+            p_sys->out_pool = nvdec_pool_Create(&p_sys->pool_owner,
+                                                &p_dec->fmt_out.video, p_sys->vctx_out,
+                                                bufferPtr, ARRAY_SIZE(outputDevicePtr));
             if (p_sys->out_pool == NULL)
-                PoolRelease(p_sys, outputDevicePtr, ARRAY_SIZE(outputDevicePtr));
-            else
-                p_sys->out_pool->p_sys = p_sys;
+                PoolRelease(&p_sys->pool_owner, bufferPtr, ARRAY_SIZE(outputDevicePtr));
         }
         CALL_CUDA_DEC(cuCtxPopCurrent, NULL);
         if (p_sys->out_pool == NULL)
@@ -506,7 +537,6 @@ static int CUDAAPI HandlePictureDisplay(void *p_opaque, CUVIDPARSERDISPINFO *p_d
         if (result != VLC_SUCCESS)
             goto error;
 
-        picctx->devicePtr = (CUdeviceptr)p_pic->p_sys;
         picctx->bufferPitch = p_sys->outputPitch;
         picctx->bufferHeight = p_sys->decoderHeight;
 



More information about the vlc-commits mailing list