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:
parent
9e50bc6237
commit
e814cb64e7
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -628,8 +628,6 @@ checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
|
||||
[[package]]
|
||||
name = "nvenc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3227c3b09b1e042dab7d8d82cea77c0404e7d0c2bbb92e7e87cb319749cd20dc"
|
||||
dependencies = [
|
||||
"bitfields",
|
||||
"libloading",
|
||||
|
||||
@ -12,7 +12,10 @@ rustls.workspace = true
|
||||
rcgen.workspace = true
|
||||
lz4_flex.workspace = true
|
||||
openh264 = { version = "0.9.9", features = ["source"] }
|
||||
nvenc = "0.1.0"
|
||||
# 上游 nvenc 0.1.0 的 encode_picture 只设 picture_type=IDR、不置 FORCEIDR 标志,
|
||||
# 导致运行期 KeyFrameReq 被编码器静默忽略(实测输出 NAL type=1 而非 5)。
|
||||
# vendor 版本补上了该标志,见 vendor/nvenc/src/safe/encoder.rs 的「本项目补丁」注释。
|
||||
nvenc = { path = "../vendor/nvenc" }
|
||||
windows = { workspace = true, features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Direct3D",
|
||||
|
||||
2
vendor/nvenc/.gitignore
vendored
Normal file
2
vendor/nvenc/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/.vscode
|
||||
63
vendor/nvenc/Cargo.toml
vendored
Normal file
63
vendor/nvenc/Cargo.toml
vendored
Normal 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",
|
||||
]
|
||||
24
vendor/nvenc/Cargo.toml.orig
generated
vendored
Normal file
24
vendor/nvenc/Cargo.toml.orig
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "nvenc"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
authors = ["AlsoSylv"]
|
||||
description = "Wrapper for the nvidia NVENC API"
|
||||
rust-version = "1.85.1"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/AlsoSylv/nvenc"
|
||||
license = "MIT"
|
||||
keywords = ["nvidia", "graphics", "media", "video", "ffi"]
|
||||
categories = ["multimedia", "external-ffi-bindings"]
|
||||
|
||||
[dependencies]
|
||||
libloading = "0.8.9"
|
||||
bitfields = "1.0.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.62"
|
||||
features = [
|
||||
"Win32_Graphics_Dxgi_Common",
|
||||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D11",
|
||||
]
|
||||
27
vendor/nvenc/LICENSE.txt
vendored
Normal file
27
vendor/nvenc/LICENSE.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Notice Regarding Standards. I do not provide a license or sublicense to
|
||||
any Intellectual Property Rights relating to any standards, including but not
|
||||
limited to any audio and/or video codec technologies such as MPEG-2, MPEG-4;
|
||||
AVC/H.264; HEVC/H.265; AAC decode/FFMPEG; AAC encode/FFMPEG; VC-1; and MP3
|
||||
(collectively, the "Media Technologies"). For clarity, you will pay any
|
||||
royalties due for such third party technologies, which may include the Media
|
||||
Technologies that are owed as a result of me providing the Software to you.
|
||||
|
||||
Copyright 2025 AlsoSylv
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
34
vendor/nvenc/README.md
vendored
Normal file
34
vendor/nvenc/README.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
### If you like my work and want to support what I do, support me on Ko-Fi 💜!
|
||||
[](https://ko-fi.com/cyberite)
|
||||
---
|
||||
|
||||
  
|
||||
|
||||
The following example is for Linux GLX
|
||||
|
||||
```rust
|
||||
use nvenc::{session::Session, encoder::Encoder};
|
||||
|
||||
fn main() {
|
||||
// Setup GLX context
|
||||
let session: Session<NeedsConfig> = Session::open_gl();
|
||||
let (session, config): (Session<NeedsInit>, NVencPresetConfig)
|
||||
= session.get_preset_config(
|
||||
NV_ENC_CODEC_H264_GUID,
|
||||
NV_ENC_PRESET_P3_GUID,
|
||||
NVencTuningInfo::LowLatency
|
||||
);
|
||||
let init_params = nvenc::session::InitParams {
|
||||
encode_guid: NV_ENC_H264_GUID,
|
||||
preset_guid: NV_ENC_PRESET_P3_GUID,
|
||||
resolution: [1920, 1080],
|
||||
aspect_ratio: [16, 9],
|
||||
frame_rate: [30, 1],
|
||||
tuning_info: NVencTuningInfo::LowLatency,
|
||||
buffer_format: NVencBufferFormat::ARGB,
|
||||
encode_config: &mut config.preset_cfg,
|
||||
enable_ptd: true,
|
||||
};
|
||||
let encoder: Encoder = session.init(init_params);
|
||||
}
|
||||
```
|
||||
203
vendor/nvenc/examples/simple_encode.rs
vendored
Normal file
203
vendor/nvenc/examples/simple_encode.rs
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::time::Instant;
|
||||
|
||||
use nvenc::bitstream::BitStream;
|
||||
use nvenc::session::InitParams;
|
||||
use nvenc::{
|
||||
session::Session,
|
||||
sys::guids::{NV_ENC_CODEC_H264_GUID, NV_ENC_PRESET_P3_GUID},
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use windows::Win32::Graphics::Direct3D11::{ID3D11Device, ID3D11Texture2D};
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn setup() -> ID3D11Device {
|
||||
let dxgi_factory: windows::Win32::Graphics::Dxgi::IDXGIFactory =
|
||||
unsafe { windows::Win32::Graphics::Dxgi::CreateDXGIFactory() }.unwrap();
|
||||
let dxgi_adapter = unsafe { dxgi_factory.EnumAdapters(0) }.unwrap();
|
||||
|
||||
let desc = unsafe { dxgi_adapter.GetDesc() }.unwrap();
|
||||
println!("{:?}", windows::core::HSTRING::from_wide(&desc.Description));
|
||||
|
||||
let mut device = None;
|
||||
let mut device_context = None;
|
||||
unsafe {
|
||||
use windows::Win32::{
|
||||
Foundation::HMODULE,
|
||||
Graphics::{
|
||||
Direct3D::{D3D_DRIVER_TYPE_UNKNOWN, D3D_FEATURE_LEVEL_11_0},
|
||||
Direct3D11::{D3D11_CREATE_DEVICE_FLAG, D3D11_SDK_VERSION, D3D11CreateDevice},
|
||||
},
|
||||
};
|
||||
|
||||
D3D11CreateDevice(
|
||||
&dxgi_adapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
HMODULE(std::ptr::null_mut()),
|
||||
D3D11_CREATE_DEVICE_FLAG(0),
|
||||
Some(&[D3D_FEATURE_LEVEL_11_0]),
|
||||
D3D11_SDK_VERSION,
|
||||
Some(&raw mut device),
|
||||
None,
|
||||
Some(&raw mut device_context),
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
let device = device.unwrap();
|
||||
let _device_context = device_context.unwrap();
|
||||
|
||||
device
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn image(device: &ID3D11Device) -> ID3D11Texture2D {
|
||||
let data: [u8; 1920 * 4] = std::array::from_fn(|idx| match idx % 4 {
|
||||
0 => 255,
|
||||
1 => 0,
|
||||
2 => 0,
|
||||
3 => 255,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
let mut texture = None;
|
||||
let desc = windows::Win32::Graphics::Direct3D11::D3D11_TEXTURE2D_DESC {
|
||||
Width: 1920,
|
||||
Height: 1080,
|
||||
MipLevels: 1,
|
||||
ArraySize: 1,
|
||||
Format: windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
SampleDesc: windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
},
|
||||
Usage: windows::Win32::Graphics::Direct3D11::D3D11_USAGE_DEFAULT,
|
||||
BindFlags: windows::Win32::Graphics::Direct3D11::D3D11_BIND_SHADER_RESOURCE.0 as u32,
|
||||
CPUAccessFlags: windows::Win32::Graphics::Dxgi::Common::DXGI_CPU_ACCESS_NONE,
|
||||
MiscFlags: 0,
|
||||
};
|
||||
let data = windows::Win32::Graphics::Direct3D11::D3D11_SUBRESOURCE_DATA {
|
||||
pSysMem: data.as_ptr() as _,
|
||||
SysMemPitch: 1920 * 4,
|
||||
SysMemSlicePitch: 0,
|
||||
};
|
||||
unsafe {
|
||||
device.CreateTexture2D(
|
||||
&raw const desc,
|
||||
Some(&raw const data),
|
||||
Some(&raw mut texture),
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
texture.unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let device = setup();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
compile_error!("Linux is currently unsupported in this example");
|
||||
#[cfg(windows)]
|
||||
let session: Session<nvenc::session::NeedsConfig> = Session::open_dx(&device).unwrap();
|
||||
assert!(
|
||||
session
|
||||
.get_encode_codecs()
|
||||
.unwrap()
|
||||
.contains(&NV_ENC_CODEC_H264_GUID)
|
||||
);
|
||||
assert!(
|
||||
session
|
||||
.get_encode_presets(NV_ENC_CODEC_H264_GUID)
|
||||
.unwrap()
|
||||
.contains(&NV_ENC_PRESET_P3_GUID)
|
||||
);
|
||||
let (session, mut config) = session
|
||||
.get_encode_preset_config_ex(
|
||||
NV_ENC_CODEC_H264_GUID,
|
||||
NV_ENC_PRESET_P3_GUID,
|
||||
nvenc::sys::enums::NVencTuningInfo::LowLatency,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let texture = image(&device);
|
||||
|
||||
config.preset_cfg.rc_params.rate_control_mode = nvenc::sys::enums::NVencParamsRcMode::VBR;
|
||||
config.preset_cfg.rc_params.average_bit_rate = 10_000_000;
|
||||
config.preset_cfg.gop_len = 0xffffffff;
|
||||
config.preset_cfg.frame_interval_p = 1;
|
||||
println!("P-Frames: {}", config.preset_cfg.frame_interval_p);
|
||||
println!("Bitrate: {}", config.preset_cfg.rc_params.average_bit_rate);
|
||||
|
||||
let init_params = InitParams {
|
||||
encode_guid: NV_ENC_CODEC_H264_GUID,
|
||||
preset_guid: NV_ENC_PRESET_P3_GUID,
|
||||
aspect_ratio: [16, 9],
|
||||
encode_config: &mut config.preset_cfg,
|
||||
tuning_info: nvenc::sys::enums::NVencTuningInfo::LowLatency,
|
||||
buffer_format: nvenc::sys::enums::NVencBufferFormat::ARGB,
|
||||
frame_rate: [30, 1],
|
||||
resolution: [1920, 1080],
|
||||
enable_ptd: true,
|
||||
max_encoder_resolution: [0, 0],
|
||||
};
|
||||
|
||||
println!("FPS: 30");
|
||||
println!("Len: 600 frames");
|
||||
println!("Expected time: {}", 600 / 30);
|
||||
println!("Codec: H264");
|
||||
println!("Tuning Info {:?}:", init_params.tuning_info);
|
||||
|
||||
let encoder = session.init_encoder(init_params).unwrap();
|
||||
let registered = encoder
|
||||
.register_resource_dx11(&texture, nvenc::sys::enums::NVencBufferFormat::ARGB, 0)
|
||||
.unwrap();
|
||||
|
||||
let (processed, to_use) = std::sync::mpsc::sync_channel::<BitStream>(2);
|
||||
let (re_use, to_process) = std::sync::mpsc::sync_channel::<BitStream>(2);
|
||||
processed
|
||||
.send(encoder.create_bitstream_buffer().unwrap())
|
||||
.unwrap();
|
||||
processed
|
||||
.send(encoder.create_bitstream_buffer().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let handle = std::thread::spawn({
|
||||
move || {
|
||||
let mut out = File::create("output.h264").unwrap();
|
||||
|
||||
while let Ok(output) = to_process.recv() {
|
||||
let lock = output.try_lock(true).unwrap();
|
||||
out.write_all(lock.as_slice()).unwrap();
|
||||
drop(lock);
|
||||
if let Err(_) = processed.send(output) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let instant = Instant::now();
|
||||
let mut i = 0;
|
||||
while i < 600 {
|
||||
if let Ok(output) = to_use.recv() {
|
||||
encoder
|
||||
.encode_picture(
|
||||
®istered,
|
||||
&output,
|
||||
i,
|
||||
instant.duration_since(Instant::now()).as_millis() as u64,
|
||||
nvenc::sys::enums::NVencBufferFormat::ARGB,
|
||||
nvenc::sys::enums::NVencPicStruct::Frame,
|
||||
nvenc::sys::enums::NVencPicType::P,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
re_use.send(output).unwrap();
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
drop(to_use);
|
||||
drop(re_use);
|
||||
handle.join().unwrap();
|
||||
}
|
||||
86
vendor/nvenc/src/lib.rs
vendored
Normal file
86
vendor/nvenc/src/lib.rs
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::{mem::MaybeUninit, sync::OnceLock};
|
||||
|
||||
use libloading::Library;
|
||||
|
||||
use crate::sys::{
|
||||
function_table::NVencFunctionList,
|
||||
result::{NVencError, NVencResult},
|
||||
version::NVENC_API_LIST_VERSION,
|
||||
};
|
||||
|
||||
mod safe;
|
||||
pub use safe::*;
|
||||
/// Contains the original C Types, functions, enums, and constants
|
||||
pub mod sys;
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
|
||||
pub const NVENC_DLL: &str = "nvEncodeAPI64.dll";
|
||||
#[cfg(all(target_arch = "x86", target_os = "windows"))]
|
||||
pub const NVENC_DLL: &str = "nvEncodeAPI.dll";
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
/// Platform specific DLL name, `libnvidia-encode.so.1` on Linux, `nvEncodeAPI64.dll` on Windows
|
||||
pub const NVENC_DLL: &str = "libnvidia-encode.so.1";
|
||||
|
||||
#[cfg(all(target_arch = "x86", windows))]
|
||||
#[macro_export]
|
||||
macro_rules! stdcall {
|
||||
(fn $args:tt $(-> $ret:tt)?) => { unsafe extern "stdcall" fn $args $(-> $ret)? };
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(all(target_arch = "x86", windows)))]
|
||||
#[macro_export]
|
||||
macro_rules! stdcall {
|
||||
(fn $args:tt $(-> $ret:ty)?) => { unsafe extern "C" fn $args $(-> $ret)? };
|
||||
}
|
||||
|
||||
pub(crate) static LIBRARY: OnceLock<NVENCLibrary> = OnceLock::new();
|
||||
|
||||
/// Struct containing the library handle, init and get_max_version number functions
|
||||
pub struct NVENCLibrary {
|
||||
#[allow(unused)]
|
||||
// Lib must stay alive for nvenc to be used
|
||||
lib: Library,
|
||||
init: stdcall!(fn(list: *mut MaybeUninit<NVencFunctionList>) -> NVencResult),
|
||||
get_max_version: stdcall!(fn(version: *mut u32) -> NVencResult),
|
||||
}
|
||||
|
||||
/// Attempt to init NVENC, returns an error if the library or loading functions cannot be found
|
||||
pub fn nvenc_init() -> Result<&'static NVENCLibrary, libloading::Error> {
|
||||
if let Some(lib) = LIBRARY.get() {
|
||||
Ok(lib)
|
||||
} else {
|
||||
let lib = unsafe { Library::new(NVENC_DLL) }?;
|
||||
let init: stdcall!(fn(function_list: *mut MaybeUninit<NVencFunctionList>) -> NVencResult) =
|
||||
*unsafe { lib.get(b"NvEncodeAPICreateInstance") }?;
|
||||
let get_max_version: stdcall!(fn(version: *mut u32) -> NVencResult) =
|
||||
*unsafe { lib.get(b"NvEncodeAPIGetMaxSupportedVersion") }?;
|
||||
|
||||
Ok(LIBRARY.get_or_init(|| NVENCLibrary {
|
||||
lib,
|
||||
init,
|
||||
get_max_version,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl NVENCLibrary {
|
||||
/// Create a new instance of the NVencFunctionList,
|
||||
pub fn create_instance(&self) -> Result<NVencFunctionList, NVencError> {
|
||||
let mut list = MaybeUninit::zeroed();
|
||||
unsafe { *(list.as_mut_ptr() as *mut u32) = NVENC_API_LIST_VERSION };
|
||||
unsafe { (self.init)(&raw mut list) }.into_error().unwrap();
|
||||
Ok(unsafe { list.assume_init() })
|
||||
}
|
||||
|
||||
pub fn get_max_version(&self) -> Result<u32, NVencError> {
|
||||
let mut version = 0;
|
||||
unsafe { (self.get_max_version)(&raw mut version) }.into_error()?;
|
||||
let minor = version & 0x0F;
|
||||
let version = (version >> 4) | minor << 28;
|
||||
Ok(version)
|
||||
}
|
||||
}
|
||||
53
vendor/nvenc/src/safe/bitstream.rs
vendored
Normal file
53
vendor/nvenc/src/safe/bitstream.rs
vendored
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
517
vendor/nvenc/src/safe/encoder.rs
vendored
Normal file
517
vendor/nvenc/src/safe/encoder.rs
vendored
Normal file
@ -0,0 +1,517 @@
|
||||
use std::ffi::{CStr, c_void};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::sync::Arc;
|
||||
use std::{mem::MaybeUninit, ptr::NonNull};
|
||||
|
||||
#[cfg(windows)]
|
||||
use windows::Win32::Graphics::Direct3D11::ID3D11Texture2D;
|
||||
|
||||
use crate::input_buffer::InputBuffer;
|
||||
use crate::safe::bitstream::BitStream;
|
||||
use crate::sys::enums::{
|
||||
NVencBufferFormat, NVencBufferUsage, NVencInputResourceType, NVencMemoryHeap, NVencPicStruct,
|
||||
NVencPicType,
|
||||
};
|
||||
use crate::sys::structs::{
|
||||
Guid, NV_ENC_CREATE_INPUT_BUFFER_VER, NV_ENC_LOCK_INPUT_BUFFER_VER, NVencCodecPicParams,
|
||||
NVencCreateInputBuffer, NVencLockInputBuffer, NVencPicParamsH264, NVencRegisterResource,
|
||||
};
|
||||
use crate::sys::{
|
||||
enums::{NVencPicFlags, NVencTuningInfo},
|
||||
function_table::NVencFunctionList,
|
||||
result::NVencError,
|
||||
structs::{
|
||||
NV_ENC_CONFIG_VER, NV_ENC_CREATE_BITSTREAM_BUFFER_VER, NV_ENC_LOCK_BITSTREAM_VER,
|
||||
NV_ENC_MAP_INPUT_RESOURCE_VER, NV_ENC_PIC_PARAMS_VER, NV_ENC_PRESET_CONFIG_VER,
|
||||
NV_ENC_REGISTER_RESOURCE_VER, NVencCreateBitstreamBuffer, NVencInitializeParams,
|
||||
NVencLockBitStream, NVencPicParams, NVencPresetConfig,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Encoder {
|
||||
pub(crate) encoder: Arc<EncoderInternal>,
|
||||
pub(crate) marker: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
pub trait EncoderInput {
|
||||
#[doc(hidden)]
|
||||
fn as_ptr(&self) -> *mut c_void;
|
||||
|
||||
fn pitch(&self) -> u32;
|
||||
fn height(&self) -> u32;
|
||||
fn width(&self) -> u32;
|
||||
}
|
||||
|
||||
impl EncoderInput for RegisteredResource {
|
||||
fn as_ptr(&self) -> *mut c_void {
|
||||
self.mapped
|
||||
}
|
||||
|
||||
fn pitch(&self) -> u32 {
|
||||
self.pitch
|
||||
}
|
||||
|
||||
fn height(&self) -> u32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
fn width(&self) -> u32 {
|
||||
self.width
|
||||
}
|
||||
}
|
||||
|
||||
impl EncoderInput for InputBuffer {
|
||||
fn as_ptr(&self) -> *mut c_void {
|
||||
self.buffer
|
||||
}
|
||||
|
||||
fn pitch(&self) -> u32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn height(&self) -> u32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
fn width(&self) -> u32 {
|
||||
self.width
|
||||
}
|
||||
}
|
||||
|
||||
impl Encoder {
|
||||
#[cfg(windows)]
|
||||
/// Registers a DX11 texture as an nvenc input resource
|
||||
pub fn register_resource_dx11(
|
||||
&self,
|
||||
resource: &ID3D11Texture2D,
|
||||
format: NVencBufferFormat,
|
||||
pitch: u32,
|
||||
) -> Result<RegisteredResource, NVencError> {
|
||||
self.encoder.register_resource_dx(resource, format, pitch)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// `resource` must not be null
|
||||
/// `ty` and `format` should match the original buffer
|
||||
pub unsafe fn register_resource_raw(
|
||||
&self,
|
||||
resource: *mut c_void,
|
||||
format: NVencBufferFormat,
|
||||
usage: NVencBufferUsage,
|
||||
ty: NVencInputResourceType,
|
||||
resolution: [u32; 2],
|
||||
pitch: u32,
|
||||
) -> Result<*mut c_void, NVencError> {
|
||||
unsafe {
|
||||
self.encoder
|
||||
.register_resource_raw(resource, format, usage, ty, resolution, pitch)
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes an encoder inout, and outputs a bit stream that can be read back
|
||||
pub fn encode_picture<I: EncoderInput>(
|
||||
&self,
|
||||
input: &I,
|
||||
output: &BitStream,
|
||||
frame_count: usize,
|
||||
timestamp: u64,
|
||||
format: NVencBufferFormat,
|
||||
pic_struct: NVencPicStruct,
|
||||
ty: NVencPicType,
|
||||
codec_params: Option<CodecPicParams>,
|
||||
) -> Result<(), NVencError> {
|
||||
self.encoder.encode_picture(
|
||||
input,
|
||||
output,
|
||||
frame_count,
|
||||
timestamp,
|
||||
format,
|
||||
pic_struct,
|
||||
ty,
|
||||
codec_params,
|
||||
)
|
||||
}
|
||||
|
||||
/// Ends the encoder session
|
||||
pub fn end_encode(&self) -> Result<(), NVencError> {
|
||||
self.encoder.end_encode()
|
||||
}
|
||||
|
||||
/// Creates a bitstream bfufer that can be used for output storage
|
||||
pub fn create_bitstream_buffer(&self) -> Result<BitStream, NVencError> {
|
||||
self.encoder.create_bitstream_buffer()
|
||||
}
|
||||
|
||||
pub fn create_input_buffer(
|
||||
&self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
memory_heap: NVencMemoryHeap,
|
||||
format: NVencBufferFormat,
|
||||
) -> Result<InputBuffer, NVencError> {
|
||||
Ok(InputBuffer {
|
||||
encoder: self.encoder.clone(),
|
||||
buffer: self
|
||||
.encoder
|
||||
.create_input_buffer(width, height, memory_heap, format)?,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct EncoderInternal {
|
||||
pub(super) encoder: NonNull<c_void>,
|
||||
pub(super) function_list: NVencFunctionList,
|
||||
}
|
||||
|
||||
/// The Nvidia encoder is technically thread-safe
|
||||
unsafe impl Send for EncoderInternal {}
|
||||
|
||||
/// The Nvidia encoder handles syncing via `lock_bit_stream` which is all that is allowed to be Send
|
||||
unsafe impl Sync for EncoderInternal {}
|
||||
|
||||
impl Drop for EncoderInternal {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping encoder, this should happen last");
|
||||
unsafe { (self.function_list.nvenc_destroy_encoder)(self.encoder.as_ptr()) };
|
||||
}
|
||||
}
|
||||
|
||||
impl EncoderInternal {
|
||||
pub(crate) fn get_encode_preset_config_ex(
|
||||
&self,
|
||||
codec: Guid,
|
||||
preset: Guid,
|
||||
tuning_info: NVencTuningInfo,
|
||||
) -> Result<NVencPresetConfig, NVencError> {
|
||||
let mut config: std::mem::MaybeUninit<NVencPresetConfig> = std::mem::MaybeUninit::zeroed();
|
||||
unsafe { &mut *config.as_mut_ptr() }.version = NV_ENC_PRESET_CONFIG_VER;
|
||||
unsafe { &mut *config.as_mut_ptr() }.preset_cfg.version = NV_ENC_CONFIG_VER;
|
||||
unsafe {
|
||||
(self.function_list.nvenc_get_encode_preset_config_ex)(
|
||||
self.encoder.as_ptr(),
|
||||
codec,
|
||||
preset,
|
||||
tuning_info,
|
||||
&raw mut config,
|
||||
)
|
||||
.into_error()?
|
||||
};
|
||||
|
||||
Ok(unsafe { config.assume_init() })
|
||||
}
|
||||
|
||||
pub(crate) fn init_encoder(
|
||||
&self,
|
||||
mut init_params: NVencInitializeParams,
|
||||
) -> Result<(), NVencError> {
|
||||
unsafe {
|
||||
(self.function_list.nvenc_initialize_encoder)(
|
||||
self.encoder.as_ptr(),
|
||||
&raw mut init_params,
|
||||
)
|
||||
}
|
||||
.into_error()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn register_resource_dx(
|
||||
self: &Arc<EncoderInternal>,
|
||||
resource: &ID3D11Texture2D,
|
||||
format: NVencBufferFormat,
|
||||
pitch: u32,
|
||||
) -> Result<RegisteredResource, NVencError> {
|
||||
use windows::Win32::Graphics::Direct3D11::D3D11_TEXTURE2D_DESC;
|
||||
use windows::core::Interface;
|
||||
|
||||
let mut desc = D3D11_TEXTURE2D_DESC::default();
|
||||
unsafe { resource.GetDesc(&raw mut desc) };
|
||||
|
||||
let registered = unsafe {
|
||||
self.register_resource_raw(
|
||||
resource.as_raw(),
|
||||
NVencBufferFormat::Undefined,
|
||||
NVencBufferUsage::Image,
|
||||
NVencInputResourceType::DirectX,
|
||||
[desc.Width, desc.Height],
|
||||
pitch,
|
||||
)?
|
||||
};
|
||||
|
||||
let mapped = unsafe { self.map_input_resource_raw(registered, format)? };
|
||||
|
||||
Ok(RegisteredResource {
|
||||
encoder: self.clone(),
|
||||
pitch,
|
||||
width: desc.Width,
|
||||
height: desc.Height,
|
||||
registered,
|
||||
mapped,
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn map_input_resource_raw(
|
||||
&self,
|
||||
resource: *mut c_void,
|
||||
format: NVencBufferFormat,
|
||||
) -> Result<*mut c_void, NVencError> {
|
||||
let mut map: crate::sys::structs::NVencMapInputResource = unsafe { std::mem::zeroed() };
|
||||
map.version = NV_ENC_MAP_INPUT_RESOURCE_VER;
|
||||
map.registered_resource = resource;
|
||||
map.mapped_buffer_format = format;
|
||||
|
||||
unsafe {
|
||||
(self.function_list.nvenc_map_input_resource)(self.encoder.as_ptr(), &raw mut map)
|
||||
}
|
||||
.into_error()?;
|
||||
|
||||
Ok(map.mapped_resource)
|
||||
}
|
||||
|
||||
pub unsafe fn register_resource_raw(
|
||||
&self,
|
||||
resource: *mut c_void,
|
||||
format: NVencBufferFormat,
|
||||
usage: NVencBufferUsage,
|
||||
ty: NVencInputResourceType,
|
||||
resolution: [u32; 2],
|
||||
pitch: u32,
|
||||
) -> Result<*mut c_void, NVencError> {
|
||||
let mut register_resource: NVencRegisterResource = unsafe { std::mem::zeroed() };
|
||||
register_resource.buffer_format = format;
|
||||
register_resource.buffer_usage = usage;
|
||||
register_resource.resource_type = ty;
|
||||
register_resource.version = NV_ENC_REGISTER_RESOURCE_VER;
|
||||
register_resource.width = resolution[0];
|
||||
register_resource.height = resolution[1];
|
||||
register_resource.pitch = pitch;
|
||||
register_resource.sub_resource_index = 0;
|
||||
register_resource.resource_to_register = resource;
|
||||
unsafe {
|
||||
(self.function_list.nvenc_register_resource)(
|
||||
self.encoder.as_ptr(),
|
||||
&raw mut register_resource,
|
||||
)
|
||||
.into_error()
|
||||
}?;
|
||||
Ok(register_resource.registered_resource)
|
||||
}
|
||||
|
||||
pub unsafe fn unmap_input_resource(
|
||||
&self,
|
||||
mapped_resource: *mut c_void,
|
||||
) -> Result<(), NVencError> {
|
||||
unsafe {
|
||||
(self.function_list.nvenc_unmap_input_resource)(self.encoder.as_ptr(), mapped_resource)
|
||||
}
|
||||
.into_error()
|
||||
}
|
||||
|
||||
pub unsafe fn unregister_resource(
|
||||
&self,
|
||||
registered_resource: *mut c_void,
|
||||
) -> Result<(), NVencError> {
|
||||
unsafe {
|
||||
(self.function_list.nvenc_unregister_resource)(
|
||||
self.encoder.as_ptr(),
|
||||
registered_resource,
|
||||
)
|
||||
}
|
||||
.into_error()
|
||||
}
|
||||
|
||||
pub fn create_input_buffer(
|
||||
&self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
memory_heap: NVencMemoryHeap,
|
||||
format: NVencBufferFormat,
|
||||
) -> Result<*mut c_void, NVencError> {
|
||||
let mut input = NVencCreateInputBuffer {
|
||||
version: NV_ENC_CREATE_INPUT_BUFFER_VER,
|
||||
width: width,
|
||||
height: height,
|
||||
memory_heap,
|
||||
buffer_fmt: format,
|
||||
rsvd: 0,
|
||||
input_buffer: std::ptr::null_mut(),
|
||||
p_sys_mem_buffer: std::ptr::null_mut(),
|
||||
rsvd1: unsafe { std::mem::zeroed() },
|
||||
rsvd2: unsafe { std::mem::zeroed() },
|
||||
};
|
||||
unsafe {
|
||||
(self.function_list.nvenc_create_input_buffer)(self.encoder.as_ptr(), &raw mut input)
|
||||
.into_error()?
|
||||
};
|
||||
|
||||
Ok(input.input_buffer)
|
||||
}
|
||||
|
||||
pub fn destroy_input_buffer(&self, buffer: *mut c_void) -> Result<(), NVencError> {
|
||||
unsafe { (self.function_list.nvenc_destroy_input_buffer)(self.encoder.as_ptr(), buffer) }
|
||||
.into_error()
|
||||
}
|
||||
|
||||
pub fn lock_input_buffer(&self, buffer: *mut c_void) -> Result<(*mut c_void, u32), NVencError> {
|
||||
let mut lock = NVencLockInputBuffer {
|
||||
version: NV_ENC_LOCK_INPUT_BUFFER_VER,
|
||||
bitflags: 0,
|
||||
input_buffer: buffer,
|
||||
buffer_data_ptr: std::ptr::null_mut(),
|
||||
pitch: 0,
|
||||
rsvd1: unsafe { std::mem::zeroed() },
|
||||
rsvd2: unsafe { std::mem::zeroed() },
|
||||
};
|
||||
|
||||
unsafe {
|
||||
(self.function_list.nvenc_lock_input_buffer)(self.encoder.as_ptr(), &raw mut lock)
|
||||
.into_error()?;
|
||||
}
|
||||
|
||||
Ok((lock.buffer_data_ptr, lock.pitch))
|
||||
}
|
||||
|
||||
pub fn unlock_input_buffer(&self, locked_buffer: *mut c_void) -> Result<(), NVencError> {
|
||||
unsafe {
|
||||
(self.function_list.nvenc_unlock_input_buffer)(self.encoder.as_ptr(), locked_buffer)
|
||||
.into_error()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_picture<I: EncoderInput>(
|
||||
&self,
|
||||
input: &I,
|
||||
output: &BitStream,
|
||||
frame_count: usize,
|
||||
timestamp: u64,
|
||||
format: NVencBufferFormat,
|
||||
pic_struct: NVencPicStruct,
|
||||
ty: NVencPicType,
|
||||
codec_params: Option<CodecPicParams>,
|
||||
) -> Result<(), NVencError> {
|
||||
let mut params: MaybeUninit<NVencPicParams> = MaybeUninit::zeroed();
|
||||
let sys_codec = match codec_params {
|
||||
None => NVencCodecPicParams { rsvd: [0; 256] },
|
||||
Some(CodecPicParams::H264(codec)) => NVencCodecPicParams {
|
||||
h264_pic_params: ManuallyDrop::new(codec),
|
||||
},
|
||||
};
|
||||
unsafe { &mut *params.as_mut_ptr() }.version = NV_ENC_PIC_PARAMS_VER;
|
||||
unsafe { &mut *params.as_mut_ptr() }.input_width = input.width();
|
||||
unsafe { &mut *params.as_mut_ptr() }.input_height = input.height();
|
||||
unsafe { &mut *params.as_mut_ptr() }.input_pitch = input.pitch();
|
||||
unsafe { &mut *params.as_mut_ptr() }.output_bitstream = output.buffer;
|
||||
unsafe { &mut *params.as_mut_ptr() }.input_buffer = input.as_ptr();
|
||||
unsafe { &mut *params.as_mut_ptr() }.buffer_format = format;
|
||||
unsafe { &mut *params.as_mut_ptr() }.picture_struct = pic_struct;
|
||||
// [本项目补丁] 只设 picture_type=IDR 不足以让 NVENC 真正输出 IDR 切片,
|
||||
// 必须同时置 encode_pic_flags |= NV_ENC_PIC_FLAG_FORCEIDR。
|
||||
//
|
||||
// 上游 0.1.0 未设置该标志,导致运行期请求关键帧时编码器静默忽略、
|
||||
// 继续输出 P 帧(实测:picture_type=IDR 但输出 NAL type=1)。
|
||||
// 首帧之所以"看起来正常",是因为 frame_idx==0 本来就强制 IDR,与本字段无关。
|
||||
//
|
||||
// 语义区分:IntraRefresh 走 ForceIntra,其余 IDR 类走 ForceIDR。
|
||||
// 必须在 `picture_type = ty` 之前计算,否则 ty 已被移动。
|
||||
let pic_flags = match &ty {
|
||||
NVencPicType::IDR => NVencPicFlags::ForceIDR as u32,
|
||||
NVencPicType::IntraRefresh => NVencPicFlags::ForceIntra as u32,
|
||||
_ => 0,
|
||||
};
|
||||
unsafe { &mut *params.as_mut_ptr() }.picture_type = ty;
|
||||
unsafe { &mut *params.as_mut_ptr() }.encode_pic_flags = pic_flags;
|
||||
unsafe { &mut *params.as_mut_ptr() }.frame_idx = frame_count as u32;
|
||||
unsafe { &mut *params.as_mut_ptr() }.input_time_stamp = timestamp;
|
||||
unsafe { &mut *params.as_mut_ptr() }.codec_pic_params = sys_codec;
|
||||
match unsafe {
|
||||
(self.function_list.nvenc_encode_picture)(self.encoder.as_ptr(), &raw mut params)
|
||||
.into_error()
|
||||
} {
|
||||
Err(err) => {
|
||||
let ptr =
|
||||
unsafe { (self.function_list.nvenc_get_last_error)(self.encoder.as_ptr()) };
|
||||
println!("{:?}", unsafe { CStr::from_ptr(ptr) });
|
||||
Err(err)
|
||||
}
|
||||
Ok(()) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_encode(&self) -> Result<(), NVencError> {
|
||||
let mut params: MaybeUninit<NVencPicParams> = MaybeUninit::zeroed();
|
||||
unsafe { &mut *params.as_mut_ptr() }.version = NV_ENC_PIC_PARAMS_VER;
|
||||
unsafe { &mut *params.as_mut_ptr() }.encode_pic_flags = NVencPicFlags::Eos as u32;
|
||||
unsafe {
|
||||
(self.function_list.nvenc_encode_picture)(self.encoder.as_ptr(), &raw mut params)
|
||||
.into_error()
|
||||
}?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn lock_bit_stream_buffer(
|
||||
&self,
|
||||
buffer: *mut c_void,
|
||||
wait: bool,
|
||||
) -> Result<NVencLockBitStream, NVencError> {
|
||||
let mut lock: MaybeUninit<NVencLockBitStream> = MaybeUninit::zeroed();
|
||||
unsafe { &mut *lock.as_mut_ptr() }.version = NV_ENC_LOCK_BITSTREAM_VER;
|
||||
unsafe { &mut *lock.as_mut_ptr() }.output_bit_stream = buffer;
|
||||
unsafe { &mut *lock.as_mut_ptr() }
|
||||
.bit_fields
|
||||
.set_do_not_wait(!wait);
|
||||
unsafe { (self.function_list.nvenc_lock_bit_stream)(self.encoder.as_ptr(), &raw mut lock) }
|
||||
.into_error()?;
|
||||
Ok(unsafe { lock.assume_init() })
|
||||
}
|
||||
|
||||
pub(crate) fn unlock_bit_stream_buffer(&self, buffer: *mut c_void) -> Result<(), NVencError> {
|
||||
unsafe { (self.function_list.nvenc_unlock_bit_stream)(self.encoder.as_ptr(), buffer) }
|
||||
.into_error()
|
||||
}
|
||||
|
||||
pub fn create_bitstream_buffer(self: &Arc<Self>) -> Result<BitStream, NVencError> {
|
||||
let mut params: NVencCreateBitstreamBuffer = unsafe { std::mem::zeroed() };
|
||||
params.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
|
||||
unsafe {
|
||||
(self.function_list.nvenc_create_bit_stream_buffer)(
|
||||
self.encoder.as_ptr(),
|
||||
&raw mut params,
|
||||
)
|
||||
}
|
||||
.into_error()?;
|
||||
Ok(BitStream {
|
||||
buffer: params.bitstream_buffer,
|
||||
encoder: self.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn destroy_bitstream_buffer(&self, buffer: *mut c_void) -> Result<(), NVencError> {
|
||||
unsafe {
|
||||
(self.function_list.nvenc_destory_bit_stream_buffer)(self.encoder.as_ptr(), buffer)
|
||||
}
|
||||
.into_error()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CodecPicParams {
|
||||
H264(NVencPicParamsH264),
|
||||
}
|
||||
|
||||
pub struct RegisteredResource {
|
||||
registered: *mut c_void,
|
||||
mapped: *mut c_void,
|
||||
pitch: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
encoder: Arc<EncoderInternal>,
|
||||
}
|
||||
|
||||
impl Drop for RegisteredResource {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.encoder.unmap_input_resource(self.mapped).unwrap() };
|
||||
unsafe { self.encoder.unregister_resource(self.registered).unwrap() };
|
||||
}
|
||||
}
|
||||
60
vendor/nvenc/src/safe/input_buffer.rs
vendored
Normal file
60
vendor/nvenc/src/safe/input_buffer.rs
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
use std::{ffi::c_void, sync::Arc};
|
||||
|
||||
use crate::{encoder::EncoderInternal, sys::result::NVencError};
|
||||
|
||||
pub struct InputBuffer {
|
||||
pub(crate) encoder: Arc<EncoderInternal>,
|
||||
pub(crate) buffer: *mut c_void,
|
||||
pub(crate) width: u32,
|
||||
pub(crate) height: u32,
|
||||
}
|
||||
|
||||
impl InputBuffer {
|
||||
pub fn lock(&self) -> Result<InputBufferLock<'_>, NVencError> {
|
||||
let (lock_ptr, pitch) = self.encoder.lock_input_buffer(self.buffer)?;
|
||||
Ok(InputBufferLock {
|
||||
input_buffer: self,
|
||||
lock_ptr,
|
||||
pitch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InputBuffer {
|
||||
fn drop(&mut self) {
|
||||
self.encoder.destroy_input_buffer(self.buffer).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InputBufferLock<'a> {
|
||||
input_buffer: &'a InputBuffer,
|
||||
lock_ptr: *mut c_void,
|
||||
pitch: u32,
|
||||
}
|
||||
|
||||
impl InputBufferLock<'_> {
|
||||
pub unsafe fn data_ptr(&self) -> *mut u8 {
|
||||
self.lock_ptr as _
|
||||
}
|
||||
|
||||
pub fn width(&self) -> u32 {
|
||||
self.input_buffer.width
|
||||
}
|
||||
|
||||
pub fn height(&self) -> u32 {
|
||||
self.input_buffer.height
|
||||
}
|
||||
|
||||
pub fn pitch(&self) -> u32 {
|
||||
self.pitch
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InputBufferLock<'_> {
|
||||
fn drop(&mut self) {
|
||||
self.input_buffer
|
||||
.encoder
|
||||
.unlock_input_buffer(self.lock_ptr)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
8
vendor/nvenc/src/safe/mod.rs
vendored
Normal file
8
vendor/nvenc/src/safe/mod.rs
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/// Contains the type for the safe BitStream buffer wrapper
|
||||
pub mod bitstream;
|
||||
/// Wrapper for the NVEncoder after creating an active session
|
||||
pub mod encoder;
|
||||
/// Wrapper around an NVenc input buffer
|
||||
pub mod input_buffer;
|
||||
/// Type-state wrapper around session initialization
|
||||
pub mod session;
|
||||
198
vendor/nvenc/src/safe/session.rs
vendored
Normal file
198
vendor/nvenc/src/safe/session.rs
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
encoder::{Encoder, EncoderInternal},
|
||||
sys::{
|
||||
enums::{NVencBufferFormat, NVencDeviceType, NVencTuningInfo},
|
||||
result::NVencError,
|
||||
structs::{
|
||||
Guid, NV_ENC_INITIALIZE_PARAMS_VER, NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER,
|
||||
NVencConfig, NVencInitializeParams, NVencOpenEncodeSessionExParams, NVencPresetConfig,
|
||||
},
|
||||
version::NVENC_API_VERSION,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Session<T> {
|
||||
encoder: Arc<EncoderInternal>,
|
||||
p: PhantomData<T>,
|
||||
}
|
||||
|
||||
pub struct NeedsConfig;
|
||||
|
||||
pub struct NeedsInit;
|
||||
|
||||
#[cfg(windows)]
|
||||
use windows::core::Interface;
|
||||
|
||||
impl Session<NeedsConfig> {
|
||||
#[cfg(windows)]
|
||||
pub fn open_dx(device: &impl Interface) -> Result<Self, NVencError> {
|
||||
let lib = crate::nvenc_init().unwrap();
|
||||
let function_list = lib.create_instance()?;
|
||||
let mut session_params: NVencOpenEncodeSessionExParams = unsafe { std::mem::zeroed() };
|
||||
session_params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
|
||||
session_params.device_type = NVencDeviceType::DirectX;
|
||||
session_params.api_version = NVENC_API_VERSION;
|
||||
session_params.device = device.as_raw();
|
||||
let mut encoder = std::ptr::null_mut();
|
||||
unsafe {
|
||||
(function_list.nvenc_open_encode_session_ex)(&raw mut session_params, &raw mut encoder)
|
||||
.into_error()
|
||||
}?;
|
||||
assert!(!encoder.is_null());
|
||||
let encoder = EncoderInternal {
|
||||
encoder: unsafe { std::ptr::NonNull::new_unchecked(encoder) },
|
||||
function_list,
|
||||
};
|
||||
Ok(Self {
|
||||
encoder: Arc::new(encoder),
|
||||
p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn open_gl() -> Result<Self, NVencError> {
|
||||
let lib = crate::nvenc_init().unwrap();
|
||||
let function_list = lib.create_instance()?;
|
||||
let mut session_params: NVencOpenEncodeSessionExParams = unsafe { std::mem::zeroed() };
|
||||
session_params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
|
||||
session_params.device_type = NVencDeviceType::OpenGL;
|
||||
session_params.api_version = NVENC_API_VERSION;
|
||||
session_params.device = std::ptr::null_mut();
|
||||
|
||||
let mut encoder = std::ptr::null_mut();
|
||||
unsafe {
|
||||
(function_list.nvenc_open_encode_session_ex)(&raw mut session_params, &raw mut encoder)
|
||||
.into_error()
|
||||
}?;
|
||||
assert!(!encoder.is_null());
|
||||
let encoder = EncoderInternal {
|
||||
encoder: unsafe { std::ptr::NonNull::new_unchecked(encoder) },
|
||||
function_list,
|
||||
};
|
||||
Ok(Self {
|
||||
encoder: Arc::new(encoder),
|
||||
p: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_encode_codecs(&self) -> Result<Box<[Guid]>, NVencError> {
|
||||
let mut count = 0;
|
||||
unsafe {
|
||||
(self.encoder.function_list.nvenc_get_encoder_guid_count)(
|
||||
self.encoder.encoder.as_ptr(),
|
||||
&raw mut count,
|
||||
)
|
||||
.into_error()
|
||||
}?;
|
||||
let mut array = vec![Guid::default(); count as usize];
|
||||
unsafe {
|
||||
(self.encoder.function_list.nvenc_get_encoder_guids)(
|
||||
self.encoder.encoder.as_ptr(),
|
||||
array.as_mut_ptr(),
|
||||
count,
|
||||
&raw mut count,
|
||||
)
|
||||
}
|
||||
.into_error()?;
|
||||
array.truncate(count as usize);
|
||||
Ok(array.into())
|
||||
}
|
||||
|
||||
pub fn get_encode_presets(&self, codec: Guid) -> Result<Box<[Guid]>, NVencError> {
|
||||
let mut count = 0;
|
||||
unsafe {
|
||||
(self.encoder.function_list.nvenc_get_encode_preset_count)(
|
||||
self.encoder.encoder.as_ptr(),
|
||||
codec.clone(),
|
||||
&raw mut count,
|
||||
)
|
||||
.into_error()
|
||||
}?;
|
||||
let mut array = vec![Guid::default(); count as usize];
|
||||
unsafe {
|
||||
(self.encoder.function_list.nvenc_get_encode_preset_guids)(
|
||||
self.encoder.encoder.as_ptr(),
|
||||
codec,
|
||||
array.as_mut_ptr(),
|
||||
count,
|
||||
&raw mut count,
|
||||
)
|
||||
}
|
||||
.into_error()?;
|
||||
array.truncate(count as usize);
|
||||
Ok(array.into())
|
||||
}
|
||||
|
||||
pub fn get_encode_preset_config_ex(
|
||||
self,
|
||||
codec: Guid,
|
||||
preset: Guid,
|
||||
tuning_info: NVencTuningInfo,
|
||||
) -> Result<(Session<NeedsInit>, NVencPresetConfig), NVencError> {
|
||||
self.encoder
|
||||
.get_encode_preset_config_ex(codec, preset, tuning_info)
|
||||
.map(|config| {
|
||||
(
|
||||
Session {
|
||||
encoder: self.encoder,
|
||||
p: PhantomData,
|
||||
},
|
||||
config,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InitParams<'a> {
|
||||
pub encode_guid: Guid,
|
||||
pub preset_guid: Guid,
|
||||
pub resolution: [u32; 2],
|
||||
pub aspect_ratio: [u32; 2],
|
||||
pub frame_rate: [u32; 2],
|
||||
pub tuning_info: NVencTuningInfo,
|
||||
pub buffer_format: NVencBufferFormat,
|
||||
pub encode_config: &'a mut NVencConfig,
|
||||
pub enable_ptd: bool,
|
||||
pub max_encoder_resolution: [u32; 2],
|
||||
// TODO: Support for async encoding and bit fields
|
||||
}
|
||||
|
||||
impl Session<NeedsInit> {
|
||||
pub fn init_encoder(self, init_params: InitParams) -> Result<Encoder, NVencError> {
|
||||
// This sucks, lol
|
||||
let raw_init_params = NVencInitializeParams {
|
||||
encode_guid: init_params.encode_guid,
|
||||
preset_guid: init_params.preset_guid,
|
||||
encode_width: init_params.resolution[0],
|
||||
encode_height: init_params.resolution[1],
|
||||
dar_width: init_params.aspect_ratio[0],
|
||||
dar_height: init_params.aspect_ratio[1],
|
||||
frame_rate_num: init_params.frame_rate[0],
|
||||
frame_rate_den: init_params.frame_rate[1],
|
||||
tuning_info: init_params.tuning_info,
|
||||
buffer_format: init_params.buffer_format,
|
||||
encode_config: init_params.encode_config as _,
|
||||
enable_ptd: init_params.enable_ptd as u32,
|
||||
version: NV_ENC_INITIALIZE_PARAMS_VER,
|
||||
enable_encode_async: 0,
|
||||
bit_flags: crate::sys::structs::NVencInitializeParamsBitfields::new(),
|
||||
priv_data_size: 0,
|
||||
rsvd: 0,
|
||||
priv_data: std::ptr::null_mut(),
|
||||
max_encode_width: init_params.max_encoder_resolution[0],
|
||||
max_encode_height: init_params.max_encoder_resolution[1],
|
||||
max_me_hint_counts_per_block: [Default::default(), Default::default()],
|
||||
num_state_buffers: 0,
|
||||
output_stats_level: crate::sys::enums::NVencOutputStatsLevel::None,
|
||||
rsvd1: unsafe { std::mem::zeroed() },
|
||||
rsvd2: unsafe { std::mem::zeroed() },
|
||||
};
|
||||
|
||||
self.encoder.init_encoder(raw_init_params)?;
|
||||
Ok(Encoder {
|
||||
encoder: self.encoder,
|
||||
marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
481
vendor/nvenc/src/sys/enums.rs
vendored
Normal file
481
vendor/nvenc/src/sys/enums.rs
vendored
Normal file
@ -0,0 +1,481 @@
|
||||
#[repr(C)]
|
||||
pub enum NVencParamsFrameFieldMode {
|
||||
Frame = 0x01,
|
||||
Field = 0x02,
|
||||
MBAFF = 0x03,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencParamsRcMode {
|
||||
ConstQP = 0x00,
|
||||
VBR = 0x01,
|
||||
CBR = 0x02,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencMultiPass {
|
||||
Disabled = 0x00,
|
||||
TwoPassQuarterResolution = 0x01,
|
||||
TwoPassFullResolution = 0x02,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencStateRestoreType {
|
||||
Full = 0x01,
|
||||
RateControl = 0x02,
|
||||
Encode = 0x03,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencOutputStatsLevel {
|
||||
None = 0,
|
||||
BlockLevel = 1,
|
||||
RowLevel = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencEmphasisMapLevel {
|
||||
Level0 = 0x0,
|
||||
Level1 = 0x1,
|
||||
Level2 = 0x2,
|
||||
Level3 = 0x3,
|
||||
Level4 = 0x4,
|
||||
Level5 = 0x5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencQPMapMode {
|
||||
Disabled = 0x0,
|
||||
Emphasis = 0x1,
|
||||
Delta = 0x2,
|
||||
/// Currently unsupported as of NVENC 13.0
|
||||
Map = 0x3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencPicStruct {
|
||||
Frame = 0x01,
|
||||
FieldTopBottom = 0x02,
|
||||
FieldBottomTop = 0x03,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencDisplayPicStruct {
|
||||
Frame = 0x0,
|
||||
FieldTopBottom = 0x1,
|
||||
FieldBottomTop = 0x2,
|
||||
Doubling = 0x3,
|
||||
Tripling = 0x4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencPicType {
|
||||
P = 0x00,
|
||||
B = 0x01,
|
||||
IDR = 0x03,
|
||||
BI = 0x04,
|
||||
Skipped = 0x05,
|
||||
IntraRefresh = 0x06,
|
||||
NonRefP = 0x07,
|
||||
Switch = 0x08,
|
||||
UNKNOWN = 0xFF,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencMVPrecision {
|
||||
Default = 0x00,
|
||||
FullPel = 0x01,
|
||||
HalfPel = 0x02,
|
||||
QuarterPel = 0x03,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencBufferFormat {
|
||||
Undefined = 0x00000000,
|
||||
NV12 = 0x00000001,
|
||||
YV12 = 0x00000010,
|
||||
IYUV = 0x00000100,
|
||||
YUV444 = 0x00001000,
|
||||
YUV420_10Bit = 0x00010000,
|
||||
YUV444_10Bit = 0x00100000,
|
||||
ARGB = 0x01000000,
|
||||
ARGB10 = 0x02000000,
|
||||
AYUV = 0x04000000,
|
||||
ABGR = 0x10000000,
|
||||
ABGR10 = 0x20000000,
|
||||
U8 = 0x40000000,
|
||||
NV16 = 0x40000001,
|
||||
P210 = 0x40000002,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NvencLevel {
|
||||
AutoSelect = 0,
|
||||
}
|
||||
|
||||
// TODO: Translate level macro
|
||||
#[repr(C)]
|
||||
pub enum H264Level {
|
||||
H264_1 = 10,
|
||||
H264_1b = 9,
|
||||
H264_11 = 11,
|
||||
H264_12 = 12,
|
||||
H264_13 = 13,
|
||||
H264_2 = 20,
|
||||
H264_21 = 21,
|
||||
H264_22 = 22,
|
||||
H264_3 = 30,
|
||||
H264_31 = 31,
|
||||
H264_32 = 32,
|
||||
H264_4 = 40,
|
||||
H264_41 = 41,
|
||||
H264_42 = 42,
|
||||
H264_5 = 50,
|
||||
H264_51 = 51,
|
||||
H264_52 = 52,
|
||||
H264_60 = 60,
|
||||
H264_61 = 61,
|
||||
H264_62 = 62,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum HEVCLevel {
|
||||
HEVC1 = 30,
|
||||
HEVC2 = 60,
|
||||
HEVC21 = 63,
|
||||
HEVC3 = 90,
|
||||
HEVC31 = 93,
|
||||
HEVC4 = 120,
|
||||
HEVC41 = 123,
|
||||
HEVC5 = 150,
|
||||
HEVC51 = 153,
|
||||
HEVC52 = 156,
|
||||
HEVC6 = 180,
|
||||
HEVC61 = 183,
|
||||
HEVC62 = 186,
|
||||
HEVCMain = 0,
|
||||
HEVCHigh = 1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum AV1Level {
|
||||
// Also AV1_0
|
||||
AV1_2 = 0,
|
||||
// Also AV1_1
|
||||
AV1_21 = 1,
|
||||
AV1_22 = 2,
|
||||
AV1_23 = 3,
|
||||
AV1_3 = 4,
|
||||
AV1_31 = 5,
|
||||
AV1_32 = 6,
|
||||
AV1_33 = 7,
|
||||
AV1_4 = 8,
|
||||
AV1_41 = 9,
|
||||
AV1_42 = 10,
|
||||
AV1_43 = 11,
|
||||
AV1_5 = 12,
|
||||
AV1_51 = 13,
|
||||
AV1_52 = 14,
|
||||
AV1_53 = 15,
|
||||
AV1_6 = 16,
|
||||
AV1_61 = 17,
|
||||
AV1_62 = 18,
|
||||
AV1_63 = 19,
|
||||
AV1_7 = 20,
|
||||
AV1_71 = 21,
|
||||
AV1_72 = 22,
|
||||
AV1_73 = 23,
|
||||
AV1AutoSelect = 24,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencPicFlags {
|
||||
ForceIntra = 0x1,
|
||||
ForceIDR = 0x2,
|
||||
OutputSpspps = 0x4,
|
||||
Eos = 0x8,
|
||||
DisableEncStateAdvance = 0x10,
|
||||
OuputReconFrame = 0x20,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencMemoryHeap {
|
||||
AutoSelect = 0,
|
||||
VID = 1,
|
||||
SystemCached = 2,
|
||||
SystemUncached = 3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencBFrameRefMode {
|
||||
Disabled = 0x0,
|
||||
Each = 0x1,
|
||||
Middle = 0x2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencH264EntropyCodingMode {
|
||||
AutoSelect = 0x0,
|
||||
Cabac = 0x1,
|
||||
Cavlc = 0x2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencH264BDirectMode {
|
||||
Autoselect = 0x0,
|
||||
Disable = 0x1,
|
||||
Temporal = 0x2,
|
||||
Spatial = 0x3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencH264FMOMode {
|
||||
AutoSelect = 0x0,
|
||||
Enable = 0x1,
|
||||
Disable = 0x2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencH264AdaptiveTransformMode {
|
||||
AutoSelect = 0x0,
|
||||
Disable = 0x1,
|
||||
Enable = 0x2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencStereoPackingMode {
|
||||
None = 0x0,
|
||||
Checkerboard = 0x1,
|
||||
ColInterleave = 0x2,
|
||||
RowInterleave = 0x3,
|
||||
SideBySide = 0x4,
|
||||
TopBottm = 0x5,
|
||||
FrameSeq = 0x6,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencInputResourceType {
|
||||
DirectX = 0x0,
|
||||
CudaDeivcePtr = 0x1,
|
||||
CudaArray = 0x2,
|
||||
OpenGLTex = 0x3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencBufferUsage {
|
||||
Image = 0x0,
|
||||
MotionVector = 0x1,
|
||||
BitStream = 0x2,
|
||||
OutputRecon = 0x4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub enum NVencDeviceType {
|
||||
DirectX = 0x0,
|
||||
Cuda = 0x1,
|
||||
OpenGL = 0x2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencNumRefFrames {
|
||||
AutoSelect = 0x0,
|
||||
Frames1 = 0x1,
|
||||
Frames2 = 0x2,
|
||||
Frames3 = 0x3,
|
||||
Frames4 = 0x4,
|
||||
Frames5 = 0x5,
|
||||
Frames6 = 0x6,
|
||||
Frames7 = 0x7,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencTemporalFilterLevel {
|
||||
Level0 = 0,
|
||||
Level4 = 4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencCaps {
|
||||
NumMaxBFrames,
|
||||
SupportedRateControlModes,
|
||||
FieldEncoding,
|
||||
MonoChrome,
|
||||
FMO,
|
||||
QPELMV,
|
||||
BDirectMode,
|
||||
CABAC,
|
||||
AdaptiveTransform,
|
||||
StereoMVC,
|
||||
MaxTemporalLayers,
|
||||
HierarchicalBFrames,
|
||||
LevelMax,
|
||||
LevelMin,
|
||||
SeperateColorPlane,
|
||||
WidthMax,
|
||||
HeightMax,
|
||||
TemporalSVC,
|
||||
DynResChnage,
|
||||
DynBitrateChange,
|
||||
DynForceConstQP,
|
||||
DynRcModeChange,
|
||||
SubframeReadBack,
|
||||
ConstrainedEncoding,
|
||||
IntraRefresh,
|
||||
CustomVBVBufSize,
|
||||
DynamicSliceMode,
|
||||
Invalidation,
|
||||
PreProcSupport,
|
||||
AsyncEncodeSupport,
|
||||
MbNumMax,
|
||||
MbPerSecMax,
|
||||
YUV444Encode,
|
||||
LoselessEncode,
|
||||
SupportSao,
|
||||
MeOnlyMode,
|
||||
LookAhead,
|
||||
TemporalAQ,
|
||||
MaxLtrFrames,
|
||||
SupportWeightedPrediction,
|
||||
DynamicQueryEncoderCapacity,
|
||||
BFrameRefMode,
|
||||
EmphasisLevelMap,
|
||||
WidthMin,
|
||||
HeightMin,
|
||||
MultipleRefFrames,
|
||||
AlphaLayerEncoding,
|
||||
NumEncoderEngines,
|
||||
SingleSliceIntraRefresh,
|
||||
DisableEncStateAdvance,
|
||||
OutputReconSurface,
|
||||
OutputBlockStats,
|
||||
SupportTemporalFilter,
|
||||
LookAheadLevel,
|
||||
UndirectionalB,
|
||||
MVHEVCEncode,
|
||||
SupportYUV422Encode,
|
||||
ExposedCount,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencHEVCCuSize {
|
||||
AutoSelect = 0,
|
||||
Size8x8 = 1,
|
||||
Size16x16 = 2,
|
||||
Size32x32 = 3,
|
||||
Size64x64 = 4,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencAV1PartSize {
|
||||
AutoSelect = 0,
|
||||
Size4x4 = 1,
|
||||
Size8x8 = 2,
|
||||
Size16x16 = 3,
|
||||
Size32x32 = 4,
|
||||
Size64x64 = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencVUIVideoFormat {
|
||||
Component = 0,
|
||||
Pal = 1,
|
||||
NTSC = 2,
|
||||
SeCam = 3,
|
||||
Mac = 4,
|
||||
Unspecified = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencVUIColorPrimaries {
|
||||
Undefined = 0,
|
||||
BT709 = 1,
|
||||
Unspecified = 2,
|
||||
Reserved = 3,
|
||||
BT470M = 4,
|
||||
BT470BG = 5,
|
||||
SMPTE170M = 6,
|
||||
SMPTE240M = 7,
|
||||
FIlm = 8,
|
||||
BT2020 = 9,
|
||||
SMPTE428 = 10,
|
||||
SMPTE431 = 11,
|
||||
SMPTE432 = 12,
|
||||
JEDECP22 = 22,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencVUITransCharacteristics {
|
||||
Undefined = 0,
|
||||
BT709 = 1,
|
||||
Unspecified = 2,
|
||||
Reserved = 3,
|
||||
BT470M = 4,
|
||||
BT470BG = 5,
|
||||
SMPTE170M = 6,
|
||||
SMPTE240M = 7,
|
||||
Linear = 8,
|
||||
Log = 9,
|
||||
LogSqrt = 10,
|
||||
IEC61966_2_4 = 11,
|
||||
SRGB = 13,
|
||||
BT2020_10 = 14,
|
||||
BT2020_12 = 15,
|
||||
SMPTE2084 = 16,
|
||||
SMPTE428 = 17,
|
||||
AribStdB67 = 18,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencVUIMatrixCoeffs {
|
||||
RGB = 0,
|
||||
BT709 = 1,
|
||||
Unspecified = 2,
|
||||
Reserved = 3,
|
||||
FCC = 4,
|
||||
BT470BG = 5,
|
||||
SMPTE170M,
|
||||
SMPTE240M,
|
||||
YCGCO = 8,
|
||||
BT2020NCL = 9,
|
||||
BT2020CL = 10,
|
||||
SMPTE2085 = 11,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencLookAheadLevel {
|
||||
Level0 = 0,
|
||||
Level1 = 1,
|
||||
Level2 = 2,
|
||||
Level3 = 3,
|
||||
AutoSelect = 15,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencBitDepth {
|
||||
Invalid = 0,
|
||||
Depth8 = 8,
|
||||
Depth10 = 10,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub enum NVencTuningInfo {
|
||||
Undefined = 0,
|
||||
HighQuality = 1,
|
||||
LowLatency = 2,
|
||||
UltraLowLatency = 3,
|
||||
Lossless = 4,
|
||||
UltraHighQuality = 5,
|
||||
Count,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NVencSplitEncodeMode {
|
||||
Audo = 0,
|
||||
AutoForced = 1,
|
||||
TwoForced = 2,
|
||||
ThreeForced = 3,
|
||||
FourForced = 4,
|
||||
Disable = 15,
|
||||
}
|
||||
214
vendor/nvenc/src/sys/function_table.rs
vendored
Normal file
214
vendor/nvenc/src/sys/function_table.rs
vendored
Normal file
@ -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);
|
||||
146
vendor/nvenc/src/sys/guids.rs
vendored
Normal file
146
vendor/nvenc/src/sys/guids.rs
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
use crate::sys::structs::Guid;
|
||||
|
||||
pub const NV_ENC_CODEC_H264_GUID: Guid = Guid::from_values(
|
||||
0x6bc82762,
|
||||
0x4e63,
|
||||
0x4ca4,
|
||||
[0xaa, 0x85, 0x1e, 0x50, 0xf3, 0x21, 0xf6, 0xbf],
|
||||
);
|
||||
pub const NV_ENC_CODEC_HEVC_GUID: Guid = Guid::from_values(
|
||||
0x790cdc88,
|
||||
0x4522,
|
||||
0x4d7b,
|
||||
[0x94, 0x25, 0xbd, 0xa9, 0x97, 0x5f, 0x76, 0x3],
|
||||
);
|
||||
pub const NV_ENC_CODEC_AV1_GUID: Guid = Guid::from_values(
|
||||
0x0a352289,
|
||||
0x0aa7,
|
||||
0x4759,
|
||||
[0x86, 0x2d, 0x5d, 0x15, 0xcd, 0x16, 0xd2, 0x54],
|
||||
);
|
||||
pub const NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID: Guid = Guid::from_values(
|
||||
0xbfd6f8e7,
|
||||
0x233c,
|
||||
0x4341,
|
||||
[0x8b, 0x3e, 0x48, 0x18, 0x52, 0x38, 0x3, 0xf4],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_BASELINE_GUID: Guid = Guid::from_values(
|
||||
0x727bcaa,
|
||||
0x78c4,
|
||||
0x4c83,
|
||||
[0x8c, 0x2f, 0xef, 0x3d, 0xff, 0x26, 0x7c, 0x6a],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_MAIN_GUID: Guid = Guid::from_values(
|
||||
0x60b5c1d4,
|
||||
0x67fe,
|
||||
0x4790,
|
||||
[0x94, 0xd5, 0xc4, 0x72, 0x6d, 0x7b, 0x6e, 0x6d],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_HIGH_GUID: Guid = Guid::from_values(
|
||||
0xe7cbc309,
|
||||
0x4f7a,
|
||||
0x4b89,
|
||||
[0xaf, 0x2a, 0xd5, 0x37, 0xc9, 0x2b, 0xe3, 0x10],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_HIGH_10_GUID: Guid = Guid::from_values(
|
||||
0x8f0c337e,
|
||||
0x186c,
|
||||
0x48e9,
|
||||
[0xa6, 0x9d, 0x7a, 0x83, 0x34, 0x08, 0x97, 0x5],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_HIGH_422_GUID: Guid = Guid::from_values(
|
||||
0xff3242e9,
|
||||
0x613c,
|
||||
0x4295,
|
||||
[0xa1, 0xe8, 0x2a, 0x7f, 0xe9, 0x4d, 0x81, 0x33],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_HIGH_444_GUID: Guid = Guid::from_values(
|
||||
0x7ac663cb,
|
||||
0xa598,
|
||||
0x4960,
|
||||
[0xb8, 0x44, 0x33, 0x9b, 0x26, 0x1a, 0x7d, 0x52],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_STEREO_GUID: Guid = Guid::from_values(
|
||||
0x40847bf5,
|
||||
0x33f7,
|
||||
0x4601,
|
||||
[0x90, 0x84, 0xe8, 0xfe, 0x3c, 0x1d, 0xb8, 0xb7],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_PROGRESSIVE_HIGH_GUID: Guid = Guid::from_values(
|
||||
0xb405afac,
|
||||
0xf32b,
|
||||
0x417b,
|
||||
[0x89, 0xc4, 0x9a, 0xbe, 0xed, 0x3e, 0x59, 0x78],
|
||||
);
|
||||
pub const NV_ENC_H264_PROFILE_CONSTRAINED_HIGH_GUID: Guid = Guid::from_values(
|
||||
0xaec1bd87,
|
||||
0xe85b,
|
||||
0x48f2,
|
||||
[0x84, 0xc3, 0x98, 0xbc, 0xa6, 0x28, 0x50, 0x72],
|
||||
);
|
||||
pub const NV_ENC_HEVC_PROFILE_MAIN_GUID: Guid = Guid::from_values(
|
||||
0xb514c39a,
|
||||
0xb55b,
|
||||
0x40fa,
|
||||
[0x87, 0x8f, 0xf1, 0x25, 0x3b, 0x4d, 0xfd, 0xec],
|
||||
);
|
||||
pub const NV_ENC_HEVC_PROFILE_MAIN10_GUID: Guid = Guid::from_values(
|
||||
0xfa4d2b6c,
|
||||
0x3a5b,
|
||||
0x411a,
|
||||
[0x80, 0x18, 0x0a, 0x3f, 0x5e, 0x3c, 0x9b, 0xe5],
|
||||
);
|
||||
pub const NV_ENC_HEVC_PROFILE_FREXT_GUID: Guid = Guid::from_values(
|
||||
0x51ec32b5,
|
||||
0x1b4c,
|
||||
0x453c,
|
||||
[0x9c, 0xbd, 0xb6, 0x16, 0xbd, 0x62, 0x13, 0x41],
|
||||
);
|
||||
pub const NV_ENC_AV1_PROFILE_MAIN_GUID: Guid = Guid::from_values(
|
||||
0x5f2a39f5,
|
||||
0xf14e,
|
||||
0x4f95,
|
||||
[0x9a, 0x9e, 0xb7, 0x6d, 0x56, 0x8f, 0xcf, 0x97],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P1_GUID: Guid = Guid::from_values(
|
||||
0xfc0a8d3e,
|
||||
0x45f8,
|
||||
0x4cf8,
|
||||
[0x80, 0xc7, 0x29, 0x88, 0x71, 0x59, 0xe, 0xbf],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P2_GUID: Guid = Guid::from_values(
|
||||
0xf581cfb8,
|
||||
0x88d6,
|
||||
0x4381,
|
||||
[0x93, 0xf0, 0xdf, 0x13, 0xf9, 0xc2, 0x7d, 0xab],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P3_GUID: Guid = Guid::from_values(
|
||||
0x36850110,
|
||||
0x3a07,
|
||||
0x441f,
|
||||
[0x94, 0xd5, 0x36, 0x70, 0x63, 0x1f, 0x91, 0xf6],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P4_GUID: Guid = Guid::from_values(
|
||||
0x90a7b826,
|
||||
0xdf06,
|
||||
0x4862,
|
||||
[0xb9, 0xd2, 0xcd, 0x6d, 0x73, 0xa0, 0x86, 0x81],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P5_GUID: Guid = Guid::from_values(
|
||||
0x21c6e6b4,
|
||||
0x297a,
|
||||
0x4cba,
|
||||
[0x99, 0x8f, 0xb6, 0xcb, 0xde, 0x72, 0xad, 0xe3],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P6_GUID: Guid = Guid::from_values(
|
||||
0x8e75c279,
|
||||
0x6299,
|
||||
0x4ab6,
|
||||
[0x83, 0x2, 0xb, 0x21, 0x5a, 0x33, 0x5c, 0xf5],
|
||||
);
|
||||
pub const NV_ENC_PRESET_P7_GUID: Guid = Guid::from_values(
|
||||
0x84848c12,
|
||||
0x6f71,
|
||||
0x4c13,
|
||||
[0x93, 0x1b, 0x53, 0xe2, 0x83, 0xf5, 0x79, 0x74],
|
||||
);
|
||||
6
vendor/nvenc/src/sys/mod.rs
vendored
Normal file
6
vendor/nvenc/src/sys/mod.rs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
pub mod enums;
|
||||
pub mod function_table;
|
||||
pub mod guids;
|
||||
pub mod result;
|
||||
pub mod structs;
|
||||
pub mod version;
|
||||
79
vendor/nvenc/src/sys/result.rs
vendored
Normal file
79
vendor/nvenc/src/sys/result.rs
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub enum NVencResult {
|
||||
Success,
|
||||
NoDevice,
|
||||
UnsupportedDevice,
|
||||
InvalidEncoderDevice,
|
||||
InvalidDevice,
|
||||
DeviceNotExist,
|
||||
InvalidPtr,
|
||||
InvalidParam,
|
||||
InvalidEvent,
|
||||
InvalidCall,
|
||||
OutOfMemory,
|
||||
NotInitialized,
|
||||
UnsupportedParam,
|
||||
LockBusy,
|
||||
NotEnoughBuffer,
|
||||
InvalidVersion,
|
||||
MapFailed,
|
||||
NeedMoreInput,
|
||||
EncoderBusy,
|
||||
EventNotRegisterd,
|
||||
Generic,
|
||||
IncompatibleClientKey,
|
||||
Unimplemented,
|
||||
ResourceRegisterFailed,
|
||||
ResourceNotRegistered,
|
||||
ResourceNotMapped,
|
||||
NeedMoreOutput,
|
||||
}
|
||||
|
||||
impl NVencResult {
|
||||
pub fn into_error(self) -> Result<(), NVencError> {
|
||||
NVencError::from_result(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl NVencError {
|
||||
pub fn from_result(value: NVencResult) -> Result<(), Self> {
|
||||
if value == NVencResult::Success {
|
||||
Ok(())
|
||||
} else {
|
||||
// Safety: They are one case different, so they always align
|
||||
unsafe { Err(std::mem::transmute::<NVencResult, NVencError>(value)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub enum NVencError {
|
||||
NoDevice = NVencResult::NoDevice as isize,
|
||||
UnsupportedDevice,
|
||||
InvalidEncoderDevice,
|
||||
InvalidDevice,
|
||||
DeviceNotExist,
|
||||
InvalidPtr,
|
||||
InvalidEvent,
|
||||
InvalidParam,
|
||||
InvalidCall,
|
||||
OutOfMemory,
|
||||
NotInitialized,
|
||||
UnsupportedParam,
|
||||
LockBusy,
|
||||
NotEnoughBuffer,
|
||||
InvalidVersion,
|
||||
MapFailed,
|
||||
NeedMoreInput,
|
||||
EncoderBusy,
|
||||
EventNotRegisterd,
|
||||
Generic,
|
||||
IncompatibleClientKey,
|
||||
Unimplemented,
|
||||
ResourceRegisterFailed,
|
||||
ResourceNotRegistered,
|
||||
ResourceNotMapped,
|
||||
NeedMoreOutput,
|
||||
}
|
||||
944
vendor/nvenc/src/sys/structs.rs
vendored
Normal file
944
vendor/nvenc/src/sys/structs.rs
vendored
Normal file
@ -0,0 +1,944 @@
|
||||
use std::{ffi::c_void, mem::ManuallyDrop};
|
||||
|
||||
use crate::sys::{
|
||||
enums::{
|
||||
NVencAV1PartSize, NVencBFrameRefMode, NVencBitDepth, NVencBufferFormat, NVencBufferUsage,
|
||||
NVencCaps, NVencDeviceType, NVencDisplayPicStruct, NVencH264AdaptiveTransformMode,
|
||||
NVencH264BDirectMode, NVencH264EntropyCodingMode, NVencH264FMOMode, NVencHEVCCuSize,
|
||||
NVencInputResourceType, NVencLookAheadLevel, NVencMVPrecision, NVencMemoryHeap,
|
||||
NVencMultiPass, NVencNumRefFrames, NVencOutputStatsLevel, NVencParamsFrameFieldMode,
|
||||
NVencParamsRcMode, NVencPicStruct, NVencPicType, NVencQPMapMode, NVencStateRestoreType,
|
||||
NVencStereoPackingMode, NVencTemporalFilterLevel, NVencTuningInfo, NVencVUIColorPrimaries,
|
||||
NVencVUIMatrixCoeffs, NVencVUITransCharacteristics, NVencVUIVideoFormat,
|
||||
},
|
||||
version::struct_version,
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub struct Guid {
|
||||
pub data1: u32,
|
||||
pub data2: u16,
|
||||
pub data3: u16,
|
||||
pub data4: [u8; 8],
|
||||
}
|
||||
|
||||
impl Guid {
|
||||
pub const fn from_values(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> Self {
|
||||
Self {
|
||||
data1,
|
||||
data2,
|
||||
data3,
|
||||
data4,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn from_u128(uuid: u128) -> Self {
|
||||
Self {
|
||||
data1: (uuid >> 96) as u32,
|
||||
data2: ((uuid >> 80) & 0xffff) as u16,
|
||||
data3: ((uuid >> 64) & 0xffff) as u16,
|
||||
data4: (uuid as u64).to_be_bytes(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencCapsParam {
|
||||
version: u32,
|
||||
caps_to_query: NVencCaps,
|
||||
rsvd: [u32; 62],
|
||||
}
|
||||
|
||||
pub const NV_ENC_CAPS_PARAM_VERSION: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencRestoreEncoderStateParams {
|
||||
version: u32,
|
||||
buffer: u32,
|
||||
state: NVencStateRestoreType,
|
||||
rsvd: u32,
|
||||
output_bit_stream: *mut c_void,
|
||||
completion_event: *mut c_void,
|
||||
rsvd1: [u32; 64],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_RESTORE_STATE_PARAMS_VER: u32 = struct_version(2);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencOutputStatsBlock {
|
||||
version: u32,
|
||||
qp: u8,
|
||||
rsvd: [u8; 3],
|
||||
bit_count: u32,
|
||||
satd_cost: u32,
|
||||
rsvd1: [u32; 12],
|
||||
}
|
||||
|
||||
pub const NV_ENC_OUTPUT_STATS_BLOCK_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencOutputStatsRow {
|
||||
version: u32,
|
||||
qp: u8,
|
||||
rsvd: [u8; 3],
|
||||
bit_count: u32,
|
||||
satd_cost: u32,
|
||||
rsvd1: [u32; 12],
|
||||
}
|
||||
|
||||
pub const NV_ENC_OUTPUT_STATS_ROW_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencEncodeOutParams {
|
||||
version: u32,
|
||||
bitstream_size_in_bytes: u32,
|
||||
rsvd: [u32; 62],
|
||||
}
|
||||
|
||||
pub const NV_ENC_ENCODE_OUT_PARAMS_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencLookAheadPicParams {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
input_buffer: *mut c_void,
|
||||
picture_type: NVencPicType,
|
||||
rsvd1: [u32; 63],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_LOOKAHEAD_PIC_PARAMS_VER: u32 = struct_version(2);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencCreateInputBuffer {
|
||||
pub version: u32,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub memory_heap: NVencMemoryHeap,
|
||||
pub buffer_fmt: NVencBufferFormat,
|
||||
pub rsvd: u32,
|
||||
pub input_buffer: *mut c_void,
|
||||
pub p_sys_mem_buffer: *mut c_void,
|
||||
pub rsvd1: [u32; 58],
|
||||
pub rsvd2: [*mut c_void; 63],
|
||||
}
|
||||
|
||||
pub const NV_ENC_CREATE_INPUT_BUFFER_VER: u32 = struct_version(2);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencCreateBitstreamBuffer {
|
||||
pub version: u32,
|
||||
#[deprecated]
|
||||
size: u32,
|
||||
#[deprecated]
|
||||
memory_heap: NVencMemoryHeap,
|
||||
rsvd: u32,
|
||||
pub bitstream_buffer: *mut c_void,
|
||||
bitstream_buffer_ptr: *mut c_void,
|
||||
rsvd1: [u32; 58],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_CREATE_BITSTREAM_BUFFER_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencMVector {
|
||||
mvx: i16,
|
||||
mvy: i16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencH264MVData {
|
||||
mv: [NVencMVector; 4],
|
||||
mb_type: u8,
|
||||
partition_type: u8,
|
||||
rsvd: u16,
|
||||
mb_cost: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencHEVCMVData {
|
||||
mv: [NVencMVector; 4],
|
||||
cu_type: u8,
|
||||
cu_size: u8,
|
||||
partition_mode: u8,
|
||||
last_cu_int_ctb: u8,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencCreateMVBuffer {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
mv_buffer: *mut c_void,
|
||||
rsvd1: [u32; 254],
|
||||
rsvd2: [*mut c_void; 63],
|
||||
}
|
||||
|
||||
pub const NV_ENC_CREATE_MV_BUFFER_VER: u32 = struct_version(2);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencQP {
|
||||
qp_inter_p: u32,
|
||||
qp_inter_b: u32,
|
||||
qp_intra: u32,
|
||||
}
|
||||
|
||||
pub const MAX_NUM_VIEWS_MINUS_1: usize = 7;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencRcParams {
|
||||
version: u32,
|
||||
pub rate_control_mode: NVencParamsRcMode,
|
||||
const_qp: NVencQP,
|
||||
pub average_bit_rate: u32,
|
||||
max_bit_rate: u32,
|
||||
vbv_buffer_size: u32,
|
||||
vbv_initial_delay: u32,
|
||||
// TODO: bit fields
|
||||
bit_fields: NVencRcParamsBitFlags,
|
||||
min_qp: NVencQP,
|
||||
max_qp: NVencQP,
|
||||
initial_rcqp: NVencQP,
|
||||
temporal_layer_idx_mask: u32,
|
||||
temporal_layer_qp: [u8; 8],
|
||||
target_quality: u8,
|
||||
target_quality_lsb: u8,
|
||||
pub look_ahead_depth: u16,
|
||||
low_delay_key_frame_scale: u8,
|
||||
y_dc_qp_index_offset: i8,
|
||||
u_dc_qp_index_offset: i8,
|
||||
v_dc_qp_index_offset: i8,
|
||||
qp_map_mode: NVencQPMapMode,
|
||||
multi_pass: NVencMultiPass,
|
||||
alpha_layer_bitrate_ratio: u32,
|
||||
cb_qp_index_offset: i8,
|
||||
cr_qp_index_offset: i8,
|
||||
rsvd2: u16,
|
||||
lookahead_level: NVencLookAheadLevel,
|
||||
view_bitrate_ratios: [u8; MAX_NUM_VIEWS_MINUS_1],
|
||||
rsvd3: u8,
|
||||
rsvd1: u32,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct NVencRcParamsBitFlags(u32);
|
||||
|
||||
impl NVencRcParamsBitFlags {}
|
||||
|
||||
pub const NV_ENC_RC_PARAMS_VER: u32 = struct_version(1);
|
||||
|
||||
pub const MAX_NUM_CLOCK_TS: usize = 3;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencClockTimeStampSet {
|
||||
pub bitflags: u32,
|
||||
pub time_offset: u32,
|
||||
}
|
||||
|
||||
impl NVencClockTimeStampSet {}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencTimeCode {
|
||||
pub display_pic_struct: NVencDisplayPicStruct,
|
||||
pub clock_timestamp: [NVencClockTimeStampSet; MAX_NUM_CLOCK_TS],
|
||||
pub skip_clock_timestamp_insertion: u32,
|
||||
}
|
||||
|
||||
pub const MULTIVIEW_MAX_NUM_REF_DISPLAY: usize = 32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct HEVC3DReferenceDisplayInfo {
|
||||
// TODO
|
||||
pub bitflags: u32,
|
||||
pub prec_ref_display_width: i32,
|
||||
pub prec_ref_viewing_dist: i32,
|
||||
pub num_ref_displays_minus1: i32,
|
||||
pub left_view_id: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub right_view_id: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub exponent_ref_display_width: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub mantissa_ref_display_width: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub exponent_ref_viewing_distance: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub mantissa_ref_viewing_distance: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub num_sample_shift_plus512: [i32; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub additional_shift_present_flag: [u8; MULTIVIEW_MAX_NUM_REF_DISPLAY],
|
||||
pub rsvd2: [u32; 4],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ChromaPoints {
|
||||
x: u16,
|
||||
y: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct MasteringDisplayInfo {
|
||||
pub g: ChromaPoints,
|
||||
pub b: ChromaPoints,
|
||||
pub r: ChromaPoints,
|
||||
pub white_point: ChromaPoints,
|
||||
pub max_luma: u32,
|
||||
pub min_luma: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ContentLightLevel {
|
||||
pub max_content_light_level: u16,
|
||||
pub max_pic_average_light_level: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfigH264VUIParameters {
|
||||
overscan_info_present_flag: u32,
|
||||
overscan_info: u32,
|
||||
video_signal_type_present_flag: u32,
|
||||
video_format: NVencVUIVideoFormat,
|
||||
video_full_range_flag: u32,
|
||||
color_description_present_flag: u32,
|
||||
color_primaries: NVencVUIColorPrimaries,
|
||||
transfer_characteristics: NVencVUITransCharacteristics,
|
||||
color_matrix: NVencVUIMatrixCoeffs,
|
||||
chroma_sample_location_flag: u32,
|
||||
chroma_sample_location_top: u32,
|
||||
chroma_sample_location_bot: u32,
|
||||
bitstream_restriction_flag: u32,
|
||||
timing_info_present_flag: u32,
|
||||
num_unit_in_ticks: u32,
|
||||
time_scale: u32,
|
||||
rsvd: [u32; 12],
|
||||
}
|
||||
|
||||
pub type NVencConfigHEVCVUIParamaters = NVencConfigH264VUIParameters;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
pub struct NVencExternalMeHintCountsPerBlockType {
|
||||
pub bitflags: u32,
|
||||
pub rsvd1: [u32; 3],
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct NVencExternalMeHint(i32);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencExternalMeSbHint {
|
||||
flags1: i16,
|
||||
flags2: i16,
|
||||
flags3: i16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfigH264 {
|
||||
bitflags: u32,
|
||||
level: u32,
|
||||
idr_period: u32,
|
||||
seperate_color_plane_flag: u32,
|
||||
disable_deblocking_filter_idc: u32,
|
||||
num_termpoal_layers: u32,
|
||||
sps_id: u32,
|
||||
pps_id: u32,
|
||||
adaptive_transform_mode: NVencH264AdaptiveTransformMode,
|
||||
fmo_mode: NVencH264FMOMode,
|
||||
bdirect_mode: NVencH264BDirectMode,
|
||||
entropy_coding_mode: NVencH264EntropyCodingMode,
|
||||
stereo_mode: NVencStereoPackingMode,
|
||||
intra_refresh_period: u32,
|
||||
intra_refresh_count: u32,
|
||||
max_num_ref_frames: u32,
|
||||
slice_mode: u32,
|
||||
slice_mode_data: u32,
|
||||
h264_vui_parameters: NVencConfigH264VUIParameters,
|
||||
ltr_num_frames: u32,
|
||||
ltr_trust_mode: u32,
|
||||
chroma_format_idc: u32,
|
||||
max_termpoal_layers: u32,
|
||||
use_b_frames_as_ref: NVencBFrameRefMode,
|
||||
num_ref_l0: NVencNumRefFrames,
|
||||
num_ref_l1: NVencNumRefFrames,
|
||||
output_bit_depth: NVencBitDepth,
|
||||
input_bit_depth: NVencBitDepth,
|
||||
tf_level: NVencTemporalFilterLevel,
|
||||
rsvd1: [u32; 264],
|
||||
rsvd: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfigHEVC {
|
||||
level: u32,
|
||||
tier: u32,
|
||||
min_cu_size: NVencHEVCCuSize,
|
||||
max_cu_size: NVencHEVCCuSize,
|
||||
bitflags: u32,
|
||||
idr_period: u32,
|
||||
intra_refresh_cnt: u32,
|
||||
max_num_ref_frames_in_dpb: u32,
|
||||
ltr_num_frames: u32,
|
||||
vps_id: u32,
|
||||
sps_id: u32,
|
||||
pps_id: u32,
|
||||
slice_mode: u32,
|
||||
slice_mode_data: u32,
|
||||
max_temporal_layers_minus_1: u32,
|
||||
hevc_vui_paramters: NVencConfigHEVCVUIParamaters,
|
||||
ltr_trust_mode: u32,
|
||||
use_b_frames_as_ref: NVencBFrameRefMode,
|
||||
tf_level: NVencTemporalFilterLevel,
|
||||
disable_deblocking_filter_idc: u32,
|
||||
output_bit_depth: NVencBitDepth,
|
||||
input_bit_depth: NVencBitDepth,
|
||||
num_temporal_layers: u32,
|
||||
num_views: u32,
|
||||
rsvd1: [u32; 208],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_MAX_TILE_COLS_AV1: usize = 64;
|
||||
pub const NV_MAX_TILE_ROWS_AV1: usize = 64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencFilmGrainParamsAV1 {
|
||||
bitfields: u32,
|
||||
point_y_value: [u8; 14],
|
||||
point_y_scaling: [u8; 14],
|
||||
point_cb_value: [u8; 10],
|
||||
point_cb_scaling: [u8; 10],
|
||||
point_cr_value: [u8; 10],
|
||||
point_cr_scaling: [u8; 10],
|
||||
ar_coeffs_y_plus128: [u8; 24],
|
||||
ar_coeffs_cb_plus128: [u8; 25],
|
||||
ar_coeffs_cr_plus128: [u8; 25],
|
||||
rsvd2: [u8; 2],
|
||||
cb_mult: u8,
|
||||
cb_luma_mult: u8,
|
||||
cb_offset: u16,
|
||||
cr_mult: u8,
|
||||
cr_luma_mult: u8,
|
||||
cr_offset: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfigAV1 {
|
||||
level: u32,
|
||||
tier: u32,
|
||||
min_part_size: NVencAV1PartSize,
|
||||
max_part_size: NVencAV1PartSize,
|
||||
bitflags: u32,
|
||||
idr_period: u32,
|
||||
intra_refresh_period: u32,
|
||||
intra_refresh_count: u32,
|
||||
max_num_ref_frames_in_dpb: u32,
|
||||
num_tiles_columns: u32,
|
||||
num_tile_rows: u32,
|
||||
rsvd2: u32,
|
||||
tile_widths: *mut u32,
|
||||
tile_heights: *mut u32,
|
||||
max_temporal_layers_minus_1: u32,
|
||||
color_primaries: NVencVUIColorPrimaries,
|
||||
transfer_characteristics: NVencVUITransCharacteristics,
|
||||
matrix_coefficients: NVencVUIMatrixCoeffs,
|
||||
color_range: u32,
|
||||
chroma_sample_position: u32,
|
||||
use_b_frames_as_ref: NVencBFrameRefMode,
|
||||
film_grain_params: NVencFilmGrainParamsAV1,
|
||||
num_fwd_refs: NVencNumRefFrames,
|
||||
num_bwd_refs: NVencNumRefFrames,
|
||||
input_bit_depth: NVencBitDepth,
|
||||
ltr_num_frames: u32,
|
||||
num_temporal_layers: u32,
|
||||
tf_level: NVencTemporalFilterLevel,
|
||||
rsvd1: [u32; 230],
|
||||
rsvd3: [*mut c_void; 62],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfigH264MeOnly {
|
||||
bitflags: u32,
|
||||
rsvd1: [u32; 255],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfigHEVCMeOnly {
|
||||
rsvd: [u32; 256],
|
||||
rsvd1: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union NVencCodecConfig {
|
||||
h264: ManuallyDrop<NVencConfigH264>,
|
||||
hevc: ManuallyDrop<NVencConfigHEVC>,
|
||||
av1: ManuallyDrop<NVencConfigAV1>,
|
||||
h264_meonly: ManuallyDrop<NVencConfigH264MeOnly>,
|
||||
hevc_meonly: ManuallyDrop<NVencConfigHEVCMeOnly>,
|
||||
rsvd: [u32; 320],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencConfig {
|
||||
pub version: u32,
|
||||
pub profile_guid: Guid,
|
||||
pub gop_len: u32,
|
||||
pub frame_interval_p: i32,
|
||||
mono_chrome_encoding: u32,
|
||||
frame_field_mode: NVencParamsFrameFieldMode,
|
||||
mv_precision: NVencMVPrecision,
|
||||
pub rc_params: NVencRcParams,
|
||||
encode_codec_config: NVencCodecConfig,
|
||||
rsvd: [u32; 278],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_CONFIG_VER: u32 = struct_version(9) | (1 << 31);
|
||||
|
||||
#[bitfields::bitfield(u32)]
|
||||
pub struct NVencInitializeParamsBitfields {
|
||||
#[bits(1)]
|
||||
pub report_slice_offsets: bool,
|
||||
#[bits(1)]
|
||||
pub enable_sub_frame_write: bool,
|
||||
#[bits(1)]
|
||||
pub enable_external_me_hints: bool,
|
||||
#[bits(1)]
|
||||
pub enable_me_only_mode: bool,
|
||||
#[bits(1)]
|
||||
pub enable_weighted_prediction: bool,
|
||||
#[bits(4)]
|
||||
pub split_encode_mode: u8,
|
||||
#[bits(1)]
|
||||
pub enable_output_in_vid_mem: bool,
|
||||
#[bits(1)]
|
||||
pub enable_recon_frame_output: bool,
|
||||
#[bits(1)]
|
||||
pub enable_output_stats: bool,
|
||||
#[bits(1)]
|
||||
pub enable_uni_directional_b: bool,
|
||||
#[bits(19)]
|
||||
pub rsvd: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencInitializeParams {
|
||||
pub version: u32,
|
||||
pub encode_guid: Guid,
|
||||
pub preset_guid: Guid,
|
||||
pub encode_width: u32,
|
||||
pub encode_height: u32,
|
||||
pub dar_width: u32,
|
||||
pub dar_height: u32,
|
||||
pub frame_rate_num: u32,
|
||||
pub frame_rate_den: u32,
|
||||
pub enable_encode_async: u32,
|
||||
pub enable_ptd: u32,
|
||||
pub bit_flags: NVencInitializeParamsBitfields,
|
||||
pub(crate) priv_data_size: u32,
|
||||
pub(crate) rsvd: u32,
|
||||
pub(crate) priv_data: *mut c_void,
|
||||
pub encode_config: *mut NVencConfig,
|
||||
pub max_encode_width: u32,
|
||||
pub max_encode_height: u32,
|
||||
pub max_me_hint_counts_per_block: [NVencExternalMeHintCountsPerBlockType; 2],
|
||||
pub tuning_info: NVencTuningInfo,
|
||||
pub buffer_format: NVencBufferFormat,
|
||||
pub num_state_buffers: u32,
|
||||
pub output_stats_level: NVencOutputStatsLevel,
|
||||
pub(crate) rsvd1: [u32; 284],
|
||||
pub(crate) rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_INITIALIZE_PARAMS_VER: u32 = struct_version(7) | (1 << 31);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencReconfigureParams {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
re_init_encode_params: NVencInitializeParams,
|
||||
bitflags: u32,
|
||||
rsvd2: u32,
|
||||
}
|
||||
|
||||
pub const NV_ENC_RECONFIGURE_PARAMS_VER: u32 = struct_version(2) | (1 << 31);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencPresetConfig {
|
||||
pub version: u32,
|
||||
rsvd: u32,
|
||||
pub preset_cfg: NVencConfig,
|
||||
rsvd1: [u32; 256],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_PRESET_CONFIG_VER: u32 = struct_version(5) | (1 << 31);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencPicParamsMVC {
|
||||
version: u32,
|
||||
view_id: u32,
|
||||
temporal_id: u32,
|
||||
priority_id: u32,
|
||||
rsvd1: [u32; 12],
|
||||
rsvd2: [*mut c_void; 8],
|
||||
}
|
||||
|
||||
pub const NV_ENC_PIC_PARAMS_MVC_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub union NVencPicParamsH264EXT {
|
||||
pub mvc_pic_params: ManuallyDrop<NVencPicParamsMVC>,
|
||||
pub rsvd1: [u32; 32],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencSeiPayload {
|
||||
pub payload_size: u32,
|
||||
pub payload_type: u32,
|
||||
pub payload: *mut u8,
|
||||
}
|
||||
|
||||
pub type NVencH264SeiPayload = NVencSeiPayload;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencPicParamsH264 {
|
||||
pub display_poc_syntax: u32,
|
||||
pub rsvd3: u32,
|
||||
pub ref_pic_flag: u32,
|
||||
pub color_plane_id: u32,
|
||||
pub force_intra_refresh_with_frame_count: u32,
|
||||
pub bitflags: u32,
|
||||
pub slice_type_data: *mut u8,
|
||||
pub slice_type_array_count: u32,
|
||||
pub sei_payload_array_count: u32,
|
||||
pub sei_payload_array: *mut NVencSeiPayload,
|
||||
pub slice_mode: u32,
|
||||
pub slice_mode_data: u32,
|
||||
pub ltr_mark_framce_idx: u32,
|
||||
pub ltr_use_frame_bitmap: u32,
|
||||
pub ltr_usage_mode: u32,
|
||||
pub force_intra_slice_count: u32,
|
||||
pub force_intra_slice_idx: *mut u32,
|
||||
pub h264_ext_pic_params: NVencPicParamsH264EXT,
|
||||
pub time_code: NVencTimeCode,
|
||||
pub rsvd: [u32; 202],
|
||||
pub rsvd2: [*mut c_void; 61],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencPicParamsHEVC {
|
||||
pub display_poc_syntax: u32,
|
||||
pub ref_pic_flag: u32,
|
||||
pub temporal_id: u32,
|
||||
pub force_intra_refresh_with_frame_count: u32,
|
||||
pub bitflags: u32,
|
||||
pub rsvd1: u32,
|
||||
pub slice_type_data: *mut u8,
|
||||
pub slice_type_array_count: u32,
|
||||
pub slice_mode: u32,
|
||||
pub slice_mode_data: u32,
|
||||
pub ltr_mark_frame_idx: u32,
|
||||
pub ltr_usage_frame_bitmap: u32,
|
||||
pub ltr_usage_mode: u32,
|
||||
pub sei_payload_array_count: u32,
|
||||
pub rsvd: u32,
|
||||
pub sei_payload_array: *mut NVencSeiPayload,
|
||||
pub time_code: NVencTimeCode,
|
||||
pub num_temporal_layers: u32,
|
||||
pub view_id: u32,
|
||||
pub _3d_reference_display_info: *mut HEVC3DReferenceDisplayInfo,
|
||||
pub max_cll: *mut ContentLightLevel,
|
||||
pub mastering_display: *mut MasteringDisplayInfo,
|
||||
pub rsvd2: [u32; 234],
|
||||
pub rsvd3: [*mut c_void; 58],
|
||||
}
|
||||
|
||||
pub type NVencAV1OBUPayload = NVencSeiPayload;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencPicParamsAV1 {
|
||||
display_poc_syntax: u32,
|
||||
ref_pic_flag: u32,
|
||||
temporal_id: u32,
|
||||
force_intra_refresh_with_frame_count: u32,
|
||||
bitflags: u32,
|
||||
num_tile_columns: u32,
|
||||
num_tile_rows: u32,
|
||||
rsvd: u32,
|
||||
tile_widths: *mut u32,
|
||||
tile_heights: *mut u32,
|
||||
obu_payload_array_count: u32,
|
||||
rsvd1: u32,
|
||||
obu_payload_array: *mut NVencAV1OBUPayload,
|
||||
file_grain_params: *mut NVencFilmGrainParamsAV1,
|
||||
ltr_mark_frame_idx: u32,
|
||||
ltr_use_frame_bitmap: u32,
|
||||
num_temporal_layers: u32,
|
||||
rsvd4: u32,
|
||||
max_cll: *mut ContentLightLevel,
|
||||
mastering_display: *mut MasteringDisplayInfo,
|
||||
rsvd2: [u32; 242],
|
||||
rsvd3: [*mut c_void; 59],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union NVencCodecPicParams {
|
||||
pub h264_pic_params: ManuallyDrop<NVencPicParamsH264>,
|
||||
pub hevc_pic_params: ManuallyDrop<NVencPicParamsHEVC>,
|
||||
av1_pic_params: ManuallyDrop<NVencPicParamsAV1>,
|
||||
pub rsvd: [u32; 256],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencPicParams {
|
||||
pub version: u32,
|
||||
pub input_width: u32,
|
||||
pub input_height: u32,
|
||||
pub input_pitch: u32,
|
||||
pub encode_pic_flags: u32,
|
||||
pub frame_idx: u32,
|
||||
pub input_time_stamp: u64,
|
||||
input_duration: u64,
|
||||
pub input_buffer: *mut c_void,
|
||||
pub output_bitstream: *mut c_void,
|
||||
// TODO: Windows only, needed for async
|
||||
completion_event: *mut c_void,
|
||||
pub buffer_format: NVencBufferFormat,
|
||||
pub picture_struct: NVencPicStruct,
|
||||
pub picture_type: NVencPicType,
|
||||
pub codec_pic_params: NVencCodecPicParams,
|
||||
me_hint_counts_per_block: [NVencExternalMeHintCountsPerBlockType; 2],
|
||||
me_external_hints: *mut NVencExternalMeHint,
|
||||
rsvd2: [u32; 7],
|
||||
rsvd5: [*mut c_void; 2],
|
||||
qp_delta_map: *mut i8,
|
||||
qp_deltra_map_size: u32,
|
||||
rsvd_bit_fields: u32,
|
||||
me_hint_ref_pic_dist: [u16; 2],
|
||||
rsvd4: u32,
|
||||
alpha_buffer: *mut c_void,
|
||||
me_external_sb_hints: *mut NVencExternalMeSbHint,
|
||||
me_sb_hints_count: u32,
|
||||
state_buffer_idx: u32,
|
||||
output_recon_buffer: *mut c_void,
|
||||
rsvd3: [u32; 284],
|
||||
rsvd6: [*mut c_void; 57],
|
||||
}
|
||||
|
||||
pub const NV_ENC_PIC_PARAMS_VER: u32 = struct_version(7) | (1 << 31);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencMeOnlyParams {
|
||||
version: u32,
|
||||
input_width: u32,
|
||||
input_height: u32,
|
||||
rsvd: u32,
|
||||
input_buffer: *mut c_void,
|
||||
reference_frame: *mut c_void,
|
||||
mv_buffer: *mut c_void,
|
||||
rsvd2: u32,
|
||||
buffer_formtat: NVencBufferFormat,
|
||||
view_id: u32,
|
||||
me_hint_counts_per_block: [NVencExternalMeHintCountsPerBlockType; 2],
|
||||
me_external_hints: NVencExternalMeHint,
|
||||
rsvd1: [u32; 241],
|
||||
rsvd3: [*mut c_void; 59],
|
||||
}
|
||||
|
||||
pub const NV_ENC_MEONLY_PARAMS_VER: u32 = struct_version(4);
|
||||
|
||||
#[bitfields::bitfield(u32)]
|
||||
pub struct NVencLockBitStreamBitFields {
|
||||
#[bits(1)]
|
||||
pub do_not_wait: bool,
|
||||
#[bits(1)]
|
||||
pub ltr_frame: bool,
|
||||
#[bits(1)]
|
||||
pub get_rc_stats: bool,
|
||||
#[bits(29)]
|
||||
rsvd: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencLockBitStream {
|
||||
pub version: u32,
|
||||
pub bit_fields: NVencLockBitStreamBitFields,
|
||||
pub output_bit_stream: *mut c_void,
|
||||
slice_offsets: *mut u32,
|
||||
frame_idx: u32,
|
||||
hw_encode_status: u32,
|
||||
num_slices: u32,
|
||||
pub bitstream_size_in_bytes: u32,
|
||||
output_time_stamp: u64,
|
||||
pub output_duration: u64,
|
||||
pub bitstream_buffer: *mut c_void,
|
||||
picture_type: NVencPicType,
|
||||
picture_struct: NVencPicStruct,
|
||||
framge_avg_qp: u32,
|
||||
frame_satd: u32,
|
||||
ltr_frame_idx: u32,
|
||||
ltr_frame_bitmap: u32,
|
||||
temporal_id: u32,
|
||||
inter_mb_count: u32,
|
||||
average_mvx: i32,
|
||||
average_mvy: i32,
|
||||
alpha_layer_size_in_bytes: u32,
|
||||
output_stats_ptr_size: u32,
|
||||
rsvd: u32,
|
||||
output_stats_ptr: *mut c_void,
|
||||
frame_idx_display: u32,
|
||||
rsvd1: [u32; 219],
|
||||
rsvd2: [*mut c_void; 63],
|
||||
rsvd_interanl: [u32; 8],
|
||||
}
|
||||
|
||||
pub const NV_ENC_LOCK_BITSTREAM_VER: u32 = struct_version(2) | (1 << 31);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencLockInputBuffer {
|
||||
pub version: u32,
|
||||
pub bitflags: u32,
|
||||
pub input_buffer: *mut c_void,
|
||||
pub buffer_data_ptr: *mut c_void,
|
||||
pub pitch: u32,
|
||||
pub rsvd1: [u32; 251],
|
||||
pub rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_LOCK_INPUT_BUFFER_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencMapInputResource {
|
||||
pub version: u32,
|
||||
sub_resource_idx: u32,
|
||||
input_resource: *mut c_void,
|
||||
pub registered_resource: *mut c_void,
|
||||
pub mapped_resource: *mut c_void,
|
||||
pub mapped_buffer_format: NVencBufferFormat,
|
||||
rsvd1: [u32; 251],
|
||||
rsvd: [*mut c_void; 63],
|
||||
}
|
||||
|
||||
pub const NV_ENC_MAP_INPUT_RESOURCE_VER: u32 = struct_version(4);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencInputResourceOpenGLTex {
|
||||
texture: u32,
|
||||
target: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencFencePointD3D12 {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
p_fence: *mut c_void,
|
||||
wait_value: u64,
|
||||
signal_value: u64,
|
||||
bit_flags: u32,
|
||||
rsvd1: [u32; 7],
|
||||
}
|
||||
|
||||
pub const NV_ENC_FENCE_POINT_D3D12_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencInputResourceD3D12 {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
input_buffer: *mut c_void,
|
||||
input_fence_point: NVencFencePointD3D12,
|
||||
rsvd1: [u32; 16],
|
||||
rsvd2: [*mut c_void; 16],
|
||||
}
|
||||
|
||||
pub const NV_ENC_INPUT_RESOURCE_D3D12_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencOutputResourceD3D12 {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
output_buffer: *mut c_void,
|
||||
output_fence_point: NVencFencePointD3D12,
|
||||
rsvd1: [u32; 16],
|
||||
rsvd2: [*mut c_void; 16],
|
||||
}
|
||||
|
||||
pub const NV_ENC_OUTPUT_RESOURCE_D3D12_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencRegisterResource {
|
||||
pub version: u32,
|
||||
pub resource_type: NVencInputResourceType,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub pitch: u32,
|
||||
pub sub_resource_index: u32,
|
||||
pub resource_to_register: *mut c_void,
|
||||
pub registered_resource: *mut c_void,
|
||||
pub buffer_format: NVencBufferFormat,
|
||||
pub buffer_usage: NVencBufferUsage,
|
||||
pub input_fence_point: *mut NVencFencePointD3D12,
|
||||
pub chroma_offset: [u32; 2],
|
||||
pub chroma_offset_in: [u32; 2],
|
||||
pub(crate) rsvd1: [u32; 244],
|
||||
pub(crate) rsvd2: [*mut c_void; 61],
|
||||
}
|
||||
|
||||
pub const NV_ENC_REGISTER_RESOURCE_VER: u32 = struct_version(5);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencStat {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
output_bit_stream: *mut c_void,
|
||||
bit_stream_size: u32,
|
||||
pic_type: u32,
|
||||
last_valid_byte_offset: u32,
|
||||
slice_offsets: [u32; 16],
|
||||
pic_idx: u32,
|
||||
frame_avg_qp: u32,
|
||||
bit_flags: u32,
|
||||
ltr_frame_idx: u32,
|
||||
intra_mb_count: u32,
|
||||
inter_mb_count: u32,
|
||||
average_mv_x: i32,
|
||||
average_mv_y: i32,
|
||||
rsvd1: [u32; 227],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_STAT_VER: u32 = struct_version(2);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencSequenceParamPayload {
|
||||
version: u32,
|
||||
in_buffer_size: u32,
|
||||
sps_id: u32,
|
||||
pps_id: u32,
|
||||
spspps_buffer: *mut c_void,
|
||||
output_spspps_payload_size: *mut u32,
|
||||
rsvd: [u32; 250],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER: u32 = struct_version(1);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencEventParams {
|
||||
version: u32,
|
||||
rsvd: u32,
|
||||
completion_event: *mut c_void,
|
||||
rsvd1: [u32; 254],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_EVENT_PARAMS_VER: u32 = struct_version(2);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct NVencOpenEncodeSessionExParams {
|
||||
pub version: u32,
|
||||
pub device_type: NVencDeviceType,
|
||||
pub device: *mut c_void,
|
||||
rsvd: *mut c_void,
|
||||
pub api_version: u32,
|
||||
rsvd1: [u32; 253],
|
||||
rsvd2: [*mut c_void; 64],
|
||||
}
|
||||
|
||||
pub const NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER: u32 = struct_version(1);
|
||||
12
vendor/nvenc/src/sys/version.rs
vendored
Normal file
12
vendor/nvenc/src/sys/version.rs
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
//! Contains the nvenc version numbers, encoded as they are in C, for the version this crate was built against
|
||||
|
||||
pub const NVENC_MAJOR_VERSION: u16 = 13;
|
||||
pub const NVENC_MINOR_VERSION: u8 = 0;
|
||||
|
||||
pub const NVENC_API_VERSION: u32 = NVENC_MAJOR_VERSION as u32 | (NVENC_MINOR_VERSION as u32) << 24;
|
||||
|
||||
pub const NVENC_API_LIST_VERSION: u32 = struct_version(2);
|
||||
|
||||
pub const fn struct_version(nvenc_api_version: u8) -> u32 {
|
||||
NVENC_API_VERSION | (nvenc_api_version as u32) << 16 | 0x7 << 28
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user