Skip to content

tonarino/nv-video-codec-rs

Repository files navigation

nv-video-codec-rs

This project wraps NVIDIA Video Codec SDK 11.0 for use in Rust. Both unsafe FFI and safe higher-level bindings are provided.

Setup

The project requires the libnvcuvid.so and libnvidia-encode.so libraries to be installed on the system. They are tied to a particular Nvidia driver and often shipped in a system package.

  • Arch Linux: nvidia-utils.
  • Debian: libnvcuvid1, libnvidia-encode1.
  • Gentoo: nvidia-drivers.
  • Ubuntu: libnvidia-decode-XXX and libnvidia-encode-XXX, where XXX is the driver version.

Safe bindings overview

Encoding

The main interface is provided by NvEncoder<ResourceManager>.

impl<ResourceManager> NvEncoder<ResourceManager> {
    pub fn create_encoder(&mut self, encoder_params: &NvEncoderParams) -> NvEncoderResult<()>;
    pub fn destroy_encoder(&mut self) -> NvEncoderResult<()>;
    pub fn get_next_input_frame(&mut self) -> &mut NvEncInputFrame;
    pub fn get_next_input_resource(&mut self) -> ResourceManager::InputResourceRef<'_>;
    pub fn encode_frame(
        &mut self,
        packet: &mut Vec<&[u8]>,
        pic_flags: EncodePicFlags,
    ) -> NvEncoderResult<()>;
    pub fn end_encode(&mut self, packet: &mut Vec<&[u8]>) -> NvEncoderResult<()>;
}

Method get_next_input_resource() provides a GPU resource that should be used as a target to upload the frame data. Once uploaded, encode_frame() processes the frame and returns the encoded data.

NvEncoderResourceManager

This trait specifies what kind of resources are used to back the frames used for encoding.

pub trait NvEncoderResourceManager {
    type InputResource;

    fn allocate_input_buffers(
        encoder: &mut NvEncoder<Self>,
        num_input_buffers: u32,
    ) -> Result<(), NvEncoderError>;

    fn release_input_buffers(encoder: &mut NvEncoder<Self>) -> Result<(), NvEncoderError>;
}

NvEncoderGL

This is a thin wrapper over NvEncoder<NvEncoderGLResourceManager> that can be used to feed the encoder with OpenGL textures.

Decoding

The decoder uses a different architecture reflecting the underlying SDK.

struct NvDecoder { ... }
impl NvDecoder {
    pub fn builder(context: Context, codec: Codec) -> NvDecoderBuilder { ... }
    pub fn decode(
        &mut self,
        data: &[u8],
        flags: DecoderPacketFlags,
        timestamp: i64,
    ) -> Result<usize, NvDecoderError> { ... }
    pub fn get_frame(&mut self) -> Option<MappedMutexGuard<'_, Frame<'a>>> { ... }
    pub fn get_width(&self) -> u32 { ... }
    pub fn get_height(&self) -> u32 { ... }
}
  1. NvDecoder can be obtained with NvDecoder::builder().x().y().z().build(), provided a cudarc CudaContext has been created.
  2. The decoder is then fed with NvDecoder::decode(data, ...), which makes it parse and process the data.
  3. If decoding is successful the results can be queried with methods like NvDecoder::get_width(), NvDecoder::get_height() and NvDecoder::get_frame() to get the actual data.
    • The frame data locality can be controlled with NvDecoderBuilder::use_device_frame().
    • There does not seem to be any code yet to process the device pointers when opting for use_device_frame(true).

About

Bindings and wrapper over the nvidia video codec sdk

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors