use std::fmt::Debug;
use super::{api::ENCODE_API, encoder::Encoder, result::EncodeError};
use crate::{
sys::nvEncodeAPI::{
GUID,
NV_ENC_BUFFER_FORMAT,
NV_ENC_CODEC_AV1_GUID,
NV_ENC_CODEC_H264_GUID,
NV_ENC_CODEC_HEVC_GUID,
NV_ENC_CODEC_PIC_PARAMS,
NV_ENC_PIC_PARAMS,
NV_ENC_PIC_PARAMS_AV1,
NV_ENC_PIC_PARAMS_H264,
NV_ENC_PIC_PARAMS_HEVC,
NV_ENC_PIC_PARAMS_VER,
NV_ENC_PIC_STRUCT,
NV_ENC_PIC_TYPE,
},
EncoderInput,
EncoderOutput,
};
#[derive(Debug)]
pub struct Session {
pub(crate) encoder: Encoder,
pub(crate) width: u32,
pub(crate) height: u32,
pub(crate) buffer_format: NV_ENC_BUFFER_FORMAT,
pub(crate) encode_guid: GUID,
}
impl Session {
#[must_use]
pub fn get_encoder(&self) -> &Encoder {
&self.encoder
}
pub fn encode_picture<I: EncoderInput, O: EncoderOutput>(
&self,
input_buffer: &mut I,
output_bitstream: &mut O,
params: EncodePictureParams,
) -> Result<(), EncodeError> {
if let Some(codec_params) = ¶ms.codec_params {
assert_eq!(
codec_params.get_codec_guid(),
self.encode_guid,
"The provided codec specific params must match the codec used"
);
}
let mut encode_pic_params = NV_ENC_PIC_PARAMS {
version: NV_ENC_PIC_PARAMS_VER,
inputWidth: self.width,
inputHeight: self.height,
inputPitch: input_buffer.pitch(),
inputBuffer: input_buffer.handle(),
outputBitstream: output_bitstream.handle(),
bufferFmt: self.buffer_format,
pictureStruct: NV_ENC_PIC_STRUCT::NV_ENC_PIC_STRUCT_FRAME,
inputTimeStamp: params.input_timestamp,
codecPicParams: params.codec_params.map(Into::into).unwrap_or_default(),
pictureType: params.picture_type,
..Default::default()
};
unsafe { (ENCODE_API.encode_picture)(self.encoder.ptr, &mut encode_pic_params) }
.result(&self.encoder)
}
pub fn end_of_stream(&self) -> Result<(), EncodeError> {
let mut encode_pic_params = NV_ENC_PIC_PARAMS::end_of_stream();
unsafe { (ENCODE_API.encode_picture)(self.encoder.ptr, &mut encode_pic_params) }
.result(&self.encoder)
}
}
impl Drop for Session {
fn drop(&mut self) {
if !std::thread::panicking() {
self.end_of_stream()
.expect("The encoder should not be busy.");
}
}
}
#[allow(missing_debug_implementations)] pub struct EncodePictureParams {
pub input_timestamp: u64,
pub picture_type: NV_ENC_PIC_TYPE,
pub codec_params: Option<CodecPictureParams>,
}
impl Default for EncodePictureParams {
fn default() -> Self {
Self {
input_timestamp: 0,
picture_type: NV_ENC_PIC_TYPE::NV_ENC_PIC_TYPE_UNKNOWN,
codec_params: None,
}
}
}
#[allow(missing_debug_implementations)] pub enum CodecPictureParams {
H264(NV_ENC_PIC_PARAMS_H264),
Hevc(NV_ENC_PIC_PARAMS_HEVC),
Av1(NV_ENC_PIC_PARAMS_AV1),
}
impl CodecPictureParams {
#[must_use]
pub fn get_codec_guid(&self) -> GUID {
match self {
Self::H264(_) => NV_ENC_CODEC_H264_GUID,
Self::Hevc(_) => NV_ENC_CODEC_HEVC_GUID,
Self::Av1(_) => NV_ENC_CODEC_AV1_GUID,
}
}
}
impl From<CodecPictureParams> for NV_ENC_CODEC_PIC_PARAMS {
fn from(value: CodecPictureParams) -> Self {
match value {
CodecPictureParams::H264(params) => Self {
h264PicParams: params,
},
CodecPictureParams::Hevc(params) => Self {
hevcPicParams: params,
},
CodecPictureParams::Av1(params) => Self {
av1PicParams: params,
},
}
}
}