[vlc-devel] [PATCH 2/6] nvdec: regroup picture-pool related code

quentin.chateau at deepskycorp.com quentin.chateau at deepskycorp.com
Mon Mar 30 11:26:51 CEST 2020


From: Quentin Chateau <quentin.chateau at deepskycorp.com>

---
 modules/hw/nvdec/nvdec.c | 150 ++++++++++++++++++++++++++-------------
 1 file changed, 100 insertions(+), 50 deletions(-)

diff --git a/modules/hw/nvdec/nvdec.c b/modules/hw/nvdec/nvdec.c
index 26f19e8a52..90fa51547b 100644
--- a/modules/hw/nvdec/nvdec.c
+++ b/modules/hw/nvdec/nvdec.c
@@ -77,6 +77,14 @@ vlc_module_end ()
 
 #define OUTPUT_WIDTH_ALIGN   16
 
+typedef struct nvdec_pool_t {
+    vlc_video_context           *vctx;
+    decoder_device_nvdec_t      *nvdec_dev;
+
+    CUdeviceptr                 outputDevicePtr[MAX_POOL_SIZE];
+    picture_pool_t              *picture_pool;
+} nvdec_pool_t;
+
 typedef struct nvdec_ctx {
     decoder_device_nvdec_t      *devsys;
     CuvidFunctions              *cuvidFunctions;
@@ -96,9 +104,8 @@ typedef struct nvdec_ctx {
     bool                        b_nvparser_success;
     size_t                      decoderHeight;
 
-    CUdeviceptr                 outputDevicePtr[MAX_POOL_SIZE];
     unsigned int                outputPitch;
-    picture_pool_t              *out_pool;
+    nvdec_pool_t                *out_pool;
 
     vlc_video_context           *vctx_out;
 } nvdec_ctx_t;
@@ -106,6 +113,89 @@ typedef struct nvdec_ctx {
 #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__)
+
+
+static void nvdec_pool_Destroy(nvdec_pool_t *pool)
+{
+    for (size_t i=0; i < ARRAY_SIZE(pool->outputDevicePtr); i++)
+        CALL_CUDA_POOL(cuMemFree, pool->outputDevicePtr[i]);
+
+    picture_pool_Release(pool->picture_pool);
+    vlc_video_context_Release(pool->vctx);
+}
+
+static nvdec_pool_t* nvdec_pool_Create(vlc_video_context *vctx,
+                                       const video_format_t *fmt,
+                                       size_t buffer_pitch,
+                                       size_t buffer_height)
+{
+    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)
+        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;
+
+        picture_resource_t res = {
+            .p_sys = pool->outputDevicePtr[i],
+        };
+        pics[i] = picture_NewFromResource(fmt, &res);
+        if (!pics[i])
+            goto free_pool;
+    }
+
+    pool->picture_pool = picture_pool_New(ARRAY_SIZE(pool->outputDevicePtr), pics);
+    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);
+
+    return pool;
+
+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;
+}
+
+static picture_t *nvdec_pool_Wait(nvdec_pool_t *pool)
+{
+    return picture_pool_Wait(pool->picture_pool);
+}
 
 static vlc_fourcc_t MapSurfaceChroma(cudaVideoChromaFormat chroma, unsigned bitDepth)
 {
@@ -180,15 +270,9 @@ static int CUDAAPI HandleVideoSequence(void *p_opaque, CUVIDEOFORMAT *p_format)
 
     if ( is_nvdec_opaque(p_dec->fmt_out.video.i_chroma) )
     {
-        for (size_t i=0; i < ARRAY_SIZE(p_sys->outputDevicePtr); i++)
-        {
-            CALL_CUDA_DEC(cuMemFree, p_sys->outputDevicePtr[i]);
-            p_sys->outputDevicePtr[i] = 0;
-        }
-
         if (p_sys->out_pool)
         {
-            picture_pool_Release(p_sys->out_pool);
+            nvdec_pool_Destroy(p_sys->out_pool);
             p_sys->out_pool = NULL;
         }
     }
@@ -259,44 +343,12 @@ static int CUDAAPI HandleVideoSequence(void *p_opaque, CUVIDEOFORMAT *p_format)
                 vlc_assert_unreachable();
         }
 
-        picture_t *pics[ARRAY_SIZE(p_sys->outputDevicePtr)];
-        for (size_t i=0; i < ARRAY_SIZE(p_sys->outputDevicePtr); i++)
-        {
-            ret = CALL_CUDA_DEC(cuMemAlloc, &p_sys->outputDevicePtr[i], ByteWidth * Height);
-            if (ret != VLC_SUCCESS || p_sys->outputDevicePtr[i] == 0)
-                goto clean_pics;
-            picture_resource_t res = {
-                .p_sys = p_sys->outputDevicePtr[i],
-            };
-            pics[i] = picture_NewFromResource( &p_dec->fmt_out.video, &res );
-            if (unlikely(pics[i] == NULL))
-            {
-                msg_Dbg(p_dec, "failed to get a picture for the buffer");
-                ret = VLC_ENOMEM;
-                goto clean_pics;
-            }
-            continue;
-clean_pics:
-            if (p_sys->outputDevicePtr[i])
-            {
-                CALL_CUDA_DEC(cuMemFree, p_sys->outputDevicePtr[i]);
-                p_sys->outputDevicePtr[i] = 0;
-            }
-            if (i > 0)
-            {
-                while (i--)
-                {
-                    picture_Release(pics[i]);
-                    CALL_CUDA_DEC(cuMemFree, p_sys->outputDevicePtr[i]);
-                    p_sys->outputDevicePtr[i] = 0;
-                }
-            }
-            break;
-        }
-        if (ret != VLC_SUCCESS)
+        p_sys->out_pool = nvdec_pool_Create(p_sys->vctx_out,
+                                            &p_dec->fmt_out.video,
+                                            ByteWidth,
+                                            Height);
+        if (p_sys->out_pool == NULL)
             goto cuda_error;
-
-        p_sys->out_pool = picture_pool_New( ARRAY_SIZE(p_sys->outputDevicePtr), pics );
     }
 
     p_sys->decoderHeight = p_format->coded_height;
@@ -364,7 +416,7 @@ static int CUDAAPI HandlePictureDisplay(void *p_opaque, CUVIDPARSERDISPINFO *p_d
 
     if ( is_nvdec_opaque(p_dec->fmt_out.video.i_chroma) )
     {
-        p_pic = picture_pool_Wait(p_sys->out_pool);
+        p_pic = nvdec_pool_Wait(p_sys->out_pool);
         if (unlikely(p_pic == NULL))
             return 0;
 
@@ -996,10 +1048,8 @@ static void CloseDecoder(vlc_object_t *p_this)
     CALL_CUDA_DEC(cuCtxPushCurrent, p_sys->devsys->cuCtx);
     CALL_CUDA_DEC(cuCtxPopCurrent, NULL);
 
-    for (size_t i=0; i < ARRAY_SIZE(p_sys->outputDevicePtr); i++)
-        CALL_CUDA_DEC(cuMemFree, p_sys->outputDevicePtr[i]);
     if (p_sys->out_pool)
-        picture_pool_Release(p_sys->out_pool);
+        nvdec_pool_Destroy(p_sys->out_pool);
     if (p_sys->cudecoder)
         CALL_CUVID(cuvidDestroyDecoder, p_sys->cudecoder);
     if (p_sys->cuparser)
-- 
2.17.1



More information about the vlc-devel mailing list