[vlc-devel] [PATCH 1/3] nvdec: always use opaque chroma as output

Quentin Chateau quentin.chateau at deepskycorp.com
Fri Mar 20 13:34:22 CET 2020


My usecase is simple, I'm using a custom vout plugin to send the video 
frames over the network, so I simply need the frames to be available in 
RAM. I'm working exclusively on linux.

As you said, opaque output is already beneficial for most linux users. 
And I think this is the way to go. The fact that CUDA opaque chromas are 
not compatible with most filters or vout can always be addressed later.

I think it would not be constructive to output CPU chromas only, it 
would not push other plugins to support CUDA opaque chromas.

On 20/03/2020 09:32, Steve Lhomme wrote:
> Maybe that's an option we could have. But that's unlikely to happen.
> Can you discuss more your usecases ? Maybe there are other ways.
>
> Also there's one case where the opaque output is better than the CPU 
> output: opengl display. So for most people on Linux. In that case the 
> CUDA > texture copy is done from GPU to GPU. If we output CPU then we 
> do GPU > CPU and that CPU buffer needs to be put back in the GPU.
>
> On 2020-03-20 8:56, Quentin Chateau wrote:
>> Well, my use case would benefit greatly from outputting CPU chromas, 
>> for the exact reason you mention.
>>
>> The idea behind this patch was rather to remove unused code...
>> On Mar 20, 2020, at 08:38, Steve Lhomme <robux4 at ycbcr.xyz 
>> <mailto:robux4 at ycbcr.xyz>> wrote:
>>
>>     The code looks correct and mostly removes dead code, as in real life
>>     there's not a case where the opaque output is refused.
>>
>>     My main concern is the timing of when this conversion is done. 
>> Moving it
>>     in the display thread just before displaying a picture is not 
>> optimal
>>     and could result in frame drops. It's a bit different than other
>>     hardware acceleration as we usually pair them with a display 
>> module that
>>     can handle them with no converter. This is not possible with NVDEC.
>>
>>     Until we have CUDA filters we would be better off only outputting 
>> CPU
>>     chromas. The same amount of computatation would be done but it would
>>     free up some time in the display thread to better drop late frames.
>>
>>     In the long run this patch is the way to go and we should do chroma
>>     conversions/deinterlacing outside of the display thread.
>>
>>     On 2020-03-19 17:42, quentin.chateau at deepskycorp.com wrote:
>>
>>         From: Quentin Chateau <quentin.chateau at deepskycorp.com>
>>
>>         MapSurfaceChroma now maps cudaChroma to opaque chromas
>>         ---
>>         modules/hw/nvdec/nvdec.c | 95 +++
>> ------------------------------------------------------------------------
>>
>>         modules/hw/nvdec/nvdec_fmt.h | 9 ----
>>         modules/hw/nvdec/nvdec_gl.c | 3 --
>>         3 files changed, 6 insertions(+), 101 deletions(-)
>>
>>         diff --git a/modules/hw/nvdec/nvdec.c b/modules/hw/nvdec/nvdec.c
>>         index 321815071d..9ee61e8c5e 100644
>>         --- a/modules/hw/nvdec/nvdec.c
>>         +++ b/modules/hw/nvdec/nvdec.c
>>         @@ -112,14 +112,14 @@ static vlc_fourcc_t
>>         MapSurfaceChroma(cudaVideoChromaFormat chroma, unsigned bitD
>>         switch (chroma) {
>>         case cudaVideoChromaFormat_420:
>>         if (bitDepth <= 8)
>>         - return VLC_CODEC_NV12;
>>         + return VLC_CODEC_NVDEC_OPAQUE;
>>         if (bitDepth <= 10)
>>         - return VLC_CODEC_P010;
>>         - return VLC_CODEC_P016;
>>         + return VLC_CODEC_NVDEC_OPAQUE_10B;
>>         + return VLC_CODEC_NVDEC_OPAQUE_16B;
>>         case cudaVideoChromaFormat_444:
>>         if (bitDepth <= 8)
>>         - return VLC_CODEC_I444;
>>         - return VLC_CODEC_I444_16L;
>>         + return VLC_CODEC_NVDEC_OPAQUE_444;
>>         + return VLC_CODEC_NVDEC_OPAQUE_444_16B;
>>         default:
>>         return 0;
>>         }
>>         @@ -130,17 +130,12 @@ static cudaVideoSurfaceFormat
>>         MapSurfaceFmt(int i_vlc_fourcc)
>>         switch (i_vlc_fourcc) {
>>         case VLC_CODEC_NVDEC_OPAQUE_10B:
>>         case VLC_CODEC_NVDEC_OPAQUE_16B:
>>         - case VLC_CODEC_P010:
>>         - case VLC_CODEC_P016:
>>         return cudaVideoSurfaceFormat_P016;
>>         case VLC_CODEC_NVDEC_OPAQUE:
>>         - case VLC_CODEC_NV12:
>>         return cudaVideoSurfaceFormat_NV12;
>>         case VLC_CODEC_NVDEC_OPAQUE_444:
>>         - case VLC_CODEC_I444:
>>         return cudaVideoSurfaceFormat_YUV444;
>>         case VLC_CODEC_NVDEC_OPAQUE_444_16B:
>>         - case VLC_CODEC_I444_16L:
>>         return cudaVideoSurfaceFormat_YUV444_16Bit;
>>         default: vlc_assert_unreachable();
>>         }
>>         @@ -150,15 +145,6 @@ static int CUtoFMT(video_format_t *fmt,
>>         const CUVIDEOFORMAT *p_format)
>>         {
>>         // bit depth and chroma
>>         unsigned int i_bpp = p_format->bit_depth_luma_minus8 + 8;
>>         - vlc_fourcc_t i_chroma;
>>         - if (is_nvdec_opaque(fmt->i_chroma))
>>         - i_chroma = fmt->i_chroma;
>>         - else
>>         - i_chroma = MapSurfaceChroma(p_format->chroma_format, i_bpp);
>>         - if (i_chroma == 0)
>>         - return VLC_EGENERIC;
>>         -
>>         - fmt->i_chroma = i_chroma;
>>         // use the real padded size when we know it fmt->i_width =
>>         p_format->coded_width;
>>         fmt->i_height = p_format->coded_height;
>>         fmt->i_x_offset = p_format->display_area.left;
>>         @@ -178,8 +164,6 @@ static int CUDAAPI HandleVideoSequence(void
>>         *p_opaque, CUVIDEOFORMAT *p_format)
>>         nvdec_ctx_t *p_sys = p_dec->p_sys;
>>         int ret;
>>
>>         - 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]);
>>         @@ -191,7 +175,6 @@ static int CUDAAPI HandleVideoSequence(void
>>         *p_opaque, CUVIDEOFORMAT *p_format)
>>         picture_pool_Release(p_sys->out_pool);
>>         p_sys->out_pool = NULL;
>>         }
>>         - }
>>
>>         // update vlc's output format using NVDEC parser's output
>>         ret = CUtoFMT(&p_dec->fmt_out.video, p_format);
>>         @@ -230,8 +213,6 @@ static int CUDAAPI HandleVideoSequence(void
>>         *p_opaque, CUVIDEOFORMAT *p_format)
>>         goto error;
>>
>>         // ensure the output surfaces have the same pitch so copies can
>>         work properly
>>         - if ( is_nvdec_opaque(p_dec->fmt_out.video.i_chroma) )
>>         - {
>>         // get the real decoder pitch
>>         CUdeviceptr frameDevicePtr = 0;
>>         CUVIDPROCPARAMS params = {
>>         @@ -297,8 +278,6 @@ clean_pics:
>>         goto error;
>>
>>         p_sys->out_pool = picture_pool_New(
>>         ARRAY_SIZE(p_sys->outputDevicePtr), pics );
>>         - }
>>         -
>>         p_sys->decoderHeight = p_format->coded_height;
>>
>>         CALL_CUDA_DEC(cuCtxPopCurrent, NULL);
>>         @@ -359,8 +338,6 @@ static int CUDAAPI HandlePictureDisplay(void
>>         *p_opaque, CUVIDPARSERDISPINFO *p_d
>>         };
>>         int result;
>>
>>         - if ( is_nvdec_opaque(p_dec->fmt_out.video.i_chroma) )
>>         - {
>>         p_pic = picture_pool_Wait(p_sys->out_pool);
>>         if (unlikely(p_pic == NULL))
>>         return 0;
>>         @@ -449,49 +426,6 @@ static int CUDAAPI
>>         HandlePictureDisplay(void *p_opaque, CUVIDPARSERDISPINFO *p_d
>>         }
>>         p_pic->context = &picctx->ctx;
>>         vlc_video_context_Hold(picctx->ctx.vctx);
>>         - }
>>         - else
>>         - {
>>         - p_pic = decoder_NewPicture(p_dec);
>>         - if (unlikely(p_pic == NULL))
>>         - return 0;
>>         -
>>         - result = CALL_CUDA_DEC(cuCtxPushCurrent, 
>> p_sys->devsys->cuCtx);
>>         - if (unlikely(result != VLC_SUCCESS))
>>         - {
>>         - picture_Release(p_pic);
>>         - return 0;
>>         - }
>>         -
>>         - unsigned int i_pitch;
>>         -
>>         - // Map decoded frame to a device pointer
>>         - result = CALL_CUVID( cuvidMapVideoFrame, p_sys->cudecoder,
>>         p_dispinfo->picture_index,
>>         - &frameDevicePtr, &i_pitch, &params );
>>         - if (result != VLC_SUCCESS)
>>         - goto error;
>>         -
>>         - // Copy decoded frame into a new VLC picture
>>         - size_t srcY = 0;
>>         - for (int i_plane = 0; i_plane < p_pic->i_planes; i_plane++) {
>>         - plane_t plane = p_pic->p[i_plane];
>>         - CUDA_MEMCPY2D cu_cpy = {
>>         - .srcMemoryType = CU_MEMORYTYPE_DEVICE,
>>         - .srcDevice = frameDevicePtr,
>>         - .srcY = srcY,
>>         - .srcPitch = i_pitch,
>>         - .dstMemoryType = CU_MEMORYTYPE_HOST,
>>         - .dstHost = plane.p_pixels,
>>         - .dstPitch = plane.i_pitch,
>>         - .WidthInBytes = i_pitch,
>>         - .Height = plane.i_visible_lines,
>>         - };
>>         - result = CALL_CUDA_DEC(cuMemcpy2D, &cu_cpy);
>>         - if (result != VLC_SUCCESS)
>>         - goto error;
>>         - srcY += p_sys->decoderHeight;
>>         - }
>>         - }
>>
>>         // Release surface on GPU
>>         result = CALL_CUVID(cuvidUnmapVideoFrame, p_sys->cudecoder,
>>         frameDevicePtr);
>>         @@ -921,25 +855,8 @@ static int OpenDecoder(vlc_object_t 
>> *p_this)
>>         goto error;
>>         }
>>
>>         - vlc_fourcc_t output_chromas[3];
>>         + vlc_fourcc_t output_chromas[2];
>>         size_t chroma_idx = 0;
>>         - if (cudaChroma == cudaVideoChromaFormat_420)
>>         - {
>>         - if (i_depth_luma >= 16)
>>         - output_chromas[chroma_idx++] = VLC_CODEC_NVDEC_OPAQUE_16B;
>>         - else if (i_depth_luma > 8)
>>         - output_chromas[chroma_idx++] = VLC_CODEC_NVDEC_OPAQUE_10B;
>>         - else
>>         - output_chromas[chroma_idx++] = VLC_CODEC_NVDEC_OPAQUE;
>>         - }
>>         - else if (cudaChroma == cudaVideoChromaFormat_444)
>>         - {
>>         - if (i_depth_luma > 8)
>>         - output_chromas[chroma_idx++] = VLC_CODEC_NVDEC_OPAQUE_444_16B;
>>         - else
>>         - output_chromas[chroma_idx++] = VLC_CODEC_NVDEC_OPAQUE_444;
>>         - }
>>         -
>>         output_chromas[chroma_idx++] = MapSurfaceChroma(cudaChroma,
>>         i_depth_luma);
>>         output_chromas[chroma_idx++] = 0;
>>
>>         diff --git a/modules/hw/nvdec/nvdec_fmt.h
>>         b/modules/hw/nvdec/nvdec_fmt.h
>>         index 25784cca6d..d84672d8fb 100644
>>         --- a/modules/hw/nvdec/nvdec_fmt.h
>>         +++ b/modules/hw/nvdec/nvdec_fmt.h
>>         @@ -51,15 +51,6 @@ static inline int CudaCheckErr(vlc_object_t
>>         *obj, CudaFunctions *cudaFunctions,
>>         return VLC_SUCCESS;
>>         }
>>
>>         -static inline bool is_nvdec_opaque(vlc_fourcc_t fourcc)
>>         -{
>>         - return fourcc == VLC_CODEC_NVDEC_OPAQUE ||
>>         - fourcc == VLC_CODEC_NVDEC_OPAQUE_10B ||
>>         - fourcc == VLC_CODEC_NVDEC_OPAQUE_16B ||
>>         - fourcc == VLC_CODEC_NVDEC_OPAQUE_444 ||
>>         - fourcc == VLC_CODEC_NVDEC_OPAQUE_444_16B;
>>         -}
>>         -
>>         /* for VLC_CODEC_NVDEC_OPAQUE / VLC_CODEC_NVDEC_OPAQUE_16B */
>>         typedef struct
>>         {
>>         diff --git a/modules/hw/nvdec/nvdec_gl.c
>>         b/modules/hw/nvdec/nvdec_gl.c
>>         index 137e730028..62a503a8e8 100644
>>         --- a/modules/hw/nvdec/nvdec_gl.c
>>         +++ b/modules/hw/nvdec/nvdec_gl.c
>>         @@ -156,9 +156,6 @@ static void Close(vlc_object_t *obj)
>>         static int Open(vlc_object_t *obj)
>>         {
>>         struct vlc_gl_interop *interop = (void *) obj;
>>         - if (!is_nvdec_opaque(interop->fmt.i_chroma))
>>         - return VLC_EGENERIC;
>>         -
>>         vlc_decoder_device *device =
>>         vlc_video_context_HoldDevice(interop->vctx);
>>         if (device == NULL || device->type != VLC_DECODER_DEVICE_NVDEC)
>>         return VLC_EGENERIC;
>>         --         2.17.1
>>
>> ------------------------------------------------------------------------
>>
>>         vlc-devel mailing list
>>         To unsubscribe or modify your subscription options:
>>         https://mailman.videolan.org/listinfo/vlc-devel
>>
>> ------------------------------------------------------------------------
>>
>>     vlc-devel mailing list
>>     To unsubscribe or modify your subscription options:
>>     https://mailman.videolan.org/listinfo/vlc-devel
>>
>>
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
>>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list