Skip to main content

adamo_sys/
lib.rs

1//! Raw FFI bindings to the Adamo SDK.
2//!
3//! This crate is a thin, `unsafe` interface — prefer the safe wrappers in
4//! [`adamo`](https://docs.rs/adamo) for normal use.
5//!
6//! All declarations match the C header generated by `cbindgen` for the
7//! `adamo-c` crate (`include/adamo/adamo.h`). Keep them in sync.
8
9#![allow(non_camel_case_types)]
10#![allow(clippy::missing_safety_doc)]
11
12use std::os::raw::{c_char, c_int, c_void};
13
14pub type adamo_protocol_t = u32;
15pub const ADAMO_PROTOCOL_UDP: adamo_protocol_t = 0;
16pub const ADAMO_PROTOCOL_QUIC: adamo_protocol_t = 1;
17pub const ADAMO_PROTOCOL_TCP: adamo_protocol_t = 2;
18
19pub type adamo_regime_t = u32;
20pub const ADAMO_REGIME_STABLE: adamo_regime_t = 0;
21pub const ADAMO_REGIME_DEGRADING: adamo_regime_t = 1;
22pub const ADAMO_REGIME_VOLATILE: adamo_regime_t = 2;
23pub const ADAMO_REGIME_RECOVERING: adamo_regime_t = 3;
24
25pub type adamo_video_backend_t = i32;
26pub const ADAMO_VIDEO_BACKEND_AUTO: adamo_video_backend_t = 0;
27pub const ADAMO_VIDEO_BACKEND_GSTREAMER: adamo_video_backend_t = 1;
28pub const ADAMO_VIDEO_BACKEND_HW_PIPELINE: adamo_video_backend_t = 2;
29
30// Opaque handles. Zero-sized placeholders — callers only ever see pointers
31// to them. `PhantomData<*mut ()>` keeps them `!Send + !Sync` by default;
32// the safe wrapper re-asserts thread-safety where the C API documents it.
33#[repr(C)]
34pub struct adamo_session_t {
35    _priv: [u8; 0],
36    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
37}
38#[repr(C)]
39pub struct adamo_publisher_t {
40    _priv: [u8; 0],
41    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
42}
43#[repr(C)]
44pub struct adamo_subscriber_t {
45    _priv: [u8; 0],
46    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
47}
48#[repr(C)]
49pub struct adamo_cb_sub_t {
50    _priv: [u8; 0],
51    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
52}
53#[repr(C)]
54pub struct adamo_liveliness_token_t {
55    _priv: [u8; 0],
56    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
57}
58#[repr(C)]
59pub struct adamo_liveliness_sub_t {
60    _priv: [u8; 0],
61    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
62}
63#[repr(C)]
64pub struct adamo_robot_t {
65    _priv: [u8; 0],
66    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
67}
68#[repr(C)]
69pub struct adamo_video_track_t {
70    _priv: [u8; 0],
71    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
72}
73
74#[repr(C)]
75pub struct adamo_sample_t {
76    pub key: *mut c_char,
77    pub payload: *mut u8,
78    pub payload_len: usize,
79    pub is_delete: i32,
80    pub timestamp_us: u64,
81}
82
83#[repr(C)]
84pub struct adamo_latency_stats_t {
85    pub regime: adamo_regime_t,
86    pub jitter_hint_ms: f32,
87    pub garch_sigma_ms: f32,
88    pub target_bitrate_kbps: u32,
89    pub loss_rate: f32,
90    pub queuing_delay_ms: f32,
91    pub timestamp_ms: u64,
92}
93
94#[repr(C)]
95#[derive(Clone, Copy)]
96pub struct adamo_video_options_t {
97    pub width: u32,
98    pub height: u32,
99    pub pixel_format: *const c_char,
100    pub codec: *const c_char,
101    pub encoder: *const c_char,
102    pub bitrate_kbps: u32,
103    pub adaptive_bitrate: i32,
104    pub min_bitrate_kbps: u32,
105    pub max_bitrate_kbps: u32,
106    pub bitrate_priority: f32,
107    pub fps: u32,
108    pub keyframe_distance: f64,
109    pub stereo: i32,
110    pub backend: adamo_video_backend_t,
111    /// Optional iceoryx2 service name to also publish every raw captured
112    /// frame to (V4L2 tracks only; null = disabled).
113    pub shm_publish: *const c_char,
114    /// Per-track video protocol (null = adamo default).
115    pub reliability: *const c_char,
116    /// Forward an already-encoded H.264/H.265 bitstream without re-encoding
117    /// (0 = off). Appended last to keep prior field offsets ABI-stable.
118    pub passthrough: i32,
119}
120
121pub type adamo_sample_cb_t =
122    Option<unsafe extern "C" fn(sample: *const adamo_sample_t, user: *mut c_void)>;
123pub type adamo_liveliness_cb_t =
124    Option<unsafe extern "C" fn(key: *const c_char, alive: c_int, user: *mut c_void)>;
125
126// docs.rs builds can't link libadamo; stub the extern block out there so
127// rustdoc still succeeds.
128#[cfg(not(docsrs))]
129unsafe extern "C" {
130    pub fn adamo_last_error() -> *const c_char;
131
132    /// Category of the last error on this thread. 0 = OK, 1 = auth,
133    /// 2 = network, 3 = timeout, 4 = invalid argument, 5 = video,
134    /// 6 = internal. Stable across releases.
135    pub fn adamo_last_error_code() -> core::ffi::c_int;
136
137    pub fn adamo_sample_free(sample: *mut adamo_sample_t);
138
139    pub fn adamo_open(api_key: *const c_char, protocol: adamo_protocol_t) -> *mut adamo_session_t;
140    pub fn adamo_open_default(api_key: *const c_char) -> *mut adamo_session_t;
141    pub fn adamo_open_mtls(
142        api_key: *const c_char,
143        protocol: adamo_protocol_t,
144    ) -> *mut adamo_session_t;
145    pub fn adamo_session_free(sess: *mut adamo_session_t);
146    pub fn adamo_session_org(sess: *const adamo_session_t) -> *const c_char;
147    pub fn adamo_session_org_len(sess: *const adamo_session_t) -> usize;
148
149    pub fn adamo_put(
150        sess: *const adamo_session_t,
151        key: *const c_char,
152        payload: *const u8,
153        payload_len: usize,
154        priority: u8,
155        express: i32,
156    ) -> i32;
157
158    pub fn adamo_publisher(
159        sess: *const adamo_session_t,
160        key: *const c_char,
161        priority: u8,
162        express: i32,
163        reliable: i32,
164    ) -> *mut adamo_publisher_t;
165    pub fn adamo_publisher_put(
166        pub_: *const adamo_publisher_t,
167        payload: *const u8,
168        payload_len: usize,
169    ) -> i32;
170    pub fn adamo_publisher_free(pub_: *mut adamo_publisher_t);
171
172    pub fn adamo_subscribe(
173        sess: *const adamo_session_t,
174        key: *const c_char,
175    ) -> *mut adamo_subscriber_t;
176    pub fn adamo_sub_recv(
177        sub: *const adamo_subscriber_t,
178        timeout_ms: u64,
179    ) -> *mut adamo_sample_t;
180    pub fn adamo_sub_try_recv(sub: *const adamo_subscriber_t) -> *mut adamo_sample_t;
181    pub fn adamo_sub_free(sub: *mut adamo_subscriber_t);
182
183    pub fn adamo_subscribe_cb(
184        sess: *const adamo_session_t,
185        key: *const c_char,
186        cb: adamo_sample_cb_t,
187        user: *mut c_void,
188    ) -> *mut adamo_cb_sub_t;
189    pub fn adamo_cb_sub_free(sub: *mut adamo_cb_sub_t);
190
191    pub fn adamo_get(
192        sess: *const adamo_session_t,
193        key: *const c_char,
194        timeout_ms: u64,
195        count_out: *mut usize,
196    ) -> *mut *mut adamo_sample_t;
197    pub fn adamo_get_replies_free(replies: *mut *mut adamo_sample_t, count: usize);
198
199    pub fn adamo_liveliness_declare(
200        sess: *const adamo_session_t,
201        token_key: *const c_char,
202    ) -> *mut adamo_liveliness_token_t;
203    pub fn adamo_liveliness_token_free(tok: *mut adamo_liveliness_token_t);
204    pub fn adamo_liveliness_get(
205        sess: *const adamo_session_t,
206        pattern: *const c_char,
207        count_out: *mut usize,
208    ) -> *mut *mut c_char;
209    pub fn adamo_liveliness_tokens_free(tokens: *mut *mut c_char, count: usize);
210    pub fn adamo_liveliness_subscribe(
211        sess: *const adamo_session_t,
212        pattern: *const c_char,
213        history: c_int,
214        cb: adamo_liveliness_cb_t,
215        user: *mut c_void,
216    ) -> *mut adamo_liveliness_sub_t;
217    pub fn adamo_liveliness_sub_free(sub: *mut adamo_liveliness_sub_t);
218
219    pub fn adamo_robot_new(
220        api_key: *const c_char,
221        name: *const c_char,
222        protocol: adamo_protocol_t,
223    ) -> *mut adamo_robot_t;
224    pub fn adamo_robot_new_default(
225        api_key: *const c_char,
226        name: *const c_char,
227    ) -> *mut adamo_robot_t;
228    pub fn adamo_video_options_default() -> adamo_video_options_t;
229    pub fn adamo_robot_video(
230        robot: *mut adamo_robot_t,
231        name: *const c_char,
232        width: u32,
233        height: u32,
234        pixel_format: *const c_char,
235        fps: u32,
236        bitrate_kbps: u32,
237        stereo: bool,
238    ) -> *mut adamo_video_track_t;
239    pub fn adamo_robot_video_with_options(
240        robot: *mut adamo_robot_t,
241        name: *const c_char,
242        width: u32,
243        height: u32,
244        pixel_format: *const c_char,
245        fps: u32,
246        bitrate_kbps: u32,
247        stereo: bool,
248        encoder: *const c_char,
249        hw_pipeline: bool,
250    ) -> *mut adamo_video_track_t;
251    pub fn adamo_robot_video_configured(
252        robot: *mut adamo_robot_t,
253        name: *const c_char,
254        opts: *const adamo_video_options_t,
255    ) -> *mut adamo_video_track_t;
256    pub fn adamo_robot_attach_video_v4l2(
257        robot: *mut adamo_robot_t,
258        name: *const c_char,
259        device: *const c_char,
260        width: u32,
261        height: u32,
262        fps: u32,
263        bitrate_kbps: u32,
264        stereo: bool,
265    ) -> i32;
266    pub fn adamo_robot_attach_video_v4l2_configured(
267        robot: *mut adamo_robot_t,
268        name: *const c_char,
269        device: *const c_char,
270        opts: *const adamo_video_options_t,
271    ) -> i32;
272    pub fn adamo_robot_attach_video_gst(
273        robot: *mut adamo_robot_t,
274        name: *const c_char,
275        pipeline: *const c_char,
276        width: u32,
277        height: u32,
278        fps: u32,
279        bitrate_kbps: u32,
280        stereo: bool,
281    ) -> i32;
282    pub fn adamo_robot_attach_video_gst_with_format(
283        robot: *mut adamo_robot_t,
284        name: *const c_char,
285        pipeline: *const c_char,
286        width: u32,
287        height: u32,
288        fps: u32,
289        bitrate_kbps: u32,
290        stereo: bool,
291        source_format: *const c_char,
292    ) -> i32;
293    pub fn adamo_robot_attach_video_gst_configured(
294        robot: *mut adamo_robot_t,
295        name: *const c_char,
296        pipeline: *const c_char,
297        opts: *const adamo_video_options_t,
298    ) -> i32;
299    pub fn adamo_robot_attach_video_shm(
300        robot: *mut adamo_robot_t,
301        name: *const c_char,
302        service: *const c_char,
303        width: u32,
304        height: u32,
305        pixel_format: *const c_char,
306        fps: u32,
307        bitrate_kbps: u32,
308        stereo: bool,
309    ) -> i32;
310    pub fn adamo_robot_attach_video_shm_configured(
311        robot: *mut adamo_robot_t,
312        name: *const c_char,
313        service: *const c_char,
314        opts: *const adamo_video_options_t,
315    ) -> i32;
316    pub fn adamo_video_track_send(
317        track: *mut adamo_video_track_t,
318        payload: *const u8,
319        payload_len: usize,
320    ) -> i32;
321    pub fn adamo_video_track_free(track: *mut adamo_video_track_t);
322    pub fn adamo_robot_run(robot: *mut adamo_robot_t) -> i32;
323    pub fn adamo_robot_free(robot: *mut adamo_robot_t);
324
325    pub fn adamo_detect_encoder() -> *const c_char;
326
327    pub fn adamo_fabric_now_us() -> u64;
328    pub fn adamo_fabric_synced() -> i32;
329    pub fn adamo_relay_rtt_us(sess: *const adamo_session_t, out_us: *mut u64) -> i32;
330
331    pub fn adamo_parse_heartbeat(
332        payload: *const u8,
333        payload_len: usize,
334        out: *mut adamo_latency_stats_t,
335    ) -> i32;
336    pub fn adamo_heartbeat_topic(
337        robot: *const c_char,
338        out: *mut c_char,
339        out_cap: usize,
340    ) -> isize;
341    pub fn adamo_ping_topic(
342        robot: *const c_char,
343        out: *mut c_char,
344        out_cap: usize,
345    ) -> isize;
346    pub fn adamo_pong_topic(
347        robot: *const c_char,
348        out: *mut c_char,
349        out_cap: usize,
350    ) -> isize;
351    pub fn adamo_measure_rtt(
352        sess: *const adamo_session_t,
353        robot: *const c_char,
354        timeout_ms: u64,
355        out_us: *mut u64,
356    ) -> i32;
357}
358
359// Silence `unused_imports` if someone pulls in the crate without calling
360// anything (e.g. docs builds).
361#[doc(hidden)]
362pub const _IMPORTS: (Option<c_int>, Option<*mut c_void>) = (None, None);