NVIDIA CUDA Video Decoder(H.264)

工作小计-GPU硬编以及依赖库 nvcuvid&nvidia-encode 已经是第三篇关于编解码的记录了。项目中用到GPU编码很久了,因为yuv太大,所以编码显得很重要。这次遇到的问题是环境的搭建问题。需要把开发机上的环境放到docker中,以保证docker中同样可以进行GPU的编码。 阅读详情


配置好CUDA开发环境,同时确保合适的显卡支持


开发时需要的 Lib 和 Header File

<span style="font-size:14px;">#ifdef  _DEBUG
#pragma comment(lib, "cutil32D.lib")
#else
#pragram comment(lib, "cutil32.lib")
#endif
#pragram comment(lib, "nvcuvid.lib")</span>


动态链接的时候,需要 nvcuvid.dll 和 cutil32.dll,所以执行的时候确保这两个dll文件路径配置。

<span style="font-size:14px;">#include "cuviddec.h"
#include "cutil.h"
#include "cutil_inline_drvapi.h"
#include "cuda_runtime_api.h"
#include "cutil_inline_runtime.h"
#include "nvcuvid.h"</span>

一些参数的注释:

CUcontext                     m_cuContext; // 类似于Windows 的 Handel

CUvideoctxlock            m_CtxLock; // 类似于CrticalSection(Windows关键段)

CUvideodecoder m_CUDADecoder; // Decoder 解码器

CUvideoparser m_hParser; // Frame Parser 分析每帧frame使用

CUDAPassStruct m_PassData; // 传递给Callback Function 的使用者自定义资料结构


调用的API

初始化:

<span style="font-size:14px;">//CUDA Test//
CUresult cudaRes = CUDA_SUCCESS;
CUdevice device = NULL;
int iCount = 0;
 
cuInit(0);
// Check for a min spec of Compute 1.1 capability before running
if (!cutilDrvCudaCapabilities(1,1)) 
{
    cutilExit(0, NULL);
    goto EF;
}
cudaRes = cuDeviceGetCount(&iCount);
if(cudaRes != CUDA_SUCCESS) 
    goto EF;
cudaRes = cuDeviceGet(&device, 0);
if(cudaRes != CUDA_SUCCESS) 
    goto EF;
cudaRes = cuCtxCreate(&m_cuContext, 0, device);
if(cudaRes != CUDA_SUCCESS) 
    goto EF;
cudaRes = cuvidCtxLockCreate(&m_CtxLock, m_cuContext);
if(cudaRes != CUDA_SUCCESS) 
    goto EF;
CUVIDDECODECREATEINFO dci;
// Fill the decoder-create-info struct from the given video-format struct.
memset(&dci, 0, sizeof(CUVIDDECODECREATEINFO));
// Create video decoder
dci.CodecType  = cudaVideoCodec_H264;
dci.ulWidth  = iW;    //视频宽度//
dci.ulHeight = iH;     //视频高度//
dci.ulNumDecodeSurfaces = 2;    
// Limit decode memory to 24MB (16M pixels at 4:2:0 = 24M bytes)
while (dci.ulNumDecodeSurfaces * dci.ulWidth * dci.ulHeight > 16*1024*1024)
{
    dci.ulNumDecodeSurfaces–;
}
dci.ChromaFormat = cudaVideoChromaFormat_420;     //输入视频的Pixelformat//
dci.OutputFormat  = cudaVideoSurfaceFormat_NV12;   //解码后输出的Pixelformat (目前只支持NV12)//
dci.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;    

// No scaling
dci.ulTargetWidth = dci.ulWidth;    //Decode后输出的宽度//
dci.ulTargetHeight = dci.ulHeight;  //Decode后输出的高度//
dci.ulNumOutputSurfaces = 2;        //英文注释说是只支持2个//
dci.ulCreationFlags = cudaVideoCreate_Default;    //可以看一下Header File的定义说明//
dci.vidLock = NULL;//ctx;
cudaRes = cuvidCreateDecoder(&m_CUDADecoder, &dci);     //建立H.264 Decoder//
if(cudaRes != CUDA_SUCCESS) 
    goto EF;</span>
<span style="font-size:14px;">
//传递的使用者结构//
m_PassData.CUDADecoder = m_CUDADecoder;
m_PassData.iWidth = dci.ulWidth;
m_PassData.iHeight = dci.ulHeight;
m_PassData.pFrameBuffer = m_pFrameBuffer;
m_PassData.puiFrameSize = &m_uiFrameSize;
m_PassData.pLocker = &m_Locker;


