[vlc-commits] nvdec: allocate all surfaces before creating the pool

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


vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Thu Sep  3 16:52:33 2020 +0200| [03b87931aa04297a3150f7b8f050c7b5088ebde7] | committer: Steve Lhomme

nvdec: allocate all surfaces before creating the pool

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

 modules/hw/nvdec/nvdec.c | 96 +++++++++++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 41 deletions(-)

diff --git a/modules/hw/nvdec/nvdec.c b/modules/hw/nvdec/nvdec.c
index 85705853ee..e255c8a4fb 100644
--- a/modules/hw/nvdec/nvdec.c
+++ b/modules/hw/nvdec/nvdec.c
@@ -78,9 +78,11 @@ vlc_module_end ()
 
 #define OUTPUT_WIDTH_ALIGN   16
 
+typedef struct nvdec_ctx  nvdec_ctx_t;
+
 typedef struct nvdec_pool_t {
     vlc_video_context           *vctx;
-    decoder_device_nvdec_t      *nvdec_dev;
+    nvdec_ctx_t                 *p_sys;
 
     CUdeviceptr                 outputDevicePtr[MAX_POOL_SIZE];
     picture_pool_t              *picture_pool;
@@ -93,7 +95,7 @@ typedef struct pic_pool_context_nvdec_t {
   nvdec_pool_t        *pool;
 } pic_pool_context_nvdec_t;
 
-typedef struct nvdec_ctx {
+struct nvdec_ctx {
     decoder_device_nvdec_t      *devsys;
     CuvidFunctions              *cuvidFunctions;
     CUVIDDECODECAPS             selectedDecoder;
@@ -116,16 +118,23 @@ typedef struct nvdec_ctx {
     nvdec_pool_t                *out_pool;
 
     vlc_video_context           *vctx_out;
-} nvdec_ctx_t;
+};
 
 #define CALL_CUDA_DEC(func, ...) CudaCheckErr(VLC_OBJECT(p_dec),  p_sys->devsys->cudaFunctions, p_sys->devsys->cudaFunctions->func(__VA_ARGS__), #func)
 #define CALL_CUDA_DEV(func, ...) CudaCheckErr(VLC_OBJECT(device), p_sys->cudaFunctions, p_sys->cudaFunctions->func(__VA_ARGS__), #func)
 #define CALL_CUVID(func, ...)    CudaCheckErr(VLC_OBJECT(p_dec),  p_sys->devsys->cudaFunctions, p_sys->cuvidFunctions->func(__VA_ARGS__), #func)
-#define CALL_CUDA_POOL(func, ...) pool->nvdec_dev->cudaFunctions->func(__VA_ARGS__)
 
 #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)
+{
+    for (size_t i=0; i < pics_count; i++)
+        p_sys->devsys->cudaFunctions->cuMemFree( buffers[i] );
+    cuvid_free_functions(&p_sys->cuvidFunctions);
+    free(p_sys);
+}
+
 static void nvdec_pool_AddRef(nvdec_pool_t *pool)
 {
     vlc_atomic_rc_inc(&pool->rc);
@@ -136,8 +145,7 @@ static void nvdec_pool_Release(nvdec_pool_t *pool)
     if (!vlc_atomic_rc_dec(&pool->rc))
         return;
 
-    for (size_t i=0; i < ARRAY_SIZE(pool->outputDevicePtr); i++)
-        CALL_CUDA_POOL(cuMemFree, pool->outputDevicePtr[i]);
+    PoolRelease(pool->p_sys, pool->outputDevicePtr, ARRAY_SIZE(pool->outputDevicePtr));
 
     picture_pool_Release(pool->picture_pool);
     vlc_video_context_Release(pool->vctx);
@@ -145,37 +153,19 @@ static void nvdec_pool_Release(nvdec_pool_t *pool)
 
 static nvdec_pool_t* nvdec_pool_Create(vlc_video_context *vctx,
                                        const video_format_t *fmt,
-                                       size_t buffer_pitch,
-                                       size_t buffer_height)
+                                       CUdeviceptr outputDevicePtr[MAX_POOL_SIZE])
 {
-    vlc_decoder_device *dec_dev = NULL;
     nvdec_pool_t *pool = calloc(1, sizeof(*pool));
-    if (!pool)
-        goto error;
-
-    dec_dev = vlc_video_context_HoldDevice(vctx);
-    if (dec_dev == NULL)
-        goto error;
-
-    pool->nvdec_dev = GetNVDECOpaqueDevice(dec_dev);
-    assert(pool->nvdec_dev != NULL);
-
-    int ret = CALL_CUDA_POOL(cuCtxPushCurrent, pool->nvdec_dev->cuCtx);
-    if (ret != CUDA_SUCCESS)
+    if (unlikely(!pool))
         goto error;
 
     picture_t *pics[ARRAY_SIZE(pool->outputDevicePtr)] = {0};
     for (size_t i=0; i < ARRAY_SIZE(pool->outputDevicePtr); i++)
     {
-        ret = CALL_CUDA_POOL(cuMemAlloc,
-                             &pool->outputDevicePtr[i],
-                             buffer_pitch * buffer_height);
-        if (ret != CUDA_SUCCESS || pool->outputDevicePtr[i] == 0)
-            goto free_pool;
-
         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];
     }
 
@@ -183,9 +173,6 @@ static nvdec_pool_t* nvdec_pool_Create(vlc_video_context *vctx,
     if (!pool->picture_pool)
         goto free_pool;
 
-    CALL_CUDA_POOL(cuCtxPopCurrent, NULL);
-    vlc_decoder_device_Release(dec_dev);
-
     pool->vctx = vctx;
     vlc_video_context_Hold(pool->vctx);
 
@@ -195,15 +182,10 @@ static nvdec_pool_t* nvdec_pool_Create(vlc_video_context *vctx,
 free_pool:
     for (size_t i=0; i < ARRAY_SIZE(pool->outputDevicePtr); i++)
     {
-        if (pool->outputDevicePtr[i] != 0)
-            CALL_CUDA_POOL(cuMemFree, pool->outputDevicePtr[i]);
         if (pics[i] != NULL)
             picture_Release(pics[i]);
     }
-    CALL_CUDA_POOL(cuCtxPopCurrent, NULL);
 error:
-    if (dec_dev)
-        vlc_decoder_device_Release(dec_dev);
     if (pool)
         free(pool);
     return NULL;
@@ -421,10 +403,39 @@ static int CUDAAPI HandleVideoSequence(void *p_opaque, CUVIDEOFORMAT *p_format)
                 vlc_assert_unreachable();
         }
 
-        p_sys->out_pool = nvdec_pool_Create(p_sys->vctx_out,
-                                            &p_dec->fmt_out.video,
-                                            ByteWidth,
-                                            Height);
+        int ret = CALL_CUDA_DEC(cuCtxPushCurrent, p_sys->devsys->cuCtx);
+        if (ret != CUDA_SUCCESS)
+            goto cuda_error;
+
+        CUdeviceptr outputDevicePtr[MAX_POOL_SIZE];
+        for (size_t i=0; i < ARRAY_SIZE(outputDevicePtr); i++)
+        {
+            ret = CALL_CUDA_DEC(cuMemAlloc,
+                                &outputDevicePtr[i],
+                                ByteWidth * Height);
+            if (ret != CUDA_SUCCESS || outputDevicePtr[i] == 0)
+            {
+                while (i)
+                    CALL_CUDA_DEC(cuMemFree, outputDevicePtr[--i]);
+                outputDevicePtr[0] = 0;
+                break;
+            }
+        }
+
+        p_sys->out_pool = NULL;
+        if (outputDevicePtr[0])
+        {
+            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);
+            if (p_sys->out_pool == NULL)
+                PoolRelease(p_sys, outputDevicePtr, ARRAY_SIZE(outputDevicePtr));
+            else
+                p_sys->out_pool->p_sys = p_sys;
+        }
+        CALL_CUDA_DEC(cuCtxPopCurrent, NULL);
         if (p_sys->out_pool == NULL)
             goto cuda_error;
     }
@@ -1089,8 +1100,11 @@ static void CloseDecoder(vlc_object_t *p_this)
         hxxx_helper_clean(&p_sys->hh);
     if (p_sys->out_pool)
         nvdec_pool_Release(p_sys->out_pool);
-    cuvid_free_functions(&p_sys->cuvidFunctions);
-    free(p_sys);
+    else
+    {
+        cuvid_free_functions(&p_sys->cuvidFunctions);
+        free(p_sys);
+    }
 }
 
 /** Decoder Device **/



More information about the vlc-commits mailing list