lit-robotics / libcamera-rs

Experimental Rust bindings for libcamera
Apache License 2.0
46 stars 15 forks source link

Can't add new control to Request #2

Closed markus-k closed 1 year ago

markus-k commented 1 year ago

First of all, thank you for creating this libcamera-wrapper! I was recently trying to create one as well (using cxx/autocxx) and almost went mad.

I'm trying to set a new control in a Request, which should be possible with the C++ API:

let mut req = active.create_request(Some(1)).unwrap();
req.add_buffer(&stream, buf).unwrap();
req.controls_mut()
    .set(ExposureTime(100000))
    .expect("Setting control failed");

But this results in Setting control failed: NotFound(7).

This of course happens because .set() expects the Control ID to exist:

https://github.com/lit-robotics/libcamera-rs/blob/5b6085408be539687c9666745bad0f33d82ee23c/libcamera-rs/src/control.rs#L80-L87

From a quick try I figured implementing this wasn't as easy as creating a new libcamera_control_list_set since there is currently no way to create a new instance of libcamera_control_value_t from Rust. If I can up with a solution, I will create a PR.

markus-k commented 1 year ago

Okay looking at the implementation in libcamera, this isn't going to work as documented.

Then again, the issue remains though, since I couldn't find a way to supply a list of Controls to camera.start().

chemicstry commented 1 year ago

Hey, thanks for reporting this.

I was recently trying to create one as well (using cxx/autocxx) and almost went mad.

I tried to do the same and that describes my experience pretty well lol. Interfacing Rust with C++, especially when templates are used is a nightmare. That's why I went the C wrapper route.

The issue should be fixed, please check if it's working. One caveat is that not all controls are supported by all cameras, so the set method can silently fail as described in the docs. Unfortunatelly, the methods to validate controls are private in libcamera :/

markus-k commented 1 year ago

Seems to work, thank you!

I think the only problem that remains is that camera.start() uses a ControlListRef, which you can't create yourself. It would probably be best if start() took a Vec<Control> here which is then copied to the C++ ControlList.

mfreeborn commented 1 year ago

I think the only problem that remains is that camera.start() uses a ControlListRef, which you can't create yourself. It would probably be best if start() took a Vec<Control> here which is then copied to the C++ ControlList.

Just came across this myself. Should start() take a Vec<Control>, or could ActiveCamera provide a controls_mut() method in the same way that Request does?

chemicstry commented 1 year ago

Just came across this myself. Should start() take a Vec<Control>, or could ActiveCamera provide a controls_mut() method in the same way that Request does?

I don't think libcamera API allows accessing camera controls to implement suggested controls_mut(). Update me if I'm wrong.

I created a fix in #6, please test and see if it works for you. Unfortunatelly, it is not possible to create Vec<Control>, because Control is a trait, which can have different types. Here is the alternative API I implemented:

let mut ctrls = ControlList::new();
ctrls.set(controls::FrameDuration(1000)).unwrap();
cam.start(Some(&ctrls)).unwrap();

Beware that UVC USB cameras ignore any controls given in start(), see here. They only accept controls from Request.

mfreeborn commented 1 year ago

It seems that regardless of whether I add the controls to start() or Request, or any combination thereof, it seems to have no effect on the framerate. I'd like to test it more properly on my raspberry pi camera to exclude the possibility that my integrated laptop camera is the issue...

chemicstry commented 1 year ago

It's likely that integrated laptop camera is attached over internal USB bus and uses UVC protocol. AFAIK, libcamera can't control UVC FPS, supported controls are these: https://github.com/kbingham/libcamera/blob/master/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp#L268

kbingham commented 1 year ago

Note that it's not that libcamera /can't/ control more features of UVC ... just that no one has added support.

If you want to fix control handling in the uvc pipeline handler, patches are most welcome at the libcamera-devel mailing list.