Skip to content

[WIP] modules/videoio: add libcamera backend for OpenCV Video I/O #27155

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

Draft
wants to merge 11 commits into
base: 5.x
Choose a base branch
from

Conversation

advait-0
Copy link

@advait-0 advait-0 commented Mar 26, 2025

Adds libcamera backend for OpenCV's Video I/O module. Provides integration with the libcamera stack, enabling native support for modern Linux camera pipelines, especially on embedded platforms like Raspberry Pi.
Implements the functionality to be used by the VideoCapture class for reading and displaying supported streams.

What works

  • Displaying frames from common formats: MJPEG, YUYV, NV12, and more.
  • Setting camera properties:
    • cv::CAP_PROP_FRAME_WIDTH – Set frame width
    • cv::CAP_PROP_FRAME_HEIGHT – Set frame height
    • cv::CAP_PROP_MODE – Select PixelFormat
      (e.g., FMT_MJPEG, FMT_YUYV, FMT_RGB888, FMT_BGR888, FMT_NV12, FMT_YUV420)
    • cv::CAP_PROP_FORMAT – Select StreamRole
      (e.g., ROLE_RAW, ROLE_VIDEO, ROLE_STILL, ROLE_VIEWFINDER)
  • Reading some set camera properties (may be unstable):
    • cv::CAP_PROP_FRAME_WIDTH
    • cv::CAP_PROP_FRAME_HEIGHT

Known issues

  • Multiple camera support works, but it is laggy for the second camera at the moment (tested with 2 cameras)
  • cv::CAP_PROP_MODE must be explicitly set, for USB and CSI cameras, to avoid crashes.

Detailed usage instructions can be found here.
Sample testing program can be found here.

Attempts to close #21653

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@asmorkalov
Copy link
Contributor

Let's use FMT_BGR888 by default, if CAP_PROP_MODE is not set by user. It's default OpenCV behaviour.

@asmorkalov
Copy link
Contributor

Raspberry Pi 4, libcamera from git default branch as in gist.
CMake:

--   Video I/O:
--     FFMPEG:                      NO
--       avcodec:                   NO
--       avformat:                  NO
--       avutil:                    NO
--       swscale:                   NO
--       avresample:                NO
--     GStreamer:                   YES (1.18.4)
--     v4l/v4l2:                    YES (linux/videodev2.h)
--     libcamera:                   YES (0.4.0)

Build:

