linuxvideo/
shared.rs

1//! FFI-compatible types that may also be exposed to Rust code.
2
3use std::fmt;
4
5// This macro enforces that all `bitflags!` types in here are marked
6// `#[repr(transparent)]` and thus FFI-safe.
7macro_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    /// Describes what kind of device an [`Output`][crate::Output] is.
28    pub enum OutputType: u32 {
29        /// This output is an analog TV modulator.
30        MODULATOR = 1,
31        /// Non-modulated analog TV, or a digital signal.
32        ANALOG = 2,
33        /// The video output will be copied to a video overlay.
34        ANALOGVGAOVERLAY = 3,
35    }
36}
37
38ffi_enum! {
39    /// Describes what kind of device an [`Input`][crate::Input] is.
40    pub enum InputType: u32 {
41        /// The input is an RF Demodulator/Tuner.
42        TUNER = 1,
43        /// Input is a camera, HDMI capture device, or another non-tuner input.
44        CAMERA = 2,
45        /// The input is a touch screen or surface.
46        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        /// Lets the driver choose.
92        ANY           = 0,
93        /// Don't use fields.
94        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    /// Data types supported by a device control.
108    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        //COMPOUND_TYPES    = 0x0100,
120        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        /// Buffers are allocated by the driver and `mmap`ped into userspace.
145        MMAP    = 1,
146        /// Buffers are allocated by userspace and a pointer is passed to the driver.
147        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    /// Flags describing the state of a device control.
181    pub struct ControlFlags: u32 {
182        /// The control is disabled and cannot be modified.
183        const DISABLED         = 0x0001;
184        /// The control is in use by another application and cannot be modified.
185        const GRABBED          = 0x0002;
186        /// The value of this control cannot be changed.
187        const READ_ONLY        = 0x0004;
188        /// Modifying the value of this control may change the value of other controls in the same
189        /// control class.
190        const UPDATE           = 0x0008;
191        /// The control is not available in the current device configuration.
192        const INACTIVE         = 0x0010;
193        /// The control's value is best displayed as a slider-like control in a UI.
194        const SLIDER           = 0x0020;
195        /// The control's value is not readable.
196        const WRITE_ONLY       = 0x0040;
197        /// The value of the control may change spuriously, even without writing to it.
198        const VOLATILE         = 0x0080;
199        /// The control's value is a non-scalar type behind a pointer.
200        const HAS_PAYLOAD      = 0x0100;
201        /// Setting the control's value will propagate to the driver, even when setting it to its
202        /// current value.
203        ///
204        /// This is typically set for "trigger" controls that execute a device action when set.
205        const EXECUTE_ON_WRITE = 0x0200;
206        /// Modifying this control's value may change the video buffer layout.
207        const MODIFY_LAYOUT    = 0x0400;
208
209        // Used internally, but not of interest to users of this library.
210        //const NEXT_CTRL        = 0x80000000;
211    }
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    /// Analog video standards.
233    pub struct AnalogStd: u64 { // NB: this is v4l2_std_id
234        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    /// Describes the capabilities of a device [`Output`][crate::Output].
269    pub struct OutputCapabilities: u32 {
270        /// The output allows configuring video timings via `VIDIOC_S_DV_TIMINGS`.
271        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    /// Describes the capabilities of a device [`Input`][crate::Input].
280    pub struct InputCapabilities: u32 {
281        /// The input allows configuring video timings via `VIDIOC_S_DV_TIMINGS`.
282        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    /// Device capabilities.
291    pub struct CapabilityFlags: u32 {
292        /// Device supports capturing video data via [`Device::video_capture`][crate::Device::video_capture].
293        const VIDEO_CAPTURE        = 0x00000001;
294        /// Device supports outputting video data via [`Device::video_output`][crate::Device::video_output].
295        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        /// Device supports capturing metadata via [`Device::meta_capture`][crate::Device::meta_capture].
320        const META_CAPTURE         = 0x00800000;
321
322        /// Device supports the read/write based I/O method.
323        const READWRITE            = 0x01000000;
324        /// Device supports asynchronous I/O (this is apparently not yet defined or used though).
325        const ASYNCIO              = 0x02000000;
326        /// Device supports the buffer-based streaming I/O method.
327        const STREAMING            = 0x04000000;
328        const META_OUTPUT          = 0x08000000;
329
330        /// Device is a touch input device.
331        const TOUCH                = 0x10000000;
332        /// Device uses the Media Controller API for configuration.
333        const IO_MC                = 0x20000000;
334        /// Driver supports per-device capabilities.
335        const DEVICE_CAPS          = 0x80000000;
336    }
337}
338
339bitflags! {
340    /// Bitflags describing the current status of a device [`Input`][crate::Input].
341    pub struct InputStatus: u32 {
342        /// Input has no power and is turned off.
343        const NO_POWER   = 0x00000001;
344        /// Input is not receiving a video signal.
345        const NO_SIGNAL  = 0x00000002;
346        /// The input signal contains no color data.
347        const NO_COLOR   = 0x00000004;
348
349        /// The input produces a horizontally flipped image which needs to be corrected in
350        /// userspace.
351        const HFLIP      = 0x00000010;
352        /// The input produces a vertically flipped image which needs to be corrected in userspace.
353        const VFLIP      = 0x00000020;
354
355        /// Analog Input: Not locked to HSYNC.
356        const NO_H_LOCK   = 0x00000100;
357        /// Analog Input: The input's [Color Killer](https://en.wikipedia.org/wiki/Color_killer) circuit is
358        /// active.
359        const COLOR_KILL  = 0x00000200;
360        /// Analog Input: Not locked to VSYNC.
361        const NO_V_LOCK   = 0x00000400;
362        /// Analog Input: No analog standard lock (when using auto-detection of the format).
363        const NO_STD_LOCK = 0x00000800;
364
365        /// Digital Input: Not synced to video data.
366        const NO_SYNC     = 0x00010000;
367        /// Digital Input: No equalizer lock.
368        const NO_EQU      = 0x00020000;
369        /// Digital Input: No carrier recovered.
370        const NO_CARRIER  = 0x00040000;
371
372        /// VCR Input: Macrovision copy protection detected.
373        const MACROVISION = 0x01000000;
374        /// Access to the video stream was denied.
375        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/// A fractional value (`numerator / denominator`).
465#[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    /// Returns this fraction as an `f32`.
493    #[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        // degenerate case where one of the arguments is 0 - the other one will be returned
568        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}