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}