[ 53%] Linking CXX shared library ../../lib/libopencv_videoio.so
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::getProperty(int) const':
cap_libcamera.cpp:(.text._ZNK2cv25CvCapture_libcamera_proxy11getPropertyEi+0x38): undefined reference to `libcamera::Request::sequence() const'
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::open()':
cap_libcamera.cpp:(.text._ZN2cv25CvCapture_libcamera_proxy4openEv+0x260): undefined reference to `libcamera::Request::addBuffer(libcamera::Stream const*, libcamera::FrameBuffer*, std::unique_ptr<libcamera::Fence, std::default_delete<libcamera::Fence> >)'
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::grabFrame()':
cap_libcamera.cpp:(.text._ZN2cv25CvCapture_libcamera_proxy9grabFrameEv+0x4c): undefined reference to `libcamera::Camera::generateConfiguration(libcamera::Span<libcamera::StreamRole const, 18446744073709551615ul>)'
collect2: error: ld returned 1 exit status
make[2]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/build.make:324: lib/libopencv_videoio.so.5.0.0] Error 1

@asmorkalov
Copy link
Contributor

Similar issue with system wide (libcamera-dev) package:

[ 45%] Linking CXX shared library ../../lib/libopencv_videoio.so
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::getProperty(int) const':
cap_libcamera.cpp:(.text._ZNK2cv25CvCapture_libcamera_proxy11getPropertyEi+0x38): undefined reference to `libcamera::Request::sequence() const'
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::open()':
cap_libcamera.cpp:(.text._ZN2cv25CvCapture_libcamera_proxy4openEv+0x260): undefined reference to `libcamera::Request::addBuffer(libcamera::Stream const*, libcamera::FrameBuffer*, std::unique_ptr<libcamera::Fence, std::default_delete<libcamera::Fence> >)'
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::grabFrame()':
cap_libcamera.cpp:(.text._ZN2cv25CvCapture_libcamera_proxy9grabFrameEv+0x4c): undefined reference to `libcamera::Camera::generateConfiguration(libcamera::Span<libcamera::StreamRole const, 18446744073709551615ul>)'
collect2: error: ld returned 1 exit status
make[2]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/build.make:324: lib/libopencv_videoio.so.5.0.0] Error 1
make[1]: *** [CMakeFiles/Makefile2:2737: modules/videoio/CMakeFiles/opencv_videoio.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

int error;
if (buffer->planes().empty())
{
std::cerr << "Buffer has no planes " << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CV_LOG_XXX macro for reporting.

Comment on lines 63 to 66
std::cerr << "plane is out of buffer: "
<< "buffer length=" << length
<< ", plane offset=" << plane.offset
<< ", plane length=" << plane.length << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same for CV_LOG_XXX

@advait-0
Copy link
Author

Raspberry Pi 4, libcamera from git default branch as in gist. CMake:

--   Video I/O:
--     FFMPEG:                      NO
--       avcodec:                   NO
--       avformat:                  NO
--       avutil:                    NO
--       swscale:                   NO
--       avresample:                NO
--     GStreamer:                   YES (1.18.4)
--     v4l/v4l2:                    YES (linux/videodev2.h)
--     libcamera:                   YES (0.4.0)

Build:

[ 53%] Linking CXX shared library ../../lib/libopencv_videoio.so
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::getProperty(int) const':
cap_libcamera.cpp:(.text._ZNK2cv25CvCapture_libcamera_proxy11getPropertyEi+0x38): undefined reference to `libcamera::Request::sequence() const'
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::open()':
cap_libcamera.cpp:(.text._ZN2cv25CvCapture_libcamera_proxy4openEv+0x260): undefined reference to `libcamera::Request::addBuffer(libcamera::Stream const*, libcamera::FrameBuffer*, std::unique_ptr<libcamera::Fence, std::default_delete<libcamera::Fence> >)'
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_libcamera.cpp.o: in function `cv::CvCapture_libcamera_proxy::grabFrame()':
cap_libcamera.cpp:(.text._ZN2cv25CvCapture_libcamera_proxy9grabFrameEv+0x4c): undefined reference to `libcamera::Camera::generateConfiguration(libcamera::Span<libcamera::StreamRole const, 18446744073709551615ul>)'
collect2: error: ld returned 1 exit status
make[2]: *** [modules/videoio/CMakeFiles/opencv_videoio.dir/build.make:324: lib/libopencv_videoio.so.5.0.0] Error 1

Hmm, I'm not sure why you are facing this issue. Raspberry pi also ships with its custom fork of libcamera, could that be causing an issue?

I have tested this on a Raspberry Pi 5 with a Picamera 2 and on my x84_64 Linux machine and it builds fine on both without any errors.

@advait-0
Copy link
Author

advait-0 commented Mar 26, 2025

Let's use FMT_BGR888 by default, if CAP_PROP_MODE is not set by user. It's default OpenCV behaviour.

Yes will do, I wasn't sure what to set as the default as many UVC cameras just sendsMJPEG and YUYV streams, so the BGR888 format crashes it. We will probably need to check the supported camera pixel formats and then update the default before configuring the stream.

@advait-0 advait-0 force-pushed the libcamera-backend branch from b3e9351 to 8be783f Compare April 7, 2025 07:02
@Lookplanes
Copy link

Thank you for your excellent initiative and contribution in developing a libcamera backend for OpenCV! We have been closely following your work and are very impressed with your progress.
Our team has also been working on a similar effort to integrate libcamera into OpenCV's Video I/O module. Our approach is based on the LCCV project and aims to provide robust and efficient libcamera support for OpenCV users.
While we see great value in your current implementation, we wanted to briefly share some of the key differences in our approach, which might be of interest and potentially beneficial to the project as a whole.
The main distinction in our design lies in how we handle the interaction with the libcamera backend and manage requests. We have adopted a multi-threaded architecture to maintain and interact with the libcamera request queue.
We believe this multi-threaded approach offers several potential advantages:

  1. Improved Responsiveness: Preventing blocking of the main OpenCV thread for a more reactive API.
  2. Enhanced Performance: Better resource utilization and potentially higher frame rates, leveraging libcamera's asynchronous nature.
  3. Greater Flexibility: More refined control over request management for advanced features and customizations.

We have achieved a highly complete implementation with this architecture, and it demonstrates promising performance in our testing. However, we are currently addressing some bugs, particularly related to rapid release and restart scenarios, before we are fully confident in submitting a pull request.

@advait-0
Copy link
Author

advait-0 commented Apr 10, 2025

Thank you for your kind words and insights @Lookplanes. It's nice to hear that your team has made significant progress with your architecture, I'm looking forward to your approach. If you’re open to it, would you be willing to share your source code or repository? I would love to collaborate on developing a solution.

@QueenofUSSR
Copy link

Thank you for your kind words and insights @Lookplanes. It's nice to hear that your team has made significant progress with your architecture, I'm looking forward to your approach. If you’re open to it, would you be willing to share your source code or repository? I would love to collaborate on developing a solution.

Certainly! Please check opencv-RPiCamera

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

Successfully merging this pull request may close these issues.

4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy