├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples ├── capture.rs ├── channel.rs ├── complex.rs ├── control.rs ├── controls.rs └── formats.rs └── src ├── lib.rs └── v4l2.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | before_script: 5 | - rustup component add clippy 6 | - rustup component add rustfmt 7 | script: 8 | - cargo clippy --version 9 | - cargo clippy --all-targets --all-features -- -D warnings -D rust_2018_idioms 10 | - cargo fmt --version 11 | - cargo fmt -- --check 12 | - cargo build --all-targets --features no_wrapper 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rscam" 3 | version = "0.5.5" 4 | description = "Wrapper for v4l2." 5 | keywords = ["v4l2", "video", "camera", "capture"] 6 | authors = ["Paul Loyd "] 7 | repository = "https://github.com/loyd/rscam" 8 | documentation = "https://docs.rs/rscam" 9 | license = "MIT OR Apache-2.0" 10 | readme = "README.md" 11 | edition = "2018" 12 | 13 | [dependencies] 14 | libc = "0.2" 15 | thiserror = "1.0.9" 16 | 17 | [features] 18 | no_wrapper = [] 19 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 Paul Loyd 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Paul Loyd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rscam 2 | 3 | [![Build status](https://travis-ci.org/loyd/rscam.svg)](https://travis-ci.org/loyd/rscam) 4 | [![Crate info](https://img.shields.io/crates/v/rscam.svg)](https://crates.io/crates/rscam) 5 | [![Documentation](https://docs.rs/rscam/badge.svg)](https://docs.rs/rscam) 6 | 7 | ## This project is no longer maintained 8 | Consider to use [https://github.com/raymanfx/libv4l-rs](libv4l-rs) or something else. 9 | If you would be interested in taking over some of the maintenance of the project, please let me know. 10 | 11 | ## Overview 12 | 13 | Rust wrapper for v4l2. 14 | 15 | ```rust 16 | let mut camera = rscam::new("/dev/video0").unwrap(); 17 | 18 | camera.start(&rscam::Config { 19 | interval: (1, 30), // 30 fps. 20 | resolution: (1280, 720), 21 | format: b"MJPG", 22 | ..Default::default() 23 | }).unwrap(); 24 | 25 | for i in 0..10 { 26 | let frame = camera.capture().unwrap(); 27 | let mut file = fs::File::create(&format!("frame-{}.jpg", i)).unwrap(); 28 | file.write_all(&frame[..]).unwrap(); 29 | } 30 | ``` 31 | 32 | The wrapper uses v4l2 (e.g. `v4l2_ioctl()` instead of `ioctl()`) until feature `no_wrapper` is enabled. The feature can be useful when it's desirable to avoid dependence on *libv4l2* (for example, cross-compilation). 33 | 34 | ## License 35 | 36 | Licensed under either of 37 | 38 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 39 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 40 | 41 | at your option. 42 | 43 | ### Contribution 44 | 45 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. 46 | -------------------------------------------------------------------------------- /examples/capture.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut camera = rscam::new("/dev/video0").unwrap(); 3 | 4 | camera 5 | .start(&rscam::Config { 6 | interval: (1, 10), 7 | resolution: (1280, 720), 8 | format: b"YUYV", 9 | ..Default::default() 10 | }) 11 | .unwrap(); 12 | 13 | for i in 1.. { 14 | let frame = camera.capture().unwrap(); 15 | println!("Frame #{} of length {}", i, frame.len()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/channel.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc; 2 | use std::thread; 3 | 4 | use rscam::{Camera, Config}; 5 | 6 | fn main() { 7 | let (tx, rx) = mpsc::channel(); 8 | 9 | thread::spawn(move || { 10 | let mut camera = Camera::new("/dev/video0").unwrap(); 11 | 12 | camera 13 | .start(&Config { 14 | interval: (1, 10), 15 | resolution: (1280, 720), 16 | format: b"MJPG", 17 | ..Default::default() 18 | }) 19 | .unwrap(); 20 | 21 | for _ in 0..10 { 22 | let frame = camera.capture().unwrap(); 23 | tx.send(frame).unwrap(); 24 | } 25 | }); 26 | 27 | for i in 0..10 { 28 | let frame = rx.recv().unwrap(); 29 | println!("Frame #{} of length {}", i, frame.len()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/complex.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::io::Write; 3 | 4 | fn main() { 5 | let mut camera = rscam::new("/dev/video0").unwrap(); 6 | 7 | for wformat in camera.formats() { 8 | let format = wformat.unwrap(); 9 | println!("{:?}", format); 10 | println!(" {:?}", camera.resolutions(format.format).unwrap()); 11 | } 12 | 13 | camera 14 | .start(&rscam::Config { 15 | interval: (1, 10), 16 | resolution: (1280, 720), 17 | format: b"MJPG", 18 | ..Default::default() 19 | }) 20 | .unwrap(); 21 | 22 | for i in 0..10 { 23 | let frame = camera.capture().unwrap(); 24 | 25 | println!("Frame of length {}", frame.len()); 26 | 27 | let mut file = fs::File::create(&format!("frame-{}.jpg", i)).unwrap(); 28 | file.write_all(&frame[..]).unwrap(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/control.rs: -------------------------------------------------------------------------------- 1 | use rscam::CID_BRIGHTNESS; 2 | use rscam::{Camera, Control, CtrlData}; 3 | 4 | fn main() { 5 | let camera = Camera::new("/dev/video0").unwrap(); 6 | 7 | let get_brightness = || match camera.get_control(CID_BRIGHTNESS) { 8 | Ok(Control { 9 | data: CtrlData::Integer { value: b, .. }, 10 | .. 11 | }) => b, 12 | _ => panic!(), 13 | }; 14 | 15 | let old = get_brightness(); 16 | 17 | println!("Current value of brightness: {}", old); 18 | camera.set_control(CID_BRIGHTNESS, &5).unwrap(); 19 | println!("New value of brightness: {}", get_brightness()); 20 | 21 | camera.set_control(CID_BRIGHTNESS, &old).unwrap(); 22 | println!("Restoring old value: {}", get_brightness()); 23 | } 24 | -------------------------------------------------------------------------------- /examples/controls.rs: -------------------------------------------------------------------------------- 1 | use rscam::FLAG_DISABLED; 2 | use rscam::{Camera, CtrlData}; 3 | 4 | fn main() { 5 | let camera = Camera::new("/dev/video0").unwrap(); 6 | 7 | for wctrl in camera.controls() { 8 | let ctrl = wctrl.unwrap(); 9 | 10 | if let CtrlData::CtrlClass = ctrl.data { 11 | println!("\n[{}]\n", ctrl.name); 12 | continue; 13 | } 14 | 15 | print!("{:>32} ", ctrl.name); 16 | 17 | if ctrl.flags & FLAG_DISABLED != 0 { 18 | println!("(disabled)"); 19 | continue; 20 | } 21 | 22 | match ctrl.data { 23 | CtrlData::Integer { 24 | value, 25 | default, 26 | minimum, 27 | maximum, 28 | step, 29 | } => println!( 30 | "(int) min={} max={} step={} default={} value={}", 31 | minimum, maximum, step, default, value 32 | ), 33 | CtrlData::Boolean { value, default } => { 34 | println!("(bool) default={} value={}", default, value) 35 | } 36 | CtrlData::Menu { 37 | value, 38 | default, 39 | ref items, 40 | .. 41 | } => { 42 | println!("(menu) default={} value={}", default, value); 43 | for item in items { 44 | println!("{:42} {}: {}", "", item.index, item.name); 45 | } 46 | } 47 | CtrlData::IntegerMenu { 48 | value, 49 | default, 50 | ref items, 51 | .. 52 | } => { 53 | println!("(intmenu) default={} value={}", default, value); 54 | for item in items { 55 | println!( 56 | "{:42} {}: {} ({:#x})", 57 | "", item.index, item.value, item.value 58 | ); 59 | } 60 | } 61 | CtrlData::Bitmask { 62 | value, 63 | default, 64 | maximum, 65 | } => println!( 66 | "(bitmask) max={:x} default={:x} value={:x}", 67 | maximum, default, value 68 | ), 69 | CtrlData::Integer64 { 70 | value, 71 | default, 72 | minimum, 73 | maximum, 74 | step, 75 | } => println!( 76 | "(int64) min={} max={} step={} default={} value={}", 77 | minimum, maximum, step, default, value 78 | ), 79 | CtrlData::String { 80 | ref value, 81 | minimum, 82 | maximum, 83 | step, 84 | } => println!( 85 | "(str) min={} max={} step={} value={}", 86 | minimum, maximum, step, value 87 | ), 88 | CtrlData::Button => println!("(button)"), 89 | _ => {} 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /examples/formats.rs: -------------------------------------------------------------------------------- 1 | use rscam::{Camera, ResolutionInfo}; 2 | 3 | fn main() { 4 | let camera = Camera::new("/dev/video0").unwrap(); 5 | 6 | for wformat in camera.formats() { 7 | let format = wformat.unwrap(); 8 | println!("{:?}", format); 9 | 10 | let resolutions = camera.resolutions(format.format).unwrap(); 11 | 12 | if let ResolutionInfo::Discretes(d) = resolutions { 13 | for resol in &d { 14 | println!( 15 | " {}x{} {:?}", 16 | resol.0, 17 | resol.1, 18 | camera.intervals(format.format, *resol).unwrap() 19 | ); 20 | } 21 | } else { 22 | println!(" {:?}", resolutions); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Fast wrapper for v4l2. 2 | //! 3 | //! ```no_run 4 | //! # use std::fs; 5 | //! # use std::io::Write; 6 | //! use rscam::{Camera, Config}; 7 | //! 8 | //! let mut camera = Camera::new("/dev/video0").unwrap(); 9 | //! 10 | //! camera.start(&Config { 11 | //! interval: (1, 30), // 30 fps. 12 | //! resolution: (1280, 720), 13 | //! format: b"MJPG", 14 | //! ..Default::default() 15 | //! }).unwrap(); 16 | //! 17 | //! for i in 0..10 { 18 | //! let frame = camera.capture().unwrap(); 19 | //! let mut file = fs::File::create(&format!("frame-{}.jpg", i)).unwrap(); 20 | //! file.write_all(&frame[..]).unwrap(); 21 | //! } 22 | //! ``` 23 | //! 24 | //! The wrapper uses v4l2 (e.g. `v4l2_ioctl()` instead of `ioctl()`) until feature `no_wrapper` is 25 | //! enabled. The feature can be useful when it's desirable to avoid dependence on *libv4l2*. 26 | 27 | #[cfg(not(any(target_os = "linux", target_os = "freebsd")))] 28 | compile_error!("rscam (v4l2) is for linux/freebsd only"); 29 | 30 | use std::convert::From; 31 | use std::fmt; 32 | use std::io; 33 | use std::ops::Deref; 34 | use std::os::unix::io::RawFd; 35 | use std::result; 36 | use std::slice; 37 | use std::str; 38 | use std::sync::Arc; 39 | 40 | pub use self::consts::*; 41 | pub use self::v4l2::pubconsts as consts; 42 | use self::v4l2::MappedRegion; 43 | 44 | mod v4l2; 45 | 46 | pub type Result = result::Result; 47 | 48 | #[derive(Debug, thiserror::Error)] 49 | pub enum Error { 50 | #[error("I/O error: {0}")] 51 | Io(#[from] io::Error), 52 | #[error("invalid or unsupported frame interval")] 53 | BadInterval, 54 | #[error("invalid or unsupported resolution (width and/or height)")] 55 | BadResolution, 56 | #[error("invalid or unsupported format of pixels")] 57 | BadFormat, 58 | #[error("invalid or unsupported field")] 59 | BadField, 60 | } 61 | 62 | pub struct Config<'a> { 63 | /// The mix of numerator and denominator. v4l2 uses frame intervals instead of frame rates. 64 | /// Default is `(1, 10)`. 65 | pub interval: (u32, u32), 66 | /// Width and height of frame. 67 | /// Default is `(640, 480)`. 68 | pub resolution: (u32, u32), 69 | /// FourCC of format (e.g. `b"RGB3"`). Note that case matters. 70 | /// Default is `b"YUYV"`. 71 | pub format: &'a [u8; 4], 72 | /// Storage method of interlaced video. See `FIELD_*` constants. 73 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/field-order.html#v4l2-field). 74 | /// Default is `FIELD_NONE` (progressive). 75 | pub field: u32, 76 | /// Number of buffers in the queue of camera. 77 | /// Default is `2`. 78 | pub nbuffers: u32, 79 | } 80 | 81 | impl<'a> Default for Config<'a> { 82 | fn default() -> Config<'a> { 83 | Config { 84 | interval: (1, 10), 85 | resolution: (640, 480), 86 | format: b"YUYV", 87 | field: FIELD_NONE, 88 | nbuffers: 2, 89 | } 90 | } 91 | } 92 | 93 | pub struct FormatInfo { 94 | /// FourCC of format (e.g. `b"H264"`). 95 | pub format: [u8; 4], 96 | /// Information about the format. 97 | pub description: String, 98 | /// Raw or compressed. 99 | pub compressed: bool, 100 | /// Whether it's transcoded from a different input format. 101 | pub emulated: bool, 102 | } 103 | 104 | impl FormatInfo { 105 | fn new(fourcc: u32, desc: &[u8], flags: u32) -> FormatInfo { 106 | FormatInfo { 107 | format: [ 108 | (fourcc & 0xff) as u8, 109 | (fourcc >> 8 & 0xff) as u8, 110 | (fourcc >> 16 & 0xff) as u8, 111 | (fourcc >> 24 & 0xff) as u8, 112 | ], 113 | description: buffer_to_string(desc), 114 | compressed: flags & v4l2::FMT_FLAG_COMPRESSED != 0, 115 | emulated: flags & v4l2::FMT_FLAG_EMULATED != 0, 116 | } 117 | } 118 | 119 | fn fourcc(fmt: [u8; 4]) -> u32 { 120 | u32::from(fmt[0]) 121 | | (u32::from(fmt[1])) << 8 122 | | (u32::from(fmt[2])) << 16 123 | | (u32::from(fmt[3])) << 24 124 | } 125 | } 126 | 127 | impl fmt::Debug for FormatInfo { 128 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 129 | let format = str::from_utf8(self.format.as_ref()).unwrap(); 130 | 131 | let flags = match (self.compressed, self.emulated) { 132 | (true, true) => ", compressed, emulated", 133 | (true, false) => ", compressed", 134 | (false, true) => ", emulated", 135 | _ => "", 136 | }; 137 | 138 | write!(f, "{} ({}{})", format, self.description, flags) 139 | } 140 | } 141 | 142 | pub enum ResolutionInfo { 143 | Discretes(Vec<(u32, u32)>), 144 | Stepwise { 145 | min: (u32, u32), 146 | max: (u32, u32), 147 | step: (u32, u32), 148 | }, 149 | } 150 | 151 | impl fmt::Debug for ResolutionInfo { 152 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 153 | match *self { 154 | ResolutionInfo::Discretes(ref d) => { 155 | write!(f, "Discretes: {}x{}", d[0].0, d[0].1)?; 156 | 157 | for res in (&d[1..]).iter() { 158 | write!(f, ", {}x{}", res.0, res.1)?; 159 | } 160 | 161 | Ok(()) 162 | } 163 | ResolutionInfo::Stepwise { min, max, step } => write!( 164 | f, 165 | "Stepwise from {}x{} to {}x{} by {}x{}", 166 | min.0, min.1, max.0, max.1, step.0, step.1 167 | ), 168 | } 169 | } 170 | } 171 | 172 | pub enum IntervalInfo { 173 | Discretes(Vec<(u32, u32)>), 174 | Stepwise { 175 | min: (u32, u32), 176 | max: (u32, u32), 177 | step: (u32, u32), 178 | }, 179 | } 180 | 181 | impl fmt::Debug for IntervalInfo { 182 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 183 | match *self { 184 | IntervalInfo::Discretes(ref d) => { 185 | write!(f, "Discretes: {}fps", d[0].1 / d[0].0)?; 186 | 187 | for res in (&d[1..]).iter() { 188 | write!(f, ", {}fps", res.1 / res.0)?; 189 | } 190 | 191 | Ok(()) 192 | } 193 | IntervalInfo::Stepwise { min, max, step } => write!( 194 | f, 195 | "Stepwise from {}fps to {}fps by {}fps", 196 | max.1 / max.0, 197 | min.1 / min.0, 198 | step.1 / step.0 199 | ), 200 | } 201 | } 202 | } 203 | 204 | pub struct Frame { 205 | /// Width and height of the frame. 206 | pub resolution: (u32, u32), 207 | /// FourCC of the format. 208 | pub format: [u8; 4], 209 | 210 | region: Arc, 211 | length: u32, 212 | fd: RawFd, 213 | buffer: v4l2::Buffer, 214 | } 215 | 216 | impl Frame { 217 | /// Return frame timestamp in microseconds using monotonically 218 | /// nondecreasing clock 219 | pub fn get_timestamp(&self) -> u64 { 220 | let t = self.buffer.timestamp; 221 | 1_000_000 * (t.tv_sec as u64) + (t.tv_usec as u64) 222 | } 223 | } 224 | 225 | impl Deref for Frame { 226 | type Target = [u8]; 227 | 228 | fn deref(&self) -> &[u8] { 229 | unsafe { slice::from_raw_parts(self.region.ptr, self.length as usize) } 230 | } 231 | } 232 | 233 | impl Drop for Frame { 234 | fn drop(&mut self) { 235 | let _ = v4l2::xioctl(self.fd, v4l2::VIDIOC_QBUF, &mut self.buffer); 236 | } 237 | } 238 | 239 | #[derive(Debug, PartialEq)] 240 | enum State { 241 | Idle, 242 | Streaming, 243 | Aborted, 244 | } 245 | 246 | pub struct Camera { 247 | fd: RawFd, 248 | state: State, 249 | resolution: (u32, u32), 250 | format: [u8; 4], 251 | buffers: Vec>, 252 | } 253 | 254 | impl Camera { 255 | pub fn new(device: &str) -> io::Result { 256 | Ok(Camera { 257 | fd: v4l2::open(device)?, 258 | state: State::Idle, 259 | resolution: (0, 0), 260 | format: [0; 4], 261 | buffers: vec![], 262 | }) 263 | } 264 | 265 | /// Get detailed info about the available formats. 266 | pub fn formats(&self) -> FormatIter<'_> { 267 | FormatIter { 268 | camera: self, 269 | index: 0, 270 | } 271 | } 272 | 273 | /// Get detailed info about the available resolutions. 274 | pub fn resolutions(&self, format: [u8; 4]) -> Result { 275 | let fourcc = FormatInfo::fourcc(format); 276 | let mut size = v4l2::Frmsizeenum::new(fourcc); 277 | 278 | v4l2::xioctl_valid(self.fd, v4l2::VIDIOC_ENUM_FRAMESIZES, &mut size)?; 279 | 280 | if fourcc != size.pixelformat { 281 | return Err(Error::BadFormat); 282 | } 283 | 284 | if size.ftype == v4l2::FRMSIZE_TYPE_DISCRETE { 285 | let mut discretes = vec![(size.discrete().width, size.discrete().height)]; 286 | size.index = 1; 287 | 288 | while v4l2::xioctl_valid(self.fd, v4l2::VIDIOC_ENUM_FRAMESIZES, &mut size)? { 289 | { 290 | let discrete = size.discrete(); 291 | discretes.push((discrete.width, discrete.height)); 292 | } 293 | size.index += 1; 294 | } 295 | 296 | Ok(ResolutionInfo::Discretes(discretes)) 297 | } else { 298 | let sw = size.stepwise(); 299 | 300 | Ok(ResolutionInfo::Stepwise { 301 | min: (sw.min_width, sw.min_height), 302 | max: (sw.max_width, sw.max_height), 303 | step: (sw.step_width, sw.step_height), 304 | }) 305 | } 306 | } 307 | 308 | /// Get detailed info about the available intervals. 309 | pub fn intervals(&self, format: [u8; 4], resolution: (u32, u32)) -> Result { 310 | let fourcc = FormatInfo::fourcc(format); 311 | let mut ival = v4l2::Frmivalenum::new(fourcc, resolution); 312 | 313 | v4l2::xioctl_valid(self.fd, v4l2::VIDIOC_ENUM_FRAMEINTERVALS, &mut ival)?; 314 | 315 | if fourcc != ival.pixelformat { 316 | return Err(Error::BadFormat); 317 | } 318 | 319 | if resolution != (ival.width, ival.height) { 320 | return Err(Error::BadResolution); 321 | } 322 | 323 | if ival.ftype == v4l2::FRMIVAL_TYPE_DISCRETE { 324 | let mut discretes = vec![(ival.discrete().numerator, ival.discrete().denominator)]; 325 | ival.index = 1; 326 | 327 | while v4l2::xioctl_valid(self.fd, v4l2::VIDIOC_ENUM_FRAMEINTERVALS, &mut ival)? { 328 | { 329 | let discrete = ival.discrete(); 330 | discretes.push((discrete.numerator, discrete.denominator)); 331 | } 332 | ival.index += 1; 333 | } 334 | 335 | Ok(IntervalInfo::Discretes(discretes)) 336 | } else { 337 | let sw = ival.stepwise(); 338 | 339 | Ok(IntervalInfo::Stepwise { 340 | min: (sw.min.numerator, sw.min.denominator), 341 | max: (sw.max.numerator, sw.max.denominator), 342 | step: (sw.step.numerator, sw.step.denominator), 343 | }) 344 | } 345 | } 346 | 347 | /// Get info about all controls. 348 | pub fn controls(&self) -> ControlIter<'_> { 349 | ControlIter { 350 | camera: self, 351 | id: 0, 352 | class: 0, 353 | } 354 | } 355 | 356 | /// Get info about available controls by class (see `CLASS_*` constants). 357 | pub fn controls_by_class(&self, class: u32) -> ControlIter<'_> { 358 | ControlIter { 359 | camera: self, 360 | id: class as u32, 361 | class, 362 | } 363 | } 364 | 365 | /// Get info about the control by id. 366 | pub fn get_control(&self, id: u32) -> io::Result { 367 | let mut qctrl = v4l2::QueryCtrl::new(id); 368 | v4l2::xioctl(self.fd, v4l2::VIDIOC_QUERYCTRL, &mut qctrl)?; 369 | 370 | let data = match qctrl.qtype { 371 | v4l2::CTRL_TYPE_INTEGER => CtrlData::Integer { 372 | value: self.get_control_value(qctrl.id)?, 373 | default: qctrl.default_value, 374 | minimum: qctrl.minimum, 375 | maximum: qctrl.maximum, 376 | step: qctrl.step, 377 | }, 378 | v4l2::CTRL_TYPE_BOOLEAN => CtrlData::Boolean { 379 | value: self.get_control_value(qctrl.id)? != 0, 380 | default: qctrl.default_value != 0, 381 | }, 382 | v4l2::CTRL_TYPE_MENU => CtrlData::Menu { 383 | value: self.get_control_value(qctrl.id)? as u32, 384 | default: qctrl.default_value as u32, 385 | items: self.get_menu_items(qctrl.id, qctrl.minimum as u32, qctrl.maximum as u32)?, 386 | }, 387 | v4l2::CTRL_TYPE_BUTTON => CtrlData::Button, 388 | v4l2::CTRL_TYPE_INTEGER64 => { 389 | let mut qectrl = v4l2::QueryExtCtrl::new(qctrl.id); 390 | 391 | v4l2::xioctl(self.fd, v4l2::VIDIOC_QUERY_EXT_CTRL, &mut qectrl)?; 392 | 393 | CtrlData::Integer64 { 394 | value: self.get_ext_control_value(qctrl.id)?, 395 | default: qectrl.default_value, 396 | minimum: qectrl.minimum, 397 | maximum: qectrl.maximum, 398 | step: qectrl.step as i64, 399 | } 400 | } 401 | v4l2::CTRL_TYPE_CTRL_CLASS => CtrlData::CtrlClass, 402 | v4l2::CTRL_TYPE_STRING => CtrlData::String { 403 | value: self.get_string_control(qctrl.id, qctrl.maximum as u32)?, 404 | minimum: qctrl.minimum as u32, 405 | maximum: qctrl.maximum as u32, 406 | step: qctrl.step as u32, 407 | }, 408 | v4l2::CTRL_TYPE_BITMASK => CtrlData::Bitmask { 409 | value: self.get_control_value(qctrl.id)? as u32, 410 | default: qctrl.default_value as u32, 411 | maximum: qctrl.maximum as u32, 412 | }, 413 | v4l2::CTRL_TYPE_INTEGER_MENU => CtrlData::IntegerMenu { 414 | value: self.get_control_value(qctrl.id)? as u32, 415 | default: qctrl.default_value as u32, 416 | items: self.get_int_menu_items( 417 | qctrl.id, 418 | qctrl.minimum as u32, 419 | qctrl.maximum as u32, 420 | )?, 421 | }, 422 | _ => CtrlData::Unknown, 423 | }; 424 | 425 | Ok(Control { 426 | id: qctrl.id, 427 | name: buffer_to_string(&qctrl.name), 428 | data, 429 | flags: qctrl.flags, 430 | }) 431 | } 432 | 433 | fn get_control_value(&self, id: u32) -> io::Result { 434 | let mut ctrl = v4l2::Control::new(id); 435 | v4l2::xioctl(self.fd, v4l2::VIDIOC_G_CTRL, &mut ctrl)?; 436 | Ok(ctrl.value) 437 | } 438 | 439 | fn get_ext_control_value(&self, id: u32) -> io::Result { 440 | let mut ctrl = v4l2::ExtControl::new(id, 0); 441 | { 442 | let mut ctrls = v4l2::ExtControls::new(id & v4l2::ID2CLASS, &mut ctrl); 443 | v4l2::xioctl(self.fd, v4l2::VIDIOC_G_EXT_CTRLS, &mut ctrls)?; 444 | } 445 | Ok(ctrl.value) 446 | } 447 | 448 | fn get_menu_items(&self, id: u32, min: u32, max: u32) -> io::Result> { 449 | let mut items = vec![]; 450 | let mut qmenu = v4l2::QueryMenu::new(id); 451 | 452 | for index in min..=max { 453 | qmenu.index = index as u32; 454 | 455 | if v4l2::xioctl_valid(self.fd, v4l2::VIDIOC_QUERYMENU, &mut qmenu)? { 456 | items.push(CtrlMenuItem { 457 | index, 458 | name: buffer_to_string(qmenu.data.name()), 459 | }); 460 | } 461 | } 462 | 463 | Ok(items) 464 | } 465 | 466 | fn get_int_menu_items(&self, id: u32, min: u32, max: u32) -> io::Result> { 467 | let mut items = vec![]; 468 | let mut qmenu = v4l2::QueryMenu::new(id); 469 | 470 | for index in min..=max { 471 | qmenu.index = index as u32; 472 | 473 | if v4l2::xioctl_valid(self.fd, v4l2::VIDIOC_QUERYMENU, &mut qmenu)? { 474 | items.push(CtrlIntMenuItem { 475 | index, 476 | value: qmenu.data.value(), 477 | }); 478 | } 479 | } 480 | 481 | Ok(items) 482 | } 483 | 484 | fn get_string_control(&self, id: u32, size: u32) -> io::Result { 485 | let mut buffer = Vec::with_capacity(size as usize + 1); 486 | let mut ctrl = v4l2::ExtControl::new(id, size + 1); 487 | ctrl.value = buffer.as_mut_ptr() as i64; 488 | let mut ctrls = v4l2::ExtControls::new(id & v4l2::ID2CLASS, &mut ctrl); 489 | v4l2::xioctl(self.fd, v4l2::VIDIOC_G_EXT_CTRLS, &mut ctrls)?; 490 | unsafe { buffer.set_len(size as usize + 1) }; 491 | Ok(buffer_to_string(&buffer[..])) 492 | } 493 | 494 | /// Set value of the control. 495 | pub fn set_control(&self, id: u32, value: &T) -> io::Result<()> { 496 | let mut ctrl = v4l2::ExtControl::new(id, 0); 497 | ctrl.value = value.unify(); 498 | let mut ctrls = v4l2::ExtControls::new(id & v4l2::ID2CLASS, &mut ctrl); 499 | v4l2::xioctl(self.fd, v4l2::VIDIOC_S_EXT_CTRLS, &mut ctrls)?; 500 | Ok(()) 501 | } 502 | 503 | /// Start streaming. 504 | /// 505 | /// # Panics 506 | /// If recalled or called after `stop()`. 507 | pub fn start(&mut self, config: &Config<'_>) -> Result<()> { 508 | assert_eq!(self.state, State::Idle); 509 | 510 | self.tune_format(config.resolution, *config.format, config.field)?; 511 | self.tune_stream(config.interval)?; 512 | self.alloc_buffers(config.nbuffers)?; 513 | 514 | if let Err(err) = self.streamon() { 515 | self.free_buffers(); 516 | return Err(Error::Io(err)); 517 | } 518 | 519 | self.resolution = config.resolution; 520 | self.format = [ 521 | config.format[0], 522 | config.format[1], 523 | config.format[2], 524 | config.format[3], 525 | ]; 526 | 527 | self.state = State::Streaming; 528 | 529 | Ok(()) 530 | } 531 | 532 | /// Blocking request of frame. 533 | /// It dequeues buffer from a driver, which will be enqueueed after destructing `Frame`. 534 | /// 535 | /// # Panics 536 | /// If called w/o streaming. 537 | pub fn capture(&self) -> io::Result { 538 | assert_eq!(self.state, State::Streaming); 539 | 540 | let mut buf = v4l2::Buffer::new(); 541 | 542 | v4l2::xioctl(self.fd, v4l2::VIDIOC_DQBUF, &mut buf)?; 543 | assert!(buf.index < self.buffers.len() as u32); 544 | 545 | Ok(Frame { 546 | resolution: self.resolution, 547 | format: self.format, 548 | region: self.buffers[buf.index as usize].clone(), 549 | length: buf.bytesused, 550 | fd: self.fd, 551 | buffer: buf, 552 | }) 553 | } 554 | 555 | /// Stop streaming. Otherwise it's called after destructing `Camera`. 556 | /// 557 | /// # Panics 558 | /// If called w/o streaming. 559 | pub fn stop(&mut self) -> io::Result<()> { 560 | assert_eq!(self.state, State::Streaming); 561 | 562 | self.streamoff()?; 563 | self.free_buffers(); 564 | 565 | self.state = State::Aborted; 566 | 567 | Ok(()) 568 | } 569 | 570 | fn tune_format(&self, resolution: (u32, u32), format: [u8; 4], field: u32) -> Result<()> { 571 | let fourcc = FormatInfo::fourcc(format); 572 | let mut fmt = v4l2::Format::new(resolution, fourcc, field as u32); 573 | 574 | v4l2::xioctl(self.fd, v4l2::VIDIOC_S_FMT, &mut fmt)?; 575 | 576 | if resolution != (fmt.fmt.width, fmt.fmt.height) { 577 | return Err(Error::BadResolution); 578 | } 579 | 580 | if fourcc != fmt.fmt.pixelformat { 581 | return Err(Error::BadFormat); 582 | } 583 | 584 | if field as u32 != fmt.fmt.field { 585 | return Err(Error::BadField); 586 | } 587 | 588 | Ok(()) 589 | } 590 | 591 | fn tune_stream(&self, interval: (u32, u32)) -> Result<()> { 592 | let mut parm = v4l2::StreamParm::new(interval); 593 | 594 | v4l2::xioctl(self.fd, v4l2::VIDIOC_S_PARM, &mut parm)?; 595 | let time = parm.parm.timeperframe; 596 | 597 | match (time.numerator * interval.1, time.denominator * interval.0) { 598 | (0, _) | (_, 0) => Err(Error::BadInterval), 599 | (x, y) if x != y => Err(Error::BadInterval), 600 | _ => Ok(()), 601 | } 602 | } 603 | 604 | fn alloc_buffers(&mut self, nbuffers: u32) -> Result<()> { 605 | let mut req = v4l2::RequestBuffers::new(nbuffers); 606 | 607 | v4l2::xioctl(self.fd, v4l2::VIDIOC_REQBUFS, &mut req)?; 608 | 609 | for i in 0..nbuffers { 610 | let mut buf = v4l2::Buffer::new(); 611 | buf.index = i; 612 | v4l2::xioctl(self.fd, v4l2::VIDIOC_QUERYBUF, &mut buf)?; 613 | 614 | let region = v4l2::mmap(buf.length as usize, self.fd, buf.m)?; 615 | self.buffers.push(Arc::new(region)); 616 | } 617 | 618 | Ok(()) 619 | } 620 | 621 | fn free_buffers(&mut self) { 622 | self.buffers.clear(); 623 | } 624 | 625 | fn streamon(&self) -> io::Result<()> { 626 | for i in 0..self.buffers.len() { 627 | let mut buf = v4l2::Buffer::new(); 628 | buf.index = i as u32; 629 | 630 | v4l2::xioctl(self.fd, v4l2::VIDIOC_QBUF, &mut buf)?; 631 | } 632 | 633 | let mut typ = v4l2::BUF_TYPE_VIDEO_CAPTURE; 634 | v4l2::xioctl(self.fd, v4l2::VIDIOC_STREAMON, &mut typ)?; 635 | 636 | Ok(()) 637 | } 638 | 639 | fn streamoff(&mut self) -> io::Result<()> { 640 | let mut typ = v4l2::BUF_TYPE_VIDEO_CAPTURE; 641 | v4l2::xioctl(self.fd, v4l2::VIDIOC_STREAMOFF, &mut typ)?; 642 | 643 | Ok(()) 644 | } 645 | } 646 | 647 | impl Drop for Camera { 648 | fn drop(&mut self) { 649 | if self.state == State::Streaming { 650 | let _ = self.stop(); 651 | } 652 | 653 | let _ = v4l2::close(self.fd); 654 | } 655 | } 656 | 657 | pub struct FormatIter<'a> { 658 | camera: &'a Camera, 659 | index: u32, 660 | } 661 | 662 | impl<'a> Iterator for FormatIter<'a> { 663 | type Item = io::Result; 664 | 665 | fn next(&mut self) -> Option> { 666 | let mut fmt = v4l2::FmtDesc::new(); 667 | fmt.index = self.index; 668 | 669 | match v4l2::xioctl_valid(self.camera.fd, v4l2::VIDIOC_ENUM_FMT, &mut fmt) { 670 | Ok(true) => { 671 | self.index += 1; 672 | Some(Ok(FormatInfo::new( 673 | fmt.pixelformat, 674 | &fmt.description, 675 | fmt.flags, 676 | ))) 677 | } 678 | Ok(false) => None, 679 | Err(err) => Some(Err(err)), 680 | } 681 | } 682 | } 683 | 684 | pub struct ControlIter<'a> { 685 | camera: &'a Camera, 686 | id: u32, 687 | class: u32, 688 | } 689 | 690 | impl<'a> Iterator for ControlIter<'a> { 691 | type Item = io::Result; 692 | 693 | fn next(&mut self) -> Option> { 694 | match self.camera.get_control(self.id | v4l2::NEXT_CTRL) { 695 | Ok(ref ctrl) if self.class > 0 && ctrl.id & v4l2::ID2CLASS != self.class as u32 => None, 696 | Err(ref err) if err.kind() == io::ErrorKind::InvalidInput => None, 697 | Ok(ctrl) => { 698 | self.id = ctrl.id; 699 | Some(Ok(ctrl)) 700 | } 701 | err @ Err(_) => Some(err), 702 | } 703 | } 704 | } 705 | 706 | pub trait Settable { 707 | fn unify(&self) -> i64; 708 | } 709 | 710 | impl Settable for i64 { 711 | fn unify(&self) -> i64 { 712 | *self 713 | } 714 | } 715 | 716 | impl Settable for i32 { 717 | fn unify(&self) -> i64 { 718 | i64::from(*self) 719 | } 720 | } 721 | 722 | impl Settable for u32 { 723 | fn unify(&self) -> i64 { 724 | i64::from(*self) 725 | } 726 | } 727 | 728 | impl Settable for bool { 729 | fn unify(&self) -> i64 { 730 | *self as i64 731 | } 732 | } 733 | 734 | impl<'a> Settable for &'a str { 735 | fn unify(&self) -> i64 { 736 | self.as_ptr() as i64 737 | } 738 | } 739 | 740 | impl Settable for String { 741 | fn unify(&self) -> i64 { 742 | self.as_ptr() as i64 743 | } 744 | } 745 | 746 | #[derive(Debug, Clone)] 747 | pub struct Control { 748 | pub id: u32, 749 | pub name: String, 750 | pub data: CtrlData, 751 | /// See `FLAG_*` constants for details. 752 | pub flags: u32, 753 | } 754 | 755 | #[derive(Debug, Clone)] 756 | pub enum CtrlData { 757 | Integer { 758 | value: i32, 759 | default: i32, 760 | minimum: i32, 761 | maximum: i32, 762 | step: i32, 763 | }, 764 | Boolean { 765 | value: bool, 766 | default: bool, 767 | }, 768 | Menu { 769 | value: u32, 770 | default: u32, 771 | items: Vec, 772 | }, 773 | Button, 774 | Integer64 { 775 | value: i64, 776 | default: i64, 777 | minimum: i64, 778 | maximum: i64, 779 | step: i64, 780 | }, 781 | CtrlClass, 782 | String { 783 | value: String, 784 | minimum: u32, 785 | maximum: u32, 786 | step: u32, 787 | }, 788 | Bitmask { 789 | value: u32, 790 | default: u32, 791 | maximum: u32, 792 | }, 793 | IntegerMenu { 794 | value: u32, 795 | default: u32, 796 | items: Vec, 797 | }, 798 | Unknown, 799 | } 800 | 801 | #[derive(Debug, Clone)] 802 | pub struct CtrlMenuItem { 803 | pub index: u32, 804 | pub name: String, 805 | } 806 | 807 | #[derive(Debug, Clone)] 808 | pub struct CtrlIntMenuItem { 809 | pub index: u32, 810 | pub value: i64, 811 | } 812 | 813 | fn buffer_to_string(buf: &[u8]) -> String { 814 | // Instead of unstable `position_elem()`. 815 | String::from_utf8_lossy(match buf.iter().position(|&c| c == 0) { 816 | Some(x) => &buf[..x], 817 | None => buf, 818 | }) 819 | .into_owned() 820 | } 821 | 822 | /// Alias for `Camera::new()`. 823 | pub fn new(device: &str) -> io::Result { 824 | Camera::new(device) 825 | } 826 | -------------------------------------------------------------------------------- /src/v4l2.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::unreadable_literal)] 2 | 3 | use std::ffi::CString; 4 | use std::os::unix::io::RawFd; 5 | use std::ptr::null_mut; 6 | use std::{io, mem, usize}; 7 | 8 | // C types and constants. 9 | use libc::timeval as Timeval; 10 | use libc::{c_ulong, c_void, off_t, size_t}; 11 | use libc::{MAP_SHARED, O_RDWR, PROT_READ, PROT_WRITE}; 12 | 13 | #[cfg(not(feature = "no_wrapper"))] 14 | mod ll { 15 | use libc::{c_char, c_int, c_ulong, c_void, off_t, size_t}; 16 | use std::os::unix::io::RawFd; 17 | 18 | pub use self::v4l2_close as close; 19 | pub use self::v4l2_ioctl as ioctl; 20 | pub use self::v4l2_mmap as mmap; 21 | pub use self::v4l2_munmap as munmap; 22 | pub use self::v4l2_open as open; 23 | 24 | #[link(name = "v4l2")] 25 | extern "C" { 26 | pub fn v4l2_open(file: *const c_char, flags: c_int, arg: c_int) -> RawFd; 27 | pub fn v4l2_close(fd: RawFd) -> c_int; 28 | pub fn v4l2_ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -> c_int; 29 | pub fn v4l2_mmap( 30 | start: *mut c_void, 31 | length: size_t, 32 | prot: c_int, 33 | flags: c_int, 34 | fd: RawFd, 35 | offset: off_t, 36 | ) -> *mut c_void; 37 | pub fn v4l2_munmap(start: *mut c_void, length: size_t) -> c_int; 38 | } 39 | } 40 | 41 | #[cfg(feature = "no_wrapper")] 42 | mod ll { 43 | use libc::{c_int, c_ulong, c_void}; 44 | use std::os::unix::io::RawFd; 45 | 46 | pub use libc::{close, mmap, munmap, open}; 47 | 48 | extern "C" { 49 | pub fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -> c_int; 50 | } 51 | } 52 | 53 | macro_rules! check_io( 54 | ($cond:expr) => 55 | (if $cond { Ok(()) } else { Err(io::Error::last_os_error()) }?) 56 | ); 57 | 58 | pub fn open(file: &str) -> io::Result { 59 | let c_str = CString::new(file)?; 60 | let fd = unsafe { ll::open(c_str.as_ptr(), O_RDWR, 0) }; 61 | check_io!(fd != -1); 62 | Ok(fd) 63 | } 64 | 65 | pub fn close(fd: RawFd) -> io::Result<()> { 66 | check_io!(unsafe { ll::close(fd) != -1 }); 67 | Ok(()) 68 | } 69 | 70 | pub fn xioctl(fd: RawFd, request: usize, arg: &mut T) -> io::Result<()> { 71 | let argp: *mut T = arg; 72 | 73 | check_io!(unsafe { 74 | let mut ok; 75 | 76 | loop { 77 | ok = ll::ioctl(fd, request as c_ulong, argp as *mut c_void) != -1; 78 | if ok || io::Error::last_os_error().kind() != io::ErrorKind::Interrupted { 79 | break; 80 | } 81 | } 82 | 83 | ok 84 | }); 85 | 86 | Ok(()) 87 | } 88 | 89 | pub fn xioctl_valid(fd: RawFd, request: usize, arg: &mut T) -> io::Result { 90 | match xioctl(fd, request, arg) { 91 | Ok(_) => Ok(true), 92 | Err(ref err) if err.kind() == io::ErrorKind::InvalidInput => Ok(false), 93 | Err(err) => Err(err), 94 | } 95 | } 96 | 97 | pub struct MappedRegion { 98 | pub ptr: *mut u8, 99 | pub len: usize, 100 | } 101 | 102 | // Instead of unstable `Unique`. 103 | unsafe impl Send for MappedRegion {} 104 | unsafe impl Sync for MappedRegion {} 105 | 106 | impl Drop for MappedRegion { 107 | fn drop(&mut self) { 108 | unsafe { 109 | ll::munmap(self.ptr as *mut c_void, self.len as size_t); 110 | } 111 | } 112 | } 113 | 114 | pub fn mmap(length: usize, fd: RawFd, offset: usize) -> io::Result { 115 | let ptr = unsafe { 116 | ll::mmap( 117 | null_mut(), 118 | length as size_t, 119 | PROT_READ | PROT_WRITE, 120 | MAP_SHARED, 121 | fd, 122 | offset as off_t, 123 | ) 124 | }; 125 | 126 | check_io!(ptr as usize != usize::MAX); 127 | Ok(MappedRegion { 128 | ptr: ptr as *mut u8, 129 | len: length, 130 | }) 131 | } 132 | 133 | #[repr(C)] 134 | pub struct Format { 135 | pub ftype: u32, 136 | #[cfg(target_pointer_width = "64")] 137 | padding: u32, 138 | pub fmt: PixFormat, 139 | space: [u8; 156], 140 | } 141 | 142 | impl Format { 143 | #[cfg(target_pointer_width = "64")] 144 | pub fn new(resolution: (u32, u32), fourcc: u32, field: u32) -> Format { 145 | Format { 146 | ftype: BUF_TYPE_VIDEO_CAPTURE, 147 | padding: 0, 148 | fmt: PixFormat::new(resolution, fourcc, field), 149 | space: [0; 156], 150 | } 151 | } 152 | 153 | #[cfg(target_pointer_width = "32")] 154 | pub fn new(resolution: (u32, u32), fourcc: u32, field: u32) -> Format { 155 | Format { 156 | ftype: BUF_TYPE_VIDEO_CAPTURE, 157 | fmt: PixFormat::new(resolution, fourcc, field), 158 | space: [0; 156], 159 | } 160 | } 161 | } 162 | 163 | #[repr(C)] 164 | pub struct PixFormat { 165 | pub width: u32, 166 | pub height: u32, 167 | pub pixelformat: u32, 168 | pub field: u32, 169 | pub bytesperline: u32, 170 | pub sizeimage: u32, 171 | pub colorspace: u32, 172 | pub private: u32, 173 | pub flags: u32, 174 | pub ycbcr_enc: u32, 175 | pub quantization: u32, 176 | } 177 | 178 | impl PixFormat { 179 | pub fn new(resolution: (u32, u32), fourcc: u32, field: u32) -> PixFormat { 180 | let mut pix_fmt: PixFormat = unsafe { mem::zeroed() }; 181 | pix_fmt.width = resolution.0; 182 | pix_fmt.height = resolution.1; 183 | pix_fmt.pixelformat = fourcc; 184 | pix_fmt.field = field; 185 | pix_fmt 186 | } 187 | } 188 | 189 | #[repr(C)] 190 | pub struct RequestBuffers { 191 | pub count: u32, 192 | pub btype: u32, 193 | pub memory: u32, 194 | reserved: [u32; 2], 195 | } 196 | 197 | impl RequestBuffers { 198 | pub fn new(nbuffers: u32) -> RequestBuffers { 199 | RequestBuffers { 200 | count: nbuffers, 201 | btype: BUF_TYPE_VIDEO_CAPTURE, 202 | memory: MEMORY_MMAP, 203 | reserved: [0; 2], 204 | } 205 | } 206 | } 207 | 208 | #[repr(C)] 209 | pub struct Buffer { 210 | pub index: u32, 211 | pub btype: u32, 212 | pub bytesused: u32, 213 | pub flags: u32, 214 | pub field: u32, 215 | pub timestamp: Timeval, 216 | pub timecode: TimeCode, 217 | pub sequence: u32, 218 | pub memory: u32, 219 | pub m: usize, // offset (__u32) or userptr (ulong) 220 | pub length: u32, 221 | pub input: u32, 222 | reserved: u32, 223 | } 224 | 225 | impl Buffer { 226 | pub fn new() -> Buffer { 227 | let mut buf: Buffer = unsafe { mem::zeroed() }; 228 | buf.btype = BUF_TYPE_VIDEO_CAPTURE; 229 | buf.memory = MEMORY_MMAP; 230 | buf 231 | } 232 | } 233 | 234 | #[repr(C)] 235 | pub struct TimeCode { 236 | pub ttype: u32, 237 | pub flags: u32, 238 | pub frames: u8, 239 | pub seconds: u8, 240 | pub minutes: u8, 241 | pub hours: u8, 242 | pub userbits: [u8; 4], 243 | } 244 | 245 | #[repr(C)] 246 | pub struct FmtDesc { 247 | pub index: u32, 248 | pub ftype: u32, 249 | pub flags: u32, 250 | pub description: [u8; 32], 251 | pub pixelformat: u32, 252 | reserved: [u32; 4], 253 | } 254 | 255 | impl FmtDesc { 256 | pub fn new() -> FmtDesc { 257 | let mut desc: FmtDesc = unsafe { mem::zeroed() }; 258 | desc.ftype = BUF_TYPE_VIDEO_CAPTURE; 259 | desc 260 | } 261 | } 262 | 263 | #[repr(C)] 264 | pub struct StreamParm { 265 | pub ptype: u32, 266 | pub parm: CaptureParm, 267 | space: [u8; 160], 268 | } 269 | 270 | impl StreamParm { 271 | pub fn new(interval: (u32, u32)) -> StreamParm { 272 | let mut parm: StreamParm = unsafe { mem::zeroed() }; 273 | parm.ptype = BUF_TYPE_VIDEO_CAPTURE; 274 | parm.parm.timeperframe.numerator = interval.0; 275 | parm.parm.timeperframe.denominator = interval.1; 276 | parm 277 | } 278 | } 279 | 280 | #[repr(C)] 281 | pub struct CaptureParm { 282 | pub capability: u32, 283 | pub capturemode: u32, 284 | pub timeperframe: Fract, 285 | pub extendedmode: u32, 286 | pub readbuffers: u32, 287 | reserved: [u32; 4], 288 | } 289 | 290 | #[repr(C)] 291 | pub struct Fract { 292 | pub numerator: u32, 293 | pub denominator: u32, 294 | } 295 | 296 | #[repr(C)] 297 | pub struct Frmsizeenum { 298 | pub index: u32, 299 | pub pixelformat: u32, 300 | pub ftype: u32, 301 | data: [u32; 6], 302 | reserved: [u32; 2], 303 | } 304 | 305 | impl Frmsizeenum { 306 | pub fn new(fourcc: u32) -> Frmsizeenum { 307 | let mut size: Frmsizeenum = unsafe { mem::zeroed() }; 308 | size.pixelformat = fourcc; 309 | size 310 | } 311 | 312 | pub fn discrete(&mut self) -> &mut FrmsizeDiscrete { 313 | unsafe { &mut *(self.data.as_mut_ptr() as *mut FrmsizeDiscrete) } 314 | } 315 | 316 | pub fn stepwise(&mut self) -> &mut FrmsizeStepwise { 317 | unsafe { &mut *(self.data.as_mut_ptr() as *mut FrmsizeStepwise) } 318 | } 319 | } 320 | 321 | #[repr(C)] 322 | pub struct FrmsizeDiscrete { 323 | pub width: u32, 324 | pub height: u32, 325 | } 326 | 327 | #[repr(C)] 328 | pub struct FrmsizeStepwise { 329 | pub min_width: u32, 330 | pub max_width: u32, 331 | pub step_width: u32, 332 | pub min_height: u32, 333 | pub max_height: u32, 334 | pub step_height: u32, 335 | } 336 | 337 | #[repr(C)] 338 | pub struct Frmivalenum { 339 | pub index: u32, 340 | pub pixelformat: u32, 341 | pub width: u32, 342 | pub height: u32, 343 | pub ftype: u32, 344 | data: [u32; 6], 345 | reserved: [u32; 2], 346 | } 347 | 348 | impl Frmivalenum { 349 | pub fn new(fourcc: u32, resolution: (u32, u32)) -> Frmivalenum { 350 | let mut ival: Frmivalenum = unsafe { mem::zeroed() }; 351 | ival.pixelformat = fourcc; 352 | ival.width = resolution.0; 353 | ival.height = resolution.1; 354 | ival 355 | } 356 | 357 | pub fn discrete(&mut self) -> &mut Fract { 358 | unsafe { &mut *(self.data.as_mut_ptr() as *mut Fract) } 359 | } 360 | 361 | pub fn stepwise(&mut self) -> &mut FrmivalStepwise { 362 | unsafe { &mut *(self.data.as_mut_ptr() as *mut FrmivalStepwise) } 363 | } 364 | } 365 | 366 | #[repr(C)] 367 | pub struct FrmivalStepwise { 368 | pub min: Fract, 369 | pub max: Fract, 370 | pub step: Fract, 371 | } 372 | 373 | #[repr(C)] 374 | pub struct QueryCtrl { 375 | pub id: u32, 376 | pub qtype: u32, 377 | pub name: [u8; 32], 378 | pub minimum: i32, 379 | pub maximum: i32, 380 | pub step: i32, 381 | pub default_value: i32, 382 | pub flags: u32, 383 | reserved: [u32; 2], 384 | } 385 | 386 | impl QueryCtrl { 387 | pub fn new(id: u32) -> QueryCtrl { 388 | let mut qctrl: QueryCtrl = unsafe { mem::zeroed() }; 389 | qctrl.id = id; 390 | qctrl 391 | } 392 | } 393 | 394 | #[repr(C)] 395 | pub struct QueryExtCtrl { 396 | pub id: u32, 397 | pub qtype: u32, 398 | pub name: [u8; 32], 399 | pub minimum: i64, 400 | pub maximum: i64, 401 | pub step: u64, 402 | pub default_value: i64, 403 | pub flags: u32, 404 | pub elem_size: u32, 405 | pub elems: u32, 406 | pub nr_of_dims: u32, 407 | pub dims: [u32; 4], 408 | reserved: [u32; 32], 409 | } 410 | 411 | impl QueryExtCtrl { 412 | pub fn new(id: u32) -> QueryExtCtrl { 413 | let mut qctrl: QueryExtCtrl = unsafe { mem::zeroed() }; 414 | qctrl.id = id; 415 | qctrl.elem_size = 8; 416 | qctrl.elems = 1; 417 | qctrl 418 | } 419 | } 420 | 421 | #[repr(C, packed)] 422 | pub struct QueryMenu { 423 | pub id: u32, 424 | pub index: u32, 425 | pub data: QueryMenuData, 426 | reserved: u32, 427 | } 428 | 429 | #[repr(C, packed)] 430 | pub union QueryMenuData { 431 | name: [u8; 32], 432 | value: i64, 433 | } 434 | 435 | impl QueryMenu { 436 | pub fn new(id: u32) -> QueryMenu { 437 | let mut menu: QueryMenu = unsafe { mem::zeroed() }; 438 | menu.id = id; 439 | menu 440 | } 441 | } 442 | 443 | impl QueryMenuData { 444 | pub fn name(&self) -> &[u8] { 445 | unsafe { &self.name[..] } 446 | } 447 | 448 | pub fn value(&self) -> i64 { 449 | unsafe { self.value } 450 | } 451 | } 452 | 453 | #[repr(C)] 454 | pub struct Control { 455 | pub id: u32, 456 | pub value: i32, 457 | } 458 | 459 | impl Control { 460 | pub fn new(id: u32) -> Control { 461 | Control { id, value: 0 } 462 | } 463 | } 464 | 465 | #[repr(C, packed)] 466 | pub struct ExtControl { 467 | pub id: u32, 468 | pub size: u32, 469 | reserved: u32, 470 | pub value: i64, 471 | } 472 | 473 | impl ExtControl { 474 | pub fn new(id: u32, size: u32) -> ExtControl { 475 | ExtControl { 476 | id, 477 | size, 478 | reserved: 0, 479 | value: 0, 480 | } 481 | } 482 | } 483 | 484 | #[repr(C)] 485 | pub struct ExtControls<'a> { 486 | pub ctrl_class: u32, 487 | pub count: u32, 488 | pub error_idx: u32, 489 | reserved: [u32; 2], 490 | pub controls: &'a mut ExtControl, 491 | } 492 | 493 | impl<'a> ExtControls<'a> { 494 | pub fn new(class: u32, ctrl: &mut ExtControl) -> ExtControls<'_> { 495 | ExtControls { 496 | ctrl_class: class, 497 | count: 1, 498 | error_idx: 0, 499 | reserved: [0; 2], 500 | controls: ctrl, 501 | } 502 | } 503 | } 504 | 505 | pub const BUF_TYPE_VIDEO_CAPTURE: u32 = 1; 506 | pub const FMT_FLAG_COMPRESSED: u32 = 1; 507 | pub const FMT_FLAG_EMULATED: u32 = 2; 508 | pub const FRMIVAL_TYPE_DISCRETE: u32 = 1; 509 | pub const FRMSIZE_TYPE_DISCRETE: u32 = 1; 510 | pub const MEMORY_MMAP: u32 = 1; 511 | 512 | pub const ID2CLASS: u32 = 0x0fff0000; 513 | pub const NEXT_CTRL: u32 = 0x80000000; 514 | 515 | // Control types. 516 | pub const CTRL_TYPE_INTEGER: u32 = 1; 517 | pub const CTRL_TYPE_BOOLEAN: u32 = 2; 518 | pub const CTRL_TYPE_MENU: u32 = 3; 519 | pub const CTRL_TYPE_BUTTON: u32 = 4; 520 | pub const CTRL_TYPE_INTEGER64: u32 = 5; 521 | pub const CTRL_TYPE_CTRL_CLASS: u32 = 6; 522 | pub const CTRL_TYPE_STRING: u32 = 7; 523 | pub const CTRL_TYPE_BITMASK: u32 = 8; 524 | pub const CTRL_TYPE_INTEGER_MENU: u32 = 9; 525 | 526 | #[allow(non_upper_case_globals)] 527 | pub mod pubconsts { 528 | // Fields. 529 | /// None, top, bottom or interplaced depending on whatever it thinks is approximate. 530 | pub const FIELD_ANY: u32 = 0; 531 | /// This device has no fields. 532 | pub const FIELD_NONE: u32 = 1; 533 | /// Top field only. 534 | pub const FIELD_TOP: u32 = 2; 535 | /// Bottom field only. 536 | pub const FIELD_BOTTOM: u32 = 3; 537 | /// Both fields interplaced. 538 | pub const FIELD_INTERLACED: u32 = 4; 539 | /// Both fields sequential into one buffer, top-bottom order. 540 | pub const FIELD_SEQ_TB: u32 = 5; 541 | /// Both fields sequential into one buffer, bottom-top order. 542 | pub const FIELD_SEQ_BT: u32 = 6; 543 | /// Both fields alternating into separate buffers. 544 | pub const FIELD_ALTERNATE: u32 = 7; 545 | /// Both fields interplaced, top field first and the top field is transmitted first. 546 | pub const FIELD_INTERLACED_TB: u32 = 8; 547 | /// Both fields interplaced, top field first and the bottom field is transmitted first. 548 | pub const FIELD_INTERLACED_BT: u32 = 9; 549 | 550 | // Control flags. 551 | /// This control is permanently disabled and should be ignored by the application. 552 | pub const FLAG_DISABLED: u32 = 0x0001; 553 | /// This control is temporarily unchangeable (e.g. another application controls resource). 554 | pub const FLAG_GRABBED: u32 = 0x0002; 555 | /// This control is permanently readable only. 556 | pub const FLAG_READ_ONLY: u32 = 0x0004; 557 | /// Changing this control may affect the value of other controls within the same control class. 558 | pub const FLAG_UPDATE: u32 = 0x0008; 559 | /// This control is not applicable to the current configuration. 560 | pub const FLAG_INACTIVE: u32 = 0x0010; 561 | /// A hint that this control is best represented as a slider-like element in a user interface. 562 | pub const FLAG_SLIDER: u32 = 0x0020; 563 | /// This control is permanently writable only. 564 | pub const FLAG_WRITE_ONLY: u32 = 0x0040; 565 | /// This control is volatile, which means that the value of the control changes continuously. 566 | /// A typical example would be the current gain value if the device is in auto-gain mode. 567 | pub const FLAG_VOLATILE: u32 = 0x0080; 568 | /// This control has a pointer type. 569 | pub const FLAG_HAS_PAYLOAD: u32 = 0x0100; 570 | /// The value provided to the control will be propagated to the driver even if it remains 571 | /// constant. This is required when the control represents an action on the hardware. 572 | /// For example: clearing an error flag or triggering the flash. 573 | pub const FLAG_EXECUTE_ON_WRITE: u32 = 0x0200; 574 | 575 | // Control classses. 576 | /// User controls. 577 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/control.html). 578 | pub const CLASS_USER: u32 = 0x00980000; 579 | /// MPEG compression controls. 580 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#mpeg-controls). 581 | pub const CLASS_MPEG: u32 = 0x00990000; 582 | /// Camera controls. 583 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#camera-controls). 584 | pub const CLASS_CAMERA: u32 = 0x009a0000; 585 | /// FM Transmitter controls. 586 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#fm-tx-controls). 587 | pub const CLASS_FM_TX: u32 = 0x009b0000; 588 | /// Flash device controls. 589 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#flash-controls). 590 | pub const CLASS_FLASH: u32 = 0x009c0000; 591 | /// JPEG compression controls. 592 | /// [details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#jpeg-controls). 593 | pub const CLASS_JPEG: u32 = 0x009d0000; 594 | /// low-level controls of image source. 595 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#image-source-controls). 596 | pub const CLASS_IMAGE_SOURCE: u32 = 0x009e0000; 597 | /// Image processing controls. 598 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#image-process-controls). 599 | pub const CLASS_IMAGE_PROC: u32 = 0x009f0000; 600 | /// Digital Video controls. 601 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#dv-controls). 602 | pub const CLASS_DV: u32 = 0x00a00000; 603 | /// FM Receiver controls. 604 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#fm-rx-controls). 605 | pub const CLASS_FM_RX: u32 = 0x00a10000; 606 | /// RF tuner controls. 607 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#rf-tuner-controls). 608 | pub const CLASS_RF_TUNER: u32 = 0x00a20000; 609 | /// Motion or object detection controls. 610 | /// [Details](http://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/extended-controls.html#detect-controls). 611 | pub const CLASS_DETECT: u32 = 0x00a30000; 612 | 613 | pub const CID_BASE: u32 = CLASS_USER | 0x900; 614 | pub const CID_USER_BASE: u32 = CID_BASE; 615 | pub const CID_USER_CLASS: u32 = CLASS_USER | 1; 616 | pub const CID_BRIGHTNESS: u32 = CID_BASE; 617 | pub const CID_CONTRAST: u32 = CID_BASE + 1; 618 | pub const CID_SATURATION: u32 = CID_BASE + 2; 619 | pub const CID_HUE: u32 = CID_BASE + 3; 620 | pub const CID_AUDIO_VOLUME: u32 = CID_BASE + 5; 621 | pub const CID_AUDIO_BALANCE: u32 = CID_BASE + 6; 622 | pub const CID_AUDIO_BASS: u32 = CID_BASE + 7; 623 | pub const CID_AUDIO_TREBLE: u32 = CID_BASE + 8; 624 | pub const CID_AUDIO_MUTE: u32 = CID_BASE + 9; 625 | pub const CID_AUDIO_LOUDNESS: u32 = CID_BASE + 10; 626 | pub const CID_BLACK_LEVEL: u32 = CID_BASE + 11; 627 | pub const CID_AUTO_WHITE_BALANCE: u32 = CID_BASE + 12; 628 | pub const CID_DO_WHITE_BALANCE: u32 = CID_BASE + 13; 629 | pub const CID_RED_BALANCE: u32 = CID_BASE + 14; 630 | pub const CID_BLUE_BALANCE: u32 = CID_BASE + 15; 631 | pub const CID_GAMMA: u32 = CID_BASE + 16; 632 | pub const CID_WHITENESS: u32 = CID_GAMMA; 633 | pub const CID_EXPOSURE: u32 = CID_BASE + 17; 634 | pub const CID_AUTOGAIN: u32 = CID_BASE + 18; 635 | pub const CID_GAIN: u32 = CID_BASE + 19; 636 | pub const CID_HFLIP: u32 = CID_BASE + 20; 637 | pub const CID_VFLIP: u32 = CID_BASE + 21; 638 | pub const CID_POWER_LINE_FREQUENCY: u32 = CID_BASE + 24; 639 | pub const CID_POWER_LINE_FREQUENCY_DISABLED: u32 = 0; 640 | pub const CID_POWER_LINE_FREQUENCY_50HZ: u32 = 1; 641 | pub const CID_POWER_LINE_FREQUENCY_60HZ: u32 = 2; 642 | pub const CID_POWER_LINE_FREQUENCY_AUTO: u32 = 3; 643 | pub const CID_HUE_AUTO: u32 = CID_BASE + 25; 644 | pub const CID_WHITE_BALANCE_TEMPERATURE: u32 = CID_BASE + 26; 645 | pub const CID_SHARPNESS: u32 = CID_BASE + 27; 646 | pub const CID_BACKLIGHT_COMPENSATION: u32 = CID_BASE + 28; 647 | pub const CID_CHROMA_AGC: u32 = CID_BASE + 29; 648 | pub const CID_COLOR_KILLER: u32 = CID_BASE + 30; 649 | pub const CID_COLORFX: u32 = CID_BASE + 31; 650 | pub const COLORFX_NONE: u32 = 0; 651 | pub const COLORFX_BW: u32 = 1; 652 | pub const COLORFX_SEPIA: u32 = 2; 653 | pub const COLORFX_NEGATIVE: u32 = 3; 654 | pub const COLORFX_EMBOSS: u32 = 4; 655 | pub const COLORFX_SKETCH: u32 = 5; 656 | pub const COLORFX_SKY_BLUE: u32 = 6; 657 | pub const COLORFX_GRASS_GREEN: u32 = 7; 658 | pub const COLORFX_SKIN_WHITEN: u32 = 8; 659 | pub const COLORFX_VIVID: u32 = 9; 660 | pub const COLORFX_AQUA: u32 = 10; 661 | pub const COLORFX_ART_FREEZE: u32 = 11; 662 | pub const COLORFX_SILHOUETTE: u32 = 12; 663 | pub const COLORFX_SOLARIZATION: u32 = 13; 664 | pub const COLORFX_ANTIQUE: u32 = 14; 665 | pub const COLORFX_SET_CBCR: u32 = 15; 666 | pub const CID_AUTOBRIGHTNESS: u32 = CID_BASE + 32; 667 | pub const CID_BAND_STOP_FILTER: u32 = CID_BASE + 33; 668 | pub const CID_ROTATE: u32 = CID_BASE + 34; 669 | pub const CID_BG_COLOR: u32 = CID_BASE + 35; 670 | pub const CID_CHROMA_GAIN: u32 = CID_BASE + 36; 671 | pub const CID_ILLUMINATORS_1: u32 = CID_BASE + 37; 672 | pub const CID_ILLUMINATORS_2: u32 = CID_BASE + 38; 673 | pub const CID_MIN_BUFFERS_FOR_CAPTURE: u32 = CID_BASE + 39; 674 | pub const CID_MIN_BUFFERS_FOR_OUTPUT: u32 = CID_BASE + 40; 675 | pub const CID_ALPHA_COMPONENT: u32 = CID_BASE + 41; 676 | pub const CID_COLORFX_CBCR: u32 = CID_BASE + 42; 677 | pub const CID_LASTP1: u32 = CID_BASE + 43; 678 | pub const CID_USER_MEYE_BASE: u32 = CID_USER_BASE + 0x1000; 679 | pub const CID_USER_BTTV_BASE: u32 = CID_USER_BASE + 0x1010; 680 | pub const CID_USER_S2255_BASE: u32 = CID_USER_BASE + 0x1030; 681 | pub const CID_USER_SI476X_BASE: u32 = CID_USER_BASE + 0x1040; 682 | pub const CID_USER_TI_VPE_BASE: u32 = CID_USER_BASE + 0x1050; 683 | pub const CID_USER_SAA7134_BASE: u32 = CID_USER_BASE + 0x1060; 684 | pub const CID_USER_ADV7180_BASE: u32 = CID_USER_BASE + 0x1070; 685 | pub const CID_MPEG_BASE: u32 = CLASS_MPEG | 0x900; 686 | pub const CID_MPEG_CLASS: u32 = CLASS_MPEG | 1; 687 | pub const CID_MPEG_STREAM_TYPE: u32 = CID_MPEG_BASE; 688 | pub const MPEG_STREAM_TYPE_MPEG2_PS: u32 = 0; 689 | pub const MPEG_STREAM_TYPE_MPEG2_TS: u32 = 1; 690 | pub const MPEG_STREAM_TYPE_MPEG1_SS: u32 = 2; 691 | pub const MPEG_STREAM_TYPE_MPEG2_DVD: u32 = 3; 692 | pub const MPEG_STREAM_TYPE_MPEG1_VCD: u32 = 4; 693 | pub const MPEG_STREAM_TYPE_MPEG2_SVCD: u32 = 5; 694 | pub const CID_MPEG_STREAM_PID_PMT: u32 = CID_MPEG_BASE + 1; 695 | pub const CID_MPEG_STREAM_PID_AUDIO: u32 = CID_MPEG_BASE + 2; 696 | pub const CID_MPEG_STREAM_PID_VIDEO: u32 = CID_MPEG_BASE + 3; 697 | pub const CID_MPEG_STREAM_PID_PCR: u32 = CID_MPEG_BASE + 4; 698 | pub const CID_MPEG_STREAM_PES_ID_AUDIO: u32 = CID_MPEG_BASE + 5; 699 | pub const CID_MPEG_STREAM_PES_ID_VIDEO: u32 = CID_MPEG_BASE + 6; 700 | pub const CID_MPEG_STREAM_VBI_FMT: u32 = CID_MPEG_BASE + 7; 701 | pub const MPEG_STREAM_VBI_FMT_NONE: u32 = 0; 702 | pub const MPEG_STREAM_VBI_FMT_IVTV: u32 = 1; 703 | pub const CID_MPEG_AUDIO_SAMPLING_FREQ: u32 = CID_MPEG_BASE + 100; 704 | pub const MPEG_AUDIO_SAMPLING_FREQ_44100: u32 = 0; 705 | pub const MPEG_AUDIO_SAMPLING_FREQ_48000: u32 = 1; 706 | pub const MPEG_AUDIO_SAMPLING_FREQ_32000: u32 = 2; 707 | pub const CID_MPEG_AUDIO_ENCODING: u32 = CID_MPEG_BASE + 101; 708 | pub const MPEG_AUDIO_ENCODING_LAYER_1: u32 = 0; 709 | pub const MPEG_AUDIO_ENCODING_LAYER_2: u32 = 1; 710 | pub const MPEG_AUDIO_ENCODING_LAYER_3: u32 = 2; 711 | pub const MPEG_AUDIO_ENCODING_AAC: u32 = 3; 712 | pub const MPEG_AUDIO_ENCODING_AC3: u32 = 4; 713 | pub const CID_MPEG_AUDIO_L1_BITRATE: u32 = CID_MPEG_BASE + 102; 714 | pub const MPEG_AUDIO_L1_BITRATE_32K: u32 = 0; 715 | pub const MPEG_AUDIO_L1_BITRATE_64K: u32 = 1; 716 | pub const MPEG_AUDIO_L1_BITRATE_96K: u32 = 2; 717 | pub const MPEG_AUDIO_L1_BITRATE_128K: u32 = 3; 718 | pub const MPEG_AUDIO_L1_BITRATE_160K: u32 = 4; 719 | pub const MPEG_AUDIO_L1_BITRATE_192K: u32 = 5; 720 | pub const MPEG_AUDIO_L1_BITRATE_224K: u32 = 6; 721 | pub const MPEG_AUDIO_L1_BITRATE_256K: u32 = 7; 722 | pub const MPEG_AUDIO_L1_BITRATE_288K: u32 = 8; 723 | pub const MPEG_AUDIO_L1_BITRATE_320K: u32 = 9; 724 | pub const MPEG_AUDIO_L1_BITRATE_352K: u32 = 10; 725 | pub const MPEG_AUDIO_L1_BITRATE_384K: u32 = 11; 726 | pub const MPEG_AUDIO_L1_BITRATE_416K: u32 = 12; 727 | pub const MPEG_AUDIO_L1_BITRATE_448K: u32 = 13; 728 | pub const CID_MPEG_AUDIO_L2_BITRATE: u32 = CID_MPEG_BASE + 103; 729 | pub const MPEG_AUDIO_L2_BITRATE_32K: u32 = 0; 730 | pub const MPEG_AUDIO_L2_BITRATE_48K: u32 = 1; 731 | pub const MPEG_AUDIO_L2_BITRATE_56K: u32 = 2; 732 | pub const MPEG_AUDIO_L2_BITRATE_64K: u32 = 3; 733 | pub const MPEG_AUDIO_L2_BITRATE_80K: u32 = 4; 734 | pub const MPEG_AUDIO_L2_BITRATE_96K: u32 = 5; 735 | pub const MPEG_AUDIO_L2_BITRATE_112K: u32 = 6; 736 | pub const MPEG_AUDIO_L2_BITRATE_128K: u32 = 7; 737 | pub const MPEG_AUDIO_L2_BITRATE_160K: u32 = 8; 738 | pub const MPEG_AUDIO_L2_BITRATE_192K: u32 = 9; 739 | pub const MPEG_AUDIO_L2_BITRATE_224K: u32 = 10; 740 | pub const MPEG_AUDIO_L2_BITRATE_256K: u32 = 11; 741 | pub const MPEG_AUDIO_L2_BITRATE_320K: u32 = 12; 742 | pub const MPEG_AUDIO_L2_BITRATE_384K: u32 = 13; 743 | pub const CID_MPEG_AUDIO_L3_BITRATE: u32 = CID_MPEG_BASE + 104; 744 | pub const MPEG_AUDIO_L3_BITRATE_32K: u32 = 0; 745 | pub const MPEG_AUDIO_L3_BITRATE_40K: u32 = 1; 746 | pub const MPEG_AUDIO_L3_BITRATE_48K: u32 = 2; 747 | pub const MPEG_AUDIO_L3_BITRATE_56K: u32 = 3; 748 | pub const MPEG_AUDIO_L3_BITRATE_64K: u32 = 4; 749 | pub const MPEG_AUDIO_L3_BITRATE_80K: u32 = 5; 750 | pub const MPEG_AUDIO_L3_BITRATE_96K: u32 = 6; 751 | pub const MPEG_AUDIO_L3_BITRATE_112K: u32 = 7; 752 | pub const MPEG_AUDIO_L3_BITRATE_128K: u32 = 8; 753 | pub const MPEG_AUDIO_L3_BITRATE_160K: u32 = 9; 754 | pub const MPEG_AUDIO_L3_BITRATE_192K: u32 = 10; 755 | pub const MPEG_AUDIO_L3_BITRATE_224K: u32 = 11; 756 | pub const MPEG_AUDIO_L3_BITRATE_256K: u32 = 12; 757 | pub const MPEG_AUDIO_L3_BITRATE_320K: u32 = 13; 758 | pub const CID_MPEG_AUDIO_MODE: u32 = CID_MPEG_BASE + 105; 759 | pub const MPEG_AUDIO_MODE_STEREO: u32 = 0; 760 | pub const MPEG_AUDIO_MODE_JOINT_STEREO: u32 = 1; 761 | pub const MPEG_AUDIO_MODE_DUAL: u32 = 2; 762 | pub const MPEG_AUDIO_MODE_MONO: u32 = 3; 763 | pub const CID_MPEG_AUDIO_MODE_EXTENSION: u32 = CID_MPEG_BASE + 106; 764 | pub const MPEG_AUDIO_MODE_EXTENSION_BOUND_4: u32 = 0; 765 | pub const MPEG_AUDIO_MODE_EXTENSION_BOUND_8: u32 = 1; 766 | pub const MPEG_AUDIO_MODE_EXTENSION_BOUND_12: u32 = 2; 767 | pub const MPEG_AUDIO_MODE_EXTENSION_BOUND_16: u32 = 3; 768 | pub const CID_MPEG_AUDIO_EMPHASIS: u32 = CID_MPEG_BASE + 107; 769 | pub const MPEG_AUDIO_EMPHASIS_NONE: u32 = 0; 770 | pub const MPEG_AUDIO_EMPHASIS_50_DIV_15_uS: u32 = 1; 771 | pub const MPEG_AUDIO_EMPHASIS_CCITT_J17: u32 = 2; 772 | pub const CID_MPEG_AUDIO_CRC: u32 = CID_MPEG_BASE + 108; 773 | pub const MPEG_AUDIO_CRC_NONE: u32 = 0; 774 | pub const MPEG_AUDIO_CRC_CRC16: u32 = 1; 775 | pub const CID_MPEG_AUDIO_MUTE: u32 = CID_MPEG_BASE + 109; 776 | pub const CID_MPEG_AUDIO_AAC_BITRATE: u32 = CID_MPEG_BASE + 110; 777 | pub const CID_MPEG_AUDIO_AC3_BITRATE: u32 = CID_MPEG_BASE + 111; 778 | pub const MPEG_AUDIO_AC3_BITRATE_32K: u32 = 0; 779 | pub const MPEG_AUDIO_AC3_BITRATE_40K: u32 = 1; 780 | pub const MPEG_AUDIO_AC3_BITRATE_48K: u32 = 2; 781 | pub const MPEG_AUDIO_AC3_BITRATE_56K: u32 = 3; 782 | pub const MPEG_AUDIO_AC3_BITRATE_64K: u32 = 4; 783 | pub const MPEG_AUDIO_AC3_BITRATE_80K: u32 = 5; 784 | pub const MPEG_AUDIO_AC3_BITRATE_96K: u32 = 6; 785 | pub const MPEG_AUDIO_AC3_BITRATE_112K: u32 = 7; 786 | pub const MPEG_AUDIO_AC3_BITRATE_128K: u32 = 8; 787 | pub const MPEG_AUDIO_AC3_BITRATE_160K: u32 = 9; 788 | pub const MPEG_AUDIO_AC3_BITRATE_192K: u32 = 10; 789 | pub const MPEG_AUDIO_AC3_BITRATE_224K: u32 = 11; 790 | pub const MPEG_AUDIO_AC3_BITRATE_256K: u32 = 12; 791 | pub const MPEG_AUDIO_AC3_BITRATE_320K: u32 = 13; 792 | pub const MPEG_AUDIO_AC3_BITRATE_384K: u32 = 14; 793 | pub const MPEG_AUDIO_AC3_BITRATE_448K: u32 = 15; 794 | pub const MPEG_AUDIO_AC3_BITRATE_512K: u32 = 16; 795 | pub const MPEG_AUDIO_AC3_BITRATE_576K: u32 = 17; 796 | pub const MPEG_AUDIO_AC3_BITRATE_640K: u32 = 18; 797 | pub const CID_MPEG_AUDIO_DEC_PLAYBACK: u32 = CID_MPEG_BASE + 112; 798 | pub const MPEG_AUDIO_DEC_PLAYBACK_AUTO: u32 = 0; 799 | pub const MPEG_AUDIO_DEC_PLAYBACK_STEREO: u32 = 1; 800 | pub const MPEG_AUDIO_DEC_PLAYBACK_LEFT: u32 = 2; 801 | pub const MPEG_AUDIO_DEC_PLAYBACK_RIGHT: u32 = 3; 802 | pub const MPEG_AUDIO_DEC_PLAYBACK_MONO: u32 = 4; 803 | pub const MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO: u32 = 5; 804 | pub const CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: u32 = CID_MPEG_BASE + 113; 805 | pub const CID_MPEG_VIDEO_ENCODING: u32 = CID_MPEG_BASE + 200; 806 | pub const MPEG_VIDEO_ENCODING_MPEG_1: u32 = 0; 807 | pub const MPEG_VIDEO_ENCODING_MPEG_2: u32 = 1; 808 | pub const MPEG_VIDEO_ENCODING_MPEG_4_AVC: u32 = 2; 809 | pub const CID_MPEG_VIDEO_ASPECT: u32 = CID_MPEG_BASE + 201; 810 | pub const MPEG_VIDEO_ASPECT_1x1: u32 = 0; 811 | pub const MPEG_VIDEO_ASPECT_4x3: u32 = 1; 812 | pub const MPEG_VIDEO_ASPECT_16x9: u32 = 2; 813 | pub const MPEG_VIDEO_ASPECT_221x100: u32 = 3; 814 | pub const CID_MPEG_VIDEO_B_FRAMES: u32 = CID_MPEG_BASE + 202; 815 | pub const CID_MPEG_VIDEO_GOP_SIZE: u32 = CID_MPEG_BASE + 203; 816 | pub const CID_MPEG_VIDEO_GOP_CLOSURE: u32 = CID_MPEG_BASE + 204; 817 | pub const CID_MPEG_VIDEO_PULLDOWN: u32 = CID_MPEG_BASE + 205; 818 | pub const CID_MPEG_VIDEO_BITRATE_MODE: u32 = CID_MPEG_BASE + 206; 819 | pub const MPEG_VIDEO_BITRATE_MODE_VBR: u32 = 0; 820 | pub const MPEG_VIDEO_BITRATE_MODE_CBR: u32 = 1; 821 | pub const CID_MPEG_VIDEO_BITRATE: u32 = CID_MPEG_BASE + 207; 822 | pub const CID_MPEG_VIDEO_BITRATE_PEAK: u32 = CID_MPEG_BASE + 208; 823 | pub const CID_MPEG_VIDEO_TEMPORAL_DECIMATION: u32 = CID_MPEG_BASE + 209; 824 | pub const CID_MPEG_VIDEO_MUTE: u32 = CID_MPEG_BASE + 210; 825 | pub const CID_MPEG_VIDEO_MUTE_YUV: u32 = CID_MPEG_BASE + 211; 826 | pub const CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: u32 = CID_MPEG_BASE + 212; 827 | pub const CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: u32 = CID_MPEG_BASE + 213; 828 | pub const CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: u32 = CID_MPEG_BASE + 214; 829 | pub const CID_MPEG_VIDEO_FRAME_RC_ENABLE: u32 = CID_MPEG_BASE + 215; 830 | pub const CID_MPEG_VIDEO_HEADER_MODE: u32 = CID_MPEG_BASE + 216; 831 | pub const MPEG_VIDEO_HEADER_MODE_SEPARATE: u32 = 0; 832 | pub const MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME: u32 = 1; 833 | pub const CID_MPEG_VIDEO_MAX_REF_PIC: u32 = CID_MPEG_BASE + 217; 834 | pub const CID_MPEG_VIDEO_MB_RC_ENABLE: u32 = CID_MPEG_BASE + 218; 835 | pub const CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: u32 = CID_MPEG_BASE + 219; 836 | pub const CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: u32 = CID_MPEG_BASE + 220; 837 | pub const CID_MPEG_VIDEO_MULTI_SLICE_MODE: u32 = CID_MPEG_BASE + 221; 838 | pub const MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: u32 = 0; 839 | pub const MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: u32 = 1; 840 | pub const MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: u32 = 2; 841 | pub const CID_MPEG_VIDEO_VBV_SIZE: u32 = CID_MPEG_BASE + 222; 842 | pub const CID_MPEG_VIDEO_DEC_PTS: u32 = CID_MPEG_BASE + 223; 843 | pub const CID_MPEG_VIDEO_DEC_FRAME: u32 = CID_MPEG_BASE + 224; 844 | pub const CID_MPEG_VIDEO_VBV_DELAY: u32 = CID_MPEG_BASE + 225; 845 | pub const CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: u32 = CID_MPEG_BASE + 226; 846 | pub const CID_MPEG_VIDEO_MV_H_SEARCH_RANGE: u32 = CID_MPEG_BASE + 227; 847 | pub const CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: u32 = CID_MPEG_BASE + 228; 848 | pub const CID_MPEG_VIDEO_H263_I_FRAME_QP: u32 = CID_MPEG_BASE + 300; 849 | pub const CID_MPEG_VIDEO_H263_P_FRAME_QP: u32 = CID_MPEG_BASE + 301; 850 | pub const CID_MPEG_VIDEO_H263_B_FRAME_QP: u32 = CID_MPEG_BASE + 302; 851 | pub const CID_MPEG_VIDEO_H263_MIN_QP: u32 = CID_MPEG_BASE + 303; 852 | pub const CID_MPEG_VIDEO_H263_MAX_QP: u32 = CID_MPEG_BASE + 304; 853 | pub const CID_MPEG_VIDEO_H264_I_FRAME_QP: u32 = CID_MPEG_BASE + 350; 854 | pub const CID_MPEG_VIDEO_H264_P_FRAME_QP: u32 = CID_MPEG_BASE + 351; 855 | pub const CID_MPEG_VIDEO_H264_B_FRAME_QP: u32 = CID_MPEG_BASE + 352; 856 | pub const CID_MPEG_VIDEO_H264_MIN_QP: u32 = CID_MPEG_BASE + 353; 857 | pub const CID_MPEG_VIDEO_H264_MAX_QP: u32 = CID_MPEG_BASE + 354; 858 | pub const CID_MPEG_VIDEO_H264_8X8_TRANSFORM: u32 = CID_MPEG_BASE + 355; 859 | pub const CID_MPEG_VIDEO_H264_CPB_SIZE: u32 = CID_MPEG_BASE + 356; 860 | pub const CID_MPEG_VIDEO_H264_ENTROPY_MODE: u32 = CID_MPEG_BASE + 357; 861 | pub const MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC: u32 = 0; 862 | pub const MPEG_VIDEO_H264_ENTROPY_MODE_CABAC: u32 = 1; 863 | pub const CID_MPEG_VIDEO_H264_I_PERIOD: u32 = CID_MPEG_BASE + 358; 864 | pub const CID_MPEG_VIDEO_H264_LEVEL: u32 = CID_MPEG_BASE + 359; 865 | pub const MPEG_VIDEO_H264_LEVEL_1_0: u32 = 0; 866 | pub const MPEG_VIDEO_H264_LEVEL_1B: u32 = 1; 867 | pub const MPEG_VIDEO_H264_LEVEL_1_1: u32 = 2; 868 | pub const MPEG_VIDEO_H264_LEVEL_1_2: u32 = 3; 869 | pub const MPEG_VIDEO_H264_LEVEL_1_3: u32 = 4; 870 | pub const MPEG_VIDEO_H264_LEVEL_2_0: u32 = 5; 871 | pub const MPEG_VIDEO_H264_LEVEL_2_1: u32 = 6; 872 | pub const MPEG_VIDEO_H264_LEVEL_2_2: u32 = 7; 873 | pub const MPEG_VIDEO_H264_LEVEL_3_0: u32 = 8; 874 | pub const MPEG_VIDEO_H264_LEVEL_3_1: u32 = 9; 875 | pub const MPEG_VIDEO_H264_LEVEL_3_2: u32 = 10; 876 | pub const MPEG_VIDEO_H264_LEVEL_4_0: u32 = 11; 877 | pub const MPEG_VIDEO_H264_LEVEL_4_1: u32 = 12; 878 | pub const MPEG_VIDEO_H264_LEVEL_4_2: u32 = 13; 879 | pub const MPEG_VIDEO_H264_LEVEL_5_0: u32 = 14; 880 | pub const MPEG_VIDEO_H264_LEVEL_5_1: u32 = 15; 881 | pub const CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: u32 = CID_MPEG_BASE + 360; 882 | pub const CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: u32 = CID_MPEG_BASE + 361; 883 | pub const CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: u32 = CID_MPEG_BASE + 362; 884 | pub const MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED: u32 = 0; 885 | pub const MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED: u32 = 1; 886 | pub const MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: u32 = 2; 887 | pub const CID_MPEG_VIDEO_H264_PROFILE: u32 = CID_MPEG_BASE + 363; 888 | pub const MPEG_VIDEO_H264_PROFILE_BASELINE: u32 = 0; 889 | pub const MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: u32 = 1; 890 | pub const MPEG_VIDEO_H264_PROFILE_MAIN: u32 = 2; 891 | pub const MPEG_VIDEO_H264_PROFILE_EXTENDED: u32 = 3; 892 | pub const MPEG_VIDEO_H264_PROFILE_HIGH: u32 = 4; 893 | pub const MPEG_VIDEO_H264_PROFILE_HIGH_10: u32 = 5; 894 | pub const MPEG_VIDEO_H264_PROFILE_HIGH_422: u32 = 6; 895 | pub const MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE: u32 = 7; 896 | pub const MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA: u32 = 8; 897 | pub const MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA: u32 = 9; 898 | pub const MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA: u32 = 10; 899 | pub const MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA: u32 = 11; 900 | pub const MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE: u32 = 12; 901 | pub const MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH: u32 = 13; 902 | pub const MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA: u32 = 14; 903 | pub const MPEG_VIDEO_H264_PROFILE_STEREO_HIGH: u32 = 15; 904 | pub const MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH: u32 = 16; 905 | pub const CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT: u32 = CID_MPEG_BASE + 364; 906 | pub const CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: u32 = CID_MPEG_BASE + 365; 907 | pub const CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: u32 = CID_MPEG_BASE + 366; 908 | pub const CID_MPEG_VIDEO_H264_VUI_SAR_IDC: u32 = CID_MPEG_BASE + 367; 909 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED: u32 = 0; 910 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_1x1: u32 = 1; 911 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_12x11: u32 = 2; 912 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_10x11: u32 = 3; 913 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_16x11: u32 = 4; 914 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_40x33: u32 = 5; 915 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_24x11: u32 = 6; 916 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_20x11: u32 = 7; 917 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_32x11: u32 = 8; 918 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_80x33: u32 = 9; 919 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_18x11: u32 = 10; 920 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_15x11: u32 = 11; 921 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_64x33: u32 = 12; 922 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_160x99: u32 = 13; 923 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_4x3: u32 = 14; 924 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_3x2: u32 = 15; 925 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_2x1: u32 = 16; 926 | pub const MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED: u32 = 17; 927 | pub const CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: u32 = CID_MPEG_BASE + 368; 928 | pub const CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0: u32 = CID_MPEG_BASE + 369; 929 | pub const CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: u32 = CID_MPEG_BASE + 370; 930 | pub const MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_CHECKERBOARD: u32 = 0; 931 | pub const MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN: u32 = 1; 932 | pub const MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW: u32 = 2; 933 | pub const MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE: u32 = 3; 934 | pub const MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM: u32 = 4; 935 | pub const MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL: u32 = 5; 936 | pub const CID_MPEG_VIDEO_H264_FMO: u32 = CID_MPEG_BASE + 371; 937 | pub const CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: u32 = CID_MPEG_BASE + 372; 938 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES: u32 = 0; 939 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES: u32 = 1; 940 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER: u32 = 2; 941 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT: u32 = 3; 942 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN: u32 = 4; 943 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN: u32 = 5; 944 | pub const MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT: u32 = 6; 945 | pub const CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP: u32 = CID_MPEG_BASE + 373; 946 | pub const CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION: u32 = CID_MPEG_BASE + 374; 947 | pub const MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT: u32 = 0; 948 | pub const MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT: u32 = 1; 949 | pub const CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE: u32 = CID_MPEG_BASE + 375; 950 | pub const CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH: u32 = CID_MPEG_BASE + 376; 951 | pub const CID_MPEG_VIDEO_H264_ASO: u32 = CID_MPEG_BASE + 377; 952 | pub const CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER: u32 = CID_MPEG_BASE + 378; 953 | pub const CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING: u32 = CID_MPEG_BASE + 379; 954 | pub const CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: u32 = CID_MPEG_BASE + 380; 955 | pub const MPEG_VIDEO_H264_HIERARCHICAL_CODING_B: u32 = 0; 956 | pub const MPEG_VIDEO_H264_HIERARCHICAL_CODING_P: u32 = 1; 957 | pub const CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER: u32 = CID_MPEG_BASE + 381; 958 | pub const CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP: u32 = CID_MPEG_BASE + 382; 959 | pub const CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: u32 = CID_MPEG_BASE + 400; 960 | pub const CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: u32 = CID_MPEG_BASE + 401; 961 | pub const CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: u32 = CID_MPEG_BASE + 402; 962 | pub const CID_MPEG_VIDEO_MPEG4_MIN_QP: u32 = CID_MPEG_BASE + 403; 963 | pub const CID_MPEG_VIDEO_MPEG4_MAX_QP: u32 = CID_MPEG_BASE + 404; 964 | pub const CID_MPEG_VIDEO_MPEG4_LEVEL: u32 = CID_MPEG_BASE + 405; 965 | pub const MPEG_VIDEO_MPEG4_LEVEL_0: u32 = 0; 966 | pub const MPEG_VIDEO_MPEG4_LEVEL_0B: u32 = 1; 967 | pub const MPEG_VIDEO_MPEG4_LEVEL_1: u32 = 2; 968 | pub const MPEG_VIDEO_MPEG4_LEVEL_2: u32 = 3; 969 | pub const MPEG_VIDEO_MPEG4_LEVEL_3: u32 = 4; 970 | pub const MPEG_VIDEO_MPEG4_LEVEL_3B: u32 = 5; 971 | pub const MPEG_VIDEO_MPEG4_LEVEL_4: u32 = 6; 972 | pub const MPEG_VIDEO_MPEG4_LEVEL_5: u32 = 7; 973 | pub const CID_MPEG_VIDEO_MPEG4_PROFILE: u32 = CID_MPEG_BASE + 406; 974 | pub const MPEG_VIDEO_MPEG4_PROFILE_SIMPLE: u32 = 0; 975 | pub const MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE: u32 = 1; 976 | pub const MPEG_VIDEO_MPEG4_PROFILE_CORE: u32 = 2; 977 | pub const MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE: u32 = 3; 978 | pub const MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY: u32 = 4; 979 | pub const CID_MPEG_VIDEO_MPEG4_QPEL: u32 = CID_MPEG_BASE + 407; 980 | pub const CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: u32 = CID_MPEG_BASE + 500; 981 | pub const CID_MPEG_VIDEO_VPX_1_PARTITION: u32 = 0; 982 | pub const CID_MPEG_VIDEO_VPX_2_PARTITIONS: u32 = 1; 983 | pub const CID_MPEG_VIDEO_VPX_4_PARTITIONS: u32 = 2; 984 | pub const CID_MPEG_VIDEO_VPX_8_PARTITIONS: u32 = 3; 985 | pub const CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4: u32 = CID_MPEG_BASE + 501; 986 | pub const CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES: u32 = CID_MPEG_BASE + 502; 987 | pub const CID_MPEG_VIDEO_VPX_1_REF_FRAME: u32 = 0; 988 | pub const CID_MPEG_VIDEO_VPX_2_REF_FRAME: u32 = 1; 989 | pub const CID_MPEG_VIDEO_VPX_3_REF_FRAME: u32 = 2; 990 | pub const CID_MPEG_VIDEO_VPX_FILTER_LEVEL: u32 = CID_MPEG_BASE + 503; 991 | pub const CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS: u32 = CID_MPEG_BASE + 504; 992 | pub const CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD: u32 = CID_MPEG_BASE + 505; 993 | pub const CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL: u32 = CID_MPEG_BASE + 506; 994 | pub const CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV: u32 = 0; 995 | pub const CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD: u32 = 1; 996 | pub const CID_MPEG_VIDEO_VPX_MIN_QP: u32 = CID_MPEG_BASE + 507; 997 | pub const CID_MPEG_VIDEO_VPX_MAX_QP: u32 = CID_MPEG_BASE + 508; 998 | pub const CID_MPEG_VIDEO_VPX_I_FRAME_QP: u32 = CID_MPEG_BASE + 509; 999 | pub const CID_MPEG_VIDEO_VPX_P_FRAME_QP: u32 = CID_MPEG_BASE + 510; 1000 | pub const CID_MPEG_VIDEO_VPX_PROFILE: u32 = CID_MPEG_BASE + 511; 1001 | pub const CID_MPEG_CX2341X_BASE: u32 = CLASS_MPEG | 0x1000; 1002 | pub const CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: u32 = CID_MPEG_CX2341X_BASE; 1003 | pub const MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL: u32 = 0; 1004 | pub const MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO: u32 = 1; 1005 | pub const CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: u32 = CID_MPEG_CX2341X_BASE + 1; 1006 | pub const CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: u32 = CID_MPEG_CX2341X_BASE + 2; 1007 | pub const MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF: u32 = 0; 1008 | pub const MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR: u32 = 1; 1009 | pub const MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT: u32 = 2; 1010 | pub const MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE: u32 = 3; 1011 | pub const MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE: u32 = 4; 1012 | pub const CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: u32 = CID_MPEG_CX2341X_BASE + 3; 1013 | pub const MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF: u32 = 0; 1014 | pub const MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR: u32 = 1; 1015 | pub const CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: u32 = CID_MPEG_CX2341X_BASE + 4; 1016 | pub const MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL: u32 = 0; 1017 | pub const MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO: u32 = 1; 1018 | pub const CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: u32 = CID_MPEG_CX2341X_BASE + 5; 1019 | pub const CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: u32 = CID_MPEG_CX2341X_BASE + 6; 1020 | pub const MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF: u32 = 0; 1021 | pub const MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR: u32 = 1; 1022 | pub const MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT: u32 = 2; 1023 | pub const MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT: u32 = 3; 1024 | pub const MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG: u32 = 4; 1025 | pub const CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: u32 = CID_MPEG_CX2341X_BASE + 7; 1026 | pub const CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: u32 = CID_MPEG_CX2341X_BASE + 8; 1027 | pub const CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: u32 = CID_MPEG_CX2341X_BASE + 9; 1028 | pub const CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: u32 = CID_MPEG_CX2341X_BASE + 10; 1029 | pub const CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: u32 = CID_MPEG_CX2341X_BASE + 11; 1030 | pub const CID_MPEG_MFC51_BASE: u32 = CLASS_MPEG | 0x1100; 1031 | pub const CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY: u32 = CID_MPEG_MFC51_BASE; 1032 | pub const CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE: u32 = CID_MPEG_MFC51_BASE + 1; 1033 | pub const CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE: u32 = CID_MPEG_MFC51_BASE + 2; 1034 | pub const MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED: u32 = 0; 1035 | pub const MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: u32 = 1; 1036 | pub const MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: u32 = 2; 1037 | pub const CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE: u32 = CID_MPEG_MFC51_BASE + 3; 1038 | pub const MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED: u32 = 0; 1039 | pub const MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME: u32 = 1; 1040 | pub const MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED: u32 = 2; 1041 | pub const CID_MPEG_MFC51_VIDEO_PADDING: u32 = CID_MPEG_MFC51_BASE + 4; 1042 | pub const CID_MPEG_MFC51_VIDEO_PADDING_YUV: u32 = CID_MPEG_MFC51_BASE + 5; 1043 | pub const CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT: u32 = CID_MPEG_MFC51_BASE + 6; 1044 | pub const CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF: u32 = CID_MPEG_MFC51_BASE + 7; 1045 | pub const CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY: u32 = CID_MPEG_MFC51_BASE + 50; 1046 | pub const CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK: u32 = CID_MPEG_MFC51_BASE + 51; 1047 | pub const CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH: u32 = CID_MPEG_MFC51_BASE + 52; 1048 | pub const CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC: u32 = CID_MPEG_MFC51_BASE + 53; 1049 | pub const CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P: u32 = CID_MPEG_MFC51_BASE + 54; 1050 | pub const CID_CAMERA_CLASS_BASE: u32 = CLASS_CAMERA | 0x900; 1051 | pub const CID_CAMERA_CLASS: u32 = CLASS_CAMERA | 1; 1052 | pub const CID_EXPOSURE_AUTO: u32 = CID_CAMERA_CLASS_BASE + 1; 1053 | pub const EXPOSURE_AUTO: u32 = 0; 1054 | pub const EXPOSURE_MANUAL: u32 = 1; 1055 | pub const EXPOSURE_SHUTTER_PRIORITY: u32 = 2; 1056 | pub const EXPOSURE_APERTURE_PRIORITY: u32 = 3; 1057 | pub const CID_EXPOSURE_ABSOLUTE: u32 = CID_CAMERA_CLASS_BASE + 2; 1058 | pub const CID_EXPOSURE_AUTO_PRIORITY: u32 = CID_CAMERA_CLASS_BASE + 3; 1059 | pub const CID_PAN_RELATIVE: u32 = CID_CAMERA_CLASS_BASE + 4; 1060 | pub const CID_TILT_RELATIVE: u32 = CID_CAMERA_CLASS_BASE + 5; 1061 | pub const CID_PAN_RESET: u32 = CID_CAMERA_CLASS_BASE + 6; 1062 | pub const CID_TILT_RESET: u32 = CID_CAMERA_CLASS_BASE + 7; 1063 | pub const CID_PAN_ABSOLUTE: u32 = CID_CAMERA_CLASS_BASE + 8; 1064 | pub const CID_TILT_ABSOLUTE: u32 = CID_CAMERA_CLASS_BASE + 9; 1065 | pub const CID_FOCUS_ABSOLUTE: u32 = CID_CAMERA_CLASS_BASE + 10; 1066 | pub const CID_FOCUS_RELATIVE: u32 = CID_CAMERA_CLASS_BASE + 11; 1067 | pub const CID_FOCUS_AUTO: u32 = CID_CAMERA_CLASS_BASE + 12; 1068 | pub const CID_ZOOM_ABSOLUTE: u32 = CID_CAMERA_CLASS_BASE + 13; 1069 | pub const CID_ZOOM_RELATIVE: u32 = CID_CAMERA_CLASS_BASE + 14; 1070 | pub const CID_ZOOM_CONTINUOUS: u32 = CID_CAMERA_CLASS_BASE + 15; 1071 | pub const CID_PRIVACY: u32 = CID_CAMERA_CLASS_BASE + 16; 1072 | pub const CID_IRIS_ABSOLUTE: u32 = CID_CAMERA_CLASS_BASE + 17; 1073 | pub const CID_IRIS_RELATIVE: u32 = CID_CAMERA_CLASS_BASE + 18; 1074 | pub const CID_AUTO_EXPOSURE_BIAS: u32 = CID_CAMERA_CLASS_BASE + 19; 1075 | pub const CID_AUTO_N_PRESET_WHITE_BALANCE: u32 = CID_CAMERA_CLASS_BASE + 20; 1076 | pub const WHITE_BALANCE_MANUAL: u32 = 0; 1077 | pub const WHITE_BALANCE_AUTO: u32 = 1; 1078 | pub const WHITE_BALANCE_INCANDESCENT: u32 = 2; 1079 | pub const WHITE_BALANCE_FLUORESCENT: u32 = 3; 1080 | pub const WHITE_BALANCE_FLUORESCENT_H: u32 = 4; 1081 | pub const WHITE_BALANCE_HORIZON: u32 = 5; 1082 | pub const WHITE_BALANCE_DAYLIGHT: u32 = 6; 1083 | pub const WHITE_BALANCE_FLASH: u32 = 7; 1084 | pub const WHITE_BALANCE_CLOUDY: u32 = 8; 1085 | pub const WHITE_BALANCE_SHADE: u32 = 9; 1086 | pub const WHITE_BALANCE_GREYWORLD: u32 = 10; 1087 | pub const CID_WIDE_DYNAMIC_RANGE: u32 = CID_CAMERA_CLASS_BASE + 21; 1088 | pub const CID_IMAGE_STABILIZATION: u32 = CID_CAMERA_CLASS_BASE + 22; 1089 | pub const CID_ISO_SENSITIVITY: u32 = CID_CAMERA_CLASS_BASE + 23; 1090 | pub const CID_ISO_SENSITIVITY_AUTO: u32 = CID_CAMERA_CLASS_BASE + 24; 1091 | pub const ISO_SENSITIVITY_MANUAL: u32 = 0; 1092 | pub const ISO_SENSITIVITY_AUTO: u32 = 1; 1093 | pub const CID_EXPOSURE_METERING: u32 = CID_CAMERA_CLASS_BASE + 25; 1094 | pub const EXPOSURE_METERING_AVERAGE: u32 = 0; 1095 | pub const EXPOSURE_METERING_CENTER_WEIGHTED: u32 = 1; 1096 | pub const EXPOSURE_METERING_SPOT: u32 = 2; 1097 | pub const EXPOSURE_METERING_MATRIX: u32 = 3; 1098 | pub const CID_SCENE_MODE: u32 = CID_CAMERA_CLASS_BASE + 26; 1099 | pub const SCENE_MODE_NONE: u32 = 0; 1100 | pub const SCENE_MODE_BACKLIGHT: u32 = 1; 1101 | pub const SCENE_MODE_BEACH_SNOW: u32 = 2; 1102 | pub const SCENE_MODE_CANDLE_LIGHT: u32 = 3; 1103 | pub const SCENE_MODE_DAWN_DUSK: u32 = 4; 1104 | pub const SCENE_MODE_FALL_COLORS: u32 = 5; 1105 | pub const SCENE_MODE_FIREWORKS: u32 = 6; 1106 | pub const SCENE_MODE_LANDSCAPE: u32 = 7; 1107 | pub const SCENE_MODE_NIGHT: u32 = 8; 1108 | pub const SCENE_MODE_PARTY_INDOOR: u32 = 9; 1109 | pub const SCENE_MODE_PORTRAIT: u32 = 10; 1110 | pub const SCENE_MODE_SPORTS: u32 = 11; 1111 | pub const SCENE_MODE_SUNSET: u32 = 12; 1112 | pub const SCENE_MODE_TEXT: u32 = 13; 1113 | pub const CID_3A_LOCK: u32 = CID_CAMERA_CLASS_BASE + 27; 1114 | pub const LOCK_EXPOSURE: u32 = 1; 1115 | pub const LOCK_WHITE_BALANCE: u32 = 1 << 1; 1116 | pub const LOCK_FOCUS: u32 = 1 << 2; 1117 | pub const CID_AUTO_FOCUS_START: u32 = CID_CAMERA_CLASS_BASE + 28; 1118 | pub const CID_AUTO_FOCUS_STOP: u32 = CID_CAMERA_CLASS_BASE + 29; 1119 | pub const CID_AUTO_FOCUS_STATUS: u32 = CID_CAMERA_CLASS_BASE + 30; 1120 | pub const AUTO_FOCUS_STATUS_IDLE: u32 = 0; 1121 | pub const AUTO_FOCUS_STATUS_BUSY: u32 = 1; 1122 | pub const AUTO_FOCUS_STATUS_REACHED: u32 = 1 << 1; 1123 | pub const AUTO_FOCUS_STATUS_FAILED: u32 = 1 << 2; 1124 | pub const CID_AUTO_FOCUS_RANGE: u32 = CID_CAMERA_CLASS_BASE + 31; 1125 | pub const AUTO_FOCUS_RANGE_AUTO: u32 = 0; 1126 | pub const AUTO_FOCUS_RANGE_NORMAL: u32 = 1; 1127 | pub const AUTO_FOCUS_RANGE_MACRO: u32 = 2; 1128 | pub const AUTO_FOCUS_RANGE_INFINITY: u32 = 3; 1129 | pub const CID_PAN_SPEED: u32 = CID_CAMERA_CLASS_BASE + 32; 1130 | pub const CID_TILT_SPEED: u32 = CID_CAMERA_CLASS_BASE + 33; 1131 | pub const CID_FM_TX_CLASS_BASE: u32 = CLASS_FM_TX | 0x900; 1132 | pub const CID_FM_TX_CLASS: u32 = CLASS_FM_TX | 1; 1133 | pub const CID_RDS_TX_DEVIATION: u32 = CID_FM_TX_CLASS_BASE + 1; 1134 | pub const CID_RDS_TX_PI: u32 = CID_FM_TX_CLASS_BASE + 2; 1135 | pub const CID_RDS_TX_PTY: u32 = CID_FM_TX_CLASS_BASE + 3; 1136 | pub const CID_RDS_TX_PS_NAME: u32 = CID_FM_TX_CLASS_BASE + 5; 1137 | pub const CID_RDS_TX_RADIO_TEXT: u32 = CID_FM_TX_CLASS_BASE + 6; 1138 | pub const CID_RDS_TX_MONO_STEREO: u32 = CID_FM_TX_CLASS_BASE + 7; 1139 | pub const CID_RDS_TX_ARTIFICIAL_HEAD: u32 = CID_FM_TX_CLASS_BASE + 8; 1140 | pub const CID_RDS_TX_COMPRESSED: u32 = CID_FM_TX_CLASS_BASE + 9; 1141 | pub const CID_RDS_TX_DYNAMIC_PTY: u32 = CID_FM_TX_CLASS_BASE + 10; 1142 | pub const CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: u32 = CID_FM_TX_CLASS_BASE + 11; 1143 | pub const CID_RDS_TX_TRAFFIC_PROGRAM: u32 = CID_FM_TX_CLASS_BASE + 12; 1144 | pub const CID_RDS_TX_MUSIC_SPEECH: u32 = CID_FM_TX_CLASS_BASE + 13; 1145 | pub const CID_RDS_TX_ALT_FREQS_ENABLE: u32 = CID_FM_TX_CLASS_BASE + 14; 1146 | pub const CID_RDS_TX_ALT_FREQS: u32 = CID_FM_TX_CLASS_BASE + 15; 1147 | pub const CID_AUDIO_LIMITER_ENABLED: u32 = CID_FM_TX_CLASS_BASE + 64; 1148 | pub const CID_AUDIO_LIMITER_RELEASE_TIME: u32 = CID_FM_TX_CLASS_BASE + 65; 1149 | pub const CID_AUDIO_LIMITER_DEVIATION: u32 = CID_FM_TX_CLASS_BASE + 66; 1150 | pub const CID_AUDIO_COMPRESSION_ENABLED: u32 = CID_FM_TX_CLASS_BASE + 80; 1151 | pub const CID_AUDIO_COMPRESSION_GAIN: u32 = CID_FM_TX_CLASS_BASE + 81; 1152 | pub const CID_AUDIO_COMPRESSION_THRESHOLD: u32 = CID_FM_TX_CLASS_BASE + 82; 1153 | pub const CID_AUDIO_COMPRESSION_ATTACK_TIME: u32 = CID_FM_TX_CLASS_BASE + 83; 1154 | pub const CID_AUDIO_COMPRESSION_RELEASE_TIME: u32 = CID_FM_TX_CLASS_BASE + 84; 1155 | pub const CID_PILOT_TONE_ENABLED: u32 = CID_FM_TX_CLASS_BASE + 96; 1156 | pub const CID_PILOT_TONE_DEVIATION: u32 = CID_FM_TX_CLASS_BASE + 97; 1157 | pub const CID_PILOT_TONE_FREQUENCY: u32 = CID_FM_TX_CLASS_BASE + 98; 1158 | pub const CID_TUNE_PREEMPHASIS: u32 = CID_FM_TX_CLASS_BASE + 112; 1159 | pub const PREEMPHASIS_DISABLED: u32 = 0; 1160 | pub const PREEMPHASIS_50_uS: u32 = 1; 1161 | pub const PREEMPHASIS_75_uS: u32 = 2; 1162 | pub const CID_TUNE_POWER_LEVEL: u32 = CID_FM_TX_CLASS_BASE + 113; 1163 | pub const CID_TUNE_ANTENNA_CAPACITOR: u32 = CID_FM_TX_CLASS_BASE + 114; 1164 | pub const CID_FLASH_CLASS_BASE: u32 = CLASS_FLASH | 0x900; 1165 | pub const CID_FLASH_CLASS: u32 = CLASS_FLASH | 1; 1166 | pub const CID_FLASH_LED_MODE: u32 = CID_FLASH_CLASS_BASE + 1; 1167 | pub const FLASH_LED_MODE_NONE: u32 = 0; 1168 | pub const FLASH_LED_MODE_FLASH: u32 = 1; 1169 | pub const FLASH_LED_MODE_TORCH: u32 = 2; 1170 | pub const CID_FLASH_STROBE_SOURCE: u32 = CID_FLASH_CLASS_BASE + 2; 1171 | pub const FLASH_STROBE_SOURCE_SOFTWARE: u32 = 0; 1172 | pub const FLASH_STROBE_SOURCE_EXTERNAL: u32 = 1; 1173 | pub const CID_FLASH_STROBE: u32 = CID_FLASH_CLASS_BASE + 3; 1174 | pub const CID_FLASH_STROBE_STOP: u32 = CID_FLASH_CLASS_BASE + 4; 1175 | pub const CID_FLASH_STROBE_STATUS: u32 = CID_FLASH_CLASS_BASE + 5; 1176 | pub const CID_FLASH_TIMEOUT: u32 = CID_FLASH_CLASS_BASE + 6; 1177 | pub const CID_FLASH_INTENSITY: u32 = CID_FLASH_CLASS_BASE + 7; 1178 | pub const CID_FLASH_TORCH_INTENSITY: u32 = CID_FLASH_CLASS_BASE + 8; 1179 | pub const CID_FLASH_INDICATOR_INTENSITY: u32 = CID_FLASH_CLASS_BASE + 9; 1180 | pub const CID_FLASH_FAULT: u32 = CID_FLASH_CLASS_BASE + 10; 1181 | pub const FLASH_FAULT_OVER_VOLTAGE: u32 = 1; 1182 | pub const FLASH_FAULT_TIMEOUT: u32 = 1 << 1; 1183 | pub const FLASH_FAULT_OVER_TEMPERATURE: u32 = 1 << 2; 1184 | pub const FLASH_FAULT_SHORT_CIRCUIT: u32 = 1 << 3; 1185 | pub const FLASH_FAULT_OVER_CURRENT: u32 = 1 << 4; 1186 | pub const FLASH_FAULT_INDICATOR: u32 = 1 << 5; 1187 | pub const FLASH_FAULT_UNDER_VOLTAGE: u32 = 1 << 6; 1188 | pub const FLASH_FAULT_INPUT_VOLTAGE: u32 = 1 << 7; 1189 | pub const FLASH_FAULT_LED_OVER_TEMPERATURE: u32 = 1 << 8; 1190 | pub const CID_FLASH_CHARGE: u32 = CID_FLASH_CLASS_BASE + 11; 1191 | pub const CID_FLASH_READY: u32 = CID_FLASH_CLASS_BASE + 12; 1192 | pub const CID_JPEG_CLASS_BASE: u32 = CLASS_JPEG | 0x900; 1193 | pub const CID_JPEG_CLASS: u32 = CLASS_JPEG | 1; 1194 | pub const CID_JPEG_CHROMA_SUBSAMPLING: u32 = CID_JPEG_CLASS_BASE + 1; 1195 | pub const JPEG_CHROMA_SUBSAMPLING_444: u32 = 0; 1196 | pub const JPEG_CHROMA_SUBSAMPLING_422: u32 = 1; 1197 | pub const JPEG_CHROMA_SUBSAMPLING_420: u32 = 2; 1198 | pub const JPEG_CHROMA_SUBSAMPLING_411: u32 = 3; 1199 | pub const JPEG_CHROMA_SUBSAMPLING_410: u32 = 4; 1200 | pub const JPEG_CHROMA_SUBSAMPLING_GRAY: u32 = 5; 1201 | pub const CID_JPEG_RESTART_INTERVAL: u32 = CID_JPEG_CLASS_BASE + 2; 1202 | pub const CID_JPEG_COMPRESSION_QUALITY: u32 = CID_JPEG_CLASS_BASE + 3; 1203 | pub const CID_JPEG_ACTIVE_MARKER: u32 = CID_JPEG_CLASS_BASE + 4; 1204 | pub const JPEG_ACTIVE_MARKER_APP0: u32 = 1; 1205 | pub const JPEG_ACTIVE_MARKER_APP1: u32 = 1 << 1; 1206 | pub const JPEG_ACTIVE_MARKER_COM: u32 = 1 << 16; 1207 | pub const JPEG_ACTIVE_MARKER_DQT: u32 = 1 << 17; 1208 | pub const JPEG_ACTIVE_MARKER_DHT: u32 = 1 << 18; 1209 | pub const CID_IMAGE_SOURCE_CLASS_BASE: u32 = CLASS_IMAGE_SOURCE | 0x900; 1210 | pub const CID_IMAGE_SOURCE_CLASS: u32 = CLASS_IMAGE_SOURCE | 1; 1211 | pub const CID_VBLANK: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 1; 1212 | pub const CID_HBLANK: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 2; 1213 | pub const CID_ANALOGUE_GAIN: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 3; 1214 | pub const CID_TEST_PATTERN_RED: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 4; 1215 | pub const CID_TEST_PATTERN_GREENR: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 5; 1216 | pub const CID_TEST_PATTERN_BLUE: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 6; 1217 | pub const CID_TEST_PATTERN_GREENB: u32 = CID_IMAGE_SOURCE_CLASS_BASE + 7; 1218 | pub const CID_IMAGE_PROC_CLASS_BASE: u32 = CLASS_IMAGE_PROC | 0x900; 1219 | pub const CID_IMAGE_PROC_CLASS: u32 = CLASS_IMAGE_PROC | 1; 1220 | pub const CID_LINK_FREQ: u32 = CID_IMAGE_PROC_CLASS_BASE + 1; 1221 | pub const CID_PIXEL_RATE: u32 = CID_IMAGE_PROC_CLASS_BASE + 2; 1222 | pub const CID_TEST_PATTERN: u32 = CID_IMAGE_PROC_CLASS_BASE + 3; 1223 | pub const CID_DV_CLASS_BASE: u32 = CLASS_DV | 0x900; 1224 | pub const CID_DV_CLASS: u32 = CLASS_DV | 1; 1225 | pub const CID_DV_TX_HOTPLUG: u32 = CID_DV_CLASS_BASE + 1; 1226 | pub const CID_DV_TX_RXSENSE: u32 = CID_DV_CLASS_BASE + 2; 1227 | pub const CID_DV_TX_EDID_PRESENT: u32 = CID_DV_CLASS_BASE + 3; 1228 | pub const CID_DV_TX_MODE: u32 = CID_DV_CLASS_BASE + 4; 1229 | pub const DV_TX_MODE_DVI_D: u32 = 0; 1230 | pub const DV_TX_MODE_HDMI: u32 = 1; 1231 | pub const CID_DV_TX_RGB_RANGE: u32 = CID_DV_CLASS_BASE + 5; 1232 | pub const DV_RGB_RANGE_AUTO: u32 = 0; 1233 | pub const DV_RGB_RANGE_LIMITED: u32 = 1; 1234 | pub const DV_RGB_RANGE_FULL: u32 = 2; 1235 | pub const CID_DV_RX_POWER_PRESENT: u32 = CID_DV_CLASS_BASE + 100; 1236 | pub const CID_DV_RX_RGB_RANGE: u32 = CID_DV_CLASS_BASE + 101; 1237 | pub const CID_FM_RX_CLASS_BASE: u32 = CLASS_FM_RX | 0x900; 1238 | pub const CID_FM_RX_CLASS: u32 = CLASS_FM_RX | 1; 1239 | pub const CID_TUNE_DEEMPHASIS: u32 = CID_FM_RX_CLASS_BASE + 1; 1240 | pub const DEEMPHASIS_DISABLED: u32 = PREEMPHASIS_DISABLED; 1241 | pub const DEEMPHASIS_50_uS: u32 = PREEMPHASIS_50_uS; 1242 | pub const DEEMPHASIS_75_uS: u32 = PREEMPHASIS_75_uS; 1243 | pub const CID_RDS_RECEPTION: u32 = CID_FM_RX_CLASS_BASE + 2; 1244 | pub const CID_RDS_RX_PTY: u32 = CID_FM_RX_CLASS_BASE + 3; 1245 | pub const CID_RDS_RX_PS_NAME: u32 = CID_FM_RX_CLASS_BASE + 4; 1246 | pub const CID_RDS_RX_RADIO_TEXT: u32 = CID_FM_RX_CLASS_BASE + 5; 1247 | pub const CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: u32 = CID_FM_RX_CLASS_BASE + 6; 1248 | pub const CID_RDS_RX_TRAFFIC_PROGRAM: u32 = CID_FM_RX_CLASS_BASE + 7; 1249 | pub const CID_RDS_RX_MUSIC_SPEECH: u32 = CID_FM_RX_CLASS_BASE + 8; 1250 | pub const CID_RF_TUNER_CLASS_BASE: u32 = CLASS_RF_TUNER | 0x900; 1251 | pub const CID_RF_TUNER_CLASS: u32 = CLASS_RF_TUNER | 1; 1252 | pub const CID_RF_TUNER_BANDWIDTH_AUTO: u32 = CID_RF_TUNER_CLASS_BASE + 11; 1253 | pub const CID_RF_TUNER_BANDWIDTH: u32 = CID_RF_TUNER_CLASS_BASE + 12; 1254 | pub const CID_RF_TUNER_LNA_GAIN_AUTO: u32 = CID_RF_TUNER_CLASS_BASE + 41; 1255 | pub const CID_RF_TUNER_LNA_GAIN: u32 = CID_RF_TUNER_CLASS_BASE + 42; 1256 | pub const CID_RF_TUNER_MIXER_GAIN_AUTO: u32 = CID_RF_TUNER_CLASS_BASE + 51; 1257 | pub const CID_RF_TUNER_MIXER_GAIN: u32 = CID_RF_TUNER_CLASS_BASE + 52; 1258 | pub const CID_RF_TUNER_IF_GAIN_AUTO: u32 = CID_RF_TUNER_CLASS_BASE + 61; 1259 | pub const CID_RF_TUNER_IF_GAIN: u32 = CID_RF_TUNER_CLASS_BASE + 62; 1260 | pub const CID_RF_TUNER_PLL_LOCK: u32 = CID_RF_TUNER_CLASS_BASE + 91; 1261 | pub const CID_DETECT_CLASS_BASE: u32 = CLASS_DETECT | 0x900; 1262 | pub const CID_DETECT_CLASS: u32 = CLASS_DETECT | 1; 1263 | pub const CID_DETECT_MD_MODE: u32 = CID_DETECT_CLASS_BASE + 1; 1264 | pub const DETECT_MD_MODE_DISABLED: u32 = 0; 1265 | pub const DETECT_MD_MODE_GLOBAL: u32 = 1; 1266 | pub const DETECT_MD_MODE_THRESHOLD_GRID: u32 = 2; 1267 | pub const DETECT_MD_MODE_REGION_GRID: u32 = 3; 1268 | pub const CID_DETECT_MD_GLOBAL_THRESHOLD: u32 = CID_DETECT_CLASS_BASE + 2; 1269 | pub const CID_DETECT_MD_THRESHOLD_GRID: u32 = CID_DETECT_CLASS_BASE + 3; 1270 | pub const CID_DETECT_MD_REGION_GRID: u32 = CID_DETECT_CLASS_BASE + 4; 1271 | } 1272 | 1273 | // IOCTL codes. 1274 | pub const VIDIOC_ENUM_FMT: usize = 3225441794; 1275 | pub const VIDIOC_ENUM_FRAMEINTERVALS: usize = 3224655435; 1276 | pub const VIDIOC_ENUM_FRAMESIZES: usize = 3224131146; 1277 | pub const VIDIOC_G_CTRL: usize = 3221771803; 1278 | pub const VIDIOC_QUERYCTRL: usize = 3225703972; 1279 | pub const VIDIOC_QUERY_EXT_CTRL: usize = 3236451943; 1280 | pub const VIDIOC_QUERYMENU: usize = 3224131109; 1281 | pub const VIDIOC_REQBUFS: usize = 3222558216; 1282 | pub const VIDIOC_S_PARM: usize = 3234616854; 1283 | #[cfg(target_os = "linux")] 1284 | pub const VIDIOC_STREAMOFF: usize = 1074026003; 1285 | #[cfg(target_os = "freebsd")] 1286 | pub const VIDIOC_STREAMOFF: usize = 2147767827; 1287 | #[cfg(target_os = "linux")] 1288 | pub const VIDIOC_STREAMON: usize = 1074026002; 1289 | #[cfg(target_os = "freebsd")] 1290 | pub const VIDIOC_STREAMON: usize = 2147767826; 1291 | 1292 | #[cfg(target_pointer_width = "64")] 1293 | pub const VIDIOC_DQBUF: usize = 3227014673; 1294 | #[cfg(target_pointer_width = "32")] 1295 | pub const VIDIOC_DQBUF: usize = 3225703953; 1296 | 1297 | #[cfg(target_pointer_width = "64")] 1298 | pub const VIDIOC_QBUF: usize = 3227014671; 1299 | #[cfg(target_pointer_width = "32")] 1300 | pub const VIDIOC_QBUF: usize = 3225703951; 1301 | 1302 | #[cfg(target_pointer_width = "64")] 1303 | pub const VIDIOC_QUERYBUF: usize = 3227014665; 1304 | #[cfg(target_pointer_width = "32")] 1305 | pub const VIDIOC_QUERYBUF: usize = 3225703945; 1306 | 1307 | #[cfg(target_pointer_width = "64")] 1308 | pub const VIDIOC_S_FMT: usize = 3234878981; 1309 | #[cfg(target_pointer_width = "32")] 1310 | pub const VIDIOC_S_FMT: usize = 3234616837; 1311 | 1312 | #[cfg(target_pointer_width = "64")] 1313 | pub const VIDIOC_G_EXT_CTRLS: usize = 3223344711; 1314 | #[cfg(target_pointer_width = "32")] 1315 | pub const VIDIOC_G_EXT_CTRLS: usize = 3222820423; 1316 | 1317 | #[cfg(target_pointer_width = "64")] 1318 | pub const VIDIOC_S_EXT_CTRLS: usize = 3223344712; 1319 | #[cfg(target_pointer_width = "32")] 1320 | pub const VIDIOC_S_EXT_CTRLS: usize = 3222820424; 1321 | 1322 | #[test] 1323 | fn test_sizes() { 1324 | if cfg!(target_pointer_width = "64") { 1325 | assert_eq!(mem::size_of::(), 208); 1326 | } else { 1327 | assert_eq!(mem::size_of::(), 204); 1328 | } 1329 | 1330 | if cfg!(target_pointer_width = "64") { 1331 | assert_eq!(mem::size_of::(), 88); 1332 | } else { 1333 | assert_eq!(mem::size_of::(), 68); 1334 | } 1335 | 1336 | assert_eq!(mem::size_of::(), 204); 1337 | assert_eq!(mem::size_of::(), 64); 1338 | assert_eq!(mem::size_of::(), 44); 1339 | assert_eq!(mem::size_of::(), 52); 1340 | assert_eq!(mem::size_of::(), 68); 1341 | assert_eq!(mem::size_of::(), 232); 1342 | assert_eq!(mem::size_of::(), 44); 1343 | assert_eq!(mem::size_of::(), 8); 1344 | assert_eq!(mem::size_of::(), 20); 1345 | 1346 | if cfg!(target_pointer_width = "64") { 1347 | assert_eq!(mem::size_of::>(), 32); 1348 | } else { 1349 | assert_eq!(mem::size_of::>(), 24); 1350 | } 1351 | } 1352 | --------------------------------------------------------------------------------