//建立 Parser //
CUVIDPARSERPARAMS oVideoParserParameters;  
memset(&oVideoParserParameters, 0, sizeof(CUVIDPARSERPARAMS));
oVideoParserParameters.CodecType = cudaVideoCodec_H264;
oVideoParserParameters.ulMaxNumDecodeSurfaces = dci.ulNumDecodeSurfaces;
oVideoParserParameters.ulMaxDisplayDelay = 4; // this flag is needed so the parser will push frames out to the decoder as quickly as it can//
oVideoParserParameters.pUserData = &m_PassData;   //传递使用者自定义的结构//
oVideoParserParameters.pfnSequenceCallback  = NULL;    // Called before decoding frames and/or whenever there is a format change//
oVideoParserParameters.pfnDecodePicture = HandlePictureDecode;    // Called when a picture is ready to be decoded (decode order)//
oVideoParserParameters.pfnDisplayPicture = HandlePictureDisplay;   // Called whenever a picture is ready to be displayed (display order)//
cudaRes = cuvidCreateVideoParser(&m_hParser, &oVideoParserParameters);
if(cudaRes != CUDA_SUCCESS) 
    goto EF;</span>


使用的顺序和 Callback Function(回调函数)

提供给 Parser使用的两个 Callback function:

<span style="font-size:14px;">static int CUDAAPI HandlePictureDecode(void * pUserData, CUVIDPICPARAMS * pPicParams);</span>      //解析完可以回调cuvidDecodePicture

<span style="font-size:14px;">static int CUDAAPI HandlePictureDisplay(void *pUserData, CUVIDPARSERDISPINFO * pPicParams);</span> //解码完成后回调的地方


使用Parser是为了取得CUVIDPICPARAMS资料后传递给 Decode API 使用

<span style="font-size:14px;">int CUDAAPI HandlePictureDecode(void * pUserData, CUVIDPICPARAMS * pPicParams)
{
    CUDAPassStruct* pa = reinterpret_cast<CUDAPassStruct *>(pUserData);
    CUresult cudaRes = cuvidDecodePicture(pa->CUDADecoder, pPicParams);
    return 1;
}

int CUDAAPI HandlePictureDisplay(void *pUserData, CUVIDPARSERDISPINFO * pPicParams)
{
    CUDAPassStruct* pa = reinterpret_cast<CUDAPassStruct *>(pUserData);
    CUVIDPROCPARAMS oVideoProcessingParameters;
    memset(&oVideoProcessingParameters, 0, sizeof(CUVIDPROCPARAMS));
    CUdeviceptr pDecodedFrame = 0;
    unsigned int nDecodedPitch = 0;
    unsigned int nWidth = 0;
    unsigned int nHeight = 0;
    CUresult oResult = cuvidMapVideoFrame(pa->CUDADecoder, pPicParams->picture_index, &pDecodedFrame, &nDecodedPitch, &oVideoProcessingParameters);
    unsigned int nv12_size = nDecodedPitch * (pa->iHeight + pa->iHeight/2);  // 12bpp
    *pa->puiFrameSize = nv12_size;
    oResult = cuMemcpyDtoH(pa->pFrameBuffer, pDecodedFrame, nv12_size);
    oResult = cuvidUnmapVideoFrame(pa->CUDADecoder, pDecodedFrame);
    return 1;
}</span>


释放


<span style="font-size:14px;">CUresult cudaRes = CUDA_SUCCESS;
cudaRes = cuvidCtxLockDestroy(m_CtxLock);
cudaRes = cuvidDestroyDecoder(m_CUDADecoder);
cudaRes = cuvidDestroyVideoParser(m_hParser);
cudaRes = cuCtxDestroy(m_cuContext);
m_CtxLock = 0;
m_CUDADecoder = 0;
m_hParser = 0;
m_cuContext = 0;</span>

外部处理

由于目前输出的Pixel Format 为 NV12,在取得解码后的 Raw Data后有两种办法:

(1)用NV12的Render显示

(2)再转换一次 PixelFormat





参考:https://hauhan.wordpress.com/2010/07/17/nvidia-cuda-h-264-decode-%E5%BF%83%E5%BE%97/


cudaEncode编码详细过程 cudaEncode编码详细过程如下: 一,ParseInputParams(argc, argv,&sEncoderParams) //配置参数:输入、输出文件,配置文件,基本的参数   二,pCudaEncoder = new VideoEncoder  (&sEnc 阅读详情

