From 058913f241bbf3ab321308bf0394729c81cdef2d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 27 Feb 2025 21:33:12 -0500 Subject: [PATCH 01/14] Add av1_vaapi to list of encoders --- src/zm_videostore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index ae6195b4d..4325aada5 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -59,6 +59,7 @@ VideoStore::CodecData VideoStore::codec_data[] = { { AV_CODEC_ID_AV1, "av1", "libsvtav1", AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P, AV_HWDEVICE_TYPE_NONE }, { AV_CODEC_ID_AV1, "av1", "libaom-av1", AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P, AV_HWDEVICE_TYPE_NONE }, { AV_CODEC_ID_AV1, "av1", "av1_qsv", AV_PIX_FMT_YUV420P, AV_PIX_FMT_QSV, AV_HWDEVICE_TYPE_QSV }, + { AV_CODEC_ID_AV1, "av1", "av1_vaapi", AV_PIX_FMT_YUV420P, AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI }, #else { AV_CODEC_ID_H265, "h265", "libx265", AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P }, From 7bb57bd373770942acbabc6d9edf326b2b760032 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 28 Feb 2025 17:40:43 +0300 Subject: [PATCH 02/14] Fix: Event page. When switching fullscreen mode by double-clicking on an image, take into account the "eventStats" block (skin.js) Otherwise, when switching to full-screen mode with the "eventStats" block displayed, empty black spaces remain on the right and left. --- web/skins/classic/js/skin.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 2fdbdfbc6..1a6afe569 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -1253,8 +1253,18 @@ var doubleClickOnStream = function(event, touchEvent) { if (target) { if (document.fullscreenElement) { + if (getCookie('zmEventStats') && eventStats) { + eventStats.toggle(true); + wrapperEventVideo.removeClass('col-sm-12').addClass('col-sm-8'); + changeScale(); + } closeFullscreen(); } else { + if (getCookie('zmEventStats') && eventStats) { + eventStats.toggle(false); + wrapperEventVideo.removeClass('col-sm-8').addClass('col-sm-12'); + changeScale(); + } openFullscreen(target); } if (isMobile()) { From d932d19f302971c087ce43aac1161805a8e63b14 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 28 Feb 2025 12:06:14 -0500 Subject: [PATCH 03/14] Bump freebsd versions and add 15 --- .cirrus.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 9f374210e..c1495c372 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,8 +2,9 @@ task: name: freebsd-build freebsd_instance: matrix: - - image_family: freebsd-14-0 - - image_family: freebsd-13-3 + - image_family: freebsd-15-0 + - image_family: freebsd-14-2 + - image_family: freebsd-13-5 prepare_script: - pkg install -yq git cmake pkgconf jpeg-turbo mysql80-client ffmpeg libvncserver libjwt catch2 p5-DBI p5-DBD-mysql p5-Date-Manip p5-Test-LWP-UserAgent p5-Sys-Mmap v4l_compat From ff666847a1dbefae7536c8ae2c1a792f77fa49ae Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Sat, 1 Mar 2025 00:42:10 +0300 Subject: [PATCH 04/14] Fix: Watch page. When switching fullscreen mode by double-clicking on an image, take into account the "sidebarView" block (skin.js) Also fixed the error of the undefined variable --- web/skins/classic/js/skin.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 1a6afe569..a5a82dd48 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -1253,17 +1253,27 @@ var doubleClickOnStream = function(event, touchEvent) { if (target) { if (document.fullscreenElement) { - if (getCookie('zmEventStats') && eventStats) { + if (getCookie('zmEventStats') && typeof eventStats !== "undefined") { + //Event page eventStats.toggle(true); wrapperEventVideo.removeClass('col-sm-12').addClass('col-sm-8'); changeScale(); + } else if (getCookie('zmCycleShow') && typeof sidebarView !== "undefined") { + //Watch page + sidebarView.toggle(true); + monitorsSetScale(monitorId); } closeFullscreen(); } else { - if (getCookie('zmEventStats') && eventStats) { + if (getCookie('zmEventStats') && typeof eventStats !== "undefined") { + //Event page eventStats.toggle(false); wrapperEventVideo.removeClass('col-sm-8').addClass('col-sm-12'); changeScale(); + } else if (getCookie('zmCycleShow') && typeof sidebarView !== "undefined") { + //Watch page + sidebarView.toggle(false); + monitorsSetScale(monitorId); } openFullscreen(target); } From c04b4b9bf23f89252044b78a3bba0dd008654d6c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 28 Feb 2025 17:50:07 -0500 Subject: [PATCH 05/14] Add av1-vaapi --- web/skins/classic/views/monitor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index bf4e4cd20..816124730 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -1161,7 +1161,8 @@ $videowriter_encoders = array( 'vp9-qsv' => 'vp9-qsv', 'libsvtav1' => 'libsvtav1', 'libaom-av1' => 'libaom-av1', - 'av1_qsv' => 'av1_qsv' + 'av1_qsv' => 'av1_qsv', + 'av1_vaapi' => 'av1_vaapi' ); echo htmlSelect('newMonitor[Encoder]', $videowriter_encoders, $monitor->Encoder()); ?> From 11ed05fb0a67b8d198b0d2db81935b9142c6db54 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 2 Mar 2025 14:35:48 -0500 Subject: [PATCH 06/14] Add canPlayCodec helper function to detect if we can play a certain codec from a given filename --- web/skins/classic/js/skin.js | 20 ++++++++++++++++++++ web/skins/classic/views/js/event.js | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js index 1a6afe569..a5b9bed1d 100644 --- a/web/skins/classic/js/skin.js +++ b/web/skins/classic/js/skin.js @@ -1367,3 +1367,23 @@ $j(document).on('keyup.global keydown.global', function(e) { }); loadFontFaceObserver(); + +function canPlayCodec(filename) { + const re = /\.(\w+)\.(\w+)$/i; + const matches = re.exec(filename); + if (matches.length) { + const video = document.createElement('video'); + if (matches[1] == 'av1') matches[1] = 'avc1'; + const can = video.canPlayType('video/mp4; codecs="'+matches[1]+'"'); + if (can == "probably") { + console.log("can play "+matches[1]); + return true; + } else if (can == "maybe") { + console.log("can maybe play "+matches[1]); + return true; + } + console.log("cannot play "+matches[1]); + return false; + } + return false; +} diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 2dddf12cf..1d0fd0c67 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -1346,6 +1346,7 @@ function initPage() { getAvailableTags(); getSelectedTags(); + // Load the event stats getStat(); zmPanZoom.init(); @@ -1359,7 +1360,10 @@ function initPage() { } //FIXME prevent blocking...not sure what is happening or best way to unblock - if (document.getElementById('videoobj')) { + const video_element = document.getElementById('videoobj'); + if (video_element) { + canPlayCodec(eventData.DefaultVideo); + vid = videojs('videoobj'); addVideoTimingTrack(vid, LabelFormat, eventData.MonitorName, eventData.Length, eventData.StartDateTime); //$j('.vjs-progress-control').append('
');//add a place for videojs only on first load From 5cff2f0904a01234425c5c77dad5b38a76175905 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 2 Mar 2025 14:37:26 -0500 Subject: [PATCH 07/14] FIx name collision on RTSP2WebStream => RTSP2WebStreamOptions --- web/includes/Monitor.php | 10 +++++----- web/skins/classic/views/monitor.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index dc79e1f8d..6b3046e79 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -197,15 +197,15 @@ class Monitor extends ZM_Object { protected static $table = 'Monitors'; - protected static $RTSP2WebStream = null; - public static function getRTSP2WebStream() { - if (!isset($RTSP2WebStream)) { - $RTSP2WebStream = array( + protected static $RTSP2WebStreamOptions = null; + public static function getRTSP2WebStreamOptions() { + if (!isset($RTSP2WebStreamOptions)) { + $RTSP2WebStreamOptions = array( 'Primary' => translate('Primary'), 'Secondary' => translate('Secondary'), ); } - return $RTSP2WebStream; + return $RTSP2WebStreamOptions; } protected $defaults = array( diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 816124730..7617a1dca 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -1232,7 +1232,7 @@ echo htmlSelect('newMonitor[OutputContainer]', $videowriter_containers, $monitor
  • - RTSP2WebStream()); ?> + RTSP2WebStream()); ?>
  • From da9ec0bf4c1e5e4745c79b3e1c7fb51f5825bf4e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 2 Mar 2025 14:37:39 -0500 Subject: [PATCH 08/14] Include DefaultVideo in eventData --- web/skins/classic/views/js/event.js.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php index 443cbb692..785b4b7a1 100644 --- a/web/skins/classic/views/js/event.js.php +++ b/web/skins/classic/views/js/event.js.php @@ -41,6 +41,7 @@ var eventData = { MaxScore: 'MaxScore() ?>', DiskSpace: 'DiskSpace(null)) ?>', Storage: 'Storage()->Name()).( $Event->SecondaryStorageId() ? ', '.validHtmlStr($Event->SecondaryStorage()->Name()) : '' ) ?>', + DefaultVideo: 'DefaultVideo()) ?>', Archived: Archived?'true':'false' ?>, Emailed: Emailed?'true':'false' ?>, Path: 'Path() ?>', From ef0d309737c22e0839eaa3566d67aaf54338fd5e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 2 Mar 2025 16:16:19 -0500 Subject: [PATCH 09/14] Use validJsStr to escape things needed for config entries. Fixes GHSA-c7hj-fxh6-8g8j --- web/skins/classic/js/skin.js.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/js/skin.js.php b/web/skins/classic/js/skin.js.php index 838def609..43150af62 100644 --- a/web/skins/classic/js/skin.js.php +++ b/web/skins/classic/js/skin.js.php @@ -153,6 +153,7 @@ if ($user) { if (isset($c['Type']) and $c['Type'] == 'integer' and $c['Value'] != '') { echo 'const '. $name . ' = '.$value.';'.PHP_EOL; } else { + $value = html_entity_decode(validJsStr($value)); echo 'const '. $name . ' = \''.$value.'\';'.PHP_EOL; } } From 034fff9623d397fe62760fe1f0f1bc536cc6b63c Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Mon, 3 Mar 2025 15:44:49 +0300 Subject: [PATCH 10/14] Fix: Changed RTSP2WebStream => RTSP2WebStreamOptions (watch.php) In addition to https://github.com/ZoneMinder/zoneminder/commit/5cff2f0904a01234425c5c77dad5b38a76175905 --- web/skins/classic/views/watch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index a09e560ec..0b6b3dea1 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -309,7 +309,7 @@ echo htmlSelect('changeRate', $maxfps_options, $options['maxfps']); RTSP2WebStream(), array('data-on-change'=>'monitorChangeStreamChannel','id'=>'streamChannel')); + echo htmlSelect('streamChannel', ZM\Monitor::getRTSP2WebStreamOptions(), $monitor->RTSP2WebStream(), array('data-on-change'=>'monitorChangeStreamChannel','id'=>'streamChannel')); echo htmlSelect('streamQuality', $streamQuality, $streamQualitySelected, array('data-on-change'=>'changeStreamQuality','id'=>'streamQuality')); ?> From 9c640c027b4f7cc566f504979bd7364e9fa8ed30 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Mon, 3 Mar 2025 19:10:39 +0300 Subject: [PATCH 11/14] Fix: Stop/start invisible/visible monitors when switching Layout (montage.js) --- web/skins/classic/views/js/montage.js | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index f36aa506f..7fdcc92b7 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -203,6 +203,7 @@ function selectLayout(new_layout_id) { changeMonitorStatusPosition(); //!!! After loading the saved layer, you must execute. monitorsSetScale(); */ + on_scroll(); setCookie('zmMontageLayout', layout_id); } // end function selectLayout(element) From 9027f3476edfd37c607a07ef3043e00118031fc5 Mon Sep 17 00:00:00 2001 From: Simpler1 Date: Mon, 3 Mar 2025 13:49:14 -0500 Subject: [PATCH 12/14] Install the web/sounds directory --- web/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/CMakeLists.txt b/web/CMakeLists.txt index 9676f1cfa..126a67022 100644 --- a/web/CMakeLists.txt +++ b/web/CMakeLists.txt @@ -6,7 +6,7 @@ add_subdirectory(api) configure_file(includes/config.php.in "${CMAKE_CURRENT_BINARY_DIR}/includes/config.php" @ONLY) # Install the web files -install(DIRECTORY vendor api ajax css fonts graphics includes js lang skins views DESTINATION "${ZM_WEBDIR}" PATTERN "*.in" EXCLUDE PATTERN "*Make*" EXCLUDE PATTERN "*cmake*" EXCLUDE) +install(DIRECTORY vendor api ajax css fonts graphics includes js lang skins sounds views DESTINATION "${ZM_WEBDIR}" PATTERN "*.in" EXCLUDE PATTERN "*Make*" EXCLUDE PATTERN "*cmake*" EXCLUDE) install(FILES index.php robots.txt DESTINATION "${ZM_WEBDIR}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/includes/config.php" DESTINATION "${ZM_WEBDIR}/includes") From c0e66efaddb3abe58048a58738d703dcf123117b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 4 Mar 2025 20:34:52 -0500 Subject: [PATCH 13/14] Put comma between map reasons --- src/zm_event.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 88bcbef7e..90fac1911 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -343,6 +343,8 @@ void Event::createNotes(std::string ¬es) { notes += ", "; notes += *setIter; } + if (mapIter != noteSetMap.begin()) + notes += ", "; } } // void Event::createNotes(std::string ¬es) From b2e4053f67a6c3f1bd6997f517e9943b11552203 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 4 Mar 2025 22:25:20 -0500 Subject: [PATCH 14/14] Add missing , --- web/skins/classic/views/monitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index bf9d2fa39..a9342d03d 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -1190,7 +1190,7 @@ $videowriter_encoders = array( 'libsvtav1' => 'libsvtav1', 'libaom-av1' => 'libaom-av1', 'av1_qsv' => 'av1_qsv', - 'av1_ni_quadra_enc' => 'av1_ni_quadra' + 'av1_ni_quadra_enc' => 'av1_ni_quadra', 'av1_vaapi' => 'av1_vaapi' ); echo htmlSelect('newMonitor[Encoder]', $videowriter_encoders, $monitor->Encoder());