From 64a2729d5fde42d23d517713592d109a5cefb269 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 2 Jul 2023 10:07:02 +0200 Subject: [PATCH 1/4] use libv4l2 (https://github.com/philips/libv4l) for local USB cameras . This allows very simple/primitive cameras to work out of the box . (like USB cameras using the gspca driver ) --- CMakeLists.txt | 2 +- src/zm_local_camera.cpp | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df2effa0a63..db4e09b86f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,7 +159,7 @@ set(ZM_CONFIG_DIR "/${CMAKE_INSTALL_SYSCONFDIR}" CACHE PATH "Location of ZoneMinder configuration, default system config directory") set(ZM_CONFIG_SUBDIR "${ZM_CONFIG_DIR}/conf.d" CACHE PATH "Location of ZoneMinder configuration subfolder, default: ZM_CONFIG_DIR/conf.d") -set(ZM_EXTRA_LIBS "" CACHE STRING +set(ZM_EXTRA_LIBS "v4l2" CACHE STRING "A list of optional libraries, separated by semicolons, e.g. ssl;theora") set(ZM_MYSQL_ENGINE "InnoDB" CACHE STRING "MySQL engine to use with database, default: InnoDB") diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 5b31a89fc20..d26359fc656 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -25,6 +25,10 @@ #include #include #include +#if ZM_HAS_V4L2 +#include +#endif // ZM_HAS_V4L2 + #if ZM_HAS_V4L2 @@ -38,13 +42,15 @@ static unsigned int BigEndian; static bool primed; +#if ZM_HAS_V4L2 static int vidioctl(int fd, int request, void *arg) { int result = -1; do { - result = ioctl(fd, request, arg); + result = v4l2_ioctl( fd, request, arg ); } while( result == -1 && errno == EINTR ); return result; } +#endif // ZM_HAS_V4L2 static _AVPIXELFORMAT getFfPixFormatFromV4lPalette(int v4l_version, int palette) { _AVPIXELFORMAT pixFormat = AV_PIX_FMT_NONE; @@ -481,7 +487,7 @@ int LocalCamera::Close() { void LocalCamera::Initialise() { Debug(3, "Opening video device %s", device.c_str()); - if ((vid_fd = open(device.c_str(), O_RDWR, 0)) < 0) + if ( (vid_fd = v4l2_open( device.c_str(), O_RDWR, 0 )) < 0 ) Fatal("Failed to open video device %s: %s", device.c_str(), strerror(errno)); struct stat st; @@ -672,7 +678,7 @@ void LocalCamera::Initialise() { Fatal("Unable to query video buffer: %s", strerror(errno)); v4l2_data.buffers[i].length = vid_buf.length; - v4l2_data.buffers[i].start = mmap(nullptr, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset); + v4l2_data.buffers[i].start = v4l2_mmap(nullptr, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset); if (v4l2_data.buffers[i].start == MAP_FAILED) Fatal("Can't map video buffer %u (%u bytes) to memory: %s(%d)", @@ -737,12 +743,12 @@ void LocalCamera::Terminate() { for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) { capturePictures[i] = nullptr; - if ( munmap(v4l2_data.buffers[i].start, v4l2_data.buffers[i].length) < 0 ) + if ( v4l2_munmap(v4l2_data.buffers[i].start, v4l2_data.buffers[i].length) < 0 ) Error("Failed to munmap buffer %d: %s", i, strerror(errno)); } } - close(vid_fd); + v4l2_close(vid_fd); primed = false; } // end LocalCamera::Terminate @@ -757,7 +763,7 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) { int enum_fd; /* Open the device */ - if ( (enum_fd = open(device.c_str(), O_RDWR, 0)) < 0 ) { + if ( (enum_fd = v4l2_open(device.c_str(), O_RDWR, 0)) < 0 ) { Error("Automatic format selection failed to open video device %s: %s", device.c_str(), strerror(errno)); return selected_palette; @@ -841,7 +847,7 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) { } /* Close the device */ - close(enum_fd); + v4l2_close(enum_fd); return selected_palette; } //uint32_t LocalCamera::AutoSelectFormat(int p_colours) @@ -866,7 +872,7 @@ bool LocalCamera::GetCurrentSettings( queryDevice = stringtf("/dev/video%d", devIndex); } - if ((vid_fd = open(queryDevice.c_str(), O_RDWR)) <= 0) { + if ((vid_fd =v4l2_open(queryDevice.c_str(), O_RDWR)) <= 0) { if (!device.empty()) { Error("Failed to open video device %s: %s", queryDevice.c_str(), strerror(errno)); if (verbose) { @@ -1149,7 +1155,7 @@ bool LocalCamera::GetCurrentSettings( *(output_ptr-1) = '\n'; } - close(vid_fd); + v4l2_close(vid_fd); if (!device.empty()) { break; } @@ -1180,6 +1186,7 @@ int LocalCamera::Control(int vid_id, int newvalue) { Warning("Given control value (%d) may be out-of-range", newvalue); } } + v4l2_close( vid_fd ); } return vid_control.value; } From 2825e900e4b0ae188ca45626e410da44c88f36d0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Mar 2026 17:08:48 -0400 Subject: [PATCH 2/4] Update src/zm_local_camera.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/zm_local_camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index d26359fc656..c95e1dfd471 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -872,7 +872,7 @@ bool LocalCamera::GetCurrentSettings( queryDevice = stringtf("/dev/video%d", devIndex); } - if ((vid_fd =v4l2_open(queryDevice.c_str(), O_RDWR)) <= 0) { + if ((vid_fd = v4l2_open(queryDevice.c_str(), O_RDWR)) < 0) { if (!device.empty()) { Error("Failed to open video device %s: %s", queryDevice.c_str(), strerror(errno)); if (verbose) { From 5ec30128fa1f6b7483c141c7c3a25f7b6ddb38a3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Mar 2026 17:09:00 -0400 Subject: [PATCH 3/4] Update CMakeLists.txt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index db4e09b86f6..df2effa0a63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,7 +159,7 @@ set(ZM_CONFIG_DIR "/${CMAKE_INSTALL_SYSCONFDIR}" CACHE PATH "Location of ZoneMinder configuration, default system config directory") set(ZM_CONFIG_SUBDIR "${ZM_CONFIG_DIR}/conf.d" CACHE PATH "Location of ZoneMinder configuration subfolder, default: ZM_CONFIG_DIR/conf.d") -set(ZM_EXTRA_LIBS "v4l2" CACHE STRING +set(ZM_EXTRA_LIBS "" CACHE STRING "A list of optional libraries, separated by semicolons, e.g. ssl;theora") set(ZM_MYSQL_ENGINE "InnoDB" CACHE STRING "MySQL engine to use with database, default: InnoDB") From f17a8cf8b73a5a86b24c8e88e0ee1019afc67d63 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 Mar 2026 17:09:11 -0400 Subject: [PATCH 4/4] Update src/zm_local_camera.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/zm_local_camera.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index c95e1dfd471..60f62598174 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -1186,7 +1186,6 @@ int LocalCamera::Control(int vid_id, int newvalue) { Warning("Given control value (%d) may be out-of-range", newvalue); } } - v4l2_close( vid_fd ); } return vid_control.value; }