2个版本
0.1.1 | 2023年8月5日 |
---|---|
0.1.0 | 2023年5月22日 |
#756 in Unix API
67 每月下载量
240KB
6.5K SLoC
Linux V4L2 API for Rust
这个crate旨在提供对Linux V4L2 API的无限制访问。
主要设计目标是安全性和开销之间的最佳平衡。实现方式比v4l更接近系统调用。接口类型封装内核类型以避免不必要的复制。
次要目标是提供原始API的全部功能集。
最终,这是我谦虚地尝试正确做事的努力。
Crates
- linux-video-core - 核心抽象和底层接口(不面向最终用户)
- linux-video - 仅支持同步操作的同步接口
- tokio-linux-video - 面向tokio用户的异步接口
- async-std-linux-video - 面向async-std用户的异步接口
使用示例
枚举设备
use linux_video::Device;
fn main() -> std::io::Result<()> {
let mut devs = Device::list()?;
while let Some(path) = devs.fetch_next()? {
let dev = Device::open(&path)?;
let caps = dev.capabilities()?;
println!("path: {}, {caps}", path.display());
}
Ok(())
}
获取功能和控制
use linux_video::Device;
fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0")?;
let caps = dev.capabilities()?;
println!("Capabilities: {caps}");
println!("Controls:");
let mut controls = dev.controls(None);
while let Some(ctrl) = controls.fetch_next()? {
println!(" {ctrl}");
if let Some(mut items) = dev.control_items(&ctrl) {
while let Some(item) = items.fetch_next()? {
println!(" {item}");
}
}
}
Ok(())
}
获取支持格式
use linux_video::{types::BufferType, Device};
fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0")?;
let caps = dev.capabilities()?;
for type_ in BufferType::ALL {
if type_.is_supported(caps.capabilities()) {
println!("{type_} formats:");
let mut fmts = dev.formats(type_);
if let Some(fmt) = fmts.fetch_next()? {
println!(" {fmt}");
if type_.content().is_video() {
let mut sizes = dev.sizes(fmt.pixel_format());
while let Some(size) = sizes.fetch_next()? {
println!(" {size}");
for size in size.sizes() {
println!(" {size}");
let mut intervals = dev.intervals(fmt.pixel_format(), size.width(), size.height());
while let Some(interval) = intervals.fetch_next()? {
println!(" {interval}");
}
}
}
}
}
}
}
Ok(())
}
使用控制
use linux_video::{types::*, Device};
fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0")?;
// Get control from device by identifier
let contrast_ctrl = dev.control(CtrlId::Contrast)?;
// Create a value for control
let mut contrast = Value::from(&contrast_ctrl);
// Get control value from device
dev.get_control(&mut contrast)?;
// Get reference to value data
let contrast_value = contrast.try_ref::<i32>().unwrap();
println!("Current contrast: {contrast_value:?}");
// Set new value by reference
*contrast.try_mut::<i32>().unwrap() = contrast_value + 10;
println!("Updated contrast: {:?}", contrast.try_ref::<i32>().unwrap());
// Set new control value to device
dev.set_control(&contrast)?;
Ok(())
}
捕获视频数据
use linux_video::{types::*, Device};
fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0")?;
// Get current format
let mut fmt = dev.format(BufferType::VideoOutput)?;
println!(" {fmt}");
// Start video capture stream
let stream = dev.stream::<In, Mmap>(ContentType::Video, 4)?;
let mut i = 0;
while let Ok(buffer) = stream.next() {
let buffer = buffer.lock();
println!("#{i} {buffer}");
// Get reference to frame buffer contents
let _data: &[u8] = buffer.as_ref();
i += 1;
if i > 30 {
break;
}
}
Ok(())
}
输出视频数据
use linux_video::{types::*, Device};
fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0")?;
// Get current format
let mut fmt = dev.format(BufferType::VideoOutput)?;
println!(" {fmt}");
// Start video output stream
let stream = dev.stream::<Out, Mmap>(ContentType::Video, 4)?;
let mut i = 0;
while let Ok(mut buffer) = stream.next() {
let mut buffer = buffer.lock();
println!("#{i} {buffer}");
// Get reference to frame buffer contents
let _data: &mut [u8] = buffer.as_mut();
i += 1;
if i > 30 {
break;
}
}
Ok(())
}
依赖关系
~6.5MB
~130K SLoC