2 个版本
0.1.1 | 2023年8月5日 |
---|---|
0.1.0 | 2023年5月22日 |
#5 in #v4l
240KB
6.5K SLoC
Async-std 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 async_std_linux_video::Device;
#[async_std::main]
async fn main() -> std::io::Result<()> {
let mut devs = Device::list().await?;
while let Some(path) = devs.fetch_next().await? {
let dev = Device::open(&path).await?;
let caps = dev.capabilities().await?;
println!("path: {}, {caps}", path.display());
}
Ok(())
}
获取功能和控件
use async_std_linux_video::Device;
#[async_std::main]
async fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0").await?;
let caps = dev.capabilities().await?;
println!("Capabilities: {caps}");
println!("Controls:");
let mut controls = dev.controls(None);
while let Some(ctrl) = controls.fetch_next().await? {
println!(" {ctrl}");
if let Some(mut items) = dev.control_items(&ctrl) {
while let Some(item) = items.fetch_next().await? {
println!(" {item}");
}
}
}
Ok(())
}
获取支持的格式
use async_std_linux_video::{types::BufferType, Device};
#[async_std::main]
async fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0").await?;
let caps = dev.capabilities().await?;
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().await? {
println!(" {fmt}");
if type_.content().is_video() {
let mut sizes = dev.sizes(fmt.pixel_format());
while let Some(size) = sizes.fetch_next().await? {
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().await? {
println!(" {interval}");
}
}
}
}
}
}
}
Ok(())
}
使用控件
use async_std_linux_video::{types::*, Device};
#[async_std::main]
async fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0").await?;
// Get control from device by identifier
let contrast_ctrl = dev.control(CtrlId::Contrast).await?;
// Create a value for control
let mut contrast = Value::from(&contrast_ctrl);
// Get control value from device
dev.get_control(&mut contrast).await?;
// 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).await?;
Ok(())
}
捕获视频数据
use async_std_linux_video::{types::*, Device};
#[async_std::main]
async fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0").await?;
// Get current format
let mut fmt = dev.format(BufferType::VideoCapture).await?;
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().await {
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 async_std_linux_video::{types::*, Device};
#[async_std::main]
async fn main() -> std::io::Result<()> {
let dev = Device::open("/dev/video0").await?;
// Get current format
let mut fmt = dev.format(BufferType::VideoOutput).await?;
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().await {
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(())
}
依赖项
~8–19MB
~276K SLoC