1#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "README.md" ) ) ]
2#![deny(missing_docs)]
3use core::fmt;
4use std::{sync::Arc, time::Duration};
5
6use binrw::binrw;
7
8mod client;
9#[cfg(feature = "async")]
10mod client_async;
11mod server;
12pub use client::Client;
13#[cfg(feature = "async")]
14pub use client_async::ClientAsync;
15use once_cell::sync::Lazy;
16use serde::{Deserialize, Serialize};
17pub use server::Server;
18use server::StreamServerInner;
19use std::net::ToSocketAddrs;
20
21#[cfg(feature = "locking-default")]
22use parking_lot::{Condvar, Mutex, RawMutex};
23
24#[cfg(feature = "locking-rt")]
25use parking_lot_rt::{Condvar, Mutex, RawMutex};
26
27#[cfg(feature = "locking-rt-safe")]
28use rtsc::pi::{Condvar, Mutex, RawMutex};
29
30const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5);
31
32static DEFAULT_SERVER: Lazy<Server> = Lazy::new(|| Server::new(DEFAULT_TIMEOUT));
33
34pub fn add_stream(format: Format, width: u16, height: u16) -> Result<Stream, Error> {
36 DEFAULT_SERVER.add_stream(format, width, height)
37}
38
39pub fn send_frame(stream_id: u16, frame: Frame) -> Result<(), Error> {
41 DEFAULT_SERVER.send_frame(stream_id, frame)
42}
43
44pub fn serve(addr: impl ToSocketAddrs + std::fmt::Debug) -> Result<(), Error> {
46 DEFAULT_SERVER.serve(addr)
47}
48
49#[derive(Clone, Debug)]
51pub struct Frame {
52 pub metadata: Option<Arc<Vec<u8>>>,
54 pub data: Arc<Vec<u8>>,
56}
57
58impl From<Vec<u8>> for Frame {
59 fn from(data: Vec<u8>) -> Self {
60 Self {
61 metadata: None,
62 data: data.into(),
63 }
64 }
65}
66
67impl From<Arc<Vec<u8>>> for Frame {
68 fn from(data: Arc<Vec<u8>>) -> Self {
69 Self {
70 metadata: None,
71 data,
72 }
73 }
74}
75
76impl Frame {
77 pub fn new(data: Arc<Vec<u8>>) -> Self {
80 Self {
81 metadata: None,
82 data,
83 }
84 }
85 pub fn new_with_metadata(metadata: Arc<Vec<u8>>, data: Arc<Vec<u8>>) -> Self {
89 Self {
90 metadata: Some(metadata),
91 data,
92 }
93 }
94}
95
96pub const API_VERSION: u8 = 2;
98
99#[derive(thiserror::Error, Debug)]
101pub enum Error {
102 #[error("Invalid stream")]
104 InvalidStream,
105 #[error("Too many streams")]
107 TooManyStreams,
108 #[error("IO error: {0}")]
110 Io(#[from] std::io::Error),
111 #[error("Unsupported API version: {0}")]
112 ApiVersion(u8),
114 #[error("Invalid binary data: {0}")]
116 Decode(#[from] binrw::Error),
117 #[error("Frame metadata too large")]
119 FrameMetaDataTooLarge,
120 #[error("Frame data too large")]
122 FrameDataTooLarge,
123 #[error("Invalid address")]
125 InvalidAddress,
126 #[error("Not ready")]
128 NotReady,
129 #[error("Timed out")]
131 #[cfg(feature = "async")]
132 AsyncTimeout(#[from] tokio::time::error::Elapsed),
133}
134
135#[binrw]
138#[br(repr = u8)]
139#[bw(repr = u8)]
140#[derive(Copy, Clone, Debug, PartialEq, Eq)]
141pub enum Format {
142 Luma8 = 0,
144 Luma16 = 1,
146 LumaA8 = 2,
148 LumaA16 = 3,
150 Rgb8 = 4,
152 Rgb16 = 5,
154 Rgba8 = 6,
156 Rgba16 = 7,
158 MJpeg = 64,
160}
161
162#[derive(Serialize, Deserialize, Clone, Debug)]
165pub struct BoundingBox {
166 #[serde(rename = "c")]
167 pub color: [u8; 3],
169 pub x: u16,
171 pub y: u16,
173 #[serde(rename = "w")]
175 pub width: u16,
176 #[serde(rename = "h")]
178 pub height: u16,
179}
180
181#[binrw]
182#[brw(little, magic = b"R")]
183#[derive(Clone, Debug)]
184struct Greetings {
185 api_version: u8,
186 streams_available: u16,
187}
188
189#[binrw]
190#[brw(little)]
191#[derive(Clone, Debug)]
192struct StreamSelect {
193 stream_id: u16,
194 max_fps: u8,
195}
196
197#[binrw]
199#[brw(little)]
200#[derive(Clone, Debug)]
201pub struct StreamInfo {
202 pub id: u16,
204 pub format: Format,
206 pub width: u16,
208 pub height: u16,
210}
211
212impl fmt::Display for StreamInfo {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(
215 f,
216 "#{}, WxH: {}x{}, Fmt: {:?}",
217 self.id, self.width, self.height, self.format
218 )
219 }
220}
221
222#[derive(Clone)]
224pub struct Stream {
225 id: u16,
226 server_inner: Arc<StreamServerInner>,
227}
228
229impl Stream {
230 pub fn id(&self) -> u16 {
232 self.id
233 }
234 pub fn send_frame(&self, frame: Frame) -> Result<(), Error> {
236 self.server_inner.send_frame(self.id, frame)
237 }
238}