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:
1 parent
9e50bc6237
commit
e814cb64e7
21 files changed
+3161
-3
No files matched your search
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
use std::{ffi::c_void, sync::Arc};
|
||||
|
||||
use crate::{safe::encoder::EncoderInternal, sys::result::NVencError};
|
||||
|
||||
pub struct BitStream {
|
||||
pub(crate) buffer: *mut c_void,
|
||||
pub(crate) encoder: Arc<EncoderInternal>,
|
||||
}
|
||||
|
||||
impl Drop for BitStream {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping bitstream buffer");
|
||||
self.encoder.destroy_bitstream_buffer(self.buffer).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for BitStream {}
|
||||
|
||||
impl BitStream {
|
||||
/// Attempts to lock the bit stream, if `wait` is true it will wait
|
||||
/// otherwise a `LockBusy` Error may be returned, in which case the
|
||||
/// client should retry in a few milliseconds
|
||||
pub fn try_lock(&self, wait: bool) -> Result<BitStreamLockGuard<'_>, NVencError> {
|
||||
let lock = self.encoder.lock_bit_stream_buffer(self.buffer, wait)?;
|
||||
Ok(BitStreamLockGuard {
|
||||
buffer: self,
|
||||
data_ptr: lock.bitstream_buffer,
|
||||
data_len: lock.bitstream_size_in_bytes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds a reference to the `BitStream` and holds the data and associated fields
|
||||
pub struct BitStreamLockGuard<'a> {
|
||||
buffer: &'a BitStream,
|
||||
data_ptr: *mut c_void,
|
||||
data_len: u32,
|
||||
}
|
||||
|
||||
impl BitStreamLockGuard<'_> {
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { std::slice::from_raw_parts(self.data_ptr as _, self.data_len as _) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for BitStreamLockGuard<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.buffer
|
||||
.encoder
|
||||
.unlock_bit_stream_buffer(self.buffer.buffer)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user