Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't add new control to Request #2

Closed
markus-k opened this issue Feb 3, 2023 · 8 comments · Fixed by #6
Closed

Can't add new control to Request #2

markus-k opened this issue Feb 3, 2023 · 8 comments · Fixed by #6

Comments

@markus-k
Copy link
Contributor

markus-k commented Feb 3, 2023

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:

pub fn set<C: Control>(&mut self, val: C) -> Result<(), ControlError> {
let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr.as_ptr(), C::ID as _) })
.ok_or(ControlError::NotFound(C::ID))?;
let ctrl_val: ControlValue = val.into();
unsafe { ctrl_val.write(val_ptr) };
Ok(())
}

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
Copy link
Contributor Author

markus-k commented Feb 3, 2023

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
Copy link
Contributor

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
Copy link
Contributor Author

markus-k commented Feb 6, 2023

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.

@chemicstry chemicstry reopened this Feb 6, 2023
@mfreeborn
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants