vaal/
lib.rs

1use deepviewrt as dvrt;
2use std::{
3    ffi::{CStr, CString},
4    io,
5    path::Path,
6    ptr,
7};
8use vaal_sys as ffi;
9pub mod error;
10pub use error::Error;
11pub use ffi::VAALBox;
12
13pub fn clock_now() -> i64 {
14    return unsafe { ffi::vaal_clock_now() };
15}
16
17pub struct Context {
18    ptr: *mut ffi::VAALContext,
19    dvrt_context: Option<dvrt::context::Context>,
20}
21
22unsafe impl Send for Context {}
23
24impl Context {
25    pub fn new(device: &str) -> Result<Self, Error> {
26        let device_cstring = match CString::new(device.as_bytes()) {
27            Ok(device_cstring) => device_cstring,
28            Err(e) => return Err(Error::WrapperError(e.to_string())),
29        };
30        let ptr = unsafe { ffi::vaal_context_create(device_cstring.as_ptr()) };
31        if ptr.is_null() {
32            return Err(Error::IoError(io::Error::last_os_error().kind()));
33        }
34
35        return Ok(Context {
36            ptr,
37            dvrt_context: None,
38        });
39    }
40
41    pub fn dvrt_context(&mut self) -> Result<&mut dvrt::context::Context, Error> {
42        if self.dvrt_context.is_some() {
43            return Ok(self.dvrt_context.as_mut().unwrap());
44        }
45        let ret = unsafe { ffi::vaal_context_deepviewrt(self.ptr) };
46        let context = unsafe { dvrt::context::Context::from_ptr(ret as _) };
47        if let Err(dvrt::error::Error::WrapperError(string)) = context {
48            return Err(Error::WrapperError(string));
49        }
50        return Ok(self.dvrt_context.insert(context.unwrap()));
51    }
52
53    pub fn load_model_file<P: AsRef<Path> + Into<Vec<u8>>>(
54        &self,
55        filename: P,
56    ) -> Result<(), Error> {
57        let c_str_filename = CString::new(filename).unwrap();
58        let result = unsafe {
59            ffi::vaal_load_model_file(
60                self.ptr,
61                c_str_filename.as_ptr() as *const std::os::raw::c_char,
62            )
63        };
64        if result != ffi::VAALError_VAAL_SUCCESS {
65            return Err(Error::from(result));
66        }
67        return Ok(());
68    }
69
70    pub fn load_image_file(
71        &mut self,
72        tensor: Option<&mut dvrt::tensor::Tensor>,
73        filename: &str,
74        roi: Option<&[i32]>,
75        pred: u32,
76    ) -> Result<(), Error> {
77        let tensor_: *mut ffi::NNTensor = if let Some(tensor_) = tensor {
78            tensor_.to_mut_ptr() as *mut ffi::NNTensor
79        } else {
80            std::ptr::null_mut() as *mut ffi::NNTensor
81        };
82
83        let roi_: *const i32 = if let Some(roi_) = roi {
84            roi_.as_ptr()
85        } else {
86            std::ptr::null() as *const i32
87        };
88
89        let c_str_filename = CString::new(filename).unwrap();
90
91        let ret = unsafe {
92            ffi::vaal_load_image_file(self.ptr, tensor_, c_str_filename.as_ptr(), roi_, pred)
93        };
94        if ret != ffi::VAALError_VAAL_SUCCESS {
95            return Err(Error::from(ret));
96        }
97        return Ok(());
98    }
99
100    pub fn boxes(&self, boxes: &mut Vec<VAALBox>, max_len: usize) -> Result<usize, Error> {
101        let mut num_boxes: usize = 0;
102        let ret = unsafe {
103            ffi::vaal_boxes(
104                self.ptr,
105                boxes.as_mut_ptr(),
106                max_len,
107                &mut num_boxes as *mut usize,
108            )
109        };
110        unsafe { boxes.set_len(num_boxes) }
111        if ret != ffi::VAALError_VAAL_SUCCESS {
112            return Err(Error::from(ret));
113        }
114        return Ok(num_boxes);
115    }
116
117    pub fn model(&self) -> Result<dvrt::model::Model, Error> {
118        let ret = unsafe { ffi::vaal_context_model(self.ptr) };
119        if ret.is_null() {
120            let err = String::from("no model loaded");
121            return Err(Error::WrapperError(err));
122        }
123
124        let ret = unsafe { dvrt::model::Model::try_from_ptr(ret) };
125        if let Err(e) = ret {
126            return Err(Error::WrapperError(e.to_string()));
127        }
128        return Ok(ret.unwrap());
129    }
130
131    pub fn unload_model(&mut self) -> Result<(), Error> {
132        let result = unsafe { ffi::vaal_unload_model(self.ptr) };
133
134        if result != ffi::VAALError_VAAL_SUCCESS {
135            return Err(Error::from(result));
136        }
137        return Ok(());
138    }
139
140    pub fn load_frame_dmabuf(
141        &self,
142        tensor: Option<&dvrt::tensor::Tensor>,
143        handle: i32,
144        fourcc: u32,
145        width: i32,
146        height: i32,
147        roi: Option<&[i32; 4]>,
148        proc: u32,
149    ) -> Result<(), Error> {
150        let roi_ = if roi.is_none() {
151            std::ptr::null()
152        } else {
153            roi.unwrap().as_ptr()
154        };
155        let ptr;
156        if tensor.is_some() {
157            ptr = tensor.unwrap().to_mut_ptr() as *mut ffi::NNTensor;
158        } else {
159            ptr = ptr::null_mut();
160        }
161        let result = unsafe {
162            ffi::vaal_load_frame_dmabuf(self.ptr, ptr, handle, fourcc, width, height, roi_, proc)
163        };
164        if result != ffi::VAALError_VAAL_SUCCESS {
165            return Err(Error::from(result));
166        }
167        return Ok(());
168    }
169
170    pub fn run_model(&self) -> Result<(), Error> {
171        let ret = unsafe { ffi::vaal_run_model(self.ptr) };
172        if ret != 0 {
173            return Err(Error::from(ret));
174        }
175
176        return Ok(());
177    }
178
179    pub fn output_tensor(&self, index: i32) -> Option<dvrt::tensor::Tensor> {
180        let ret = unsafe { ffi::vaal_output_tensor(self.ptr, index) };
181        if ret.is_null() {
182            return None;
183        }
184
185        let tensor = unsafe { dvrt::tensor::Tensor::from_ptr(ret as _, false) };
186        if tensor.is_err() {
187            return None;
188        }
189        return Some(tensor.unwrap());
190    }
191
192    pub fn output_count(&self) -> Result<i32, Error> {
193        let ret = unsafe { ffi::vaal_output_count(self.ptr) };
194        if ret == 0 {
195            return Err(Error::WrapperError(String::from(
196                "context is invalid, has no model loaded, or the model does not identify any outputs",
197            )));
198        }
199
200        return Ok(ret);
201    }
202
203    pub fn output_name(&self, index: i32) -> Option<&str> {
204        let ret = unsafe { ffi::vaal_output_name(self.ptr, index) };
205        if ret.is_null() {
206            return None;
207        }
208
209        let cstr_name = unsafe { CStr::from_ptr(ret) };
210        match cstr_name.to_str() {
211            Ok(name) => return Some(name),
212            Err(_) => return None,
213        };
214    }
215
216    pub fn label(&self, index: i32) -> Result<&str, Error> {
217        let result = unsafe { ffi::vaal_label(self.ptr, index as std::os::raw::c_int) };
218
219        if result.is_null() {
220            return Err(Error::WrapperError("invalid label index".to_string()));
221        }
222        let cstr_label = unsafe { CStr::from_ptr(result) };
223        let label = match cstr_label.to_str() {
224            Ok(label) => label,
225            Err(e) => return Err(Error::WrapperError(e.to_string())),
226        };
227        if label == "" {
228            return Err(Error::WrapperError("invalid label index".to_string()));
229        }
230        return Ok(label);
231    }
232
233    pub fn labels(&self) -> Vec<&str> {
234        let mut labels = Vec::<&str>::new();
235        let mut i = 0;
236        loop {
237            match self.label(i) {
238                Ok(label) => labels.push(label),
239                Err(_) => {
240                    return labels;
241                }
242            };
243            i += 1;
244        }
245    }
246
247    pub fn parameter_gets() {}
248
249    pub fn parameter_sets(&self, name: &str, value: &str) -> Result<(), Error> {
250        let len = value.len();
251        let name = match CString::new(name) {
252            Ok(name) => name,
253            Err(e) => return Err(Error::WrapperError(e.to_string())),
254        };
255        let value = match CString::new(value) {
256            Ok(value) => value,
257            Err(e) => return Err(Error::WrapperError(e.to_string())),
258        };
259        let ret =
260            unsafe { ffi::vaal_parameter_sets(self.ptr, name.into_raw(), value.into_raw(), len) };
261        if ret != ffi::VAALError_VAAL_SUCCESS {
262            return Err(Error::from(ret));
263        }
264        return Ok(());
265    }
266
267    pub fn parameter_getf() {}
268
269    pub fn parameter_setf(&self, name: &str, value: &[f32]) -> Result<(), Error> {
270        let len = value.len();
271        let name = match CString::new(name) {
272            Ok(name) => name,
273            Err(e) => return Err(Error::WrapperError(e.to_string())),
274        };
275        let ret =
276            unsafe { ffi::vaal_parameter_setf(self.ptr, name.into_raw(), value.as_ptr(), len) };
277        if ret != ffi::VAALError_VAAL_SUCCESS {
278            return Err(Error::from(ret));
279        }
280        return Ok(());
281    }
282
283    pub fn parameter_geti() {}
284
285    pub fn parameter_seti(&self, name: &str, value: &[i32]) -> Result<(), Error> {
286        let len = value.len();
287        let name = match CString::new(name) {
288            Ok(name) => name,
289            Err(e) => return Err(Error::WrapperError(e.to_string())),
290        };
291        let ret =
292            unsafe { ffi::vaal_parameter_seti(self.ptr, name.into_raw(), value.as_ptr(), len) };
293        if ret != ffi::VAALError_VAAL_SUCCESS {
294            return Err(Error::from(ret));
295        }
296        return Ok(());
297    }
298
299    pub fn parameter_getu() {}
300
301    pub fn parameter_setu(&self, name: &str, value: &[u32]) -> Result<(), Error> {
302        let len = value.len();
303        let name = match CString::new(name) {
304            Ok(name) => name,
305            Err(e) => return Err(Error::WrapperError(e.to_string())),
306        };
307        let ret =
308            unsafe { ffi::vaal_parameter_setu(self.ptr, name.into_raw(), value.as_ptr(), len) };
309        if ret != ffi::VAALError_VAAL_SUCCESS {
310            return Err(Error::from(ret));
311        }
312        return Ok(());
313    }
314}
315
316impl Drop for Context {
317    fn drop(&mut self) {
318        unsafe { ffi::vaal_context_release(self.ptr) };
319    }
320}