You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下基于NVIDIA SDK的C++异步HEVC编码:DXGI纹理输出到stdout

配置NVENC编码会话对接DXGI帧并输出到stdout

核心流程步骤

从DXGI捕获帧到输出HEVC码流到stdout的核心链路:初始化NVENC上下文→创建与DXGI纹理兼容的输入表面→配置异步编码参数→阻塞式获取编码结果→输出到stdout。

1. 初始化NVENC编码会话

首先初始化编码器参数,指定HEVC编码格式、开启异步模式,并关联DXGI对应的D3D11设备(避免跨GPU内存拷贝):

NV_ENC_INITIALIZE_PARAMS initParams = { NV_ENC_INITIALIZE_PARAMS_VER };
initParams.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
initParams.presetGUID = NV_ENC_PRESET_P7_GUID; // 按需选择预设(P7是质量优先,P1是速度优先)
initParams.enableAsyncEncoding = true;
initParams.d3d11Device = yourD3D11Device; // 从DXGI资源关联的D3D设备获取
initParams.width = captureWidth; // 匹配DXGI捕获的分辨率
initParams.height = captureHeight;
initParams.frameRateNum = 60; // 按需设置帧率
initParams.frameRateDen = 1;
initParams.bitrate = 8000000; // 目标比特率,单位bps

// 初始化编码器
nvEncInitializeEncoder(encoderHandle, &initParams);

2. 注册DXGI纹理为NVENC输入资源

将捕获到的IDXGIResource转成ID3D11Texture2D,直接注册为NVENC的输入资源(无需拷贝GPU内存):

ID3D11Texture2D* dxgiTexture = nullptr;
yourCapturedDxgiResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&dxgiTexture);

NV_ENC_CREATE_INPUT_RESOURCE inputResParams = { NV_ENC_CREATE_INPUT_RESOURCE_VER };
inputResParams.width = captureWidth;
inputResParams.height = captureHeight;
inputResParams.format = NV_ENC_BUFFER_FORMAT_ABGR; // 匹配DXGI常用的B8G8R8A8_UNORM格式
inputResParams.resourceToRegister = dxgiTexture;

// 创建NVENC输入资源句柄
nvEncCreateInputResource(encoderHandle, &inputResParams, &nvencInputResHandle);

3. 配置异步编码参数

设置异步编码标记,指定待编码的输入资源:

NV_ENC_ENCODE_PIC_PARAMS encodeParams = { NV_ENC_ENCODE_PIC_PARAMS_VER };
encodeParams.inputResource = nvencInputResHandle;
encodeParams.asyncEncode = true;
encodeParams.picType = NV_ENC_PIC_TYPE_AUTO; // 让编码器自动判断I/P帧
encodeParams.inputTimeStamp = frameTimestamp; // 按需设置时间戳,用于码流同步

4. 阻塞获取编码结果并输出到stdout

调用编码接口后,阻塞等待编码完成,直接将NAL单元写入stdout:

// 发起异步编码请求(非阻塞,但后续lock会等待完成)
nvEncEncodePicture(encoderHandle, &encodeParams);

NV_ENC_LOCK_BITSTREAM lockParams = { NV_ENC_LOCK_BITSTREAM_VER };
// 阻塞等待编码完成,获取压缩后的比特流
nvEncLockBitstream(encoderHandle, &lockParams);

// 直接输出到stdout,实时推送给父进程
fwrite(lockParams.bitstreamBufferPtr, 1, lockParams.bitstreamSize, stdout);
fflush(stdout); // 强制刷新缓冲区,避免父进程延迟接收

// 解锁比特流,释放编码器资源
nvEncUnlockBitstream(encoderHandle, &lockParams);

关键注意事项

  • 资源生命周期:编码完成前不要释放DXGI纹理,NVENC会直接访问GPU内存中的帧数据。
  • 格式匹配:必须保证DXGI纹理的像素格式、分辨率与NVENC输入资源完全一致,否则会触发编码错误。
  • 线程安全:如果多线程处理帧,需为每个线程创建独立的NVENC编码器实例,避免并发调用冲突。
  • 缓冲区处理:输出到stdout后必须调用fflush,否则数据会暂存在用户态缓冲区,导致Go主进程无法实时接收。

内容的提问来源于stack exchange,提问作者Tiger Yang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 10:10:49