相关推荐

CUDA和FFMPEG硬件解码视频流

其他博客给出的教程要么只是给出了伪代码,非常的模糊,要么是基于D3D进行显示,使得给出的源码非常复杂,而无法看出CUDA解码的核心框架,而本文将其他非核心部分剥离出去,视频播放部分通过opencv调用cv::mat显示。示例中NvDecodeD3D9.cpp实现了D3D环境的创建,CUDA模块的初始化,其中取视频帧图像显示的函数如下,该函数实现了从解码图像队列取出图像(实际上是显存指针),完成格式转换(NV12到ARGB),最后映射到D3D的Texture进行显示等功能,代码中我给出了关键部位的解释。

yinshipin007的博客 2163

NVVL:硬件加速视频帧加载库如何彻底改变机器学习训练效率?

NVVL(NVIDIA Video Loader)是一款专为机器学习训练设计的硬件加速视频帧加载库,它通过利用GPU硬件解码能力,显著提升视频数据预处理速度,帮助开发者突破传统CPU加载瓶颈,实现更高效的模型训练流程。无论是处理大型视频数据集还是实时视频流,NVVL都能提供低延迟、高吞吐量的视频帧加载方案,让AI训练效率提升3-5倍不再是难事! ## 🚀 为什么选择硬件加速视频加载? 在传统

gitblog_00945的博客 631

FFmpeg硬件解码加速后端对接:从原理到NVIDIA CUDA实战

硬件解码是音视频处理中提升性能、降低CPU负载的核心技术,其原理在于将解码计算任务从通用CPU卸载到专用硬件单元(如GPU的编解码引擎)。这项技术通过释放CPU资源,为实时转码、高清流媒体处理和AI视觉分析等复杂业务逻辑提供了关键的性能保障。在工程实践中,FFmpeg作为广泛使用的多媒体框架,提供了统一的硬件加速抽象接口,开发者需要对接特定硬件后端以实现高效解码。本文以NVIDIA CUDA为例,深入解析了硬件设备上下文(hwdevice)的创建、硬件解码器(hwaccel)的配置以及GPU帧处理流程,涵盖

Hi, Sun 514

【ACCELERATED GSTREAMER USER GUIDE】3 Video Decode Using gst-v4l2

在您的管道中,nvv4l2decoder 接收解析后的 H.264 视频流,并使用 NVIDIA GPU 的硬件加速能力将其解码为原始视频帧。然而,需要注意的是,nv3dsink 可能不是所有 NVIDIA 平台和 GStreamer 版本的通用解决方案,并且它的具体行为可能因 NVIDIA 的驱动程序和 SDK 更新而有所不同。:您的系统必须安装了与您的 NVIDIA GPU 兼容的驱动程序,并且这些驱动程序必须支持您正在使用的 GStreamer 插件。

qq_43298381的博客 1249

NVIDIA Video Codec SDK实战:从环境搭建到首个硬件加速应用

本文详细介绍了NVIDIA Video Codec SDK的实战应用,从环境搭建到首个硬件加速应用的开发流程。通过调用GPU进行视频编解码,显著提升4K视频转码等任务的效率,适用于视频会议、直播推流等实时性要求高的场景。文章包含环境配置、SDK安装、示例编译及性能优化等实用技巧,帮助开发者快速掌握硬件加速技术。

weixin_30615767的博客 356

保姆级教程:在Ubuntu 22.04上为GStreamer 1.22编译NVIDIA NVENC/NVDEC插件(含CUDA 12.x适配)

本文提供在Ubuntu 22.04上为GStreamer 1.22编译NVIDIA NVENC/NVDEC插件的详细教程,涵盖环境准备、依赖安装、插件编译及性能调优全流程。特别适配CUDA 12.x,帮助开发者高效实现GPU加速视频编解码,提升4K/8K视频处理能力。

388

FFmpeg解码器查找实战:如何用avcodec_find_decoder_by_name快速匹配H.264解码器

本文深入解析了FFmpeg中avcodec_find_decoder_by_name API的工作原理与实战应用。通过对比ID查找与名称查找的核心差异,详细阐述了如何利用该函数精准匹配并启用H.264硬件解码器(如h264_qsv),同时提供了健壮的回退策略与常见问题排查方法,帮助开发者实现高性能、高兼容性的解码器初始化。

life6的博客 454

