From 47a64192909cf153e40ba094588e1a531d46f465 Mon Sep 17 00:00:00 2001 From: Ghazi-raad Date: Fri, 28 Nov 2025 09:40:08 +0000 Subject: [PATCH] Merge pull request #28086 from Ghazi-raad:fix/aravis-default-pixel-format-26523 fix: set default pixel format for Aravis cameras when unsupported format #28086 Fixes #26523 This PR fixes an issue where Aravis VideoCapture returns empty frames when the camera's pixel format is not explicitly set via CAP_PROP_FOURCC. Problem: The Aravis backend's retrieveFrame() function only processes four specific pixel formats: - ARV_PIXEL_FORMAT_MONO_8 - ARV_PIXEL_FORMAT_BAYER_GR_8 - ARV_PIXEL_FORMAT_MONO_12 - ARV_PIXEL_FORMAT_MONO_16 If the camera has a different pixel format configured (or the camera's default format is unsupported), retrieveFrame() returns false on line 333 and all frames appear empty. This happens even though: - The camera opens successfully (isOpened() returns true) - The camera is capturing data - The user has set up autotrigger and auto-exposure correctly Root Cause: In open() at line 271, the code retrieves the camera's current pixel format with arv_camera_get_pixel_format(). But if this format doesn't match one of the four supported formats, there's no fallback, causing all subsequent frames to fail retrieval. Solution: Added a check after retrieving the camera's pixel format. If the format is not one of the four supported formats, the code now: 1. Sets pixelFormat to a sensible default (MONO_8) 2. Applies this format to the camera via arv_camera_set_pixel_format() This ensures: - Cameras work out-of-the-box without requiring explicit CAP_PROP_FOURCC setup - Users can still override the format with CAP_PROP_FOURCC if needed - Behavior matches user expectations from other camera backends (V4L2, MSMF, etc.) The default of MONO_8 was chosen because it's the most universally supported format across USB3 Vision and GigE Vision cameras. Changes: modules/videoio/src/cap_aravis.cpp: Added pixel format validation and default setting (10 lines) Testing: With this fix: - Cameras with unsupported default formats will automatically switch to MONO_8 - The sample code from the issue works without uncommenting the CAP_PROP_FOURCC line - Users can still explicitly set their preferred format via CAP_PROP_FOURCC Pull Request Readiness Checklist: - [x] I agree to contribute to the project under Apache 2 License. - [x] 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 - [x] The PR is proposed to the proper branch (4.x) - [x] There is a reference to the original bug report and related work (issue #26523) - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable N/A - This requires specialized USB3 Vision / GigE Vision hardware not available in CI - [x] The feature is well documented and sample code can be built with the project CMake The fix maintains existing API behavior and makes the backend work as expected --- modules/videoio/src/cap_aravis.cpp | 41 +++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/modules/videoio/src/cap_aravis.cpp b/modules/videoio/src/cap_aravis.cpp index ba0899dd0c..b5be51b30c 100644 --- a/modules/videoio/src/cap_aravis.cpp +++ b/modules/videoio/src/cap_aravis.cpp @@ -127,6 +127,8 @@ protected: void autoExposureControl(const Mat &); + double getExpectedMidGrey(ArvPixelFormat fmt) const; + ArvCamera *camera; // Camera to control. ArvStream *stream; // Object for video stream reception. void *framebuffer; // @@ -269,6 +271,19 @@ bool CvCaptureCAM_Aravis::open( int index ) // get initial values pixelFormat = arv_camera_get_pixel_format(camera, NULL); + + // If camera's pixel format is not one of the supported formats, set a default + if (pixelFormat != ARV_PIXEL_FORMAT_MONO_8 && + pixelFormat != ARV_PIXEL_FORMAT_BAYER_GR_8 && + pixelFormat != ARV_PIXEL_FORMAT_MONO_12 && + pixelFormat != ARV_PIXEL_FORMAT_MONO_16) { + pixelFormat = ARV_PIXEL_FORMAT_MONO_8; + arv_camera_set_pixel_format(camera, pixelFormat, NULL); + CV_LOG_WARNING(NULL, "Current camera pixel format is not supported. Failed back to MONO_8."); + } + + midGrey = getExpectedMidGrey(pixelFormat); + exposure = exposureAvailable ? arv_camera_get_exposure_time(camera, NULL) : 0; gain = gainAvailable ? arv_camera_get_gain(camera, NULL) : 0; fps = arv_camera_get_frame_rate(camera, NULL); @@ -489,6 +504,26 @@ double CvCaptureCAM_Aravis::getProperty( int property_id ) const return -1.0; } +double CvCaptureCAM_Aravis::getExpectedMidGrey(ArvPixelFormat fmt) const +{ + double grey = 0.; + switch(fmt) + { + case ARV_PIXEL_FORMAT_MONO_8: + case ARV_PIXEL_FORMAT_BAYER_GR_8: + grey = 128.; + break; + case ARV_PIXEL_FORMAT_MONO_12: + grey = 2048.; + break; + case ARV_PIXEL_FORMAT_MONO_16: + grey = 32768.; + break; + } + + return grey; +} + bool CvCaptureCAM_Aravis::setProperty( int property_id, double value ) { switch(property_id) { @@ -535,24 +570,22 @@ bool CvCaptureCAM_Aravis::setProperty( int property_id, double value ) case MODE_GREY: case MODE_Y800: newFormat = ARV_PIXEL_FORMAT_MONO_8; - targetGrey = 128; break; case MODE_Y12: newFormat = ARV_PIXEL_FORMAT_MONO_12; - targetGrey = 2048; break; case MODE_Y16: newFormat = ARV_PIXEL_FORMAT_MONO_16; - targetGrey = 32768; break; case MODE_GRBG: newFormat = ARV_PIXEL_FORMAT_BAYER_GR_8; - targetGrey = 128; break; } + if(newFormat != pixelFormat) { stopCapture(); arv_camera_set_pixel_format(camera, pixelFormat = newFormat, NULL); + midGrey = getExpectedMidGrey(newFormat); startCapture(); } }