diff --git a/Cargo.lock b/Cargo.lock index b5f28aa..5c45cc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/agent/Cargo.toml b/agent/Cargo.toml index 6d6475d..f8b4e0a 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -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", diff --git a/vendor/nvenc/.gitignore b/vendor/nvenc/.gitignore new file mode 100644 index 0000000..0f84cc9 --- /dev/null +++ b/vendor/nvenc/.gitignore @@ -0,0 +1,2 @@ +/target +/.vscode \ No newline at end of file diff --git a/vendor/nvenc/Cargo.toml b/vendor/nvenc/Cargo.toml new file mode 100644 index 0000000..5cdc4e9 --- /dev/null +++ b/vendor/nvenc/Cargo.toml @@ -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 等类型已不存在), +# 直接跑 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", +] diff --git a/vendor/nvenc/Cargo.toml.orig b/vendor/nvenc/Cargo.toml.orig new file mode 100644 index 0000000..23e582e --- /dev/null +++ b/vendor/nvenc/Cargo.toml.orig @@ -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", +] diff --git a/vendor/nvenc/LICENSE.txt b/vendor/nvenc/LICENSE.txt new file mode 100644 index 0000000..ef75b2a --- /dev/null +++ b/vendor/nvenc/LICENSE.txt @@ -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. \ No newline at end of file diff --git a/vendor/nvenc/README.md b/vendor/nvenc/README.md new file mode 100644 index 0000000..f390038 --- /dev/null +++ b/vendor/nvenc/README.md @@ -0,0 +1,34 @@ +### If you like my work and want to support what I do, support me on Ko-Fi 💜! +[![Ko-Fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/cyberite) +--- + +![Crates.io MSRV](https://img.shields.io/crates/msrv/nvenc?style=for-the-badge) ![Crates.io License](https://img.shields.io/crates/l/nvenc?style=for-the-badge) ![GitHub Repo stars](https://img.shields.io/github/stars/AlsoSylv/nvenc?style=for-the-badge) + +The following example is for Linux GLX + +```rust +use nvenc::{session::Session, encoder::Encoder}; + +fn main() { + // Setup GLX context + let session: Session = Session::open_gl(); + let (session, config): (Session, 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); +} +``` \ No newline at end of file diff --git a/vendor/nvenc/examples/simple_encode.rs b/vendor/nvenc/examples/simple_encode.rs new file mode 100644 index 0000000..6cdcccf --- /dev/null +++ b/vendor/nvenc/examples/simple_encode.rs @@ -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 = 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::(2); + let (re_use, to_process) = std::sync::mpsc::sync_channel::(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(); +} diff --git a/vendor/nvenc/src/lib.rs b/vendor/nvenc/src/lib.rs new file mode 100644 index 0000000..74c1a8b --- /dev/null +++ b/vendor/nvenc/src/lib.rs @@ -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 = 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) -> 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) -> 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 { + 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 { + 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) + } +} diff --git a/vendor/nvenc/src/safe/bitstream.rs b/vendor/nvenc/src/safe/bitstream.rs new file mode 100644 index 0000000..97167ef --- /dev/null +++ b/vendor/nvenc/src/safe/bitstream.rs @@ -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, +} + +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, 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(); + } +} diff --git a/vendor/nvenc/src/safe/encoder.rs b/vendor/nvenc/src/safe/encoder.rs new file mode 100644 index 0000000..9c36f42 --- /dev/null +++ b/vendor/nvenc/src/safe/encoder.rs @@ -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, + 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 { + 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( + &self, + input: &I, + output: &BitStream, + frame_count: usize, + timestamp: u64, + format: NVencBufferFormat, + pic_struct: NVencPicStruct, + ty: NVencPicType, + codec_params: Option, + ) -> 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 { + self.encoder.create_bitstream_buffer() + } + + pub fn create_input_buffer( + &self, + width: u32, + height: u32, + memory_heap: NVencMemoryHeap, + format: NVencBufferFormat, + ) -> Result { + 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, + 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 { + let mut config: std::mem::MaybeUninit = 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, + resource: &ID3D11Texture2D, + format: NVencBufferFormat, + pitch: u32, + ) -> Result { + 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( + &self, + input: &I, + output: &BitStream, + frame_count: usize, + timestamp: u64, + format: NVencBufferFormat, + pic_struct: NVencPicStruct, + ty: NVencPicType, + codec_params: Option, + ) -> Result<(), NVencError> { + let mut params: MaybeUninit = 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 = 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 { + let mut lock: MaybeUninit = 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) -> Result { + 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, +} + +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() }; + } +} diff --git a/vendor/nvenc/src/safe/input_buffer.rs b/vendor/nvenc/src/safe/input_buffer.rs new file mode 100644 index 0000000..bf98d4d --- /dev/null +++ b/vendor/nvenc/src/safe/input_buffer.rs @@ -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, + pub(crate) buffer: *mut c_void, + pub(crate) width: u32, + pub(crate) height: u32, +} + +impl InputBuffer { + pub fn lock(&self) -> Result, 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(); + } +} diff --git a/vendor/nvenc/src/safe/mod.rs b/vendor/nvenc/src/safe/mod.rs new file mode 100644 index 0000000..45d8e74 --- /dev/null +++ b/vendor/nvenc/src/safe/mod.rs @@ -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; diff --git a/vendor/nvenc/src/safe/session.rs b/vendor/nvenc/src/safe/session.rs new file mode 100644 index 0000000..e68fb76 --- /dev/null +++ b/vendor/nvenc/src/safe/session.rs @@ -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 { + encoder: Arc, + p: PhantomData, +} + +pub struct NeedsConfig; + +pub struct NeedsInit; + +#[cfg(windows)] +use windows::core::Interface; + +impl Session { + #[cfg(windows)] + pub fn open_dx(device: &impl Interface) -> Result { + 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 { + 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, 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, 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, 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 { + pub fn init_encoder(self, init_params: InitParams) -> Result { + // 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, + }) + } +} diff --git a/vendor/nvenc/src/sys/enums.rs b/vendor/nvenc/src/sys/enums.rs new file mode 100644 index 0000000..b439158 --- /dev/null +++ b/vendor/nvenc/src/sys/enums.rs @@ -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, +} diff --git a/vendor/nvenc/src/sys/function_table.rs b/vendor/nvenc/src/sys/function_table.rs new file mode 100644 index 0000000..cef8562 --- /dev/null +++ b/vendor/nvenc/src/sys/function_table.rs @@ -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, + ) -> 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) -> NVencResult +); +type NvencLockBitStream = stdcall!( + fn( + encoder: *mut c_void, + lock_bitstream_buffer_params: *mut MaybeUninit, + ) -> 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); diff --git a/vendor/nvenc/src/sys/guids.rs b/vendor/nvenc/src/sys/guids.rs new file mode 100644 index 0000000..bce3cac --- /dev/null +++ b/vendor/nvenc/src/sys/guids.rs @@ -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], +); diff --git a/vendor/nvenc/src/sys/mod.rs b/vendor/nvenc/src/sys/mod.rs new file mode 100644 index 0000000..8e85cce --- /dev/null +++ b/vendor/nvenc/src/sys/mod.rs @@ -0,0 +1,6 @@ +pub mod enums; +pub mod function_table; +pub mod guids; +pub mod result; +pub mod structs; +pub mod version; diff --git a/vendor/nvenc/src/sys/result.rs b/vendor/nvenc/src/sys/result.rs new file mode 100644 index 0000000..0379e6d --- /dev/null +++ b/vendor/nvenc/src/sys/result.rs @@ -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::(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, +} diff --git a/vendor/nvenc/src/sys/structs.rs b/vendor/nvenc/src/sys/structs.rs new file mode 100644 index 0000000..f92163e --- /dev/null +++ b/vendor/nvenc/src/sys/structs.rs @@ -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, + hevc: ManuallyDrop, + av1: ManuallyDrop, + h264_meonly: ManuallyDrop, + hevc_meonly: ManuallyDrop, + 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, + 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, + pub hevc_pic_params: ManuallyDrop, + av1_pic_params: ManuallyDrop, + 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); diff --git a/vendor/nvenc/src/sys/version.rs b/vendor/nvenc/src/sys/version.rs new file mode 100644 index 0000000..7fb7935 --- /dev/null +++ b/vendor/nvenc/src/sys/version.rs @@ -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 +}