NVIDIA vGPU License服务器及GPU驱动部署配置详解

一、背景 在Horizon Daas环境,因部分桌面虚拟机采用vGPU规格发布,因此环境中需要有GPU License服务器,完成对租户环境的GPU许可。 当配置有vGPU桌面虚拟机发起License授权请求后,授权服务器会根据License中所包含的GRID License版本,加载不同的vGPU驱动(普通驱动和专业Quodra卡驱动)。目前vPC和vApp的License对应加载的都是普通的显示驱动。 二、vGPU License服务器的工作原理 vGPU跟传统的GPU类似,具有固定数量的GPU帧缓冲器

企业实战系列集 ●●● https://ximenjianxue.blog.youkuaiyun.com 5900

DroidCam OBS插件FFmpeg硬件解码指南:D3D11VA、CUDA与VideoToolbox实战

**DroidCam OBS插件**(droidcam-obs-plugin)是一个把 Android / iOS 手机摄像头作为推流源接入 OBS Studio 的开源项目,其视频流基于 FFmpeg 解码。本指南带你快速搞懂它的 **FFmpeg 硬件解码**机制:Windows 下如何自动走 D3D11VA 或 CUDA,macOS 下如何用 VideoToolbox 硬解,以及如何一键开启

gitblog_00112的博客 949

从源码编译GPU加速版FFmpeg:解锁NVIDIA硬件编解码性能

视频编解码是多媒体处理的核心技术,其原理是将原始视频数据通过压缩算法转换为更小的码流,以节省存储和传输带宽。传统CPU软编解码虽然兼容性好,但在处理高分辨率、多路视频流时面临算力瓶颈。硬件编解码技术通过调用GPU专用电路(如NVIDIA的NVENC/NVDEC),将计算负载从CPU卸载,实现了数量级的性能提升,尤其适用于4K/8K视频转码、实时流媒体处理和批量视频处理等场景。本文聚焦于如何从源码编译支持NVIDIA GPU加速的FFmpeg,深入解析NVENC硬件编码器和NVDEC解码器的集成方法,涵盖依赖

weixin_30536513的博客 309

VideoDecoder 解析实时视频流

H264实时流解码

Android 557

FFmpeg 实战:基于 Ubuntu 操作系统裸机部署具有 NVIDIA GPU 硬件加速编码能力的 FFmpeg

本文介绍了在Ubuntu 24.04系统上配置具有NVIDIA GPU硬件加速编码能力的FFmpeg的完整流程。主要内容包括:1)硬件准备要求(NVIDIA Tesla V100显卡、PCIe x16插槽、BIOS开启4G以上解码);2)软件依赖安装(NVIDIA驱动、CUDA Toolkit 12.9 Update 2);3)FFmpeg编译配置要点。文章提供了详细的版本兼容性说明和命令验证方法,并附相关参考文档链接,帮助用户实现视频编解码的GPU硬件加速功能。

SteveJrong's Blog 364

CUDA视频解码库实战:cuviddec.h与nvcuvid.h详解

CUDA(Compute Unified Device Architecture)是由NVIDIA推出的并行计算平台和编程模型,它使得开发者能够使用NVIDIA的GPU(图形处理单元)进行通用计算。自2007年首次发布以来,CUDA已经成为高性能计算领域的关键工具,支持从深度学习、科学模拟到视频处理等多个领域的并行计算任务。

weixin_42527589的博客 1190

C++结合OpenCV与NVIDIA SDK实现MP4视频GPU硬解码全流程详解

视频解码是多媒体处理的基础环节,其核心原理是将压缩编码的视频数据流还原为原始像素帧。传统CPU软解码在处理高分辨率、高帧率视频时面临巨大计算压力,难以满足实时分析、视频转码及AI推理前处理等高吞吐量场景的需求。GPU硬解码技术通过调用显卡专用的解码硬件单元(如NVIDIA的NVDEC),将解码任务从CPU卸载至GPU,能显著提升解码效率并降低CPU占用,是实现高性能视频处理管线的关键技术。在工程实践中,开发者常利用NVIDIA Video Codec SDK直接操作底层硬件,并结合OpenCV进行高效的图像

weixin_34321753的博客 593

H.264编解码的CUDA实现,并行加速算法

H.264编解码的CUDA实现,并行加速算法,内部实现了H.264视频编解码的CUDA实现,能够编译通过,已经过测试,并且还添加了注释信息。

光电系统光轴校准与偏差控制实战指南

