fix(agent): vendor nvenc 并补 FORCEIDR 标志——修复运行期关键帧请求被静默忽略

根因(实测确认,非推测)
上游 nvenc 0.1.0 的 encode_picture 只设置 picture_type=NV_ENC_PIC_TYPE_IDR,
却从未设置 encode_pic_flags=NV_ENC_PIC_FLAG_FORCEIDR。NVENC 会据此忽略请求、
继续输出 P 帧。首帧之所以「看起来正常」,是因为 frame_idx==0 本来就强制 IDR,
与该字段无关——这也是该缺陷长期未被发现的原因。

证据(同一 frame_count=4,修复前后)
- 修复前:输出 NAL 首字节 0x61 → 0x61 & 0x1F = 1 = 普通 P 片
- 修复后:输出 NAL 首字节 0x65 → 0x65 & 0x1F = 5 = IDR 片

影响
这解释了构建运行手册 §6.1 记录的「静止桌面黑屏」:NVENC 路径的重编 IDR 从未
真正生效,KeyFrameReq 拿不到 IDR 就无法从解码错误中恢复。

改动
- 新增 vendor/nvenc(上游为 MIT 许可,可自由修改分发,符合商用要求)
- vendor/nvenc/src/safe/encoder.rs:picture_type=IDR 时置 ForceIDR;
  IntraRefresh 时置 ForceIntra。改动处有「本项目补丁」注释标记
- agent/Cargo.toml:nvenc 改为 path 依赖指向 vendor 版本

建议后续向上游提 PR(github.com/AlsoSylv/nvenc),以降低长期维护成本。

验证:跳帧后发 KeyFrameReq,第 3 帧即收到 IDR 并解码成功
This commit is contained in:
郑博文 committed 2026-10-28 16:05:41 +08:00
1 parent 9e50bc6237
commit e814cb64e7
21 files changed
+3161 -3

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2024"
rust-version = "1.85.1"
name = "nvenc"
version = "0.1.0"
authors = ["AlsoSylv"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Wrapper for the nvidia NVENC API"
readme = "README.md"
keywords = [
"nvidia",
"graphics",
"media",
"video",
"ffi",
]
categories = [
"multimedia",
"external-ffi-bindings",
]
license = "MIT"
repository = "https://github.com/AlsoSylv/nvenc"
[lib]
name = "nvenc"
path = "src/lib.rs"
# 上游 README 的示例是已过时的 Linux GLX 用法(Session<NeedsConfig> 等类型已不存在),
# 直接跑 doctest 会失败。本项目只做 vendor 补丁、不维护文档示例,故关闭。
doctest = false
[[example]]
name = "simple_encode"
path = "examples/simple_encode.rs"
[dependencies.bitfields]
version = "1.0.2"
[dependencies.libloading]
version = "0.8.9"
[target."cfg(windows)".dependencies.windows]
version = "0.62"
features = [
"Win32_Graphics_Dxgi_Common",
"Win32_Graphics_Direct3D",
"Win32_Graphics_Direct3D11",
]