name: nvenc-nvdec description: NVIDIA硬件视频编码/解码集成。配置NVENC编码参数,设置NVDEC解码管道,处理编解码器配置,与CUDA集成进行前后处理,并管理视频内存表面。 allowed-tools: Bash(*) 读取 写入 编辑 全局搜索 Grep 网络获取 metadata: author: babysitter-sdk version: “1.0.0” category: 视频处理 backlog-id: SK-014
nvenc-nvdec
您是 nvenc-nvdec - 一个专门用于NVIDIA硬件视频编码和解码集成的技能。此技能提供GPU加速视频处理的专家级能力。
概述
此技能支持AI驱动的视频处理,包括:
- 配置NVENC编码参数
- 设置NVDEC解码管道
- 处理编解码器配置(H.264、H.265、AV1)
- 与CUDA集成进行前后处理
- 管理视频内存表面
- 分析编码/解码性能
- 处理多流编码
- 支持B帧和前视配置
先决条件
- 支持NVENC/NVDEC的NVIDIA GPU
- Video Codec SDK 12.0+
- CUDA Toolkit 11.0+
- 支持NVENC的FFmpeg(可选)
能力
1. NVENC编码器设置
初始化硬件编码器:
#include <nvEncodeAPI.h>
// 创建编码器实例
NV_ENCODE_API_FUNCTION_LIST nvenc = {NV_ENCODE_API_FUNCTION_LIST_VER};
NvEncodeAPICreateInstance(&nvenc);
void* encoder = NULL;
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS sessionParams = {
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER};
sessionParams.device = cudaDevice;
sessionParams.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
sessionParams.apiVersion = NVENCAPI_VERSION;
nvenc.nvEncOpenEncodeSessionEx(&sessionParams, &encoder);
// 查询编码器能力
NV_ENC_CAPS_PARAM capsParam = {NV_ENC_CAPS_PARAM_VER};
capsParam.capsToQuery = NV_ENC_CAPS_SUPPORTED_RATECONTROL_MODES;
int capsVal;
nvenc.nvEncGetEncodeCaps(encoder, NV_ENC_CODEC_H264_GUID, &capsParam, &capsVal);
2. 编码配置
配置编码器参数:
// 初始化编码器配置
NV_ENC_INITIALIZE_PARAMS initParams = {NV_ENC_INITIALIZE_PARAMS_VER};
NV_ENC_CONFIG encodeConfig = {NV_ENC_CONFIG_VER};
initParams.encodeConfig = &encodeConfig;
// 获取预设配置
NV_ENC_PRESET_CONFIG presetConfig = {NV_ENC_PRESET_CONFIG_VER};
presetConfig.presetCfg = {NV_ENC_CONFIG_VER};
nvenc.nvEncGetEncodePresetConfigEx(encoder,
NV_ENC_CODEC_H264_GUID,
NV_ENC_PRESET_P4_GUID, // 平衡预设
NV_ENC_TUNING_INFO_HIGH_QUALITY,
&presetConfig);
memcpy(&encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG));
// 设置基本参数
initParams.encodeGUID = NV_ENC_CODEC_H264_GUID;
initParams.presetGUID = NV_ENC_PRESET_P4_GUID;
initParams.encodeWidth = 1920;
initParams.encodeHeight = 1080;
initParams.frameRateNum = 60;
initParams.frameRateDen = 1;
initParams.enablePTD = 1; // 启用图片类型决策
// 码率控制
encodeConfig.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
encodeConfig.rcParams.averageBitRate = 8000000; // 8 Mbps
encodeConfig.rcParams.maxBitRate = 12000000; // 12 Mbps 最大
// B帧和前视
encodeConfig.frameIntervalP = 3; // I/P帧间隔
encodeConfig.rcParams.lookaheadDepth = 20;
encodeConfig.rcParams.enableLookahead = 1;
// 初始化编码器
nvenc.nvEncInitializeEncoder(encoder, &initParams);
3. HEVC/H.265配置
设置HEVC编码:
// HEVC特定配置
initParams.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
NV_ENC_CONFIG_HEVC* hevcConfig = &encodeConfig.encodeCodecConfig.hevcConfig;
hevcConfig->chromaFormatIDC = 1; // 4:2:0
hevcConfig->pixelBitDepthMinus8 = 0; // 8位
hevcConfig->idrPeriod = encodeConfig.gopLength;
hevcConfig->enableIntraRefresh = 0;
hevcConfig->maxCUSize = NV_ENC_HEVC_CUSIZE_32x32;
hevcConfig->minCUSize = NV_ENC_HEVC_CUSIZE_8x8;
// 10位HDR
hevcConfig->pixelBitDepthMinus8 = 2; // 10位
hevcConfig->chromaFormatIDC = 1;
// 层级和级别
hevcConfig->tier = NV_ENC_TIER_HEVC_MAIN;
hevcConfig->level = NV_ENC_LEVEL_HEVC_51;
4. NVDEC解码器设置
初始化硬件解码器:
#include <nvcuvid.h>
// 创建CUDA视频解析器
CUVIDPARSERPARAMS parserParams = {};
parserParams.CodecType = cudaVideoCodec_H264;
parserParams.ulMaxNumDecodeSurfaces = 4;
parserParams.ulMaxDisplayDelay = 2;
parserParams.pUserData = this;
parserParams.pfnSequenceCallback = HandleVideoSequence;
parserParams.pfnDecodePicture = HandlePictureDecode;
parserParams.pfnDisplayPicture = HandlePictureDisplay;
CUvideoparser parser;
cuvidCreateVideoParser(&parser, &parserParams);
// 序列回调 - 创建解码器
int HandleVideoSequence(void* userData, CUVIDEOFORMAT* format) {
CUVIDDECODECREATEINFO createInfo = {};
createInfo.CodecType = format->codec;
createInfo.ulWidth = format->coded_width;
createInfo.ulHeight = format->coded_height;
createInfo.ulNumDecodeSurfaces = 8;
createInfo.ChromaFormat = format->chroma_format;
createInfo.OutputFormat = cudaVideoSurfaceFormat_NV12;
createInfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Adaptive;
createInfo.ulTargetWidth = format->display_area.right;
createInfo.ulTargetHeight = format->display_area.bottom;
createInfo.ulNumOutputSurfaces = 2;
CUvideodecoder decoder;
cuvidCreateDecoder(&decoder, &createInfo);
return 1; // 返回解码表面数量
}
5. CUDA集成
使用CUDA处理视频帧:
// 将解码帧映射到CUDA
CUVIDPROCPARAMS procParams = {};
procParams.progressive_frame = 1;
procParams.output_stream = cudaStream;
unsigned int pitch;
CUdeviceptr framePtr;
cuvidMapVideoFrame(decoder, pictureIndex, &framePtr, &pitch, &procParams);
// 使用CUDA内核处理
processFrameKernel<<<blocks, threads, 0, cudaStream>>>(
(unsigned char*)framePtr, pitch, width, height);
// 取消映射
cuvidUnmapVideoFrame(decoder, framePtr);
// 编码:注册CUDA资源
NV_ENC_REGISTER_RESOURCE registerResource = {NV_ENC_REGISTER_RESOURCE_VER};
registerResource.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR;
registerResource.resourceToRegister = (void*)cudaFrame;
registerResource.width = width;
registerResource.height = height;
registerResource.pitch = pitch;
registerResource.bufferFormat = NV_ENC_BUFFER_FORMAT_NV12;
registerResource.bufferUsage = NV_ENC_INPUT_IMAGE;
nvenc.nvEncRegisterResource(encoder, ®isterResource);
6. 编码帧
提交帧进行编码:
// 映射输入缓冲区
NV_ENC_MAP_INPUT_RESOURCE mapInput = {NV_ENC_MAP_INPUT_RESOURCE_VER};
mapInput.registeredResource = registeredResource;
nvenc.nvEncMapInputResource(encoder, &mapInput);
// 配置图片参数
NV_ENC_PIC_PARAMS picParams = {NV_ENC_PIC_PARAMS_VER};
picParams.inputBuffer = mapInput.mappedResource;
picParams.bufferFmt = mapInput.mappedBufferFmt;
picParams.inputWidth = width;
picParams.inputHeight = height;
picParams.outputBitstream = bitstreamBuffer;
picParams.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
picParams.inputTimeStamp = frameNumber;
// 编码
nvenc.nvEncEncodePicture(encoder, &picParams);
// 锁定并检索比特流
NV_ENC_LOCK_BITSTREAM lockBitstream = {NV_ENC_LOCK_BITSTREAM_VER};
lockBitstream.outputBitstream = bitstreamBuffer;
nvenc.nvEncLockBitstream(encoder, &lockBitstream);
// 复制编码数据
memcpy(outputBuffer, lockBitstream.bitstreamBufferPtr,
lockBitstream.bitstreamSizeInBytes);
nvenc.nvEncUnlockBitstream(encoder, bitstreamBuffer);
nvenc.nvEncUnmapInputResource(encoder, mapInput.mappedResource);
7. 多流编码
处理多个编码会话:
// 查询最大编码会话数
NV_ENC_CAPS_PARAM capsParam = {NV_ENC_CAPS_PARAM_VER};
capsParam.capsToQuery = NV_ENC_CAPS_NUM_MAX_TEMPORAL_LAYERS;
// 创建多个编码器进行并发编码
std::vector<void*> encoders(numStreams);
for (int i = 0; i < numStreams; i++) {
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS sessionParams = {
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER};
sessionParams.device = cudaDevice;
sessionParams.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
nvenc.nvEncOpenEncodeSessionEx(&sessionParams, &encoders[i]);
}
// 使用CUDA流并行编码流
for (int i = 0; i < numStreams; i++) {
// 每个编码器使用自己的CUDA流
cudaStreamCreate(&streams[i]);
// 异步提交帧
}
8. FFmpeg集成
使用NVENC与FFmpeg:
# 使用NVENC编码
ffmpeg -hwaccel cuda -hwaccel_output_format cuda \
-i input.mp4 \
-c:v h264_nvenc \
-preset p4 \
-tune hq \
-rc vbr \
-b:v 8M \
-maxrate 12M \
-bufsize 16M \
output.mp4
# HEVC编码
ffmpeg -hwaccel cuda -i input.mp4 \
-c:v hevc_nvenc \
-preset p7 \
-rc constqp \
-qp 23 \
output_hevc.mp4
# 使用NVDEC解码,处理,使用NVENC编码
ffmpeg -hwaccel cuda -hwaccel_output_format cuda \
-i input.mp4 \
-vf "scale_cuda=1280:720" \
-c:v h264_nvenc \
output_720p.mp4
# AV1编码(RTX 40系列)
ffmpeg -hwaccel cuda -i input.mp4 \
-c:v av1_nvenc \
-preset p4 \
-b:v 5M \
output_av1.mp4
流程集成
此技能与以下流程集成:
gpu-image-video-processing.js- 视频处理工作流
输出格式
{
"operation": "encode-session",
"status": "success",
"configuration": {
"codec": "H.265/HEVC",
"resolution": "1920x1080",
"framerate": 60,
"bitrate_mbps": 8,
"preset": "P4",
"rc_mode": "VBR"
},
"performance": {
"fps": 245,
"latency_ms": 4.1,
"gpu_utilization_pct": 35
},
"output": {
"format": "HEVC",
"file": "output.hevc",
"size_mb": 125.4
}
}
依赖项
- Video Codec SDK 12.0+
- CUDA Toolkit 11.0+
- FFmpeg(可选)
约束
- 每个GPU的NVENC会话有限(检查nvidia-smi)
- 某些预设并非在所有GPU上都可用
- AV1需要RTX 40系列或更新型号
- B帧数量受硬件限制