From aabe577675a23d1bf555b7b1900c1f73bd8eb989 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Wed, 29 May 2024 22:23:01 +0300 Subject: [PATCH 01/23] Added Scales = 480, 640, 800, 1024, 1280, 1600 px (config.php) --- web/skins/classic/includes/config.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/web/skins/classic/includes/config.php b/web/skins/classic/includes/config.php index 684b8b51c..d14addaf5 100644 --- a/web/skins/classic/includes/config.php +++ b/web/skins/classic/includes/config.php @@ -44,18 +44,24 @@ $rates = array( $scales = array( # We use 0 instead of words because we are saving this in the monitor # and use this array to populate the default scale option - '0' => translate('Auto'), + '0' => translate('Auto'), # '400' => '4x', # '300' => '3x', # '200' => '2x', # '150' => '1.5x', - '100' => translate('Actual'), + '100' => translate('Actual'), # '75' => '3/4x', # '50' => '1/2x', # '33' => '1/3x', # '25' => '1/4x', # '12.5' => '1/8x', - 'fit_to_width' => translate('Fit to width'), + 'fit_to_width' => translate('Fit to width'), + '480px' => translate('Max width 480px'), + '640px' => translate('Max width 640px'), + '800px' => translate('Max width 800px'), + '1024px' => translate('Max width 1024px'), + '1280px' => translate('Max width 1280px'), + '1600px' => translate('Max width 1600px'), ); if ( isset($_REQUEST['view']) && ($_REQUEST['view'] == 'montage') ) { From 510784599c62f55427950663c7b819c21aa909e5 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Thu, 30 May 2024 01:02:11 +0300 Subject: [PATCH 02/23] Added Scales = Max 480, 640, 800, 1024, 1280, 1600 px (watch.js) --- web/skins/classic/views/js/watch.js | 31 ++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index df7df9428..4d4744f08 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1319,7 +1319,10 @@ function monitorsSetScale(id=null) { const scale = $j('#scale').val(); let resize; let width; + let maxWidth = ''; let height; + let overrideHW = false; + let defScale = 0; if (scale == '0') { //Auto, Width is calculated based on the occupied height so that the image and control buttons occupy the visible part of the screen. @@ -1336,23 +1339,37 @@ function monitorsSetScale(id=null) { resize = false; width = parseInt(window.innerWidth * panZoomScale) + 'px'; height = 'auto'; + } else if (scale.indexOf("px") > -1) { + maxWidth = scale; + resize = true; + width = 'auto'; + height = 'auto'; + overrideHW = true; + defScale = parseInt(Math.min(stringToNumber(scale), window.innerWidth) / curentMonitor.width * panZoomScale * 100); } if (resize) { - document.getElementById('monitor'+id).style.width = 'max-content'; //Required when switching from resize=false to resize=true - } - //curentMonitor.setScale(0, el.clientWidth * panZoomScale + 'px', el.clientHeight * panZoomScale + 'px', {resizeImg:true, scaleImg:panZoomScale}); - curentMonitor.setScale(0, width, height, {resizeImg: resize, scaleImg: panZoomScale}); - if (!resize) { + if (scale == '0') { + document.getElementById('monitor'+id).style.width = 'max-content'; //Required when switching from resize=false to resize=true + } + document.getElementById('monitor'+id).style.maxWidth = maxWidth; + } else { document.getElementById('liveStream'+id).style.height = ''; + document.getElementById('monitor'+id).style.width = width; + document.getElementById('monitor'+id).style.maxWidth = ''; if (scale == 'fit_to_width') { document.getElementById('monitor'+id).style.width = ''; } else if (scale == '100') { - document.getElementById('monitor'+id).style.width = 'max-content'; document.getElementById('liveStream'+id).style.width = width; } } - } else { + //curentMonitor.setScale(0, maxWidth ? maxWidth : width, height, {resizeImg: resize, scaleImg: panZoomScale}); + curentMonitor.setScale(defScale, width, height, {resizeImg: resize, scaleImg: panZoomScale}); + if (overrideHW) { + document.getElementById('liveStream'+id).style.height = 'auto'; + document.getElementById('monitor'+id).style.width = 'auto'; + } + } else { for ( let i = 0, length = monitors.length; i < length; i++ ) { const id = monitors[i].id; //const el = document.getElementById('liveStream'+id); From eb376931682a799e8db4613c9a7ae21de361bb55 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Thu, 30 May 2024 01:05:17 +0300 Subject: [PATCH 03/23] Fix: eslint added lost space (watch.js) --- web/skins/classic/views/js/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 4d4744f08..831092147 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1369,7 +1369,7 @@ function monitorsSetScale(id=null) { document.getElementById('liveStream'+id).style.height = 'auto'; document.getElementById('monitor'+id).style.width = 'auto'; } - } else { + } else { for ( let i = 0, length = monitors.length; i < length; i++ ) { const id = monitors[i].id; //const el = document.getElementById('liveStream'+id); From 18628dbc4422944567f6a6cedd35b5931d02d916 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Thu, 30 May 2024 23:26:10 +0300 Subject: [PATCH 04/23] Added setting stream quality (config.php) Measured in % Used to change the Scale up (increase quality) or down (reduce network traffic) --- web/skins/classic/includes/config.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/web/skins/classic/includes/config.php b/web/skins/classic/includes/config.php index d14addaf5..492abb6a7 100644 --- a/web/skins/classic/includes/config.php +++ b/web/skins/classic/includes/config.php @@ -64,6 +64,21 @@ $scales = array( '1600px' => translate('Max width 1600px'), ); +$streamQuality = array( + # In % + '+50' => '+50%', + '+40' => '+40%', + '+30' => '+30%', + '+20' => '+20%', + '+10' => '+10%', + '0' => translate('Optimal'), + '-10' => '-10%', + '-20' => '-20%', + '-30' => '-30%', + '-40' => '-40%', + '-50' => '-50%', +); + if ( isset($_REQUEST['view']) && ($_REQUEST['view'] == 'montage') ) { unset($scales['auto']); //Remove auto on montage, use everywhere else } From 68e00d7d960692d0171fb6da317fec960e0d800a Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 00:16:28 +0300 Subject: [PATCH 05/23] Added $streamQuality processing & other (event.js) Added Scale display Added $streamQuality processing Added new options for selecting maximum width in $scales Minor fixes related to Scale Commented out unused code from the old version of Pan Zoom. In the future it should probably be completely removed. --- web/skins/classic/views/js/event.js | 70 ++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index d2b460ded..48259ebf8 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -41,6 +41,7 @@ var coordinateMouse = { }; var leftBtnStatus = {Down: false, UpAfterDown: false}; var updateScale = false; //Scale needs to be updated +var currentScale = 0; // Temporarily, because need to put things in order with the "scale" variable = "select" block $j(document).on("keydown", "", function(e) { e = e || window.event; @@ -276,6 +277,10 @@ function changeCodec() { location.replace(thisUrl + '?view=event&eid=' + eventData.Id + filterQuery + sortQuery+'&codec='+$j('#codec').val()); } +function deltaScale () { + return parseInt(currentScale/100*$j('#streamQuality').val()); // "-" - Decrease quality, "+" - Increase image quality in % +} + function changeScale() { const scaleSel = $j('#scale').val(); let newWidth; @@ -295,26 +300,36 @@ function changeScale() { //Actual, 100% of original size newWidth = eventData.Width; newHeight = eventData.Height; - scale = 100; + currentScale = 100; } else if (scaleSel == '0') { //Auto, Width is calculated based on the occupied height so that the image and control buttons occupy the visible part of the screen. newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, bottomEl, $j('#wrapperEventVideo')); newWidth = newSize.width; newHeight = newSize.height; - scale = newSize.autoScale; + currentScale = newSize.autoScale; } else if (scaleSel == 'fit_to_width') { //Fit to screen width newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo')); newWidth = newSize.width; newHeight = newSize.height; //newHeight = 'auto'; - scale = newSize.autoScale; + currentScale = newSize.autoScale; + } else if (scaleSel.indexOf("px") > -1) { + newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo')); // Only for calculating the maximum width! + const w = Math.min(stringToNumber(scaleSel), newSize.width); + const h = w / (eventData.Width / eventData.Height); + newWidth = parseInt(w); + newHeight = parseInt(h); + currentScale = parseInt(w / eventData.Width * 100); + currentScale = currentScale; } + //console.log(`Real dimensions: ${eventData.Width} X ${eventData.Height}, Scale: ${currentScale}, deltaScale: ${deltaScale()}, New dimensions: ${newWidth} X ${newHeight}`); + eventViewer.width(newWidth); eventViewer.height(newHeight); if (!vid) { // zms needs extra sizing - streamScale(scale); + streamScale(currentScale); drawProgressBar(); } if (cueFrames) { @@ -325,7 +340,7 @@ function changeScale() { // After a resize, check if we still have room to display the event stats table onStatsResize(newWidth); - updateScale = true; + //updateScale = true; /* OLD version scale = parseFloat($j('#scale').val()); @@ -364,6 +379,12 @@ function changeScale() { */ } // end function changeScale +function changeStreamQuality () { + const streamQuality = $j('#streamQuality').val(); + setCookie('zmStreamQuality', streamQuality); + streamScale(currentScale); +} + function changeReplayMode() { var replayMode = $j('#replayMode').val(); @@ -449,15 +470,17 @@ function getCmdResponse(respObj, respText) { streamPlay( ); } $j('#progressValue').html(secsToTime(parseInt(streamStatus.progress))); - $j('#zoomValue').html(streamStatus.zoom); + //$j('#zoomValue').html(streamStatus.zoom); + $j('#zoomValue').html(zmPanZoom.panZoom[eventData.MonitorId].getScale().toFixed(1)); if (streamStatus.zoom == '1.0') { setButtonState('zoomOutBtn', 'unavail'); } else { setButtonState('zoomOutBtn', 'inactive'); } - if (scale && (streamStatus.scale !== undefined) && (streamStatus.scale != scale)) { - console.log("Stream not scaled, re-applying", scale, streamStatus.scale); - streamScale(scale); + + if (currentScale && (streamStatus.scale !== undefined) && (streamStatus.scale != currentScale + deltaScale())) { + console.log("Stream not scaled, re-applying", currentScale + deltaScale(), streamStatus.scale); + streamScale(currentScale); } updateProgressBar(); @@ -510,9 +533,11 @@ function playClicked( ) { if (zmsBroke) { // The assumption is that the command failed because zms exited, so restart the stream. const img = document.getElementById('evtStream'); - const src = img.src; + let src = img.src; + const url = new URL(src); + url.searchParams.set('scale', currentScale); // In event.php we don’t yet know what scale to substitute. Let it be for now. img.src = ''; - img.src = src; + img.src = url; zmsBroke = false; } else { streamReq({command: CMD_PLAY}); @@ -686,6 +711,7 @@ function tagAndPrev(action) { streamPrev(action); } +/* Not used function vjsPanZoom(action, x, y) { //Pan and zoom with centering where the click occurs var outer = $j('#videoobj'); var video = outer.children().first(); @@ -758,13 +784,16 @@ function streamZoomOut() { streamReq({command: CMD_ZOOMOUT}); } } +*/ function streamScale(scale) { + scale += deltaScale(); if (document.getElementById('evtStream')) { streamReq({command: CMD_SCALE, scale: (scale>100) ? 100 : scale}); } } +/* function streamPan(x, y) { if (vid) { vjsPanZoom('pan', x, y); @@ -772,6 +801,7 @@ function streamPan(x, y) { streamReq({command: CMD_PAN, x: x, y: y}); } } +*/ function streamSeek(offset) { if (vid) { @@ -808,7 +838,7 @@ function getEventResponse(respObj, respText) { $j('#modeValue').html('Replay'); $j('#zoomValue').html('1'); $j('#rate').val('100'); - vjsPanZoom('zoomOut'); + //vjsPanZoom('zoomOut'); } else { drawProgressBar(); } @@ -1019,6 +1049,7 @@ function handleClick(event) { } } else { // +++ Old ZoomPan algorithm. + /* if (vid && (event.target.id != 'videoobj')) { return; // ignore clicks on control bar } @@ -1045,10 +1076,11 @@ function handleClick(event) { updatePrevCoordinatFrame(x, y); //Fixing current coordinates after scaling or shifting } } - // --- Old ZoomPan algorithm. + */// --- Old ZoomPan algorithm. } } +/* function shiftImgFrame() { //We calculate the coordinates of the image displacement and shift the image let newPosX = parseInt(PrevCoordinatFrame.x - coordinateMouse.shiftMouse_x); let newPosY = parseInt(PrevCoordinatFrame.y - coordinateMouse.shiftMouse_y); @@ -1082,8 +1114,10 @@ function getCoordinateMouse(event) { //We get the current cursor coordinates tak return {x: parseInt((event.pageX - pos.left) * scaleX), y: parseInt((event.pageY - pos.top) * scaleY)}; //The point of the mouse click relative to the dimensions of the real frame. } +*/ function handleMove(event) { +/* if (panZoomEnabled) { return; } @@ -1126,6 +1160,7 @@ function handleMove(event) { leftBtnStatus.UpAfterDown = false; } // --- Old ZoomPan algorithm. +*/ } // Manage the DELETE CONFIRMATION modal button @@ -1277,6 +1312,7 @@ function initPage() { // Load the event stats getStat(); zmPanZoom.init(); + changeStreamQuality (); if (getEvtStatsCookie() != 'on') { eventStats.toggle(false); @@ -1341,7 +1377,8 @@ function initPage() { } } // end if videojs or mjpeg stream progressBarNav(); - if (scale == '0') changeScale(); +// if (scale == '0') changeScale(); + changeScale(); nearEventsQuery(eventData.Id); initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues document.querySelectorAll('select[name="rate"]').forEach(function(el) { @@ -1634,9 +1671,10 @@ function initPage() { if (updateScale) { const eventViewer = $j(vid ? '#videoobj' : '#evtStream'); const panZoomScale = panZoomEnabled ? zmPanZoom.panZoom[eventData.MonitorId].getScale() : 1; - const newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo'), panZoomScale); + const newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#videoFeed'), panZoomScale); scale = newSize.autoScale > 100 ? 100 : newSize.autoScale; - //streamScale(scale); + currentScale = scale; + streamScale(currentScale); updateScale = false; } }, 500); From 5706bf2ade2e487ed63044a8b53af9441a34372d Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 00:51:49 +0300 Subject: [PATCH 06/23] Added $streamQuality processing (MonitorStream.js) --- web/js/MonitorStream.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/web/js/MonitorStream.js b/web/js/MonitorStream.js index 27b8f838f..c69ffffac 100644 --- a/web/js/MonitorStream.js +++ b/web/js/MonitorStream.js @@ -94,6 +94,7 @@ function MonitorStream(monitorData) { * height should be auto, 100%, integer +px * param.resizeImg be boolean (added only for using GridStack & PanZoom on Montage page) * param.scaleImg scaling 1=100% (added only for using PanZoom on Montage & Watch page) + * param.streamQuality in %, numeric value from -50 to +50) * */ this.setScale = function(newscale, width, height, param = {}) { const img = this.getElement(); @@ -173,10 +174,15 @@ function MonitorStream(monitorData) { $j(img).closest('.monitorStream')[0].style.overflow = 'hidden'; } } - this.setStreamScale(newscale); + let streamQuality = 0; + if (param.streamQuality) { + streamQuality = param.streamQuality; + newscale += parseInt(newscale/100*streamQuality); + } + this.setStreamScale(newscale, streamQuality); }; // setScale - this.setStreamScale = function(newscale) { + this.setStreamScale = function(newscale, streamQuality=0) { const img = this.getElement(); if (!img) { console.log("No img in setScale"); @@ -187,7 +193,7 @@ function MonitorStream(monitorData) { newscale = parseInt(100*parseInt(stream_frame.width())/this.width); } if (newscale > 100) newscale = 100; // we never request a larger image, as it just wastes bandwidth - if (newscale < 25) newscale = 25; // Arbitrary, lower values look bad + if (newscale < 25 && streamQuality > -1) newscale = 25; // Arbitrary, lower values look bad if (newscale <= 0) newscale = 100; this.scale = newscale; if (this.connKey) { From 0be93427c8346ec0d55b66c9bc6db4531b4342ac Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 00:55:34 +0300 Subject: [PATCH 07/23] Added $streamQuality processing (watch.js) --- web/skins/classic/views/js/watch.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 831092147..9bfb8ea1b 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -162,6 +162,13 @@ function changeScale() { setScale(); */ } + +function changeStreamQuality () { + const streamQuality = $j('#streamQuality').val(); + setCookie('zmStreamQuality', streamQuality); + monitorsSetScale(monitorId); +} + // Implement current scale, as opposed to changing it function setScale() { /* @@ -1364,7 +1371,7 @@ function monitorsSetScale(id=null) { } } //curentMonitor.setScale(0, maxWidth ? maxWidth : width, height, {resizeImg: resize, scaleImg: panZoomScale}); - curentMonitor.setScale(defScale, width, height, {resizeImg: resize, scaleImg: panZoomScale}); + curentMonitor.setScale(defScale, width, height, {resizeImg: resize, scaleImg: panZoomScale, streamQuality: $j('#streamQuality').val()}); if (overrideHW) { document.getElementById('liveStream'+id).style.height = 'auto'; document.getElementById('monitor'+id).style.width = 'auto'; From 7d86df0c04057f720af64d86ed92979893f9dbfa Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 01:04:03 +0300 Subject: [PATCH 08/23] Chore: eslint MonitorStream.js --- web/js/MonitorStream.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/js/MonitorStream.js b/web/js/MonitorStream.js index c69ffffac..1b98ca17b 100644 --- a/web/js/MonitorStream.js +++ b/web/js/MonitorStream.js @@ -174,7 +174,7 @@ function MonitorStream(monitorData) { $j(img).closest('.monitorStream')[0].style.overflow = 'hidden'; } } - let streamQuality = 0; + let streamQuality = 0; if (param.streamQuality) { streamQuality = param.streamQuality; newscale += parseInt(newscale/100*streamQuality); From d4a963b7cf648d9e49bf036b5b46682bc987200b Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 01:05:35 +0300 Subject: [PATCH 09/23] Chore: eslint (watch.js) --- web/skins/classic/views/js/watch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 9bfb8ea1b..cf47df615 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -163,7 +163,7 @@ function changeScale() { */ } -function changeStreamQuality () { +function changeStreamQuality() { const streamQuality = $j('#streamQuality').val(); setCookie('zmStreamQuality', streamQuality); monitorsSetScale(monitorId); From 282f11a8943dbaff120201c9e596ee7e5e49085c Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 01:11:55 +0300 Subject: [PATCH 10/23] Chore: eslint (event.js) --- web/skins/classic/views/js/event.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 48259ebf8..1b4b7bf42 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -277,7 +277,7 @@ function changeCodec() { location.replace(thisUrl + '?view=event&eid=' + eventData.Id + filterQuery + sortQuery+'&codec='+$j('#codec').val()); } -function deltaScale () { +function deltaScale() { return parseInt(currentScale/100*$j('#streamQuality').val()); // "-" - Decrease quality, "+" - Increase image quality in % } @@ -379,7 +379,7 @@ function changeScale() { */ } // end function changeScale -function changeStreamQuality () { +function changeStreamQuality() { const streamQuality = $j('#streamQuality').val(); setCookie('zmStreamQuality', streamQuality); streamScale(currentScale); @@ -533,7 +533,7 @@ function playClicked( ) { if (zmsBroke) { // The assumption is that the command failed because zms exited, so restart the stream. const img = document.getElementById('evtStream'); - let src = img.src; + const src = img.src; const url = new URL(src); url.searchParams.set('scale', currentScale); // In event.php we don’t yet know what scale to substitute. Let it be for now. img.src = ''; @@ -1312,7 +1312,7 @@ function initPage() { // Load the event stats getStat(); zmPanZoom.init(); - changeStreamQuality (); + changeStreamQuality(); if (getEvtStatsCookie() != 'on') { eventStats.toggle(false); @@ -1377,7 +1377,7 @@ function initPage() { } } // end if videojs or mjpeg stream progressBarNav(); -// if (scale == '0') changeScale(); + //if (scale == '0') changeScale(); changeScale(); nearEventsQuery(eventData.Id); initialAlarmCues(eventData.Id); //call ajax+renderAlarmCues From fb866a1edc1325fd849537bd28fc8ee436145bbe Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 01:15:39 +0300 Subject: [PATCH 11/23] Added $streamQuality processing (watch.php) --- web/skins/classic/views/watch.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index 34dbba457..d5228b36a 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -165,6 +165,15 @@ if ( !isset($scales[$scale])) { } $options['scale'] = 0; //Somewhere something is spoiled because of this... +$streamQualitySelected = '0'; +if (isset($_REQUEST['streamQuality'])) { + $streamQualitySelected = $_REQUEST['streamQuality']; +} else if (isset($_COOKIE['zmStreamQuality'])) { + $streamQualitySelected = $_COOKIE['zmStreamQuality']; +} else if (isset($_SESSION['zmStreamQuality']) ) { + $streamQualitySelected = $_SESSION['zmStreamQuality']; +} + if (isset($_REQUEST['width'])) { $options['width'] = validInt($_REQUEST['width']); } else if ( isset($_COOKIE['zmWatchWidth']) and $_COOKIE['zmWatchWidth'] ) { @@ -276,6 +285,10 @@ echo htmlSelect('changeRate', $maxfps_options, $options['maxfps']); 'scale', 'data-on-change-this'=>'changeScale') ); ?> + + + 'changeStreamQuality','id'=>'streamQuality')); ?> + From ee9206eff603d615bb08baced7fc641d1b6c48c7 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 01:18:54 +0300 Subject: [PATCH 12/23] Added $streamQuality processing (event.php) --- web/skins/classic/views/event.php | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 52e36ebf4..47893dc1a 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -52,7 +52,7 @@ if ($rate > 1600) { zm_setcookie('zmEventRate', $rate); } -// $scaleSelected - временно для адаптации нового алгоритма, т.к. $scale может быть только численное значение ! +// $scaleSelected - temporarily to adapt the new algorithm, because $scale can only be a numeric value! if (isset($_REQUEST['scale'])) { $scale = validInt($_REQUEST['scale']); $scaleSelected = $_REQUEST['scale']; @@ -63,8 +63,18 @@ if (isset($_REQUEST['scale'])) { $scale = validInt($monitor->DefaultScale()); $scaleSelected = $monitor->DefaultScale(); } -if (!validInt($scale) and $scale != '0') { - $scale = '0'; +//if (!validInt($scale) and $scale != '0') { +// $scale = '0'; +//} +$scale = '10'; // temporarily to adapt the new algorithm, not used in new calculations! + +$streamQualitySelected = '0'; +if (isset($_REQUEST['streamQuality'])) { + $streamQualitySelected = $_REQUEST['streamQuality']; +} else if (isset($_COOKIE['zmStreamQuality'])) { + $streamQualitySelected = $_COOKIE['zmStreamQuality']; +} else if (isset($_SESSION['zmStreamQuality']) ) { + $streamQualitySelected = $_SESSION['zmStreamQuality']; } $showZones = false; @@ -227,6 +237,10 @@ if ( $Event->Id() and !file_exists($Event->Path()) ) 'changeScale','id'=>'scale')); ?> +
+ + 'changeStreamQuality','id'=>'streamQuality')); ?> +
'changeCodec','id'=>'codec')); ?> @@ -402,9 +416,9 @@ if ( (ZM_WEB_STREAM_METHOD == 'mpeg') && ZM_MPEG_LIVE_FORMAT ) { - From 1751789fb96f01b4dd6041f4d1ed5f5ec475fbde Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 13:32:35 +0300 Subject: [PATCH 13/23] Rename 'Max width 480px' to 'Max 480px' Etc. (config.php) Because the image can be in either a landscape or a portrait, which means you need to control both the width and height --- web/skins/classic/includes/config.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/includes/config.php b/web/skins/classic/includes/config.php index 492abb6a7..09824a86d 100644 --- a/web/skins/classic/includes/config.php +++ b/web/skins/classic/includes/config.php @@ -56,12 +56,12 @@ $scales = array( # '25' => '1/4x', # '12.5' => '1/8x', 'fit_to_width' => translate('Fit to width'), - '480px' => translate('Max width 480px'), - '640px' => translate('Max width 640px'), - '800px' => translate('Max width 800px'), - '1024px' => translate('Max width 1024px'), - '1280px' => translate('Max width 1280px'), - '1600px' => translate('Max width 1600px'), + '480px' => translate('Max 480px'), + '640px' => translate('Max 640px'), + '800px' => translate('Max 800px'), + '1024px' => translate('Max 1024px'), + '1280px' => translate('Max 1280px'), + '1600px' => translate('Max 1600px'), ); $streamQuality = array( From fc127b7c47c26cc82ec73724cb0c8b263f3362d3 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 13:55:59 +0300 Subject: [PATCH 14/23] $streamQuality applied to portrait mode (watch.js) --- web/skins/classic/views/js/watch.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index cf47df615..228d82a32 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1330,6 +1330,7 @@ function monitorsSetScale(id=null) { let height; let overrideHW = false; let defScale = 0; + const landscape = curentMonitor.width / curentMonitor.height > 1 ? true : false; //Image orientation. if (scale == '0') { //Auto, Width is calculated based on the occupied height so that the image and control buttons occupy the visible part of the screen. @@ -1347,12 +1348,17 @@ function monitorsSetScale(id=null) { width = parseInt(window.innerWidth * panZoomScale) + 'px'; height = 'auto'; } else if (scale.indexOf("px") > -1) { + if (landscape) { maxWidth = scale; + defScale = parseInt(Math.min(stringToNumber(scale), window.innerWidth) / curentMonitor.width * panZoomScale * 100); + height = 'auto'; + } else { + defScale = parseInt(Math.min(stringToNumber(scale), window.innerHeight) / curentMonitor.height * panZoomScale * 100); + height = scale; + } resize = true; width = 'auto'; - height = 'auto'; overrideHW = true; - defScale = parseInt(Math.min(stringToNumber(scale), window.innerWidth) / curentMonitor.width * panZoomScale * 100); } if (resize) { @@ -1360,6 +1366,10 @@ function monitorsSetScale(id=null) { document.getElementById('monitor'+id).style.width = 'max-content'; //Required when switching from resize=false to resize=true } document.getElementById('monitor'+id).style.maxWidth = maxWidth; + if (!landscape) { //PORTRAIT + document.getElementById('monitor'+id).style.width = 'max-content'; + document.getElementById('liveStream'+id).style.height = height; + } } else { document.getElementById('liveStream'+id).style.height = ''; document.getElementById('monitor'+id).style.width = width; @@ -1373,9 +1383,13 @@ function monitorsSetScale(id=null) { //curentMonitor.setScale(0, maxWidth ? maxWidth : width, height, {resizeImg: resize, scaleImg: panZoomScale}); curentMonitor.setScale(defScale, width, height, {resizeImg: resize, scaleImg: panZoomScale, streamQuality: $j('#streamQuality').val()}); if (overrideHW) { + if (!landscape) { //PORTRAIT + document.getElementById('monitor'+id).style.width = 'max-content'; + } else { document.getElementById('liveStream'+id).style.height = 'auto'; document.getElementById('monitor'+id).style.width = 'auto'; } + } } else { for ( let i = 0, length = monitors.length; i < length; i++ ) { const id = monitors[i].id; From ac85492f1ba84a62e597d95aa8144750d508a4a0 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 13:59:14 +0300 Subject: [PATCH 15/23] $streamQuality applied to portrait mode (event.js) --- web/skins/classic/views/js/event.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 1b4b7bf42..20a98d587 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -289,6 +289,7 @@ function changeScale() { const alarmCue = $j('#alarmCues'); const bottomEl = $j('#replayStatus'); + const landscape = eventData.width / eventData.height > 1 ? true : false; //Image orientation. setCookie('zmEventScale'+eventData.MonitorId, scaleSel); @@ -312,12 +313,17 @@ function changeScale() { newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo')); newWidth = newSize.width; newHeight = newSize.height; - //newHeight = 'auto'; currentScale = newSize.autoScale; } else if (scaleSel.indexOf("px") > -1) { newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo')); // Only for calculating the maximum width! - const w = Math.min(stringToNumber(scaleSel), newSize.width); - const h = w / (eventData.Width / eventData.Height); + let w, h; + if (landscape) { + w = Math.min(stringToNumber(scaleSel), newSize.width); + h = w / (eventData.Width / eventData.Height); + } else { + h = Math.min(stringToNumber(scaleSel), newSize.height); + w = h * (eventData.Width / eventData.Height); + } newWidth = parseInt(w); newHeight = parseInt(h); currentScale = parseInt(w / eventData.Width * 100); @@ -472,11 +478,11 @@ function getCmdResponse(respObj, respText) { $j('#progressValue').html(secsToTime(parseInt(streamStatus.progress))); //$j('#zoomValue').html(streamStatus.zoom); $j('#zoomValue').html(zmPanZoom.panZoom[eventData.MonitorId].getScale().toFixed(1)); - if (streamStatus.zoom == '1.0') { - setButtonState('zoomOutBtn', 'unavail'); - } else { - setButtonState('zoomOutBtn', 'inactive'); - } + //if (streamStatus.zoom == '1.0') { + // setButtonState('zoomOutBtn', 'unavail'); + //} else { + // setButtonState('zoomOutBtn', 'inactive'); + //} if (currentScale && (streamStatus.scale !== undefined) && (streamStatus.scale != currentScale + deltaScale())) { console.log("Stream not scaled, re-applying", currentScale + deltaScale(), streamStatus.scale); From c6c916d9ef2e0ec9c39f3a5a872a8b48341ea3fd Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 14:01:07 +0300 Subject: [PATCH 16/23] Chore: eslint event.js --- web/skins/classic/views/js/event.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 20a98d587..2023f9397 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -316,7 +316,7 @@ function changeScale() { currentScale = newSize.autoScale; } else if (scaleSel.indexOf("px") > -1) { newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo')); // Only for calculating the maximum width! - let w, h; + const w, h; if (landscape) { w = Math.min(stringToNumber(scaleSel), newSize.width); h = w / (eventData.Width / eventData.Height); From d5a8d931e663ff18eacaa9cc50be3953e932594e Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 14:07:53 +0300 Subject: [PATCH 17/23] Chore: eslint (watch.js) --- web/skins/classic/views/js/watch.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/js/watch.js b/web/skins/classic/views/js/watch.js index 228d82a32..ba63b29c5 100644 --- a/web/skins/classic/views/js/watch.js +++ b/web/skins/classic/views/js/watch.js @@ -1349,7 +1349,7 @@ function monitorsSetScale(id=null) { height = 'auto'; } else if (scale.indexOf("px") > -1) { if (landscape) { - maxWidth = scale; + maxWidth = scale; defScale = parseInt(Math.min(stringToNumber(scale), window.innerWidth) / curentMonitor.width * panZoomScale * 100); height = 'auto'; } else { @@ -1386,9 +1386,9 @@ function monitorsSetScale(id=null) { if (!landscape) { //PORTRAIT document.getElementById('monitor'+id).style.width = 'max-content'; } else { - document.getElementById('liveStream'+id).style.height = 'auto'; - document.getElementById('monitor'+id).style.width = 'auto'; - } + document.getElementById('liveStream'+id).style.height = 'auto'; + document.getElementById('monitor'+id).style.width = 'auto'; + } } } else { for ( let i = 0, length = monitors.length; i < length; i++ ) { From 5565b8cca10b6e203e834e3c84994940c6e1dd0a Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 14:53:55 +0300 Subject: [PATCH 18/23] Fix: variable declaration (event.js) --- web/skins/classic/views/js/event.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js index 2023f9397..f91299377 100644 --- a/web/skins/classic/views/js/event.js +++ b/web/skins/classic/views/js/event.js @@ -316,7 +316,7 @@ function changeScale() { currentScale = newSize.autoScale; } else if (scaleSel.indexOf("px") > -1) { newSize = scaleToFit(eventData.Width, eventData.Height, eventViewer, false, $j('#wrapperEventVideo')); // Only for calculating the maximum width! - const w, h; + let w = h = ''; if (landscape) { w = Math.min(stringToNumber(scaleSel), newSize.width); h = w / (eventData.Width / eventData.Height); From 35ea66737872cc03a2f7229fd8d950015e423e23 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 15:35:15 +0300 Subject: [PATCH 19/23] Added $streamQuality processing (montage.js) --- web/skins/classic/views/js/montage.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index 50972c691..3b162e567 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -947,6 +947,12 @@ function panZoomOut(el) { zmPanZoom.zoomOut(el); } +function changeStreamQuality() { + const streamQuality = $j('#streamQuality').val(); + setCookie('zmStreamQuality', streamQuality); + monitorsSetScale(); +} + function monitorsSetScale(id=null) { // This function will probably need to be moved to the main JS file, because now used on Watch & Montage pages if (id || typeof monitorStream !== 'undefined') { @@ -960,13 +966,13 @@ function monitorsSetScale(id=null) { } const el = document.getElementById('liveStream'+id); const panZoomScale = panZoomEnabled ? zmPanZoom.panZoom[id].getScale() : 1; - currentMonitor.setScale(0, el.clientWidth * panZoomScale + 'px', el.clientHeight * panZoomScale + 'px', {resizeImg: false}); + currentMonitor.setScale(0, el.clientWidth * panZoomScale + 'px', el.clientHeight * panZoomScale + 'px', {resizeImg: false, streamQuality: $j('#streamQuality').val()}); } else { for ( let i = 0, length = monitors.length; i < length; i++ ) { const id = monitors[i].id; const el = document.getElementById('liveStream'+id); const panZoomScale = panZoomEnabled ? zmPanZoom.panZoom[id].getScale() : 1; - monitors[i].setScale(0, parseInt(el.clientWidth * panZoomScale) + 'px', parseInt(el.clientHeight * panZoomScale) + 'px', {resizeImg: false}); + monitors[i].setScale(0, parseInt(el.clientWidth * panZoomScale) + 'px', parseInt(el.clientHeight * panZoomScale) + 'px', {resizeImg: false, streamQuality: $j('#streamQuality').val()}); } } } From e5e7cb470f5e45eb8ea5599e716de85a4840ad06 Mon Sep 17 00:00:00 2001 From: IgorA100 Date: Fri, 31 May 2024 15:36:23 +0300 Subject: [PATCH 20/23] Added $streamQuality processing (montage.php) --- web/skins/classic/views/montage.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index 549e61cf1..6403594a7 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -162,6 +162,15 @@ scaleControl is no longer used! */ } +$streamQualitySelected = '0'; +if (isset($_REQUEST['streamQuality'])) { + $streamQualitySelected = $_REQUEST['streamQuality']; +} else if (isset($_COOKIE['zmStreamQuality'])) { + $streamQualitySelected = $_COOKIE['zmStreamQuality']; +} else if (isset($_SESSION['zmStreamQuality']) ) { + $streamQualitySelected = $_SESSION['zmStreamQuality']; +} + if (!empty($_REQUEST['maxfps']) and validFloat($_REQUEST['maxfps']) and ($_REQUEST['maxfps']>0)) { $options['maxfps'] = validHtmlStr($_REQUEST['maxfps']); } else if (isset($_COOKIE['zmMontageRate'])) { @@ -290,6 +299,10 @@ echo htmlSelect('changeRate', $maxfps_options, $options['maxfps'], array('id'=>' 'ratio', 'data-on-change'=>'changeRatioForAll', 'class'=>'chosen')); ?> + + + 'changeStreamQuality','id'=>'streamQuality')); ?> +