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
+214
@@ -0,0 +1,214 @@
|
||||
use std::{ffi::c_char, mem::MaybeUninit, os::raw::c_void};
|
||||
|
||||
use crate::{
|
||||
stdcall,
|
||||
sys::{
|
||||
enums::{NVencBufferFormat, NVencTuningInfo},
|
||||
result::NVencResult,
|
||||
structs::{
|
||||
Guid, NVencCapsParam, NVencCreateBitstreamBuffer, NVencCreateInputBuffer,
|
||||
NVencInitializeParams, NVencLockBitStream, NVencLockInputBuffer, NVencMapInputResource,
|
||||
NVencOpenEncodeSessionExParams, NVencPicParams, NVencPresetConfig,
|
||||
NVencRegisterResource,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct NVencFunctionList {
|
||||
pub version: u32,
|
||||
rsvd: u32,
|
||||
#[deprecated]
|
||||
nvenc_open_encode_session: NvencOpenEncodeSession,
|
||||
pub nvenc_get_encoder_guid_count: NvencGetEncodeGuidCount,
|
||||
nvenc_get_encoder_profile_guid_count: NvencGetEncodeProfileGuidCount,
|
||||
nvenc_get_encoder_profile_guids: NvencGetEncodeProfileGuids,
|
||||
pub nvenc_get_encoder_guids: NvencGetEncodeGuids,
|
||||
nvenc_get_input_format_count: NvencGetInputFormatCount,
|
||||
nvenc_get_input_formats: NvencGetInputFormats,
|
||||
nvenc_get_encode_caps: NvencGetEncodeCaps,
|
||||
pub nvenc_get_encode_preset_count: NvencGetEncodePresetCount,
|
||||
pub nvenc_get_encode_preset_guids: NvencGetEncodePresetGuids,
|
||||
nvenc_get_encode_preset_config: NvencGetEncodePresetConfig,
|
||||
pub nvenc_initialize_encoder: NvencInitializeEncoder,
|
||||
pub nvenc_create_input_buffer: NvencCreateInputBuffer,
|
||||
pub nvenc_destroy_input_buffer: NvencDestroyInputBuffer,
|
||||
pub nvenc_create_bit_stream_buffer: NvencCreateBitStreamBuffer,
|
||||
pub nvenc_destory_bit_stream_buffer: NvencDestroyBitStreamBuffer,
|
||||
pub nvenc_encode_picture: NvencEncodePicture,
|
||||
pub nvenc_lock_bit_stream: NvencLockBitStream,
|
||||
pub nvenc_unlock_bit_stream: NvencUnlockBitStream,
|
||||
pub nvenc_lock_input_buffer: NvencLockInputBuffer,
|
||||
pub nvenc_unlock_input_buffer: NvencUnlockInputBuffer,
|
||||
nvenc_get_encode_stats: NvencGetEncodeStats,
|
||||
nvenc_get_sequence_params: NvencGetSequenceParams,
|
||||
nvenc_register_async_event: NvencRegisterAsyncEvent,
|
||||
nvenc_unregister_async_event: NvencUnregisterAsyncEvent,
|
||||
pub nvenc_map_input_resource: NvencMapInputResource,
|
||||
pub nvenc_unmap_input_resource: NvencUnmapInputResource,
|
||||
pub nvenc_destroy_encoder: NvencDestroyEncoder,
|
||||
nvenc_invalidate_ref_frames: NvencInvalidateRefFrames,
|
||||
pub nvenc_open_encode_session_ex: NvencOpenEncodeSessionEx,
|
||||
pub nvenc_register_resource: NvencRegisterResource,
|
||||
pub nvenc_unregister_resource: NvencUnRegisterResource,
|
||||
nvenc_reconfigure_encoder: NvencReconfigureEncoder,
|
||||
rsvd1: *mut c_void,
|
||||
nvenc_create_mv_buffer: NvencCreateMVBuffer,
|
||||
nvenc_destory_mv_buffer: NvencDestoryMVBuffer,
|
||||
nvenc_run_motion_estimation_only: NvencRunMotionEstimationOnly,
|
||||
pub nvenc_get_last_error: NvencGetLastError,
|
||||
nvenc_set_io_cuda_streams: NvencSetIOCudaStreams,
|
||||
pub nvenc_get_encode_preset_config_ex: NvencGetEncodePresetConfigEx,
|
||||
nvenc_get_sequence_params_ex: NvencGetSequenceParamsEx,
|
||||
nvenc_store_encoder_state: NvencStoreEncoderState,
|
||||
nvenc_look_ahead_picture: NvencLookAheadPicture,
|
||||
rsvd2: [*mut c_void; 275],
|
||||
}
|
||||
|
||||
type NvencOpenEncodeSession =
|
||||
stdcall!(fn(device: *mut c_void, device_type: i32, encoder: *mut *mut c_void) -> NVencResult);
|
||||
type NvencGetEncodeGuidCount =
|
||||
stdcall!(fn(encoder: *mut c_void, encoder_guid_count: *mut u32) -> NVencResult);
|
||||
type NvencGetEncodeGuids = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
guids: *mut Guid,
|
||||
guid_array_size: u32,
|
||||
guid_count: *mut u32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodeProfileGuidCount = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
encode_guid: Guid,
|
||||
encoder_profile_guid_count: *mut u32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodeProfileGuids = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
profile_guids: *mut Guid,
|
||||
guid_array_size: u32,
|
||||
guid_count: *mut u32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetInputFormatCount = stdcall!(
|
||||
fn(encoder: *mut c_void, encoder_guid: Guid, input_fmt_count: *mut u32) -> NVencResult
|
||||
);
|
||||
type NvencGetInputFormats = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
input_formats: *mut NVencBufferFormat,
|
||||
input_format_array_size: u32,
|
||||
input_format_count: *mut u32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodeCaps = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
encoder_guid: Guid,
|
||||
caps_param: *mut NVencCapsParam,
|
||||
caps_val: *mut i32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodePresetCount = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
encoder_guid: Guid,
|
||||
encoder_preset_guid_count: *mut u32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodePresetGuids = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
encode_guid: Guid,
|
||||
preset_guids: *mut Guid,
|
||||
guid_array_size: u32,
|
||||
encoder_preset_guid_count: *mut u32,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodePresetConfig = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
encode_guid: Guid,
|
||||
preset_guid: Guid,
|
||||
preset_config: *mut NVencPresetConfig,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencGetEncodePresetConfigEx = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
encode_guid: Guid,
|
||||
preset_guid: Guid,
|
||||
tuning_info: NVencTuningInfo,
|
||||
preset_config: *mut MaybeUninit<NVencPresetConfig>,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencInitializeEncoder = stdcall!(
|
||||
fn(encoder: *mut c_void, create_encode_params: *mut NVencInitializeParams) -> NVencResult
|
||||
);
|
||||
type NvencCreateInputBuffer = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
create_input_buffer_params: *mut NVencCreateInputBuffer,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencDestroyInputBuffer =
|
||||
stdcall!(fn(encoder: *mut c_void, input_buffer: *mut c_void) -> NVencResult);
|
||||
type NvencCreateBitStreamBuffer = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
create_bit_stream_buffer_params: *mut NVencCreateBitstreamBuffer,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencDestroyBitStreamBuffer =
|
||||
stdcall!(fn(encoder: *mut c_void, bitstream_buffer: *mut c_void) -> NVencResult);
|
||||
type NvencEncodePicture = stdcall!(
|
||||
fn(encoder: *mut c_void, encode_pic_params: *mut MaybeUninit<NVencPicParams>) -> NVencResult
|
||||
);
|
||||
type NvencLockBitStream = stdcall!(
|
||||
fn(
|
||||
encoder: *mut c_void,
|
||||
lock_bitstream_buffer_params: *mut MaybeUninit<NVencLockBitStream>,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencUnlockBitStream =
|
||||
stdcall!(fn(encoder: *mut c_void, bitstream_buffer: *mut c_void) -> NVencResult);
|
||||
type NvencLockInputBuffer = stdcall!(
|
||||
fn(encoder: *mut c_void, lock_input_buffer_params: *mut NVencLockInputBuffer) -> NVencResult
|
||||
);
|
||||
type NvencUnlockInputBuffer =
|
||||
stdcall!(fn(encoder: *mut c_void, input_buffer: *mut c_void) -> NVencResult);
|
||||
type NvencGetEncodeStats = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencGetSequenceParams = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencRegisterAsyncEvent = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencUnregisterAsyncEvent = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencMapInputResource = stdcall!(
|
||||
fn(encoder: *mut c_void, map_input_resource_params: *mut NVencMapInputResource) -> NVencResult
|
||||
);
|
||||
type NvencUnmapInputResource =
|
||||
stdcall!(fn(encoder: *mut c_void, mapped_input_buffer: *mut c_void) -> NVencResult);
|
||||
type NvencDestroyEncoder = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencInvalidateRefFrames = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencOpenEncodeSessionEx = stdcall!(
|
||||
fn(
|
||||
open_session_ex_params: *mut NVencOpenEncodeSessionExParams,
|
||||
encoder: *mut *mut c_void,
|
||||
) -> NVencResult
|
||||
);
|
||||
type NvencRegisterResource = stdcall!(
|
||||
fn(encoder: *mut c_void, register_res_params: *mut NVencRegisterResource) -> NVencResult
|
||||
);
|
||||
type NvencUnRegisterResource =
|
||||
stdcall!(fn(encoder: *mut c_void, registered_res: *mut c_void) -> NVencResult);
|
||||
type NvencReconfigureEncoder = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
|
||||
type NvencCreateMVBuffer = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencDestoryMVBuffer = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencRunMotionEstimationOnly = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencGetLastError = stdcall!(fn(encoder: *mut c_void) -> *const c_char);
|
||||
type NvencSetIOCudaStreams = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencGetSequenceParamsEx = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencStoreEncoderState = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
type NvencLookAheadPicture = stdcall!(fn(encoder: *mut c_void) -> NVencResult);
|
||||
Reference in new issue
Block a user