1use std::fmt;
4
5macro_rules! bitflags {
8 ($($t:tt)*) => {
9 bitflags::bitflags! {
10 #[repr(transparent)]
11 $($t)*
12 }
13 };
14}
15
16ffi_enum! {
17 pub enum TunerType: u32 {
18 RADIO = 1,
19 ANALOG_TV = 2,
20 DIGITAL_TV = 3,
21 SDR = 4,
22 RF = 5,
23 }
24}
25
26ffi_enum! {
27 pub enum OutputType: u32 {
29 MODULATOR = 1,
31 ANALOG = 2,
33 ANALOGVGAOVERLAY = 3,
35 }
36}
37
38ffi_enum! {
39 pub enum InputType: u32 {
41 TUNER = 1,
43 CAMERA = 2,
45 TOUCH = 3,
47 }
48}
49
50ffi_enum! {
51 pub enum Colorspace: u32 {
52 DEFAULT = 0,
53 SMPTE170M = 1,
54 SMPTE240M = 2,
55 REC709 = 3,
56 BT878 = 4,
57 _470_SYSTEM_M = 5,
58 _470_SYSTEM_BG = 6,
59 JPEG = 7,
60 SRGB = 8,
61 OPRGB = 9,
62 BT2020 = 10,
63 RAW = 11,
64 DCI_P3 = 12,
65 }
66}
67
68ffi_enum! {
69 pub enum Quantization: u32 {
70 DEFAULT = 0,
71 FULL_RANGE = 1,
72 LIM_RANGE = 2,
73 }
74}
75
76ffi_enum! {
77 pub enum XferFunc: u32 {
78 DEFAULT = 0,
79 _709 = 1,
80 SRGB = 2,
81 OPRGB = 3,
82 SMPTE240M = 4,
83 NONE = 5,
84 DCI_P3 = 6,
85 SMPTE2084 = 7,
86 }
87}
88
89ffi_enum! {
90 pub enum Field: u32 {
91 ANY = 0,
93 NONE = 1,
95 TOP = 2,
96 BOTTOM = 3,
97 INTERLACED = 4,
98 SEQ_TB = 5,
99 SEQ_BT = 6,
100 ALTERNATE = 7,
101 INTERLACED_TB = 8,
102 INTERLACED_BT = 9,
103 }
104}
105
106ffi_enum! {
107 pub enum CtrlType: u32 {
109 INTEGER = 1,
110 BOOLEAN = 2,
111 MENU = 3,
112 BUTTON = 4,
113 INTEGER64 = 5,
114 CTRL_CLASS = 6,
115 STRING = 7,
116 BITMASK = 8,
117 INTEGER_MENU = 9,
118
119 U8 = 0x0100,
121 U16 = 0x0101,
122 U32 = 0x0102,
123 AREA = 0x0106,
124
125 H264_SPS = 0x0200,
126 H264_PPS = 0x0201,
127 H264_SCALING_MATRIX = 0x0202,
128 H264_SLICE_PARAMS = 0x0203,
129 H264_DECODE_PARAMS = 0x0204,
130 H264_PRED_WEIGHTS = 0x0205,
131
132 FWHT_PARAMS = 0x0220,
133
134 VP8_FRAME = 0x0240,
135
136 MPEG2_QUANTISATION = 0x0250,
137 MPEG2_SEQUENCE = 0x0251,
138 MPEG2_PICTURE = 0x0252,
139 }
140}
141
142ffi_enum! {
143 pub enum Memory: u32 {
144 MMAP = 1,
146 USERPTR = 2,
148 OVERLAY = 3,
149 DMABUF = 4,
150 }
151}
152
153ffi_enum! {
154 pub enum TimecodeType: u32 {
155 T_24FPS = 1,
156 T_25FPS = 2,
157 T_30FPS = 3,
158 T_50FPS = 4,
159 T_60FPS = 5,
160 }
161}
162
163ffi_enum! {
164 pub enum FrmSizeType: u32 {
165 DISCRETE = 1,
166 CONTINUOUS = 2,
167 STEPWISE = 3,
168 }
169}
170
171ffi_enum! {
172 pub enum FrmIvalType: u32 {
173 DISCRETE = 1,
174 CONTINUOUS = 2,
175 STEPWISE = 3,
176 }
177}
178
179bitflags! {
180 pub struct ControlFlags: u32 {
182 const DISABLED = 0x0001;
184 const GRABBED = 0x0002;
186 const READ_ONLY = 0x0004;
188 const UPDATE = 0x0008;
191 const INACTIVE = 0x0010;
193 const SLIDER = 0x0020;
195 const WRITE_ONLY = 0x0040;
197 const VOLATILE = 0x0080;
199 const HAS_PAYLOAD = 0x0100;
201 const EXECUTE_ON_WRITE = 0x0200;
206 const MODIFY_LAYOUT = 0x0400;
208
209 }
212}
213
214pub(crate) const CONTROL_FLAGS_NEXT_CTRL: u32 = 0x80000000;
215
216bitflags! {
217 pub struct FormatFlags: u32 {
218 const COMPRESSED = 0x0001;
219 const EMULATED = 0x0002;
220 const CONTINUOUS_BYTESTREAM = 0x0004;
221 const DYN_RESOLUTION = 0x0008;
222 const ENC_CAP_FRAME_INTERVAL = 0x0010;
223 const CSC_COLORSPACE = 0x0020;
224 const CSC_XFER_FUNC = 0x0040;
225 const CSC_YCBCR_ENC = 0x0080;
226 const CSC_HSV_ENC = Self::CSC_YCBCR_ENC.bits;
227 const CSC_QUANTIZATION = 0x0100;
228 }
229}
230
231bitflags! {
232 pub struct AnalogStd: u64 { const PAL_B = 0x0000001;
235 const PAL_B1 = 0x0000002;
236 const PAL_G = 0x0000004;
237 const PAL_H = 0x0000008;
238 const PAL_I = 0x0000010;
239 const PAL_D = 0x0000020;
240 const PAL_D1 = 0x0000040;
241 const PAL_K = 0x0000080;
242
243 const PAL_M = 0x0000100;
244 const PAL_N = 0x0000200;
245 const PAL_NC = 0x0000400;
246 const PAL_60 = 0x0000800;
247
248 const NTSC_M = 0x00001000;
249 const NTSC_M_JP = 0x00002000;
250 const NTSC_443 = 0x00004000;
251 const NTSC_M_KR = 0x00008000;
252
253 const SECAM_B = 0x00010000;
254 const SECAM_D = 0x00020000;
255 const SECAM_G = 0x00040000;
256 const SECAM_H = 0x00080000;
257 const SECAM_K = 0x00100000;
258 const SECAM_K1 = 0x00200000;
259 const SECAM_L = 0x00400000;
260 const SECAM_LC = 0x00800000;
261
262 const ATSC_8_VSB = 0x01000000;
263 const ATSC_16_VSB = 0x02000000;
264 }
265}
266
267bitflags! {
268 pub struct OutputCapabilities: u32 {
270 const DV_TIMINGS = 0x00000002;
272 const CUSTOM_TIMINGS = Self::DV_TIMINGS.bits;
273 const STD = 0x00000004;
274 const NATIVE_SIZE = 0x00000008;
275 }
276}
277
278bitflags! {
279 pub struct InputCapabilities: u32 {
281 const DV_TIMINGS = 0x00000002;
283 const CUSTOM_TIMINGS = Self::DV_TIMINGS.bits;
284 const STD = 0x00000004;
285 const NATIVE_SIZE = 0x00000008;
286 }
287}
288
289bitflags! {
290 pub struct CapabilityFlags: u32 {
292 const VIDEO_CAPTURE = 0x00000001;
294 const VIDEO_OUTPUT = 0x00000002;
296 const VIDEO_OVERLAY = 0x00000004;
297 const VBI_CAPTURE = 0x00000010;
298 const VBI_OUTPUT = 0x00000020;
299 const SLICED_VBI_CAPTURE = 0x00000040;
300 const SLICED_VBI_OUTPUT = 0x00000080;
301 const RDS_CAPTURE = 0x00000100;
302 const VIDEO_OUTPUT_OVERLAY = 0x00000200;
303 const HW_FREQ_SEEK = 0x00000400;
304 const RDS_OUTPUT = 0x00000800;
305
306 const VIDEO_CAPTURE_MPLANE = 0x00001000;
307 const VIDEO_OUTPUT_MPLANE = 0x00002000;
308 const VIDEO_M2M_MPLANE = 0x00004000;
309 const VIDEO_M2M = 0x00008000;
310
311 const TUNER = 0x00010000;
312 const AUDIO = 0x00020000;
313 const RADIO = 0x00040000;
314 const MODULATOR = 0x00080000;
315
316 const SDR_CAPTURE = 0x00100000;
317 const EXT_PIX_FORMAT = 0x00200000;
318 const SDR_OUTPUT = 0x00400000;
319 const META_CAPTURE = 0x00800000;
321
322 const READWRITE = 0x01000000;
324 const ASYNCIO = 0x02000000;
326 const STREAMING = 0x04000000;
328 const META_OUTPUT = 0x08000000;
329
330 const TOUCH = 0x10000000;
332 const IO_MC = 0x20000000;
334 const DEVICE_CAPS = 0x80000000;
336 }
337}
338
339bitflags! {
340 pub struct InputStatus: u32 {
342 const NO_POWER = 0x00000001;
344 const NO_SIGNAL = 0x00000002;
346 const NO_COLOR = 0x00000004;
348
349 const HFLIP = 0x00000010;
352 const VFLIP = 0x00000020;
354
355 const NO_H_LOCK = 0x00000100;
357 const COLOR_KILL = 0x00000200;
360 const NO_V_LOCK = 0x00000400;
362 const NO_STD_LOCK = 0x00000800;
364
365 const NO_SYNC = 0x00010000;
367 const NO_EQU = 0x00020000;
369 const NO_CARRIER = 0x00040000;
371
372 const MACROVISION = 0x01000000;
374 const NO_ACCESS = 0x02000000;
376 const VTR = 0x04000000;
377 }
378}
379
380bitflags! {
381 pub struct VbiFlags: u32 {
382 const UNSYNC = 1 << 0;
383 const INTERLACED = 1 << 1;
384 }
385}
386
387bitflags! {
388 pub struct ServiceSet: u32 {
389 const TELETEXT_B = 0x0001;
390 const VPS = 0x0400;
391 const CAPTION_525 = 0x1000;
392 const WSS_625 = 0x4000;
393 }
394}
395
396bitflags! {
397 pub struct PixFmtFlag: u32 {
398 const PREMUL_ALPHA = 0x00000001;
399 const SET_CSC = 0x00000002;
400 }
401}
402
403bitflags! {
404 pub struct BufCap: u32 {
405 const SUPPORTS_MMAP = 1 << 0;
406 const SUPPORTS_USERPTR = 1 << 1;
407 const SUPPORTS_DMABUF = 1 << 2;
408 const SUPPORTS_REQUESTS = 1 << 3;
409 const SUPPORTS_ORPHANED_BUFS = 1 << 4;
410 const SUPPORTS_M2M_HOLD_CAPTURE_BUF = 1 << 5;
411 const SUPPORTS_MMAP_CACHE_HINTS = 1 << 6;
412 }
413}
414
415bitflags! {
416 pub struct BufFlag: u32 {
417 const MAPPED = 0x00000001;
418 const QUEUED = 0x00000002;
419 const DONE = 0x00000004;
420 const KEYFRAME = 0x00000008;
421 const PFRAME = 0x00000010;
422 const BFRAME = 0x00000020;
423 const ERROR = 0x00000040;
424 const IN_REQUEST = 0x00000080;
425 const TIMECODE = 0x00000100;
426 const M2M_HOLD_CAPTURE_BUF = 0x00000200;
427 const PREPARED = 0x00000400;
428 const NO_CACHE_INVALIDATE = 0x00000800;
429 const NO_CACHE_CLEAN = 0x00001000;
430 const TIMESTAMP_MASK = 0x0000e000;
431 const TIMESTAMP_UNKNOWN = 0x00000000;
432 const TIMESTAMP_MONOTONIC = 0x00002000;
433 const TIMESTAMP_COPY = 0x00004000;
434 const TIMESTAMP_SRC_MASK = 0x00070000;
435 const TIMESTAMP_SRC_EOF = 0x00000000;
436 const TIMESTAMP_SRC_SOE = 0x00010000;
437 const LAST = 0x00100000;
438 const REQUEST_FD = 0x00800000;
439 }
440}
441
442bitflags! {
443 pub struct TimecodeFlags: u32 {
444 const DROPFRAME = 0x0001;
445 const COLORFRAME = 0x0002;
446 const USERBITS_MASK = 0x000C;
447 const USERBITS_USERDEFINED = 0x0000;
448 const USERBITS_8BITCHARS = 0x0008;
449 }
450}
451
452bitflags! {
453 pub struct StreamParamCaps: u32 {
454 const TIMEPERFRAME = 0x1000;
455 }
456}
457
458bitflags! {
459 pub struct CaptureParamFlags: u32 {
460 const HIGHQUALITY = 0x0001;
461 }
462}
463
464#[derive(Clone, Copy, Hash)]
466#[repr(C)]
467pub struct Fract {
468 numerator: u32,
469 denominator: u32,
470}
471
472impl Fract {
473 #[inline]
474 pub fn new(numerator: u32, denominator: u32) -> Self {
475 assert_ne!(denominator, 0, "denominator must not be zero");
476 Self {
477 numerator,
478 denominator,
479 }
480 }
481
482 #[inline]
483 pub fn numerator(&self) -> u32 {
484 self.numerator
485 }
486
487 #[inline]
488 pub fn denominator(&self) -> u32 {
489 self.denominator
490 }
491
492 #[inline]
494 pub fn as_f32(&self) -> f32 {
495 self.numerator as f32 / self.denominator as f32
496 }
497}
498
499impl fmt::Display for Fract {
500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501 write!(f, "{}/{}", self.numerator, self.denominator)
502 }
503}
504
505impl fmt::Debug for Fract {
506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
507 fmt::Display::fmt(self, f)
508 }
509}
510
511impl PartialEq for Fract {
512 fn eq(&self, other: &Self) -> bool {
513 let [a, b] = same_denom(*self, *other);
514 a.numerator == b.numerator
515 }
516}
517
518impl Eq for Fract {}
519
520impl PartialOrd for Fract {
521 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
522 let [a, b] = same_denom(*self, *other);
523 a.numerator.partial_cmp(&b.numerator)
524 }
525}
526
527impl Ord for Fract {
528 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
529 let [a, b] = same_denom(*self, *other);
530 a.numerator.cmp(&b.numerator)
531 }
532}
533
534fn same_denom(f1: Fract, f2: Fract) -> [Fract; 2] {
535 let multiple = lcm(f1.denominator, f2.denominator);
536 [
537 Fract::new(f1.numerator * (multiple / f1.denominator), multiple),
538 Fract::new(f2.numerator * (multiple / f2.denominator), multiple),
539 ]
540}
541
542const fn gcd(mut a: u32, mut b: u32) -> u32 {
543 while b > 0 {
544 let t = b;
545 b = a % b;
546 a = t;
547 }
548
549 a
550}
551
552const fn lcm(a: u32, b: u32) -> u32 {
553 a * b / gcd(a, b)
554}
555
556#[cfg(test)]
557mod tests {
558 use super::*;
559
560 #[test]
561 fn test_gcd() {
562 assert_eq!(gcd(6, 9), 3);
563 assert_eq!(gcd(7, 13), 1);
564 assert_eq!(1920 / gcd(1920, 1080), 16);
565 assert_eq!(1080 / gcd(1920, 1080), 9);
566
567 assert_eq!(gcd(0, 7), 7);
569 assert_eq!(gcd(7, 0), 7);
570 assert_eq!(gcd(0, 0), 0);
571 }
572
573 #[test]
574 fn test_lcm() {
575 assert_eq!(lcm(1, 1), 1);
576 assert_eq!(lcm(1, 3), 3);
577 assert_eq!(lcm(3, 1), 3);
578
579 assert_eq!(lcm(3, 5), 15);
580 assert_eq!(lcm(5, 3), 15);
581 }
582
583 #[test]
584 fn test_same_denom() {
585 let a = Fract::new(2, 3);
586 let b = Fract::new(3, 5);
587 let [x, y] = same_denom(a, b);
588 assert_eq!(x.numerator, 10);
589 assert_eq!(x.denominator, 15);
590 assert_eq!(y.numerator, 9);
591 assert_eq!(y.denominator, 15);
592 }
593}