raymanfx / libv4l-rs Goto Github PK
View Code? Open in Web Editor NEWVideo4Linux2 bindings for Rust
License: MIT License
Video4Linux2 bindings for Rust
License: MIT License
I noticed a low FPS on my camera while using the crate, I think this may be the cause:
If .start()
has not been called, calling the .next()
method on an MMapStream
queues all the buffers.
If .start()
has been called it attempts to queue a single buffer.
Manually queuing the buffers at start can then cause an InvalidInput
on the first call to .next()
as it tries to re-queue the buffer.
let buffer_count = 4;
let v4l2_device = v4l::Device::with_path("/dev/video0").expect("failed to open video");
let mut stream = mmap::Stream::with_buffers(&v4l2_device, Type::VideoCapture, buffer_count)
.expect("failed to create stream");
stream.start().expect("failed to start stream");
loop {
let (_, meta) = stream.next().expect("failed to get image");
println!("seq: {}, timestamp: {}", meta.sequence, meta.timestamp);
}
InvalidInput
let buffer_count = 4;
let v4l2_device = v4l::Device::with_path("/dev/video0").expect("failed to open video");
let mut stream = mmap::Stream::with_buffers(&v4l2_device, Type::VideoCapture, buffer_count)
.expect("failed to create stream");
for index in 0..buffer_count as usize {
stream.queue(index).expect("failed to queue buffer");
}
stream.start().expect("failed to start stream");
loop {
let (_, meta) = stream.next().expect("failed to get image"); // <-- fails here
println!("seq: {}, timestamp: {}", meta.sequence, meta.timestamp);
}
let buffer_count = 4;
let v4l2_device = v4l::Device::with_path("/dev/video0").expect("failed to open video");
let mut stream = mmap::Stream::with_buffers(&v4l2_device, Type::VideoCapture, buffer_count)
.expect("failed to create stream");
for index in 1..buffer_count as usize {
stream.queue(index).expect("failed to queue buffer");
}
stream.start().expect("failed to start stream");
loop {
let (_, meta) = stream.next().expect("failed to get image");
println!("seq: {}, timestamp: {}", meta.sequence, meta.timestamp);
}
Hi, there is a panic happening when using this lib inside an i.MX 8M Plus
:
v4l-0.14.0/src/control.rs:172:45: called Result::unwrap() on an Err value: ()
Maybe we are missing part of the specification?
Below is the output of v4l2-ctl --list-ctrls-menus
for both devices available:
root@ucm-imx8m-plus:~# v4l2-ctl --list-ctrls-menus --device=/dev/video0
User Controls
rotate 0x00980922 (int) : min=0 max=270 step=90 default=0 value=0 flags=modify-layout
min_number_of_capture_buffers 0x00980927 (int) : min=1 max=16 step=1 default=1 value=1 flags=read-only, volatile
min_number_of_output_buffers 0x00980928 (int) : min=1 max=16 step=1 default=1 value=1 flags=read-only, volatile
get_max_roi_region_number 0x009819b2 (int) : min=0 max=8 step=1 default=0 value=8 flags=read-only, volatile
vsi_priv_v4l2_roi_params_set 0x009819b3 (unknown): type=164 value=unsupported payload type flags=has-payload
get_max_ipcm_region_number 0x009819b4 (int) : min=0 max=2 step=1 default=0 value=2 flags=read-only, volatile
vsi_priv_v4l2_ipcm_params_set 0x009819b5 (unknown): type=165 value=unsupported payload type flags=has-payload
Codec Controls
video_b_frames 0x009909ca (int) : min=0 max=0 step=1 default=0 value=0 flags=update
video_gop_size 0x009909cb (int) : min=1 max=2147483647 step=1 default=30 value=30
video_bitrate_mode 0x009909ce (menu) : min=0 max=1 default=0 value=0 (Variable Bitrate) flags=update
0: Variable Bitrate
1: Constant Bitrate
video_bitrate 0x009909cf (int) : min=10000 max=288000000 step=1 default=2097152 value=2097152
frame_level_rate_control_enable 0x009909d7 (bool) : default=0 value=0
sequence_header_mode 0x009909d8 (menu) : min=0 max=1 default=1 value=1 (Joined With 1st Frame)
0: Separate Buffer
1: Joined With 1st Frame
h264_mb_level_rate_control 0x009909da (bool) : default=0 value=0
number_of_mbs_in_a_slice 0x009909dc (int) : min=1 max=120 step=1 default=1 value=1
slice_partitioning_method 0x009909dd (menu) : min=0 max=1 default=0 value=0 (Single)
0: Single
1: Max Macroblocks
repeat_sequence_header 0x009909e2 (bool) : default=1 value=1
force_key_frame 0x009909e5 (button) : value=0 flags=write-only, execute-on-write
h264_i_frame_qp_value 0x00990a5e (int) : min=-1 max=51 step=1 default=30 value=30
h264_p_frame_qp_value 0x00990a5f (int) : min=-1 max=51 step=1 default=30 value=30
h264_b_frame_qp_value 0x00990a60 (int) : min=-1 max=51 step=1 default=30 value=30
h264_minimum_qp_value 0x00990a61 (int) : min=0 max=51 step=1 default=0 value=0
h264_maximum_qp_value 0x00990a62 (int) : min=0 max=51 step=1 default=51 value=51
h264_cpb_buffer_size 0x00990a64 (int) : min=0 max=288000000 step=1 default=0 value=0
h264_level 0x00990a67 (menu) : min=0 max=15 default=14 value=14 (5)
0: 1
1: 1b
2: 1.1
3: 1.2
4: 1.3
5: 2
6: 2.1
7: 2.2
8: 3
9: 3.1
10: 3.2
11: 4
12: 4.1
13: 4.2
14: 5
15: 5.1
h264_profile 0x00990a6b (menu) : min=0 max=16 default=0 value=0 (Baseline)
0: Baseline
1: Constrained Baseline
2: Main
3: Extended
4: High
5: High 10
6: High 422
7: High 444 Predictive
8: High 10 Intra
9: High 422 Intra
10: High 444 Intra
11: CAVLC 444 Intra
12: Scalable Baseline
13: Scalable High
14: Scalable High Intra
15: Stereo High
16: Multiview High
h264_chroma_qp_index_offset 0x00990a80 (int) : min=-12 max=12 step=1 default=0 value=0
vpx_minimum_qp_value 0x00990afb (int) : min=0 max=127 step=1 default=0 value=0
vpx_maximum_qp_value 0x00990afc (int) : min=0 max=127 step=1 default=127 value=127
vpx_i_frame_qp_value 0x00990afd (int) : min=-1 max=127 step=1 default=30 value=30
vpx_p_frame_qp_value 0x00990afe (int) : min=-1 max=127 step=1 default=30 value=30
vp8_profile 0x00990aff (menu) : min=0 max=3 default=0 value=0 (0)
0: 0
1: 1
2: 2
3: 3
vp9_profile 0x00990b00 (menu) : min=0 max=3 default=0 value=0 (0)
0: 0
1: 1
2: 2
3: 3
hevc_minimum_qp_value 0x00990b58 (int) : min=0 max=51 step=1 default=0 value=0
hevc_maximum_qp_value 0x00990b59 (int) : min=0 max=51 step=1 default=51 value=51
hevc_i_frame_qp_value 0x00990b5a (int) : min=-1 max=51 step=1 default=30 value=30
hevc_p_frame_qp_value 0x00990b5b (int) : min=-1 max=51 step=1 default=30 value=30
hevc_profile 0x00990b67 (menu) : min=0 max=2 default=0 value=0 (Main)
0: Main
1: Main Still Picture
2: Main 10
hevc_level 0x00990b68 (menu) : min=0 max=8 default=7 value=7 (5)
0: 1
1: 2
2: 2.1
3: 3
4: 3.1
5: 4
6: 4.1
7: 5
8: 5.1
root@ucm-imx8m-plus:~# v4l2-ctl --list-ctrls-menus --device=/dev/video1
User Controls
min_number_of_capture_buffers 0x00980927 (int) : min=1 max=16 step=1 default=1 value=1 flags=read-only, volatile
min_number_of_output_buffers 0x00980928 (int) : min=1 max=16 step=1 default=1 value=1 flags=read-only, volatile
frame_disable_reorder_ctrl 0x009819b1 (bool) : default=0 value=0
vsi_get_10bit_meta 0x009819b6 (unknown): type=166 value=unsupported payload type flags=read-only, volatile, has-payload
en_disable_secure_mode 0x009819b7 (bool) : default=0 value=0
Codec Controls
h264_profile 0x00990a6b (menu) : min=0 max=16 default=0 value=0 (Baseline)
0: Baseline
1: Constrained Baseline
2: Main
3: Extended
4: High
5: High 10
6: High 422
7: High 444 Predictive
8: High 10 Intra
9: High 422 Intra
10: High 444 Intra
11: CAVLC 444 Intra
12: Scalable Baseline
13: Scalable High
14: Scalable High Intra
15: Stereo High
16: Multiview High
vp8_profile 0x00990aff (menu) : min=0 max=3 default=0 value=0 (0)
0: 0
1: 1
2: 2
3: 3
vp9_profile 0x00990b00 (menu) : min=0 max=3 default=0 value=0 (0)
0: 0
1: 1
2: 2
3: 3
hevc_profile 0x00990b67 (menu) : min=0 max=2 default=0 value=0 (Main)
0: Main
1: Main Still Picture
2: Main 10
Thanks
Its boring to have a for loop that iterates over each control and set_control to set the default value.
Minimal reproducible example:
extern crate clap;
extern crate v4l;
use clap::{App, Arg};
use v4l::prelude::*;
fn main() {
let matches = App::new("v4l device")
.version("0.2")
.author("Christopher N. Hesse <[email protected]>")
.about("Video4Linux device example")
.arg(
Arg::with_name("device")
.short("d")
.long("device")
.value_name("INDEX or PATH")
.help("Device node path or index (default: 0)")
.takes_value(true),
)
.get_matches();
// Determine which device to use
let mut path: String = matches
.value_of("device")
.unwrap_or("/dev/video0")
.to_string();
if path.parse::<u64>().is_ok() {
path = format!("/dev/video{}", path);
}
println!("Using device: {}\n", path);
let device = CaptureDevice::with_path(path).unwrap();
println!("Formats:");
for fmt in device.enum_formats().unwrap() {
println!("\t{:#?}", fmt.description);
println!("\t\tflags: {:#}", fmt.flags);
println!("\t\tformat: {:#}", fmt.fourcc);
}
}
Output:
v4l-rs-bug-repro is ๐ฆ v0.1.0 via ๐ฆ v1.45.2
โฏ RUST_BACKTRACE=1 cargo run -- --device=/dev/video2
Compiling v4l-rs-bug-repro v0.1.0 (/home/ibiyemi/projects/scratch/v4l-rs-bug-repro)
Finished dev [unoptimized + debuginfo] target(s) in 0.56s
Running `target/debug/v4l-rs-bug-repro --device=/dev/video2`
Using device: /dev/video2
Formats:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', src/main.rs:38:16
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/libunwind.rs:86
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:78
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:59
4: core::fmt::write
at src/libcore/fmt/mod.rs:1076
5: std::io::Write::write_fmt
at src/libstd/io/mod.rs:1537
6: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:62
7: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:49
8: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:198
9: std::panicking::default_hook
at src/libstd/panicking.rs:218
10: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:486
11: rust_begin_unwind
at src/libstd/panicking.rs:388
12: core::panicking::panic_fmt
at src/libcore/panicking.rs:101
13: core::option::expect_none_failed
at src/libcore/option.rs:1272
14: core::result::Result<T,E>::unwrap
at /home/ibiyemi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/result.rs:1005
15: v4l_rs_bug_repro::main
at src/main.rs:38
16: std::rt::lang_start::{{closure}}
at /home/ibiyemi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67
17: std::rt::lang_start_internal::{{closure}}
at src/libstd/rt.rs:52
18: std::panicking::try::do_call
at src/libstd/panicking.rs:297
19: std::panicking::try
at src/libstd/panicking.rs:274
20: std::panic::catch_unwind
at src/libstd/panic.rs:394
21: std::rt::lang_start_internal
at src/libstd/rt.rs:51
22: std::rt::lang_start
at /home/ibiyemi/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67
23: main
24: __libc_start_main
25: _start
Where /dev/video2
is a v4l2loopback
device with no capture formats.
Hi there,
I wanted to ask if this crate is still maintained and if you do not have the time to maintain it anymore could add a contributor who can review and merge the pull requests and publish new versions on crates.io.
This crate is really useful and in my opinion the best wrapper around v4l for rust currently.
I'd be happy to help here!
I am trying to minimize latency as much as possible, so i want to tell the stream to write directly into a region of memory i reserved elsewhere. Where another piece of my code reads out of it. Is that possible with this crate?
Hi, it seems that the 0.12.2 release has been already cut in 8ff1ecb, but https://crates.io/crates/v4l still shows 0.12.1 as the latest release. 0.12.2 contains a fix (#35) that seems to help us significantly, so it would be cool to get it out. Thanks!
CC @bschwind.
error: failed to run custom build command for `v4l2-sys-mit v0.2.0`
Caused by:
process didn't exit successfully: `/home/whqee/devel/rust/hello_v4l2/target/release/build/v4l2-sys-mit-e9452ce4c76c1710/build-script-build` (exit status: 101)
--- stderr
error: unknown target triple 'riscv64gc-unknown-linux-gnu', please use -triple or -arch
thread 'main' panicked at 'libclang error; possible causes include:
- Invalid flag syntax
- Unrecognized flags
- Invalid flag arguments
- File I/O errors
- Host vs. target architecture mismatch
If you encounter an error missing from this list, please file an issue or a PR!', /home/whqee/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.56.0/src/ir/context.rs:531:15
stack backtrace:
0: rust_begin_unwind
at /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/std/src/panicking.rs:575:5
1: core::panicking::panic_fmt
at /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/panicking.rs:64:14
2: core::panicking::panic_display
at /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/panicking.rs:147:5
3: core::panicking::panic_str
at /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/panicking.rs:131:5
4: core::option::expect_failed
at /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/option.rs:1924:5
5: core::option::Option<T>::expect
6: bindgen::ir::context::BindgenContext::new
7: bindgen::Bindings::generate
8: bindgen::Builder::generate
9: build_script_build::main
10: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
It would be nice to have a new release with the latest updates o the library!
Btw, long term fan!
the current version of v4l2-sys-mit on crates depends on bindgen 0.56, which in turns depends on nom 5.1.2
, which triggers cargo's future incompatibility warning:
warning: the following packages contain code that will be rejected by a future version of Rust: nom v5.1.2
the version in the git repository doesn't have this problem.
Hey, sorry for the issue.
I seem to be consistently getting about 7.5FPS running any capture examples (stream_forward_mmap
, stream_capture_mmap
). This happens even when varying the format that I'm using for the device.
I'm wondering if there could be something I'm doing wrong? the format I'm using doesn't even seem to support 7.5 FPS for any of it's formats... which is strange.
Let me know if there's any advice you can give me.
I'm trying to run a stream capture example on arm64 device and getting this type of error:
The application panicked (crashed).
Message: attempted to zero-initialize type `buffer::Metadata`, which is invalid
Location: library/core/src/panicking.rs:126
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ BACKTRACE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฎ 7 frames hidden โฎ
8: core::panicking::panic_nounwind_fmt::hef625da4d1887edc
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:96
9: core::panicking::panic_nounwind::h39541cbd5a72f09a
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:126
10: core::mem::zeroed::hffae7c8a55c7cecb
at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/mem/mod.rs:653
11: v4l::io::mmap::stream::Stream::with_buffers::h57158218617a1fba
at /home/noah/.cargo/git/checkouts/libv4l-rs-917e1f4ffd90b94a/9844291/src/io/mmap/stream.rs:55
12: lib::mediaengine::MediaEngine::process_video::{{closure}}::h36fd47a510f39921
As if it is enclosed in unsafe
this may be somehow expected, I guess, but how could I overcome this?
Or is this me lacking some compiler settings?
I am trying to execute your example but i am getting this error:
Stream couldn't started: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }
I am using pop-os 22.04 and using droidcam as a camera.
Hi
I'm using WSL 2 on windows 10 to cross compile eye-rs to Raspberry Pi 3B+ ( so armv7-unknown-linux-gnueabihf). However, when I build an example script it throws this:
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/v4l2/api.rs:65:52
|
65 | libc::mmap(start, length, prot, flags, fd, offset)
| ^^^^^^ expected `i32`, found `i64`
|
help: you can convert an `i64` to `i32` and panic if the converted value wouldn't fit
|
65 | libc::mmap(start, length, prot, flags, fd, offset.try_into().unwrap())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/buffers/userptr_manager.rs:106:38
|
106 | v4l2_buf.m.userptr = buf.as_ptr() as u64;
| ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64`
|
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit
|
106 | v4l2_buf.m.userptr = (buf.as_ptr() as u64).try_into().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/buffers/userptr_manager.rs:147:34
|
147 | v4l2_buf.m.userptr = buf.as_ptr() as u64;
| ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64`
|
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit
|
147 | v4l2_buf.m.userptr = (buf.as_ptr() as u64).try_into().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/timestamp.rs:40:18
|
40 | sec: tv.tv_sec,
| ^^^^^^^^^ expected `i64`, found `i32`
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/timestamp.rs:41:19
|
41 | usec: tv.tv_usec,
| ^^^^^^^^^^ expected `i64`, found `i32`
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/timestamp.rs:53:21
|
53 | tv.tv_sec = self.sec;
| ^^^^^^^^ expected `i32`, found `i64`
|
help: you can convert an `i64` to `i32` and panic if the converted value wouldn't fit
|
53 | tv.tv_sec = self.sec.try_into().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> /cargo/registry/src/github.com-1ecc6299db9ec823/v4l-0.7.2/src/timestamp.rs:54:22
|
54 | tv.tv_usec = self.usec;
| ^^^^^^^^^ expected `i32`, found `i64`
|
help: you can convert an `i64` to `i32` and panic if the converted value wouldn't fit
|
54 | tv.tv_usec = self.usec.try_into().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0308`.
error: could not compile `v4l`.
I get the same errors even when using 0.10.
I spotted this in here: CmdrMoozy@c3c4923
I know this should be a pull request but in
impl From<Timestamp> for time::Duration {
fn from(ts: Timestamp) -> Self {
time::Duration::new(ts.sec as u64, (ts.usec / 1000) as u32)
}
}
ts.usec
should be multiplied by 1000 and not divided
This is less of an issue
but more of me seeking help. I'm trying to capture frames with Queue from next
branch and getting all frame buffers set to zero. I've checked ffmpeg
and it could capture frames as expected.
This is what I'm doing:
let afd = AsyncFd::with_interest(Arc::clone(&handle), Interest::READABLE)?;
let mut queue =
Queue::with_mmap(Arc::clone(&handle), Type::VideoCapture, Self::BUFFER_COUNT)?;
for i in 0..queue.len() {
let metadata = queue.query_buf(i as u32).unwrap();
let buf = queue.index_mut(i);
buf.fill(0);
queue.enqueue(&metadata).unwrap();
}
let queue = queue.start_stream()?;
.............................
loop {
let mut guard = self.device_poll_handler.ready(Interest::READABLE).await?;
// remove a buffer from the drivers' outgoing queue
let metadata @ Metadata { sequence: _, timestamp: _, flags: _, bytesused: _, .. } =
match self.queue.dequeue() {
Ok(buf) => buf,
Err(ref err) if err.kind() == ErrorKind::WouldBlock => {
guard.clear_ready();
continue;
}
Err(err) => return Err(err),
};
let buffer = self.queue.index(metadata.index as _);
info!(
"Frame#{}(index {}/pointer: {:?}): {:?}`",
metadata.sequence,
metadata.index,
buffer.as_ptr(),
&buffer[..40],
);
let result = Ok(VideoFrame {
metadata,
buffer: Bytes::copy_from_slice(&buffer[..metadata.bytesused as _]),
// queue: &self.queue,
ntp_timestamp: SystemTime::now(), // .duration_since(self.shift + Duration::from(timestamp))
// .unwrap().as_millis().into(),
});
self.queue.enqueue(&metadata).unwrap();
return result;
}
Here what I'm getting in output:
2023-11-07T16:15:17.180491Z INFO lib::mediaengine: Opened video device 1 with format:
width : 1920
height : 1080
fourcc : H264
field : progressive
stride : 0
size : 778240
colorspace : sRGB
quantization : default
transfer : default transfer function
and Parameters:
capabilities : TIME_PER_FRAME
modes : (empty)
interval : 30/300 [s]
2023-11-07T16:15:17.883648Z INFO lib::mediaengine::video: Frame#10090(index 2/pointer: 0x7f8e9fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:17.983515Z INFO lib::mediaengine::video: Frame#10091(index 3/pointer: 0x7f8d5fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.083395Z INFO lib::mediaengine::video: Frame#10092(index 4/pointer: 0x7f8c1fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.183530Z INFO lib::mediaengine::video: Frame#10093(index 5/pointer: 0x7f7ec00000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.283405Z INFO lib::mediaengine::video: Frame#10094(index 6/pointer: 0x7f7d800000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.384713Z INFO lib::mediaengine::video: Frame#10095(index 7/pointer: 0x7f7c400000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.486195Z INFO lib::mediaengine::video: Frame#10096(index 0/pointer: 0x7f96298000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.584187Z INFO lib::mediaengine::video: Frame#10097(index 1/pointer: 0x7f94e98000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.683948Z INFO lib::mediaengine::video: Frame#10098(index 2/pointer: 0x7f8e9fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.783278Z INFO lib::mediaengine::video: Frame#10099(index 3/pointer: 0x7f8d5fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.883003Z INFO lib::mediaengine::video: Frame#10100(index 4/pointer: 0x7f8c1fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:18.983262Z INFO lib::mediaengine::video: Frame#10101(index 5/pointer: 0x7f7ec00000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.083439Z INFO lib::mediaengine::video: Frame#10102(index 6/pointer: 0x7f7d800000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.183494Z INFO lib::mediaengine::video: Frame#10103(index 7/pointer: 0x7f7c400000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.287652Z INFO lib::mediaengine::video: Frame#10104(index 0/pointer: 0x7f96298000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.384111Z INFO lib::mediaengine::video: Frame#10105(index 1/pointer: 0x7f94e98000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.483396Z INFO lib::mediaengine::video: Frame#10106(index 2/pointer: 0x7f8e9fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.583426Z INFO lib::mediaengine::video: Frame#10107(index 3/pointer: 0x7f8d5fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.683899Z INFO lib::mediaengine::video: Frame#10108(index 4/pointer: 0x7f8c1fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.783537Z INFO lib::mediaengine::video: Frame#10109(index 5/pointer: 0x7f7ec00000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.883382Z INFO lib::mediaengine::video: Frame#10110(index 6/pointer: 0x7f7d800000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:19.983671Z INFO lib::mediaengine::video: Frame#10111(index 7/pointer: 0x7f7c400000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:20.083790Z INFO lib::mediaengine::video: Frame#10112(index 0/pointer: 0x7f96298000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:20.183754Z INFO lib::mediaengine::video: Frame#10113(index 1/pointer: 0x7f94e98000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:20.283560Z INFO lib::mediaengine::video: Frame#10114(index 2/pointer: 0x7f8e9fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:20.383660Z INFO lib::mediaengine::video: Frame#10115(index 3/pointer: 0x7f8d5fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
2023-11-07T16:15:20.483666Z INFO lib::mediaengine::video: Frame#10116(index 4/pointer: 0x7f8c1fa000): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
I'm sure I'm doing something wrong but maybe someone can help me anyway?
Hi,
I'm trying to include dependency using only v4l2-sys
v4l = { version = "0.5.0", features = [ "v4l2" ] }
but it fails:
fatal error: 'libv4l1.h' file not found
Yeah, I know, I can install it but why does it even need this header if I selected v4l2
feature.
Would it be possible to publish the version in the next
branch to crates.io?
I've been working on a simple h264 streaming crate based on this branch but I'm now blocked on publishing it until next
goes live:
Hi,
I'm using your library to configure a Raspberry Pi as Output device and have run into an issue when trying to stream.
It seems that there is a line missing in src/io/mmap/stream.rs:218
that reads the returned index from the DQBUF ioctl.
In the CaptureStream you do this:
fn dequeue(&mut self) -> io::Result<usize> {
let mut v4l2_buf: v4l2_buffer;
unsafe {
v4l2_buf = mem::zeroed();
v4l2_buf.type_ = self.buf_type as u32;
v4l2_buf.memory = Memory::Mmap as u32;
v4l2::ioctl(
self.handle.fd(),
v4l2::vidioc::VIDIOC_DQBUF,
&mut v4l2_buf as *mut _ as *mut std::os::raw::c_void,
)?;
}
self.arena_index = v4l2_buf.index as usize;
self.buf_meta[self.arena_index] = Metadata {
bytesused: v4l2_buf.bytesused,
flags: v4l2_buf.flags.into(),
field: v4l2_buf.field,
timestamp: v4l2_buf.timestamp.into(),
sequence: v4l2_buf.sequence,
};
Ok(self.arena_index)
}
However in the OutputStream implementation the line self.arena_index = v4l2_buf.index as usize;
is missing.
When I added that line all started working.
Please let me know if you need any more info or if I'm doing something wrong.
Thanks!
If v4l
crate expects user to enable either libv4l
or v4l2
features then there should probably be some #[cfg(...)] comile_error!()
stating this if none or both of the features are enabled.
Now I get something like:
error[E0432]: unresolved import `crate::v4l_sys`
--> /home/vi/.cargo/registry/src/-3d9d141e372ea94e/v4l-0.14.0/src/v4l2/videodev.rs:1:12
|
1 | use crate::v4l_sys::v4l2_ext_control;
| ^^^^^^^ could not find `v4l_sys` in the crate root
(many similar compiler errors)
I was wondering if this crate supports safe ioctl
calls to set parameters like this:
https://github.com/loyd/rscam/blob/master/examples/control.rs#L18
Searching for ioctl
only finds unsafe calls, so I assume there isn't safe wrapper available at the moment?
Hello @raymanfx ,
first of, I want to thank you for creating this crate. Unfortunately I'm wondering about some decisions that you did in this crate.
You implemented an mmap
interface where you can queue multiple buffers, but in the way you are using it
images are always only generated once you call io::mmap::stream::dequeue
so you will never have images queued up ready to use.
For that to work you need to open the filedescriptor as NONBLOCK
.
Also with your current iteration I'm not sure why queue
and dequeue
are still public as you cannot do anything with them.
You can dequeue
a new image, you get a buffer_index
but you cannot get the image from this index, as the arena is private
and you don't have any get
and get_meta
functions anymore. We are currently using it in this way: We run an analysis on an
image, get the next image and skip all images that were asynchronously taken in the meantime (see NONBLOCK above) until we reach the newest image that is available at this time, without waiting for a new one. This isn't possible with the use of the next
method. As you will always wait for a new image, regardless of how long it waits. For this to work you also need a method to poll the filedescriptor to you
know if there are images waiting currently.
For the changes we made to do that, you can look at our fork here: https://github.com/HULKs/libv4l-rs/tree/hulksChanges
If you want to, we can come to an understanding on how to integrate these changes properly into your crate. It would be nicer
to have one good v4l wrapper instead of forking and maintaining a second one.
Have a nice day!
I'm not sure if I'm misunderstanding how these licenses work, but this library is licensed under the MIT license, even though libv4l
is LGPL. Is that correct? Does this mean that I can use this library without having to worry about the terms of the LGPL license (such as releasing my source code)?
The video delay is very large. Is there a way to solve it. I'm a novice.
It seems that Stream::handle()
from #63 has been merged to master, but is not available on crates.io. Would it be possible to publish it? We would really appreciate it, as it is exactly what my team and I need for our project :).
I would like to be able to define a nice PREFERRED_FORMAT
constant for my project, but mine is ugly because I have to manually list all of the fields. Perhaps v4l::Format::new
could be changed to
const fn new(width: u32, height: u32, fourcc: FourCC) -> Self {
Format {
width,
height,
fourcc,
field_order: FieldOrder::Any,
stride: 0,
size: 0,
flags: Flags::empty(), // <- used to be Flags::from(0), which isn't const fn
colorspace: Colorspace::Default,
quantization: Quantization::Default,
transfer: TransferFunction::Default,
}
}
I think this change would make this library much more ergonomic.
First, thanks for the great work on this crate.
I'm running into a bit of a strange issue where my video stream is refusing to start. My settings for the device:
let mut fmt = dev.format()?;
fmt.fourcc = FourCC::new(b"BA81");
fmt.width = 640;
fmt.height = 480;
fmt.stride = 640;
fmt.size = 640 * 480;
fmt.field_order = FieldOrder::Progressive;
fmt.colorspace = Colorspace::RAW;
dev.set_format(&fmt)?;
// Using an mmap stream:
mmap::Stream::with_buffers(&dev, Type::VideoCapture, 8)
When I check syslog, I see a bunch of the following:
Jul 23 00:08:38 pi3 kernel: [33785.523627] unicam 3f801000.csi: Wrong width or height 640x480 (remote pad set to 3280x2464)
Jul 23 00:08:38 pi3 kernel: [33785.523643] unicam 3f801000.csi: Failed to start media pipeline: -22
Versions and such:
# v4l-utils package
1.20.0-2
# uname -a
Linux pi3 5.15.32-v8+ #1538 SMP PREEMPT Thu Mar 31 19:40:39 BST 2022 aarch64 GNU/Linux
The main question I have is: how can I configure that remote pad setting? Seems to be part of the issue here.
Hi!
Those strings coming from unused bytes of fixed size arrays are converted to UTF-8 along with trailing zeros. I think this zeros can be trimmed safely.
let caps = device_info.query_caps()?;
println!("caps = {:#?}", caps);
caps = Capabilities {
driver: "uvcvideo\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}",
card: "A4 TECH USB2.0 PC Camera E: A4 \u{0}",
bus: "usb-0000:00:14.0-3.2\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}",
version: (
5,
3,
18,
),
capabilities: VIDEO_CAPTURE | EXT_PIX_FORMAT | STREAMING,
}
Raspberry Pi only supports the multi-planar API.
Could we get another method (or modify the current v4l::output::device::Device.enum_formats
method) that allows us to specify the buffer type?
We need to allow
libv4l-rs/src/output/device.rs
Line 97 in 2ab400d
to be
v4l2_fmt.type_ = v4l2_buf_type_V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
Reference v4l::buffer::BufferType::VideoOutputMplane
.
Formats with names such as YUYV 4:2:2
appear as "YUYV 4:2:2\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}UYV"
instead. I think this is because the parsing is not stopping at the first nul byte.
Hey, I'm not digging in to the example, so I'm not sure if it's something to worry about, but running the glium example I get the following error:
Using device: /dev/video0
Active format:
width : 640
height : 480
fourcc : YUYV
field : progressive
stride : 1280
size : 614400
colorspace : sRGB
quantization : default
transfer : default transfer function
Active parameters:
capabilities : TIME_PER_FRAME
modes : (empty)
interval : 1/30 [s]
thread 'main' panicked at 'Texture data size mismatch', /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/glium-0.27.0/src/texture/any.rs:148:13
stack backtrace:
0: std::panicking::begin_panic
at /home/michael/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:519:12
1: glium::texture::any::new_texture
at /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/glium-0.27.0/src/texture/any.rs:148:13
2: glium::texture::texture2d::Texture2d::new_impl
at ./target/debug/build/glium-aab36beb853d0737/out/textures.rs:2899:95
3: glium::texture::texture2d::Texture2d::new
at ./target/debug/build/glium-aab36beb853d0737/out/textures.rs:2862:21
4: glium::main::{{closure}}
at ./examples/glium.rs:168:30
5: winit::platform_impl::platform::sticky_exit_callback
at /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.22.2/src/platform_impl/linux/mod.rs:698:5
6: winit::platform_impl::platform::x11::EventLoop<T>::run_return
at /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.22.2/src/platform_impl/linux/x11/mod.rs:274:13
7: winit::platform_impl::platform::x11::EventLoop<T>::run
at /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.22.2/src/platform_impl/linux/x11/mod.rs:390:9
8: winit::platform_impl::platform::EventLoop<T>::run
at /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.22.2/src/platform_impl/linux/mod.rs:645:35
9: winit::event_loop::EventLoop<T>::run
at /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.22.2/src/event_loop.rs:149:9
10: glium::main
at ./examples/glium.rs:161:5
11: core::ops::function::FnOnce::call_once
at /home/michael/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Thought I'd just let you know.
Can you please add functions to convert the stream to a image from the image crate?
Or is there already a crate/examples which does this easily?
V4L2 supports hardware encoding and decoding via it's Memory to Memory (M2M) mode. Would it be possible to add support for hardware encoding to libv4l-rs?
This tutorial ( https://lalitm.com/hw-encoding-raspi/ ) seems to lay out how to do it for people how are fluent in C (ie. not myself, not without staring at it for a long time ๐ ).
Would this fit within the way things are setup in this library? Would it make more sense to try to build HW encode/decode separately on top of something like nix?
Also I'm not sure but this seems related to #15.
Hey, I've been checking out different rust libraries for v4l, and I noticed this one doesn't use the bytesused field for v4l2_buffer. I'm trying to send webcam frames over a network, so I'm trying to get the smallest possible frame sizes.
In the standard example:
use v4l::prelude::*;
let mut dev = CaptureDevice::new(0).expect("Failed to open device");
let mut stream =
MmapStream::with_buffers(&mut dev, 4).expect("Failed to create buffer stream");
loop {
let frame = stream.next().unwrap();
println!(
"Buffer size: {}, seq: {}, timestamp: {}",
frame.len(),
frame.meta().seq,
frame.meta().timestamp
);
}
The len value is reported as 1843789 on my machine, even though I know that only about 33K of those bytes are used to describe an actual frame. Is there a way in this library to find how many bytes are framedata? I know that rscam is able to give me the real sizes through the v4l2_buffer.bytesused. It seems like that is more intuitive for the user.
When I try to build v4l2-sys-mit v0.2.0
on Fedora it fails with the error below. I have tried in a clean Fedora container with the same results. Works in a Ubuntu container.
Compiling v4l2-sys-mit v0.2.0
error: failed to run custom build command for `v4l2-sys-mit v0.2.0`
Caused by:
process didn't exit successfully: `/webcam/target/debug/build/v4l2-sys-mit-8a538bcaf39af04d/build-script-build` (exit status: 101)
--- stderr
thread 'main' panicked at /root/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-0.56.0/src/ir/context.rs:846:9:
"v4l2_pix_format_union_(anonymous_at_/usr/include/linux/videodev2_h_500_2)" is not a valid Ident
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I ran into a bug with device enumeration. The following script misplaces part of the index:
fn main() {
let device_list = v4l::context::enum_devices();
for device in device_list.iter() {
let index = device.index();
let path = device.path();
println!("Device index: {} and path {}", index, path.display());
}
}
Produces the following output:
Device index: 3 and path /dev/video3
Device index: 2 and path /dev/video2
Device index: 1 and path /dev/video1
Device index: 0 and path /dev/video0
Device index: 11 and path /dev/video11
Device index: 1 and path /dev/video10
As you see, the last line drops a zero.
Cards 10 and 11 are v4l2-loopbacks created with the following line:
v4l2loopback devices=2 card_label="VirtualCam1,VirtualCam2" exclusive_caps=1,0 video_nr=10,11
Edit: Trying to fix missing line-breaks
I trying to implement async versions of CaptureStream
/OutputStream
traits (i.e. with next
function which returns Future
).
I see that Stream
types internally has reference to Handle
but this ref hasn't accessible via public interface.
Also I see that Device
type has function handle
which returns reference to internal Handle
.
How about adding similar functions to our stream types too?
I don't sure may we add it to Stream
trait directly.
In any case I need a way to get file descriptors from streams.
Any ideas?
When I start a stream and unplug the camera, the stream.next()
call blocks forever. It would be nice if I could set a timeout. Perhaps I'm missing something, but I can't see a way to do that in this library.
It seems like there's a poll function that's made for this.
Perhaps this should be the standard behavior - I think most users would expect an error when a camera is unplugged.
Currently set_control uses VIDIOC_S_CTRL
however sometimes it is also useful to use VIDIOC_S_EXT_CTRLS
:
https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/extended-controls.html
Cargo.toml
[package]
name = "v4l2_test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
v4l = { version = "0.14.0", features = ["libv4l"] }
cargo build -v
Fresh glob v0.3.1
Fresh unicode-ident v1.0.12
Fresh proc-macro2 v1.0.78
Fresh quote v1.0.35
Fresh bitflags v2.4.2
Fresh minimal-lexical v0.2.1
Fresh linux-raw-sys v0.4.13
Fresh memchr v2.7.1
Fresh regex-syntax v0.8.2
Fresh cfg-if v1.0.0
Fresh rustix v0.38.30
Fresh regex-automata v0.4.4
Fresh nom v7.1.3
Fresh libloading v0.8.1
Fresh syn v2.0.48
Fresh either v1.9.0
Fresh home v0.5.9
Fresh clang-sys v1.7.0
Fresh which v4.4.2
Fresh prettyplease v0.2.16
Fresh cexpr v0.6.0
Fresh regex v1.10.3
Fresh shlex v1.3.0
Fresh log v0.4.20
Fresh lazy_static v1.4.0
Fresh bitflags v1.3.2
Fresh lazycell v1.3.0
Fresh rustc-hash v1.1.0
Fresh peeking_take_while v0.1.2
Fresh bindgen v0.65.1
Fresh libc v0.2.152
Dirty v4l2-sys-mit v0.3.0: the file `target/debug/build/v4l2-sys-mit-86f56289e69f4dfe/out/v4l2_bindings.rs` has changed (1705912026.817375900s, 817375900ns after last build at 1705912026.000000000s)
Compiling v4l2-sys-mit v0.3.0
Dirty v4l-sys v0.3.0: the file `target/debug/build/v4l-sys-2fff74701d7ec040/out/libv4l_bindings.rs` has changed (1705912027.600018400s, 600018400ns after last build at 1705912027.000000000s)
Compiling v4l-sys v0.3.0
Running `/home/deehy/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name v4l2_sys_mit --edition=2018 /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l2-sys-mit-0.3.0/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=261 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=4ad9c7016295d975 -C extra-filename=-4ad9c7016295d975 --out-dir /mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps -L dependency=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps --cap-lints allow`
Running `/home/deehy/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name v4l_sys --edition=2018 /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-sys-0.3.0/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=261 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=4a232513af6dbc6e -C extra-filename=-4a232513af6dbc6e --out-dir /mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps -L dependency=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps --cap-lints allow -l v4l1 -l v4l2 -l v4lconvert`
Compiling v4l v0.14.0
Running `/home/deehy/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name v4l --edition=2018 /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=261 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="default"' --cfg 'feature="libv4l"' --cfg 'feature="v4l-sys"' --cfg 'feature="v4l2"' --cfg 'feature="v4l2-sys"' -C metadata=8a2a37446c628d66 -C extra-filename=-8a2a37446c628d66 --out-dir /mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps -L dependency=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps --extern bitflags=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/libbitflags-b7cee2ca4fb438d0.rmeta --extern libc=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/liblibc-a00c9f6be6c2f4ac.rmeta --extern v4l_sys=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/libv4l_sys-4a232513af6dbc6e.rmeta --extern v4l2_sys=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/libv4l2_sys_mit-4ad9c7016295d975.rmeta --cap-lints allow`
error[E0428]: the name `detail` is defined multiple times
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/v4l2/api.rs:59:1
|
8 | mod detail {
| ---------- previous definition of the module `detail` here
...
59 | mod detail {
| ^^^^^^^^^^ `detail` redefined here
|
= note: `detail` must be defined only once in the type namespace of this module
error[E0252]: the name `v4l_sys` is defined multiple times
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/lib.rs:74:9
|
71 | pub use v4l_sys;
| ------- previous import of the module `v4l_sys` here
...
74 | pub use v4l2_sys as v4l_sys;
| ^^^^^^^^^^^^^^^^^^^ `v4l_sys` reimported here
|
= note: `v4l_sys` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
74 | pub use v4l2_sys as other_v4l_sys;
| ~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0425]: cannot find function `v4l2_open` in this scope
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/v4l2/api.rs:14:9
|
14 | v4l2_open(path, flags)
| ^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
9 + use v4l_sys::v4l2_open;
|
error[E0425]: cannot find function `v4l2_close` in this scope
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/v4l2/api.rs:17:9
|
17 | v4l2_close(fd)
| ^^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
9 + use v4l_sys::v4l2_close;
|
error[E0425]: cannot find function `v4l2_ioctl` in this scope
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/v4l2/api.rs:27:9
|
27 | v4l2_ioctl(
| ^^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
9 + use v4l_sys::v4l2_ioctl;
|
error[E0425]: cannot find function `v4l2_mmap` in this scope
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/v4l2/api.rs:44:9
|
44 | v4l2_mmap(
| ^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
9 + use v4l_sys::v4l2_mmap;
|
error[E0425]: cannot find function `v4l2_munmap` in this scope
--> /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/v4l2/api.rs:54:9
|
54 | v4l2_munmap(start, length.try_into().expect("usize -> c size_t failed"))
| ^^^^^^^^^^^ not found in this scope
|
help: consider importing this function
|
9 + use v4l_sys::v4l2_munmap;
|
Some errors have detailed explanations: E0252, E0425, E0428.
For more information about an error, try `rustc --explain E0252`.
error: could not compile `v4l` (lib) due to 7 previous errors
Caused by:
process didn't exit successfully: `/home/deehy/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name v4l --edition=2018 /home/deehy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/v4l-0.14.0/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=261 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="default"' --cfg 'feature="libv4l"' --cfg 'feature="v4l-sys"' --cfg 'feature="v4l2"' --cfg 'feature="v4l2-sys"' -C metadata=8a2a37446c628d66 -C extra-filename=-8a2a37446c628d66 --out-dir /mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps -L dependency=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps --extern bitflags=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/libbitflags-b7cee2ca4fb438d0.rmeta --extern libc=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/liblibc-a00c9f6be6c2f4ac.rmeta --extern v4l_sys=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/libv4l_sys-4a232513af6dbc6e.rmeta --extern v4l2_sys=/mnt/c/Users/dongf/Source/Rust/v4l2_test/target/debug/deps/libv4l2_sys_mit-4ad9c7016295d975.rmeta --cap-lints allow` (exit status: 1)
Using the examples/stream_forward_mmap.rs
example I am unable to stream to a v4l2loopback device and then play it with ffplay.
The last working version is the one from commit 67ace34. commit 8586075 and after does not work for me.
$ cargo build --examples && ./target/debug/examples/stream_forward_mmap -d 0 -o 2 -c 100
# output appearing to work
In another terminal:
$ ffplay /dev/video2
ffplay version n4.3.1 Copyright (c) 2003-2020 the FFmpeg developers
built with gcc 10.2.0 (GCC)
configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmfx --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librav1e --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-nvdec --enable-nvenc --enable-shared --enable-version3
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
libpostproc 55. 7.100 / 55. 7.100
nan : 0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0
Using the (now deprecated) example forward_video
and this patch #22 worked fine.
I cloned master, and ran cargo build --examples
, then ran ./target/debug/examples/stream_forward_mmap -d 4 -o 0
(and yes, my loopback is /dev/video/0
and my USB webcam is /dev/video/4
- i double checked).
The result is a panic with a message about slice lengths not matching:
thread 'main' panicked at 'source slice length (460800) does not match destination slice length (1228800)', /home/filip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/mod.rs:2775:13
Complete output in enclosed text file.
Any idea what's wrong? I'm a bit of a beginner at both Rust and V4l2
Hi,
I'm not sure if this is me misunderstanding something but when I fill the mmap output buffer with data I do not see a way to set the bytesUsed. Im streaming mjpeg and depending of the encoding the data size changes. As far as I can see now always the max buffer size is set. I tried using the meta struct to set meta.bytesused
but that does not seem to be used in the library. As a workaround i did this in src/io/mmap/stream.rs
:
diff --git a/src/io/mmap/stream.rs b/src/io/mmap/stream.rs
index 8a30846..13b21fc 100644
--- a/src/io/mmap/stream.rs
+++ b/src/io/mmap/stream.rs
@@ -190,9 +190,7 @@ impl<'a, 'b> OutputStream<'b> for Stream<'a> {
v4l2_buf.type_ = self.buf_type as u32;
v4l2_buf.memory = Memory::Mmap as u32;
v4l2_buf.index = index as u32;
- // output settings
- let bytes = self.arena.get_unchecked_mut(index);
- v4l2_buf.bytesused = bytes.len() as u32;
+ v4l2_buf.bytesused = self.buf_meta[index].bytesused;
v4l2_buf.field = self.buf_meta[index].field;
v4l2::ioctl(
However I do not know if this breaks other usage of the OutputStream. Am I missing something? Or am I on the right track and should my change be expanded to cover all situations.
Thanks in advance!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.