diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f70c471 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: cargo + directory: / + schedule: + interval: weekly + - package-ecosystem: github-actions + directory: /.github/workflows/ + schedule: + interval: weekly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d8af7d..9576516 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-20.04 steps: - run: sudo apt-get install libv4l-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-20.04 steps: - run: sudo apt-get install libv4l-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -53,7 +53,7 @@ jobs: name: Rustfmt runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -70,7 +70,7 @@ jobs: runs-on: ubuntu-20.04 steps: - run: sudo apt-get install libv4l-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: profile: minimal @@ -93,7 +93,7 @@ jobs: runs-on: ubuntu-20.04 steps: - run: sudo apt-get install libv4l-dev - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/CHANGELOG.md b/CHANGELOG.md index f2ec853..eaeaeef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,15 @@ Multi-planar capture will not be targeted in the near future unless someone else ### Added - Basic multi-planar streaming support +## [0.14.0] - 2023-05-13 +### Added +- Expose raw file descriptor of streams through `Stream::handle()` +### Changed +- Updated `bindgen` dependency to 0.65.1 +### Fixed +- Use proper C FFI struct field for `Integer64` controls +- Fix example in README.md to account for the negotiated pixelformat + ## [0.13.1] - 2022-12-08 ### Fixed - Do not block when the device is disconnected diff --git a/Cargo.toml b/Cargo.toml index 381e95b..9832faf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,14 +9,14 @@ readme = "README.md" repository= "https://github.com/raymanfx/libv4l-rs" [dependencies] -bitflags = "1.2.1" +bitflags = "2" libc = "0.2" -v4l-sys = { path = "v4l-sys", version = "0.2.1", optional = true } -v4l2-sys = { path = "v4l2-sys", version = "0.2.1", package="v4l2-sys-mit", optional = true } +v4l-sys = { path = "v4l-sys", version = "0.3.0", optional = true } +v4l2-sys = { path = "v4l2-sys", version = "0.3.0", package="v4l2-sys-mit", optional = true } [dev-dependencies] glium = "0.27.0" -jpeg-decoder = "0.2.1" +jpeg-decoder = "0.3.0" [features] default = ["v4l2"] diff --git a/README.md b/README.md index 2fcd7bd..5c8206e 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ fn main() { fmt.width = 1280; fmt.height = 720; fmt.fourcc = FourCC::new(b"YUYV"); - dev.set_format(&fmt).expect("Failed to write format"); + let fmt = dev.set_format(&fmt).expect("Failed to write format"); // The actual format chosen by the device driver may differ from what we // requested! Print it out to get an idea of what is actually used now. diff --git a/src/buffer.rs b/src/buffer.rs index 4c30dcd..8d5fd01 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -1,4 +1,3 @@ -use bitflags::bitflags; use std::fmt; use crate::timestamp::Timestamp; @@ -39,8 +38,8 @@ impl Type { } } -bitflags! { - #[allow(clippy::unreadable_literal)] +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Flags: u32 { /// Buffer is mapped const MAPPED = 0x00000001; @@ -91,7 +90,7 @@ impl Default for Flags { impl From for Flags { fn from(flags: u32) -> Self { - Self::from_bits_truncate(flags) + Self::from_bits_retain(flags) } } diff --git a/src/capability.rs b/src/capability.rs index 60bb6a7..835e2e6 100644 --- a/src/capability.rs +++ b/src/capability.rs @@ -1,10 +1,9 @@ -use bitflags::bitflags; use std::{fmt, str}; use crate::v4l_sys::*; -bitflags! { - #[allow(clippy::unreadable_literal)] +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Flags: u32 { const VIDEO_CAPTURE = 0x00000001; const VIDEO_OUTPUT = 0x00000002; @@ -46,7 +45,7 @@ bitflags! { impl From for Flags { fn from(flags: u32) -> Self { - Self::from_bits_truncate(flags) + Self::from_bits_retain(flags) } } diff --git a/src/control.rs b/src/control.rs index 5736ad7..db434af 100644 --- a/src/control.rs +++ b/src/control.rs @@ -1,4 +1,3 @@ -use bitflags::bitflags; use std::convert::{TryFrom, TryInto}; use std::{ffi, fmt, mem, str}; @@ -63,8 +62,8 @@ impl fmt::Display for Type { } } -bitflags! { - #[allow(clippy::unreadable_literal)] +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Flags: u32 { const DISABLED = 0x0001; const GRABBED = 0x0002; @@ -85,7 +84,7 @@ bitflags! { impl From for Flags { fn from(flags: u32) -> Self { - Self::from_bits_truncate(flags) + Self::from_bits_retain(flags) } } diff --git a/src/device.rs b/src/device.rs index c67e8c5..356f6af 100644 --- a/src/device.rs +++ b/src/device.rs @@ -5,11 +5,11 @@ use std::{io, mem}; use libc; -use crate::control; +use crate::capability::Capabilities; +use crate::control::{self, Control, Description}; use crate::v4l2; use crate::v4l2::videodev::v4l2_ext_controls; use crate::v4l_sys::*; -use crate::{capability::Capabilities, control::Control}; pub const PLANES_ONE: bool = false; pub const PLANES_MANY: bool = true; @@ -100,7 +100,7 @@ impl Device { } /// Returns the supported controls for a device such as gain, focus, white balance, etc. - pub fn query_controls(&self) -> io::Result> { + pub fn query_controls(&self) -> io::Result> { let mut controls = Vec::new(); unsafe { let mut v4l2_ctrl: v4l2_query_ext_ctrl = mem::zeroed(); @@ -115,7 +115,7 @@ impl Device { ) { Ok(_) => { // get the basic control information - let mut control = control::Description::from(v4l2_ctrl); + let mut control = Description::from(v4l2_ctrl); // if this is a menu control, enumerate its items if control.typ == control::Type::Menu @@ -175,29 +175,16 @@ impl Device { Ok(controls) } - /// Returns the control value for an ID + /// Returns the current control value from its [`Description`] /// /// # Arguments /// - /// * `id` - Control identifier - pub fn control(&self, id: u32) -> io::Result { + /// * `desc` - Control description + pub fn control(&self, desc: &Description) -> io::Result { unsafe { - let mut queryctrl = v4l2_query_ext_ctrl { - id, - ..mem::zeroed() - }; - v4l2::ioctl( - self.handle().fd(), - v4l2::vidioc::VIDIOC_QUERY_EXT_CTRL, - &mut queryctrl as *mut _ as *mut std::os::raw::c_void, - )?; - - // determine the control type - let description = control::Description::from(queryctrl); - // query the actual control value let mut v4l2_ctrl = v4l2_ext_control { - id, + id: desc.id, ..mem::zeroed() }; let mut v4l2_ctrls = v4l2_ext_controls { @@ -211,7 +198,7 @@ impl Device { &mut v4l2_ctrls as *mut _ as *mut std::os::raw::c_void, )?; - let value = match description.typ { + let value = match desc.typ { control::Type::Integer64 => { control::Value::Integer(v4l2_ctrl.__bindgen_anon_1.value64) } @@ -229,7 +216,7 @@ impl Device { } }; - Ok(Control { id, value }) + Ok(Control { id: desc.id, value }) } } diff --git a/src/format/description.rs b/src/format/description.rs index 9c71b33..e5f0039 100644 --- a/src/format/description.rs +++ b/src/format/description.rs @@ -1,11 +1,10 @@ -use bitflags::bitflags; use std::{fmt, str}; use crate::format::FourCC; use crate::v4l_sys::*; -bitflags! { - #[allow(clippy::unreadable_literal)] +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Flags : u32 { const COMPRESSED = 0x0001; const EMULATED = 0x0002; @@ -16,7 +15,7 @@ bitflags! { impl From for Flags { fn from(flags: u32) -> Self { - Self::from_bits_truncate(flags) + Self::from_bits_retain(flags) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index d44bf2e..3500629 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -1,4 +1,3 @@ -use bitflags::bitflags; use std::{convert::TryFrom, fmt, mem}; use crate::v4l_sys::*; @@ -21,8 +20,8 @@ pub use quantization::Quantization; pub mod transfer; pub use transfer::TransferFunction; -bitflags! { - #[allow(clippy::unreadable_literal)] +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Flags : u32 { const PREMUL_ALPHA = 0x00000001; } @@ -30,7 +29,7 @@ bitflags! { impl From for Flags { fn from(flags: u32) -> Self { - Self::from_bits_truncate(flags) + Self::from_bits_retain(flags) } } diff --git a/src/io/mmap/arena.rs b/src/io/mmap/arena.rs index 2d6dd97..4852a09 100644 --- a/src/io/mmap/arena.rs +++ b/src/io/mmap/arena.rs @@ -106,17 +106,21 @@ impl<'a> Arena<'a> { // each plane has to be mapped separately let mut planes = Vec::new(); for plane in &v4l2_planes { + let (length, offset) = if !self.buf_type.planar() { + (v4l2_buf.length as usize, v4l2_buf.m.offset as libc::off_t) + } else { + (plane.length as usize, plane.m.mem_offset as libc::off_t) + }; let ptr = v4l2::mmap( ptr::null_mut(), - plane.length as usize, + length, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED, self.handle.fd(), - plane.m.mem_offset as libc::off_t, + offset, )?; - planes.push(slice::from_raw_parts_mut::( - ptr as *mut u8, plane.length as usize + ptr as *mut u8, length, )); } diff --git a/src/parameters.rs b/src/parameters.rs index 713d432..a46b0c0 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -1,16 +1,15 @@ -use bitflags::bitflags; use std::fmt; -bitflags! { +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Capabilities: u32 { - #[allow(clippy::unreadable_literal)] const TIME_PER_FRAME = 0x1000; } } impl From for Capabilities { fn from(caps: u32) -> Self { - Self::from_bits_truncate(caps) + Self::from_bits_retain(caps) } } diff --git a/src/v4l2/api.rs b/src/v4l2/api.rs index a832122..0f6fb1d 100644 --- a/src/v4l2/api.rs +++ b/src/v4l2/api.rs @@ -40,7 +40,7 @@ mod detail { ) -> *mut std::os::raw::c_void { // libv4l expects `request` to be a u64, but this is not guaranteed on all platforms. // For the default CI platform (x86_64) clippy will complain about a useless conversion. - #![allow(clippy::useless_conversion)] + #![allow(clippy::useless_conversion, clippy::unnecessary_cast)] v4l2_mmap( start, length.try_into().expect("usize -> c size_t failed"), @@ -51,6 +51,7 @@ mod detail { ) } pub unsafe fn munmap(start: *mut std::os::raw::c_void, length: usize) -> std::os::raw::c_int { + #![allow(clippy::useless_conversion)] v4l2_munmap(start, length.try_into().expect("usize -> c size_t failed")) } } diff --git a/src/video/capture/parameters.rs b/src/video/capture/parameters.rs index 644596f..1a3a89f 100644 --- a/src/video/capture/parameters.rs +++ b/src/video/capture/parameters.rs @@ -1,11 +1,11 @@ -use bitflags::bitflags; use std::{fmt, mem}; use crate::fraction::Fraction; use crate::parameters::Capabilities; use crate::v4l_sys::*; -bitflags! { +bitflags::bitflags! { + #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub struct Modes: u32 { const HIGH_QUALITY = 0x1000; } @@ -13,7 +13,7 @@ bitflags! { impl From for Modes { fn from(caps: u32) -> Self { - Self::from_bits_truncate(caps) + Self::from_bits_retain(caps) } } diff --git a/v4l-sys/Cargo.toml b/v4l-sys/Cargo.toml index 4382ae1..f0f7f1c 100644 --- a/v4l-sys/Cargo.toml +++ b/v4l-sys/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "v4l-sys" description = "Raw video4linux (v4l) bindings" -version = "0.2.1" +version = "0.3.0" authors = ["Christopher N. Hesse "] edition = "2018" license = "MIT" -links = "v4l1 v4l2 4lconvert" +links = "v4l1 v4l2 v4lconvert" build = "build.rs" [build-dependencies] -bindgen = "0.59" +bindgen = "0.69.1" diff --git a/v4l-sys/src/lib.rs b/v4l-sys/src/lib.rs index f8d806e..e534a8b 100644 --- a/v4l-sys/src/lib.rs +++ b/v4l-sys/src/lib.rs @@ -3,7 +3,5 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(non_upper_case_globals)] -// https://github.com/rust-lang/rust-bindgen/issues/1651 -#![allow(unaligned_references)] include!(concat!(env!("OUT_DIR"), "/libv4l_bindings.rs")); diff --git a/v4l2-sys/Cargo.toml b/v4l2-sys/Cargo.toml index eb6442e..c1dd6bc 100644 --- a/v4l2-sys/Cargo.toml +++ b/v4l2-sys/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "v4l2-sys-mit" description = "Raw v4l2 bindings (MIT licensed)" -version = "0.2.1" +version = "0.3.0" authors = ["Christopher N. Hesse "] edition = "2018" license = "MIT" build = "build.rs" [build-dependencies] -bindgen = "0.59" +bindgen = "0.69.1" diff --git a/v4l2-sys/src/lib.rs b/v4l2-sys/src/lib.rs index 3a7885b..1c2f4ec 100644 --- a/v4l2-sys/src/lib.rs +++ b/v4l2-sys/src/lib.rs @@ -3,7 +3,5 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(non_upper_case_globals)] -// https://github.com/rust-lang/rust-bindgen/issues/1651 -#![allow(unaligned_references)] include!(concat!(env!("OUT_DIR"), "/v4l2_bindings.rs"));