├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── nvidia-video-codec-sys ├── .gitignore ├── Cargo.toml ├── LICENSE ├── build.rs └── src │ └── lib.rs └── src ├── cuda ├── context.rs ├── device.rs └── mod.rs ├── lib.rs └── macros.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 7 | target 8 | Cargo.lock 9 | 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nvidia-video-codec" 3 | version = "0.1.0" 4 | authors = ["Luca Barbato "] 5 | license = "MIT" 6 | description = "NVIDIA Video Codec bindings" 7 | repository = "https://github.com/rust-av/nvidia-video-codec-rs" 8 | readme = "README.md" 9 | keywords = ["NVIDIA", "cuvid", "nvenc"] 10 | 11 | [dependencies] 12 | nvidia-video-codec-sys = { version = "0.1.0", path = "nvidia-video-codec-sys" } 13 | 14 | [workspace] 15 | members = ["nvidia-video-codec-sys"] 16 | 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Luca Barbato 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NVIDIA Video Codec SDK bindings 2 | 3 | [![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 4 | 5 | It is a simple [binding][1] and safe abstraction over the [nvidia video codec sdk][2]. 6 | 7 | ## Building 8 | 9 | The bindings are generated using the headers and libraries that ought to be present in the system. 10 | 11 | By default the headers are looked up on `/opt/cuda/include` and `/opt/nvidia-video-codec/include` and the libraries are assumed to be present in the default path (and provided by the driver). 12 | 13 | It is possible to override the search paths for the headers by setting the environment variables `CUDA_INCLUDE_PATH` and `NVIDIA_VIDEO_CODEC_INCLUDE_PATH`. 14 | 15 | A [convenience repackaging][3] of the cuvid and nvenc headers is available and known to work fine with the bindings. 16 | 17 | ## TODO 18 | - [x] Simple bindings 19 | - [x] cuda 20 | - [x] cuvid 21 | - [x] nvenc 22 | 23 | - [ ] Safe abstraction 24 | - [ ] support cuda 25 | - [ ] support cuvid 26 | - [ ] support nvenc 27 | 28 | - [ ] Examples 29 | - [ ] simple decode 30 | - [ ] simple encode 31 | 32 | [1]: https://github.com/servo/rust-bindgen 33 | [2]: https://developer.nvidia.com/nvidia-video-codec-sdk 34 | [3]: https://github.com/lu-zero/nvidia-video-codec 35 | -------------------------------------------------------------------------------- /nvidia-video-codec-sys/.gitignore: -------------------------------------------------------------------------------- 1 | src/cuda.rs 2 | src/cuvid.rs 3 | src/nvenc.rs 4 | -------------------------------------------------------------------------------- /nvidia-video-codec-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nvidia-video-codec-sys" 3 | version = "0.1.0" 4 | authors = ["Luca Barbato "] 5 | license = "MIT" 6 | description = "FFI bindings to NVIDIA Video Codec" 7 | repository = "https://github.com/rust-av/nvidia-video-codec-rs" 8 | 9 | build = "build.rs" 10 | 11 | [build-dependencies] 12 | bindgen = "0.54.0" 13 | 14 | [dependencies] 15 | -------------------------------------------------------------------------------- /nvidia-video-codec-sys/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Luca Barbato 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /nvidia-video-codec-sys/build.rs: -------------------------------------------------------------------------------- 1 | extern crate bindgen; 2 | 3 | use std::env; 4 | use std::fs::OpenOptions; 5 | use std::io::Write; 6 | use std::path::PathBuf; 7 | 8 | fn format_write(builder: bindgen::Builder, output: &str) { 9 | let s = builder.generate() 10 | .unwrap() 11 | .to_string() 12 | .replace("/**", "/*") 13 | .replace("/*!", "/*"); 14 | 15 | let mut file = OpenOptions::new() 16 | .write(true) 17 | .truncate(true) 18 | .create(true) 19 | .open(output) 20 | .unwrap(); 21 | 22 | let _ = file.write(s.as_bytes()); 23 | } 24 | 25 | fn common_builder() -> bindgen::Builder { 26 | bindgen::builder() 27 | .raw_line("#![allow(dead_code)]") 28 | .raw_line("#![allow(non_camel_case_types)]") 29 | .raw_line("#![allow(non_snake_case)]") 30 | .raw_line("#![allow(non_upper_case_globals)]") 31 | } 32 | 33 | fn find_dir(default: &'static str, env_key: &'static str) -> PathBuf { 34 | match env::var_os(env_key) { 35 | Some(val) => PathBuf::from(&val), 36 | _ => PathBuf::from(default), 37 | } 38 | } 39 | 40 | fn main() { 41 | let cuda_include = find_dir("/opt/cuda/include", "CUDA_INCLUDE_PATH"); 42 | let nvc_include = find_dir("/opt/nvidia-video-codec/include", 43 | "NVIDIA_VIDEO_CODEC_INCLUDE_PATH"); 44 | 45 | // TODO support windows 46 | println!("cargo:rustc-link-lib=dylib={}", "cuda"); 47 | println!("cargo:rustc-link-lib=dylib={}", "nvcuvid"); 48 | println!("cargo:rustc-link-lib=dylib={}", "nvidia-encode"); 49 | 50 | 51 | let cuda_builder = common_builder() 52 | .clang_arg(format!("-I{}", cuda_include.to_string_lossy())) 53 | .header(cuda_include.join("cuda.h").to_string_lossy()); 54 | 55 | // Manually fix the comment so rustdoc won't try to pick them 56 | format_write(cuda_builder, "src/cuda.rs"); 57 | 58 | let cuvid_builder = common_builder() 59 | .clang_arg(format!("-I{}", nvc_include.to_string_lossy())) 60 | .clang_arg(format!("-I{}", cuda_include.to_string_lossy())) 61 | .header(nvc_include.join("nvcuvid.h").to_string_lossy()); 62 | 63 | format_write(cuvid_builder, "src/cuvid.rs"); 64 | 65 | let nvenc_builder = common_builder() 66 | .clang_arg(format!("-I{}", nvc_include.to_string_lossy())) 67 | .header(nvc_include.join("nvEncodeAPI.h").to_string_lossy()); 68 | 69 | format_write(nvenc_builder, "src/nvenc.rs"); 70 | } 71 | -------------------------------------------------------------------------------- /nvidia-video-codec-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | // TODO do w/out the unions? 2 | #![feature(untagged_unions)] 3 | 4 | pub mod cuda; 5 | pub mod cuvid; 6 | pub mod nvenc; 7 | 8 | #[cfg(test)] 9 | mod tests { 10 | use super::cuda::*; 11 | #[test] 12 | fn init_and_version() { 13 | let ret = unsafe { cuInit(0) }; 14 | println!("{:?}", ret); 15 | 16 | let ver = unsafe { 17 | let mut ver = 0; 18 | cuDriverGetVersion(&mut ver as *mut i32); 19 | ver 20 | }; 21 | 22 | println!("Version {}", ver); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/cuda/context.rs: -------------------------------------------------------------------------------- 1 | use ffi::cuda::*; 2 | 3 | use cuda::device::CuDevice; 4 | 5 | pub struct CuContext { 6 | context : CUcontext, 7 | } 8 | 9 | impl CuContext { 10 | pub fn new(dev : CuDevice, flags : u32) -> Result { 11 | let mut ctx = CuContext { context : 0 }; 12 | let res = unsafe { cuCtxCreate(&mut ctx.context as *mut CUcontext, dev.device) } 13 | 14 | wrap!(ctx, res) 15 | } 16 | 17 | pub fn get_api_version(&self) -> Result { 18 | let mut ver = 0; 19 | let res = unsafe { cuGetApiVersion(self.context, &mut ver as *mut u32)}; 20 | 21 | wrap!(ver, res) 22 | } 23 | 24 | pub fn pop() -> Result<, CUresult> { 25 | let res = unsafe { cuCtxPopCurrent 26 | } 27 | } 28 | 29 | /* TODO: leverage clone/drop/deref traits 30 | impl Clone for CuContext { 31 | 32 | } 33 | 34 | impl Deref for CuContext { 35 | 36 | } 37 | */ 38 | 39 | impl Drop for CuContext { 40 | fn drop(&mut self) { 41 | unsafe { 42 | cuCtxDestroy(self.context); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/cuda/device.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_int; 2 | use std::os::raw::c_char; 3 | 4 | use ffi::cuda::*; 5 | use ffi::cuda::cudaError_enum::*; 6 | 7 | pub struct CuDevice { 8 | device: CUdevice, 9 | } 10 | 11 | impl CuDevice { 12 | pub fn new(ordinal: c_int) -> Result { 13 | let mut d = CuDevice { device: 0 }; 14 | let res = unsafe { cuDeviceGet(&mut d.device as *mut i32, ordinal) }; 15 | 16 | wrap!(d, res) 17 | } 18 | 19 | pub fn get_attribute(&self, attr: CUdevice_attribute) -> Result { 20 | let mut pi = 0; 21 | let res = unsafe { cuDeviceGetAttribute(&mut pi as *mut i32, attr, self.device) }; 22 | 23 | wrap!(pi, res) 24 | } 25 | 26 | pub fn get_name(&self) -> Result { 27 | let mut name = vec![0; 256]; 28 | let res = unsafe { 29 | cuDeviceGetName(name.as_mut_ptr() as *mut c_char, 30 | name.len() as i32, 31 | self.device) 32 | }; 33 | let val = String::from_utf8(name).unwrap(); 34 | 35 | wrap!(val, res) 36 | } 37 | 38 | pub fn get_total_mem(&self) -> Result { 39 | let mut val = 0; 40 | let res = unsafe { cuDeviceTotalMem_v2(&mut val as *mut usize, self.device) }; 41 | 42 | wrap!(val, res) 43 | } 44 | } 45 | 46 | pub fn get_count() -> Result { 47 | let mut val = 0; 48 | let res = unsafe { cuDeviceGetCount(&mut val as *mut i32) }; 49 | 50 | wrap!(val, res) 51 | } 52 | 53 | #[cfg(test)] 54 | mod tests { 55 | use ffi::cuda::cuInit; 56 | use super::*; 57 | 58 | #[test] 59 | fn device_enum() { 60 | let _ = unsafe { cuInit(0) }; 61 | 62 | for i in 0..get_count().unwrap() { 63 | let dev = CuDevice::new(i).unwrap(); 64 | 65 | println!("{} {}", 66 | dev.get_name().unwrap(), 67 | dev.get_total_mem().unwrap()); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/cuda/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod device; 2 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate nvidia_video_codec_sys as ffi; 2 | 3 | #[macro_use] 4 | mod macros; 5 | 6 | pub mod cuda; 7 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! wrap { 2 | ($val:ident, $res:ident) => ( 3 | if $res == CUDA_SUCCESS { 4 | Ok($val) 5 | } else { 6 | Err($res) 7 | } 8 | ) 9 | } 10 | 11 | 12 | --------------------------------------------------------------------------------