光轴作为光电系统的空间基准坐标系,直接影响多光谱传感器的协同工作精度。在包含可见光、红外与激光测距的复合系统中,光轴偏差会导致目标识别误差与打击精度下降。通过机械基准建立、光学通道粗调和多光谱协同校准等工厂级标定流程,结合千米靶标法、星点校准法等野战应急方案,可有效控制光轴偏差。典型应用场景中,温度补偿与振动抑制技术能维持光轴稳定性,如某舰载系统通过500Hz高频视觉伺服实现0.3mrad振动补偿。掌握这些光轴标定与保持策略,对提升光电系统在侦察、测距等场景的实战性能具有关键价值。

weixin_36149538的博客 273

Scanner视频解码揭秘:NVIDIA NVDEC、Intel VAAPI与软件解码的GPU加速完全指南

**Scanner 视频解码**是这套大规模视频分析框架的性能核心。Scanner(Efficient video analysis at scale)为视频分析提供了统一的解码抽象层,内置 **NVIDIA NVDEC(硬件 GPU 解码)**、**Intel VAAPI(Intel Media SDK/MFX 硬件加速)** 与 **FFmpeg 软件解码** 三套实现,通过编译期开关自动适配

gitblog_00199的博客 1031

ARM学习 | 紧耦合存储器 (TCM)

TCM 是一种专用的片上存储器,直接与处理器核心耦合。确定性访问:由于不涉及缓存替换或一致性管理,访问延迟固定。高带宽:TCM 通常通过专用总线连接处理器核心,可以提供更高的数据吞吐率。用户管理:TCM 的分配和管理完全由开发者控制,不依赖硬件缓存策略。ARM 处理器中的 TCM 通常分为ITCM(指令紧耦合存储器)和DTCM(数据紧耦合存储器),分别用于存储指令和数据。TCM 是 ARM 处理器中不可忽视的重要特性,在实时系统和高性能嵌入式应用中具有重要地位。

qq_43167806的博客 3329

Nvidia硬解码总结

本文章是转的别人的文章,写在这里是方便自己查看。 Nvidia硬解码总结 1.前言   本文的主要目的是对近期进行的nvidia硬件解码工作的记录和总结。至于为什么研究nvidia硬件解码的具体内容,其实主要是为了在项目中能够利用nvidia的硬件解码和编码能力,提高单机的编解码并行能力。截止当前,nvidia的硬件编码官方提供了nvenc的方法,且在ffmpeg

tao_fuqiang的专栏 8775

全志V3S嵌入式驱动开发(编译器升级到7.5)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 看过我们文章的朋友都知道,前面为了做v3s的驱动,对linux kernel进行了两次升级。第一次升级时从4.10.y升级到4.14.y,另外一次升级是从4.14.y升级到5.2.y。这中间最主要的原因,就是为了驱动适配的需要,更新的内核可以对硬件驱动有更好的支持,架构也更合理。 如果说内核升级尚且可以理解,那为什么要对编译器升级呢?这里面,最重要的一点就是语言的升

嵌入式-老费,一个分享专业嵌入式知识的blog 1164

药物对接仿真软件:HADDOCK_(16).实践项目:抗体-抗原对接案例

定义分子结构文件。

kkchenjj的博客 578

【视频开发】Nvidia硬解码总结

Nvidia硬解码总结 1.前言   本文的主要目的是对近期进行的nvidia硬件解码工作的记录和总结。至于为什么研究nvidia硬件解码的具体内容,其实主要是为了在项目中能够利用nvidia的硬件解码和编码能力,提高单机的编解码并行能力。截止当前,nvidia的硬件编码官方提供了nvenc的方法,且在ffmpeg中已经增加了对nvenc的编码库。对于硬件解码,官方提供了基于cuda的解码方法

ZhangPY的专栏 8168

Android 13.0 Launcher3中去掉Hotseat功能实现

在13.0系统产品定制化开发中,在Launcher3的定制化需求也是特别多的,由产品是小屏幕的产品,所以产品需求Launcher3 页面布局的原因,要求Launcher3 需要去掉Hotseat 不显示Hotseat下面几个图标,而做满屏app的显示,从而达到美观的效果,下面就来分析去掉Hotseat从而实现这个功能

安卓兼职framework和app工程师的博客 1326
上一篇: H.264简介
下一篇: NVIDIA的资源网站
tkp2014
博客等级 码龄12年 137粉丝 241原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值