diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 2f8b8b3745..e3c53d7cdd 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -268,6 +268,14 @@ typedef uint32_t __u32; #define V4L2_PIX_FMT_Y12 v4l2_fourcc('Y', '1', '2', ' ') #endif +#ifndef V4L2_PIX_FMT_Y16 +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') +#endif + +#ifndef V4L2_PIX_FMT_Y16_BE +#define V4L2_PIX_FMT_Y16_BE v4l2_fourcc_be('Y', '1', '6', ' ') +#endif + #ifndef V4L2_PIX_FMT_ABGR32 #define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4') #endif @@ -609,6 +617,7 @@ bool CvCaptureCAM_V4L::autosetup_capture_mode_v4l2() V4L2_PIX_FMT_JPEG, #endif V4L2_PIX_FMT_Y16, + V4L2_PIX_FMT_Y16_BE, V4L2_PIX_FMT_Y12, V4L2_PIX_FMT_Y10, V4L2_PIX_FMT_GREY, @@ -668,6 +677,7 @@ bool CvCaptureCAM_V4L::convertableToRgb() const case V4L2_PIX_FMT_SGBRG8: case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_Y16: + case V4L2_PIX_FMT_Y16_BE: case V4L2_PIX_FMT_Y10: case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_BGR24: @@ -716,6 +726,7 @@ void CvCaptureCAM_V4L::v4l2_create_frame() size.height = size.height * 3 / 2; // "1.5" channels break; case V4L2_PIX_FMT_Y16: + case V4L2_PIX_FMT_Y16_BE: case V4L2_PIX_FMT_Y12: case V4L2_PIX_FMT_Y10: depth = IPL_DEPTH_16U; @@ -1731,8 +1742,21 @@ void CvCaptureCAM_V4L::convertToRgb(const Buffer ¤tBuffer) return; case V4L2_PIX_FMT_Y16: { + // https://www.kernel.org/doc/html/v4.10/media/uapi/v4l/pixfmt-y16.html + // This is a grey-scale image with a depth of 16 bits per pixel. The least significant byte is stored at lower memory addresses (little-endian). + // Note: 10-bits precision is not supported + cv::Mat temp(imageSize, CV_8UC1, buffers[MAX_V4L_BUFFERS].memories[MEMORY_RGB].start); + cv::extractChannel(cv::Mat(imageSize, CV_8UC2, start), temp, 1); // 1 - second channel + cv::cvtColor(temp, destination, COLOR_GRAY2BGR); + return; + } + case V4L2_PIX_FMT_Y16_BE: + { + // https://www.kernel.org/doc/html/v4.10/media/uapi/v4l/pixfmt-y16-be.html + // This is a grey-scale image with a depth of 16 bits per pixel. The most significant byte is stored at lower memory addresses (big-endian). + // Note: 10-bits precision is not supported cv::Mat temp(imageSize, CV_8UC1, buffers[MAX_V4L_BUFFERS].memories[MEMORY_RGB].start); - cv::Mat(imageSize, CV_16UC1, start).convertTo(temp, CV_8U, 1.0 / 256); + cv::extractChannel(cv::Mat(imageSize, CV_8UC2, start), temp, 0); // 0 - first channel cv::cvtColor(temp, destination, COLOR_GRAY2BGR); return; } diff --git a/modules/videoio/test/test_precomp.hpp b/modules/videoio/test/test_precomp.hpp index c39dc7da13..b4f340897e 100644 --- a/modules/videoio/test/test_precomp.hpp +++ b/modules/videoio/test/test_precomp.hpp @@ -60,7 +60,8 @@ inline std::string fourccToString(int fourcc) inline std::string fourccToStringSafe(int fourcc) { std::string res = fourccToString(fourcc); - std::replace_if(res.begin(), res.end(), [](uint8_t c){ return c < '0' || c > 'z'; }, '_'); + // TODO: return hex values for invalid characters + std::transform(res.begin(), res.end(), res.begin(), [](uint8_t c) { return (c >= '0' && c <= 'z') ? c : (c == ' ' ? '_' : 'x'); }); return res; } diff --git a/modules/videoio/test/test_v4l2.cpp b/modules/videoio/test/test_v4l2.cpp index 6763e2e33c..5d56ac097c 100644 --- a/modules/videoio/test/test_v4l2.cpp +++ b/modules/videoio/test/test_v4l2.cpp @@ -34,6 +34,13 @@ #ifndef V4L2_PIX_FMT_XBGR32 #define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') #endif +#ifndef V4L2_PIX_FMT_Y16 +#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') +#endif +#ifndef V4L2_PIX_FMT_Y16_BE +#define V4L2_PIX_FMT_Y16_BE v4l2_fourcc_be('Y', '1', '6', ' ') +#endif + using namespace cv; @@ -111,6 +118,7 @@ vector all_params = { // { V4L2_PIX_FMT_SGBRG8, 1, CV_8U, 1.f, 1.f }, { V4L2_PIX_FMT_RGB24, 3, CV_8U, 1.f, 1.f }, { V4L2_PIX_FMT_Y16, 1, CV_16U, 1.f, 1.f }, + { V4L2_PIX_FMT_Y16_BE, 1, CV_16U, 1.f, 1.f }, { V4L2_PIX_FMT_Y10, 1, CV_16U, 1.f, 1.f }, { V4L2_PIX_FMT_GREY, 1, CV_8U, 1.f, 1.f }, { V4L2_PIX_FMT_BGR24, 3, CV_8U, 1.f, 1.f },