Compare commits
30 Commits
master
...
feature/op
Author | SHA1 | Date | |
---|---|---|---|
0e4b75746d | |||
41db18e1ed | |||
836bf6240e | |||
831e6b8541 | |||
81195e7b48 | |||
40e1effa2d | |||
56456bddda | |||
b1257a4c51 | |||
fb7d7735be | |||
b296552e35 | |||
689e75d3d8 | |||
557a0eef46 | |||
172f67c7ca | |||
8d6367d16c | |||
3eeef5410f | |||
6400f4cfd6 | |||
75a214962c | |||
124dc33828 | |||
45a2e5894d | |||
d238b1fffe | |||
ee57799005 | |||
43709cef34 | |||
b950fef806 | |||
96803e9b66 | |||
1f4bb40b44 | |||
02ca4bdd8e | |||
d3754e7a86 | |||
f9c86b2832 | |||
e84a1346b4 | |||
f13aca1c7f |
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@ -8,10 +8,16 @@
|
||||
"name": "Launch addon",
|
||||
"type": "firefox",
|
||||
"request": "launch",
|
||||
"port":6000,
|
||||
"port": 6000,
|
||||
"reAttach": true,
|
||||
"addonType": "webExtension",
|
||||
"addonPath": "${workspaceFolder}/dist-ff",
|
||||
"pathMappings": [
|
||||
{
|
||||
"url": "webpack:///",
|
||||
"path": "${workspaceFolder}/src/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"firefox": {
|
||||
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -43,6 +43,7 @@
|
||||
"tabitem",
|
||||
"tablist",
|
||||
"tamius",
|
||||
"stdev",
|
||||
"textbox",
|
||||
"ultrawidify",
|
||||
"unmark",
|
||||
|
4045
package-lock.json
generated
4045
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ if(Debug.debug)
|
||||
console.log("Loading: ExtensionConf.js");
|
||||
|
||||
var ExtensionConf = {
|
||||
arDetect: {
|
||||
aard: {
|
||||
disabledReason: "", // if automatic aspect ratio has been disabled, show reason
|
||||
allowedMisaligned: 0.05, // top and bottom letterbox thickness can differ by this much.
|
||||
// Any more and we don't adjust ar.
|
||||
@ -138,6 +138,100 @@ var ExtensionConf = {
|
||||
testRowOffset: 0.02 // we test this % of height from detected edge
|
||||
}
|
||||
},
|
||||
aardGl: {
|
||||
disabledReason: "", // if automatic aspect ratio has been disabled, show reason
|
||||
allowedMisaligned: 0.05, // top and bottom letterbox thickness can differ by this much.
|
||||
// Any more and we don't adjust ar.
|
||||
allowedArVariance: 0.075, // amount by which old ar can differ from the new (1 = 100%)
|
||||
timers: { // autodetection frequency
|
||||
playing: 333, // while playing
|
||||
paused: 3000, // while paused
|
||||
error: 3000, // after error
|
||||
minimumTimeout: 5,
|
||||
},
|
||||
sampleCols: 32,
|
||||
canvasDimensions: {
|
||||
sampleCanvas: { // size of image sample for detecting aspect ratio. Bigger size means more accurate results,
|
||||
// at the expense of performance. Width == sample texture size (size of webGL canvas is pegged
|
||||
// on sample count)
|
||||
width: 32,
|
||||
height: 360,
|
||||
},
|
||||
},
|
||||
|
||||
// samplingInterval: 10, // we sample at columns at (width/this) * [ 1 .. this - 1]
|
||||
blackframe: {
|
||||
sufficientColorVariance: 0.10, // calculate difference between average intensity and pixel, for every pixel for every color
|
||||
// component. Average intensity is normalized to where 0 is black and 1 is biggest value for
|
||||
// that component. If sum of differences between normalized average intensity and normalized
|
||||
// component varies more than this % between color components, we can afford to use less strict
|
||||
// cummulative treshold.
|
||||
cumulativeThresholdLax: 1600,
|
||||
cumulativeThresholdStrict: 2560,// if we add values of all pixels together and get more than this, the frame is bright enough.
|
||||
// (note: blackframe is 16x9 px -> 144px total. cumulative threshold can be reached fast)
|
||||
blackPixelsCondition: 0.6, // How much pixels must be black (1 all, 0 none) before we consider frame as black. Takes
|
||||
// precedence over cumulative threshold: if blackPixelsCondition is met, the frame is dark
|
||||
// regardless of whether cumulative threshold has been reached.
|
||||
},
|
||||
blackbar: {
|
||||
blackLevel: 10, // everything darker than 10/255 across all RGB components is considered black by
|
||||
// default. blackLevel can decrease if we detect darker black.
|
||||
threshold: 16, // if pixel is darker than the sum of black level and this value, we count it as black
|
||||
// on 0-255. Needs to be fairly high (8 might not cut it) due to compression
|
||||
// artifacts in the video itself
|
||||
frameThreshold: 4, // treshold, but when doing blackframe test
|
||||
imageThreshold: 16, // in order to detect pixel as "not black", the pixel must be brighter than
|
||||
// the sum of black level, threshold and this value.
|
||||
gradientThreshold: 2, // When trying to determine thickness of the black bars, we take 2 values: position of
|
||||
// the last pixel that's darker than our threshold, and position of the first pixel that's
|
||||
// brighter than our image threshold. If positions are more than this many pixels apart,
|
||||
// we assume we aren't looking at letterbox and thus don't correct the aspect ratio.
|
||||
gradientSampleSize: 16, // How far do we look to find the gradient
|
||||
maxGradient: 6, // if two neighbouring pixels in gradientSampleSize differ by more than this, then we aren't
|
||||
// looking at a gradient
|
||||
gradientNegativeTreshold: -2,
|
||||
gradientMaxSD: 6, // reserved for future use
|
||||
antiGradientMode: AntiGradientMode.Lax,
|
||||
},
|
||||
variableBlackbarThresholdOptions: { // In case of poor bitrate videos, jpeg artifacts may cause us issues
|
||||
// FOR FUTURE USE
|
||||
enabled: true, // allow increasing blackbar threshold
|
||||
disableArDetectOnMax: true, // disable autodetection when threshold goes over max blackbar threshold
|
||||
maxBlackbarThreshold: 48, // max threshold (don't increase past this)
|
||||
thresholdStep: 8, // when failing to set aspect ratio, increase threshold by this much
|
||||
increaseAfterConsecutiveResets: 2 // increase if AR resets this many times in a row
|
||||
},
|
||||
guardLine: { // all pixels on the guardline need to be black, or else we trigger AR recalculation
|
||||
// (if AR fails to be recalculated, we reset AR)
|
||||
enabled: true,
|
||||
ignoreEdgeMargin: 0.20, // we ignore anything that pokes over the black line this close to the edge
|
||||
// (relative to width of the sample)
|
||||
imageTestThreshold: 0.1, // when testing for image, this much pixels must be over blackbarThreshold
|
||||
edgeTolerancePx: 2, // black edge violation is performed this far from reported 'last black pixel'
|
||||
edgeTolerancePercent: null // unused. same as above, except use % of canvas height instead of pixels
|
||||
},
|
||||
fallbackMode: {
|
||||
enabled: true,
|
||||
safetyBorderPx: 5, // determines the thickness of safety border in fallback mode
|
||||
noTriggerZonePx: 8 // if we detect edge less than this many pixels thick, we don't correct.
|
||||
},
|
||||
arSwitchLimiter: { // to be implemented
|
||||
switches: 2, // we can switch this many times
|
||||
period: 2.0 // per this period
|
||||
},
|
||||
pillarTest: {
|
||||
ignoreThinPillarsPx: 5, // ignore pillars that are less than this many pixels thick.
|
||||
allowMisaligned: 0.05 // left and right edge can vary this much (%)
|
||||
},
|
||||
textLineTest: {
|
||||
nonTextPulse: 0.10, // if a single continuous pulse has this many non-black pixels, we aren't dealing
|
||||
// with text. This value is relative to canvas width (%)
|
||||
pulsesToConfirm: 10, // this is a threshold to confirm we're seeing text.
|
||||
pulsesToConfirmIfHalfBlack: 5, // this is the threshold to confirm we're seeing text if longest black pulse
|
||||
// is over 50% of the canvas width
|
||||
testRowOffset: 0.02 // we test this % of height from detected edge
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
minLogZoom: -1,
|
||||
maxLogZoom: 3,
|
||||
|
@ -330,7 +330,7 @@ class Logger {
|
||||
}
|
||||
|
||||
canLogFile(component) {
|
||||
if (!this.conf.fileOptions.enabled || this.temp_disable) {
|
||||
if (!(this.conf.fileOptions?.enabled) || this.temp_disable) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(component) && component.length ) {
|
||||
|
801
src/ext/lib/ar-detect/AardGl.js
Normal file
801
src/ext/lib/ar-detect/AardGl.js
Normal file
@ -0,0 +1,801 @@
|
||||
import Debug from '../../conf/Debug';
|
||||
import EdgeDetect from './edge-detect/EdgeDetect';
|
||||
import EdgeStatus from './edge-detect/enums/EdgeStatusEnum';
|
||||
import EdgeDetectPrimaryDirection from './edge-detect/enums/EdgeDetectPrimaryDirectionEnum';
|
||||
import EdgeDetectQuality from './edge-detect/enums/EdgeDetectQualityEnum';
|
||||
import GuardLine from './GuardLine';
|
||||
import DebugCanvas from './DebugCanvas';
|
||||
import VideoAlignment from '../../../common/enums/video-alignment.enum';
|
||||
import AspectRatio from '../../../common/enums/aspect-ratio.enum';
|
||||
import { generateHorizontalAdder } from './gllib/shader-generators/HorizontalAdderGenerator';
|
||||
import { getBasicVertexShader } from './gllib/shaders/vertex-shader';
|
||||
import { sleep } from '../Util';
|
||||
|
||||
/**
|
||||
* AardGl: Hardware accelerated aspect ratio detection script, based on WebGL
|
||||
*/
|
||||
class AardGl {
|
||||
|
||||
constructor(videoData){
|
||||
this.logger = videoData.logger;
|
||||
this.conf = videoData;
|
||||
this.video = videoData.video;
|
||||
this.settings = videoData.settings;
|
||||
|
||||
this.setupTimer = null;
|
||||
|
||||
this.sampleCols = [];
|
||||
|
||||
this.canFallback = true;
|
||||
this.fallbackMode = false;
|
||||
|
||||
this.blackLevel = this.settings.active.aard.blackbar.blackLevel;
|
||||
|
||||
this.arid = (Math.random()*100).toFixed();
|
||||
|
||||
// ar detector starts in this state. running main() sets both to false
|
||||
this._halted = true;
|
||||
this._exited = true;
|
||||
|
||||
// we can tick manually, for debugging
|
||||
this._manualTicks = false;
|
||||
this._nextTick = false;
|
||||
|
||||
this.canDoFallbackMode = false;
|
||||
this.logger.log('info', 'init', `[AardGl::ctor] creating new AardGl. arid: ${this.arid}`);
|
||||
|
||||
this.glData = {
|
||||
positionBuffer: null,
|
||||
textureCoordsBuffer: null,
|
||||
textureCoordsLocation: null
|
||||
};
|
||||
|
||||
// delete this:
|
||||
this.count = 0;
|
||||
this.greenC = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* HELPER FUNCTIONS
|
||||
*
|
||||
*/
|
||||
//#region helpers
|
||||
|
||||
canTriggerFrameCheck(lastFrameCheckStartTime) {
|
||||
if (this._paused) {
|
||||
return false;
|
||||
}
|
||||
if (this.video.ended || this.video.paused){
|
||||
// we slow down if ended or pausing. Detecting is pointless.
|
||||
// we don't stop outright in case seeking happens during pause/after video was
|
||||
// ended and video gets into 'playing' state again
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.aard.timers.paused;
|
||||
}
|
||||
if (this.video.error){
|
||||
// če je video pavziran, še vedno skušamo zaznati razmerje stranic - ampak bolj poredko.
|
||||
// if the video is paused, we still do autodetection. We just do it less often.
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.aard.timers.error;
|
||||
}
|
||||
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.aard.timers.playing;
|
||||
}
|
||||
|
||||
isRunning(){
|
||||
return ! (this._halted || this._paused || this._exited);
|
||||
}
|
||||
|
||||
scheduleInitRestart(timeout, force_reset){
|
||||
if(! timeout){
|
||||
timeout = 100;
|
||||
}
|
||||
// don't allow more than 1 instance
|
||||
if(this.setupTimer){
|
||||
clearTimeout(this.setupTimer);
|
||||
}
|
||||
|
||||
var ths = this;
|
||||
this.setupTimer = setTimeout(function(){
|
||||
ths.setupTimer = null;
|
||||
try{
|
||||
ths.main();
|
||||
} catch(e) {
|
||||
this.logger('error', 'debug', `[AardGl::scheduleInitRestart] <@${this.arid}> Failed to start main(). Error:`,e);
|
||||
}
|
||||
ths = null;
|
||||
},
|
||||
timeout
|
||||
);
|
||||
}
|
||||
|
||||
getTimeout(baseTimeout, startTime){
|
||||
var execTime = (performance.now() - startTime);
|
||||
|
||||
return baseTimeout;
|
||||
}
|
||||
|
||||
async nextFrame() {
|
||||
return new Promise(resolve => window.requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
getDefaultAr() {
|
||||
return this.video.videoWidth / this.video.videoHeight;
|
||||
}
|
||||
|
||||
resetBlackLevel(){
|
||||
this.blackLevel = this.settings.active.aard.blackbar.blackLevel;
|
||||
}
|
||||
|
||||
clearImageData(id) {
|
||||
if (ArrayBuffer.transfer) {
|
||||
ArrayBuffer.transfer(id, 0);
|
||||
}
|
||||
id = undefined;
|
||||
}
|
||||
//#endregion
|
||||
//#region canvas management
|
||||
attachCanvas(canvas){
|
||||
if(this.attachedCanvas)
|
||||
this.attachedCanvas.remove();
|
||||
|
||||
// todo: place canvas on top of the video instead of random location
|
||||
canvas.style.position = "absolute";
|
||||
canvas.style.left = "200px";
|
||||
canvas.style.top = "1200px";
|
||||
canvas.style.zIndex = 10000;
|
||||
|
||||
document.getElementsByTagName("body")[0]
|
||||
.appendChild(canvas);
|
||||
}
|
||||
|
||||
canvasReadyForDrawWindow(){
|
||||
this.logger.log('info', 'debug', `%c[AardGl::canvasReadyForDrawWindow] <@${this.arid}> canvas is ${this.canvas.height === window.innerHeight ? '' : 'NOT '}ready for drawWindow(). Canvas height: ${this.canvas.height}px; window inner height: ${window.innerHeight}px.`)
|
||||
|
||||
return this.canvas.height == window.innerHeight
|
||||
}
|
||||
//#endregion
|
||||
//#region aard control
|
||||
|
||||
start() {
|
||||
this.logger.log('info', 'debug', `"%c[AardGl::start] <@${this.arid}> Starting automatic aspect ratio detection`, _ard_console_start);
|
||||
|
||||
if (this.conf.resizer.lastAr.type === AspectRatio.Automatic) {
|
||||
// ensure first autodetection will run in any case
|
||||
this.conf.resizer.setLastAr({type: AspectRatio.Automatic, ratio: this.getDefaultAr()});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// launch main() if it's currently not running:
|
||||
this.main();
|
||||
// automatic detection starts halted. If halted=false when main first starts, extension won't run
|
||||
// this._paused is undefined the first time we run this function, which is effectively the same thing
|
||||
// as false. Still, we'll explicitly fix this here.
|
||||
this._paused = false;
|
||||
this._halted = false;
|
||||
this._paused = false;
|
||||
}
|
||||
|
||||
stop(){
|
||||
this.logger.log('info', 'debug', `"%c[AardGl::stop] <@${this.arid}> Stopping automatic aspect ratio detection`, _ard_console_stop);
|
||||
this._halted = true;
|
||||
// this.conf.resizer.setArLastAr();
|
||||
}
|
||||
|
||||
pause() {
|
||||
// pause only if we were running before. Don't pause if we aren't running
|
||||
// (we are running when _halted is neither true nor undefined)
|
||||
if (this._halted === false) {
|
||||
this._paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
unpause() {
|
||||
// pause only if we were running before. Don't pause if we aren't running
|
||||
// (we are running when _halted is neither true nor undefined)
|
||||
if (this._paused && this._halted === false) {
|
||||
this._paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
setManualTick(manualTick) {
|
||||
this._manualTicks = manualTick;
|
||||
}
|
||||
|
||||
tick() {
|
||||
this._nextTick = true;
|
||||
}
|
||||
//#endregion
|
||||
//#region WebGL helpers
|
||||
glInitBuffers(width, height) {
|
||||
// create buffers and bind them
|
||||
this.glData.positionBuffer = this.gl.createBuffer();
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.glData.positionBuffer);
|
||||
|
||||
// create rectangle for drawing
|
||||
this.glSetRectangle(this.gl, width, height);
|
||||
|
||||
// create texture coordinate buffer
|
||||
this.glData.textureCoordsBuffer = this.gl.createBuffer();
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.glData.textureCoordsBuffer);
|
||||
|
||||
// create index buffer
|
||||
this.glData.indexBuffer = this.gl.createBuffer();
|
||||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.glData.indexBuffer);
|
||||
|
||||
// This array defines each face as two triangles, using the
|
||||
// indices into the vertex array to specify each triangle's
|
||||
// position.
|
||||
const indices = [0, 1, 2, 3, 4, 5];
|
||||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), this.gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
glSetRectangle(glContext, width, height) {
|
||||
glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([
|
||||
0, 0, //
|
||||
width, 0, // this line are swapped over for experiment
|
||||
0, height, // this triangle is flipped. This and
|
||||
0, height,
|
||||
width, 0,
|
||||
width, height
|
||||
]), glContext.STATIC_DRAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates shader
|
||||
* @param {*} glContext — gl context
|
||||
* @param {*} shaderSource — shader code (as returned by a shader generator, for example)
|
||||
* @param {*} shaderType — shader type (gl[context].FRAGMENT_SHADER or gl[context].VERTEX_SHADER)
|
||||
*/
|
||||
compileShader(glContext, shaderSource, shaderType) {
|
||||
const shader = glContext.createShader(shaderType);
|
||||
|
||||
// load source and compile shader
|
||||
glContext.shaderSource(shader, shaderSource);
|
||||
glContext.compileShader(shader);
|
||||
|
||||
// check if shader was compiled successfully
|
||||
if (! glContext.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
||||
this.logger.log('error', ['init', 'debug', 'arDetect'], `%c[AardGl::setupShader] <@${this.arid}> Failed to setup shader. Error given:`, _ard_console_stop, this.gl.getShaderInfoLog(shader));
|
||||
glContext.deleteShader(shader);
|
||||
return null;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates gl program
|
||||
* @param {*} glContext — gl context
|
||||
* @param {*} shaders — shaders (previously compiled with setupShader())
|
||||
*/
|
||||
compileProgram(glContext, shaders) {
|
||||
console.log(glContext, shaders);
|
||||
const program = glContext.createProgram();
|
||||
for (const shader of shaders) {
|
||||
console.log("shader", shader);
|
||||
glContext.attachShader(program, shader);
|
||||
}
|
||||
glContext.linkProgram(program);
|
||||
if (! glContext.getProgramParameter(program, glContext.LINK_STATUS)) {
|
||||
this.logger.log('error', ['init', 'debug', 'arDetect'], `%c[AardGl::setupProgram] <@${this.arid}> Failed to setup program.`, glContext.getProgramInfoLog(program), _ard_console_stop);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
program,
|
||||
attribLocations: {
|
||||
vertexPosition: this.gl.getAttribLocation(program, 'aVertexPosition'),
|
||||
textureCoord: this.gl.getAttribLocation(program, 'aTextureCoord'),
|
||||
},
|
||||
uniformLocations: {
|
||||
u_frame: this.gl.getUniformLocation(program, 'u_frame'),
|
||||
}
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
/*
|
||||
* --------------------
|
||||
* SETUP AND CLEANUP
|
||||
* --------------------
|
||||
*/
|
||||
|
||||
//#region init and destroy
|
||||
init(){
|
||||
this.logger.log('info', 'init', `[AardGl::init] <@${this.arid}> Initializing autodetection.`);
|
||||
|
||||
try {
|
||||
if (this.settings.canStartAutoAr()) {
|
||||
this.setup();
|
||||
} else {
|
||||
throw "Settings prevent autoar from starting"
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.log('error', ['init', 'debug', 'aard'], `%c[AardGl::init] <@${this.arid}> Initialization failed.`, _ard_console_stop, e);
|
||||
}
|
||||
}
|
||||
|
||||
destroy(){
|
||||
this.logger.log('info', 'init', `%c[AardGl::destroy] <@${this.arid}> Destroying aard.`, _ard_console_stop, e);
|
||||
// this.debugCanvas.destroy();
|
||||
this.stop();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
setup(cwidth, cheight){
|
||||
this.logger.log('info', 'init', `[AardGl::setup] <@${this.arid}> Starting autodetection setup.`);
|
||||
//
|
||||
// [-1] check for zero-width and zero-height videos. If we detect this, we kick the proverbial
|
||||
// can some distance down the road. This problem will prolly fix itself soon. We'll also
|
||||
// not do any other setup until this issue is fixed
|
||||
//
|
||||
if(this.video.videoWidth === 0 || this.video.videoHeight === 0 ){
|
||||
this.logger.log('warn', 'debug', `[AardGl::setup] <@${this.arid}> This video has zero width or zero height. Dimensions: ${this.video.videoWidth} × ${this.video.videoHeight}`);
|
||||
|
||||
this.scheduleInitRestart();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// [0] initiate "dependencies" first
|
||||
//
|
||||
|
||||
// This is space for EdgeDetector and GuardLine init
|
||||
|
||||
//
|
||||
// [1] initiate canvases
|
||||
//
|
||||
|
||||
if (!cwidth) {
|
||||
cwidth = this.settings.active.aardGl.canvasDimensions.sampleCanvas.width;
|
||||
cheight = this.settings.active.aardGl.canvasDimensions.sampleCanvas.height;
|
||||
}
|
||||
|
||||
if (this.canvas) {
|
||||
this.canvas.remove();
|
||||
}
|
||||
if (this.blackframeCanvas) {
|
||||
this.blackframeCanvas.remove();
|
||||
}
|
||||
|
||||
// things to note: we'll be keeping canvas in memory only.
|
||||
this.canvas = document.createElement("canvas");
|
||||
this.canvas.width = cwidth;
|
||||
this.canvas.height = cheight;
|
||||
this.blackframeCanvas = document.createElement("canvas");
|
||||
this.blackframeCanvas.width = this.settings.active.aard.canvasDimensions.blackframeCanvas.width;
|
||||
this.blackframeCanvas.height = this.settings.active.aard.canvasDimensions.blackframeCanvas.height;
|
||||
|
||||
// FOR DEBUG PURPOSES ONLY — REMOVE!
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
|
||||
this.canvas.style.position = "fixed";
|
||||
this.canvas.style.left = `50px`;
|
||||
this.canvas.style.top = `64px`;
|
||||
this.canvas.style.zIndex = 10002;
|
||||
|
||||
body.appendChild(this.canvas);
|
||||
// END FOR DEBUG PURPOSES ONLY
|
||||
|
||||
// this.context = this.canvas.getContext("2d");
|
||||
|
||||
this.pixelBuffer = new Uint8Array(cwidth * cheight * 4);
|
||||
|
||||
//
|
||||
// [2] SETUP WEBGL STUFF —————————————————————————————————————————————————————————————————————————————————
|
||||
//#region webgl setup
|
||||
|
||||
this.glSetup(cwidth, cheight);
|
||||
|
||||
console.log("glsetup complete")
|
||||
|
||||
// do setup once
|
||||
// tho we could do it for every frame
|
||||
this.canvasScaleFactor = cheight / this.video.videoHeight;
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//
|
||||
// [5] do other things setup needs to do
|
||||
//
|
||||
|
||||
// this.detectionTimeoutEventCount = 0;
|
||||
// this.resetBlackLevel();
|
||||
|
||||
// // if we're restarting AardGl, we need to do this in order to force-recalculate aspect ratio
|
||||
// this.conf.resizer.setLastAr({type: AspectRatio.Automatic, ratio: this.getDefaultAr()});
|
||||
|
||||
// this.canvasImageDataRowLength = cwidth << 2;
|
||||
// this.noLetterboxCanvasReset = false;
|
||||
|
||||
// if (this.settings.canStartAutoAr() ) {
|
||||
// this.start();
|
||||
// }
|
||||
|
||||
// if(Debug.debugCanvas.enabled){
|
||||
// // this.debugCanvas.init({width: cwidth, height: cheight});
|
||||
// // DebugCanvas.draw("test marker","test","rect", {x:5, y:5}, {width: 5, height: 5});
|
||||
// }
|
||||
|
||||
this.conf.arSetupComplete = true;
|
||||
console.log("DRAWING BUFFER SIZE:", this.gl.drawingBufferWidth, '×', this.gl.drawingBufferHeight);
|
||||
|
||||
// start autodetection after setup is complete
|
||||
this.start();
|
||||
}
|
||||
|
||||
glSetup(cwidth, cheight) {
|
||||
this.gl = this.canvas.getContext("webgl");
|
||||
|
||||
if (this.gl === null) {
|
||||
throw new Error('Unable to initialize WebGL. WebGL may not be supported by machine.');
|
||||
}
|
||||
|
||||
// set color to half-transparent blue initially, for testing purposes
|
||||
if (process.env.CHANNEL === 'dev') {
|
||||
try {
|
||||
this.gl.clearColor(0, 0, 1.0, 0.5);
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
||||
} catch (e) {
|
||||
console.error("failing to clear channel!", e);
|
||||
}
|
||||
} else {
|
||||
this.gl.clearColor(0, 0, 0.0, 0.0);
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// load shaders and stuff. PixelSize for horizontalAdder should be 1/sample canvas width
|
||||
const vertexShaderSrc = getBasicVertexShader();
|
||||
const horizontalAdderShaderSrc = generateHorizontalAdder(10, 1 / cwidth); // todo: unhardcode 10 as radius
|
||||
|
||||
// compile shaders
|
||||
const vertexShader = this.compileShader(this.gl, vertexShaderSrc, this.gl.VERTEX_SHADER);
|
||||
const horizontalAdderShader = this.compileShader(this.gl, horizontalAdderShaderSrc, this.gl.FRAGMENT_SHADER);
|
||||
|
||||
// link shaders to program
|
||||
const programInfo = this.compileProgram(this.gl, [vertexShader, horizontalAdderShader]);
|
||||
this.glProgram = programInfo.program;
|
||||
this.glData.attribLocations = programInfo.attribLocations;
|
||||
this.glData.uniformLocations = programInfo.uniformLocations;
|
||||
|
||||
// look up where the vertex data needs to go
|
||||
// const positionLocation = this.gl.getAttributeLocation(glProgram, 'a_position');
|
||||
// const textureCoordsLocation = this.gl.getAttributeLocation(glProgram, 'a_textureCoords');
|
||||
|
||||
console.log("program compiled. init buffers");
|
||||
|
||||
this.glInitBuffers(this.settings.active.aardGl.sampleCols, cheight);
|
||||
|
||||
console.log("program compiled. buffer init complete");
|
||||
|
||||
this.texture = this.gl.createTexture();
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture);
|
||||
|
||||
// texture is half-transparent blue by default. Helps with debugging.
|
||||
// this.gl.texImage2D(
|
||||
// this.gl.TEXTURE_2D, // target
|
||||
// 0, // level
|
||||
// this.gl.RGBA, // internal format
|
||||
// 1, 1, 0, // width, height, border
|
||||
// this.gl.RGBA, // format of content
|
||||
// this.gl.UNSIGNED_BYTE, // type
|
||||
// new ArrayBufferView([0, 0, 255, 128])
|
||||
// );
|
||||
|
||||
// set some parameters
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
||||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
||||
|
||||
// we need a rectangle. This is output data, not texture. This means that the size of the rectangle should be
|
||||
// [sample count] x height of the sample, as shader can sample frame at a different resolution than what gets
|
||||
// rendered here. We don't need all horizontal pixels on our output. We do need all vertical pixels, though)
|
||||
this.glSetRectangle(this.gl, this.settings.active.aard.sampleCols, cheight);
|
||||
|
||||
console.log("gl setup complete");
|
||||
}
|
||||
|
||||
|
||||
drawScene() {
|
||||
if (this.count++ % 10 === 0) {
|
||||
this.greenC = !this.greenC;
|
||||
}
|
||||
// clear canvas
|
||||
this.gl.clearColor(0, this.greenC ? 0.5 : 0, 0.75, 0.5);
|
||||
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
||||
|
||||
this.gl.useProgram(this.glProgram);
|
||||
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.glData.positionBuffer);
|
||||
this.gl.vertexAttribPointer(this.glData.attribLocations.vertexPosition, 3, this.gl.FLOAT, false, 0, 0);
|
||||
|
||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.glData.textureCoordsBuffer);
|
||||
this.gl.vertexAttribPointer(this.glData.attribLocations.textureCoord, size, type, normalized, stride, offset)
|
||||
|
||||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.glData.indexBuffer);
|
||||
|
||||
// run our program
|
||||
this.gl.useProgram(this.glProgram);
|
||||
|
||||
// Tell WebGL we want to affect texture unit 0
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
|
||||
// Bind the texture to texture unit 0
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
|
||||
// Tell the shader we bound the texture to texture unit 0
|
||||
gl.uniform1i(this.glData.uniformLocations.u_frame, 0);
|
||||
|
||||
// this.gl.drawElements(this.gl.TRIANGLES, 2, this.gl.UNSIGNED_BYTE, 0);
|
||||
this.gl.drawArrays(this.gl.TRIANGLES, 0, 2)
|
||||
|
||||
// get the pixels back out:
|
||||
this.gl.readPixels(0, 0, width, height, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.pixelBuffer);
|
||||
}
|
||||
|
||||
updateTexture() {
|
||||
const level = 0;
|
||||
const internalFormat = this.gl.RGBA;
|
||||
const sourceFormat = this.gl.RGBA;
|
||||
const sourceType = this.gl.UNSIGNED_BYTE;
|
||||
|
||||
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture);
|
||||
|
||||
// if (this.resizeInput) {
|
||||
// TODO: check if 'width' and 'height' mean the input gets resized
|
||||
// this.gl.texImage2D(gl.TEXTURE_2D, level, internalformat, width, height, border, format, type, pixels)
|
||||
// } else {
|
||||
console.log(this.video)
|
||||
this.gl.texImage2D(this.gl.TEXTURE_2D, level, internalFormat, sourceFormat, sourceType, this.video);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
async main() {
|
||||
this.logger.log('info', 'debug', `"%c[AardGl::main] <@${this.arid}> Entering main function.`, _ard_console_start);
|
||||
if (this._paused) {
|
||||
// unpause if paused
|
||||
this._paused = false;
|
||||
return; // main loop still keeps executing. Return is needed to avoid a million instances of autodetection
|
||||
}
|
||||
|
||||
console.log("we werent paused");
|
||||
|
||||
if (!this._halted) {
|
||||
// we are already running, don't run twice
|
||||
// this would have handled the 'paused' from before, actually.
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("we werent halted");
|
||||
|
||||
let exitedRetries = 10;
|
||||
|
||||
while (!this._exited && exitedRetries --> 0) {
|
||||
this.logger.log('warn', 'debug', `[AardGl::main] <@${this.arid}> We are trying to start another instance of autodetection on current video, but the previous instance hasn't exited yet. Waiting for old instance to exit ...`);
|
||||
await sleep(this.settings.active.aard.timers.tickrate);
|
||||
}
|
||||
if (!this._exited) {
|
||||
this.logger.log('error', 'debug', `[AardGl::main] <@${this.arid}> Previous instance didn't exit in time. Not starting a new one.`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("no other instances")
|
||||
|
||||
this.logger.log('info', 'debug', `%c[AardGl::main] <@${this.arid}> Starting a new instance.`);
|
||||
|
||||
// we need to unhalt:
|
||||
this._halted = false;
|
||||
this._exited = false;
|
||||
|
||||
// set initial timestamps so frame check will trigger the first time we run the loop
|
||||
let lastFrameCheckStartTime = Date.now() - (this.settings.active.aardGl.timers.playing << 1);
|
||||
|
||||
const frameCheckTimes = new Array(10).fill(-1);
|
||||
let frameCheckBufferIndex = 0;
|
||||
let fcstart, fctime;
|
||||
|
||||
this.logger.log('info', 'debug', `"%c[AardGl::start] <@${this.arid}> Starting aardGL loop!`, _ard_console_start);
|
||||
|
||||
try {
|
||||
while (this && !this._halted) {
|
||||
// NOTE: we separated tickrate and inter-check timeouts so that when video switches
|
||||
// state from 'paused' to 'playing', we don't need to wait for the rest of the longer
|
||||
// paused state timeout to finish.
|
||||
|
||||
if ( (!this._manualTicks && this.canTriggerFrameCheck(lastFrameCheckStartTime)) || this._nextTick) {
|
||||
this._nextTick = false;
|
||||
|
||||
lastFrameCheckStartTime = Date.now();
|
||||
fcstart = performance.now();
|
||||
|
||||
try {
|
||||
this.frameCheck();
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'debug', `%c[AardGl::main] <@${this.arid}> Frame check failed:`, "color: #000, background: #f00", e);
|
||||
}
|
||||
|
||||
if (Debug.performanceMetrics) {
|
||||
fctime = performance.now() - fcstart;
|
||||
frameCheckTimes[frameCheckBufferIndex % frameCheckTimes.length] = fctime;
|
||||
this.conf.pageInfo.sendPerformanceUpdate({frameCheckTimes: frameCheckTimes, lastFrameCheckTime: fctime});
|
||||
++frameCheckBufferIndex;
|
||||
}
|
||||
}
|
||||
|
||||
await this.nextFrame();
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'debug', `%c[AardGl::main] <@${this.arid}> Main autodetection loop crashed. Reason?`, e, _ard_console_stop);
|
||||
}
|
||||
|
||||
this.logger.log('info', 'debug', `%c[AardGl::main] <@${this.arid}> Main autodetection loop exited. Halted? ${this._halted}`, _ard_console_stop);
|
||||
this._exited = true;
|
||||
}
|
||||
|
||||
frameCheck(){
|
||||
try {
|
||||
if(! this.video){
|
||||
this.logger.log('error', 'debug', `%c[AardGl::frameCheck] <@${this.arid}> Video went missing. Destroying current instance of videoData.`);
|
||||
this.conf.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// we dont have blackframe canvas atm
|
||||
// if (!this.blackframeContext) {
|
||||
// this.init();
|
||||
// }
|
||||
|
||||
var startTime = performance.now();
|
||||
|
||||
//
|
||||
// [0] try drawing image to canvas
|
||||
//
|
||||
let imageData;
|
||||
|
||||
try {
|
||||
// this.drawFrame();
|
||||
|
||||
|
||||
this.fallbackMode = false;
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'arDetect', `%c[AardGl::frameCheck] <@${this.arid}> %c[AardGl::frameCheck] can't draw image on canvas. ${this.canDoFallbackMode ? 'Trying canvas.drawWindow instead' : 'Doing nothing as browser doesn\'t support fallback mode.'}`, "color:#000; backgroud:#f51;", e);
|
||||
}
|
||||
|
||||
// [1] update frame
|
||||
try {
|
||||
this.updateTexture();
|
||||
this.drawScene();
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'aardGl', `%c[AardGl::frameCheck] <@${this.arid}> Something went wrong while trying to update/draw video frame with gl!`, "color:#000; backgroud:#f51;", e);
|
||||
}
|
||||
|
||||
console.log("TEXTURE DRAWN!", this.pixelBuffer)
|
||||
|
||||
// [N] clear data
|
||||
|
||||
this.clearImageData(imageData);
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'debug', `%c[AardGl::frameCheck] <@${this.arid}> Error during framecheck.`, "background: #000; color: #fa2", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* -------------------------
|
||||
* DATA PROCESSING HELPERS
|
||||
* -------------------------
|
||||
*/
|
||||
//#region result processing
|
||||
calculateArFromEdges(edges) {
|
||||
// if we don't specify these things, they'll have some default values.
|
||||
if(edges.top === undefined){
|
||||
edges.top = 0;
|
||||
edges.bottom = 0;
|
||||
edges.left = 0; // RESERVED FOR FUTURE — CURRENTLY UNUSED
|
||||
edges.right = 0; // THIS FUNCTION CAN PRESENTLY ONLY HANDLE LETTERBOX
|
||||
}
|
||||
|
||||
let letterbox = edges.top + edges.bottom;
|
||||
|
||||
|
||||
if (! this.fallbackMode) {
|
||||
// Since video is stretched to fit the canvas, we need to take that into account when calculating target
|
||||
// aspect ratio and correct our calculations to account for that
|
||||
|
||||
const fileAr = this.video.videoWidth / this.video.videoHeight;
|
||||
const canvasAr = this.canvas.width / this.canvas.height;
|
||||
let widthCorrected;
|
||||
|
||||
if (edges.top && edges.bottom) {
|
||||
// in case of letterbox, we take canvas height as canon and assume width got stretched or squished
|
||||
|
||||
if (fileAr != canvasAr) {
|
||||
widthCorrected = this.canvas.height * fileAr;
|
||||
} else {
|
||||
widthCorrected = this.canvas.width;
|
||||
}
|
||||
|
||||
return widthCorrected / (this.canvas.height - letterbox);
|
||||
}
|
||||
} else {
|
||||
// fallback mode behaves a wee bit differently
|
||||
|
||||
let zoomFactor = 1;
|
||||
|
||||
// there's stuff missing from the canvas. We need to assume canvas' actual height is bigger by a factor x, where
|
||||
// x = [video.zoomedHeight] / [video.unzoomedHeight]
|
||||
//
|
||||
// letterbox also needs to be corrected:
|
||||
// letterbox += [video.zoomedHeight] - [video.unzoomedHeight]
|
||||
|
||||
var vbr = this.video.getBoundingClientRect();
|
||||
|
||||
zoomFactor = vbr.height / this.video.clientHeight;
|
||||
letterbox += vbr.height - this.video.clientHeight;
|
||||
|
||||
var trueHeight = this.canvas.height * zoomFactor - letterbox;
|
||||
|
||||
if(edges.top > 1 && edges.top <= this.settings.active.aard.fallbackMode.noTriggerZonePx ){
|
||||
this.logger.log('info', 'arDetect', `%c[AardGl::calculateArFromEdges] <@${this.arid}> Edge is in the no-trigger zone. Aspect ratio change is not triggered.`)
|
||||
return;
|
||||
}
|
||||
|
||||
// varnostno območje, ki naj ostane črno (da lahko v fallback načinu odkrijemo ožanje razmerja stranic).
|
||||
// x2, ker je safetyBorderPx definiran za eno stran.
|
||||
// safety border so we can detect aspect ratio narrowing (21:9 -> 16:9).
|
||||
// x2 because safetyBorderPx is for one side.
|
||||
trueHeight += (this.settings.active.aard.fallbackMode.safetyBorderPx << 1);
|
||||
|
||||
return this.canvas.width * zoomFactor / trueHeight;
|
||||
}
|
||||
}
|
||||
|
||||
processAr(trueAr){
|
||||
this.detectedAr = trueAr;
|
||||
|
||||
// poglejmo, če se je razmerje stranic spremenilo
|
||||
// check if aspect ratio is changed:
|
||||
var lastAr = this.conf.resizer.getLastAr();
|
||||
if (lastAr.type === AspectRatio.Automatic && lastAr.ratio !== null){
|
||||
// spremembo lahko zavrnemo samo, če uporabljamo avtomatski način delovanja in če smo razmerje stranic
|
||||
// že nastavili.
|
||||
//
|
||||
// we can only deny aspect ratio changes if we use automatic mode and if aspect ratio was set from here.
|
||||
|
||||
var arDiff = trueAr - lastAr.ar;
|
||||
|
||||
if (arDiff < 0)
|
||||
arDiff = -arDiff;
|
||||
|
||||
var arDiff_percent = arDiff / trueAr;
|
||||
|
||||
// ali je sprememba v mejah dovoljenega? Če da -> fertik
|
||||
// is ar variance within acceptable levels? If yes -> we done
|
||||
this.logger.log('info', 'arDetect', `%c[AardGl::processAr] <@${this.arid}> New aspect ratio varies from the old one by this much:\n`,"color: #aaf","old Ar", lastAr.ar, "current ar", trueAr, "arDiff (absolute):",arDiff,"ar diff (relative to new ar)", arDiff_percent);
|
||||
|
||||
if (arDiff < trueAr * this.settings.active.aard.allowedArVariance){
|
||||
this.logger.log('info', 'arDetect', `%c[AardGl::processAr] <@${this.arid}> Aspect ratio change denied — diff %: ${arDiff_percent}`, "background: #740; color: #fa2");
|
||||
return;
|
||||
}
|
||||
this.logger.log('info', 'arDetect', `%c[AardGl::processAr] <@${this.arid}> aspect ratio change accepted — diff %: ${arDiff_percent}`, "background: #153; color: #4f9");
|
||||
}
|
||||
this.logger.log('info', 'debug', `%c[AardGl::processAr] <@${this.arid}> Triggering aspect ratio change. New aspect ratio: ${trueAr}`, _ard_console_change);
|
||||
|
||||
this.conf.resizer.updateAr({type: AspectRatio.Automatic, ratio: trueAr}, {type: AspectRatio.Automatic, ratio: trueAr});
|
||||
}
|
||||
//#endregion
|
||||
//#region data processing / frameCheck helpers
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
var _ard_console_stop = "background: #000; color: #f41";
|
||||
var _ard_console_start = "background: #000; color: #00c399";
|
||||
var _ard_console_change = "background: #000; color: #ff8";
|
||||
|
||||
export default AardGl;
|
@ -25,7 +25,7 @@ class ArDetector {
|
||||
this.canFallback = true;
|
||||
this.fallbackMode = false;
|
||||
|
||||
this.blackLevel = this.settings.active.arDetect.blackbar.blackLevel;
|
||||
this.blackLevel = this.settings.active.aard.blackbar.blackLevel;
|
||||
|
||||
this.arid = (Math.random()*100).toFixed();
|
||||
|
||||
@ -97,8 +97,8 @@ class ArDetector {
|
||||
//
|
||||
|
||||
if (!cwidth) {
|
||||
cwidth = this.settings.active.arDetect.canvasDimensions.sampleCanvas.width;
|
||||
cheight = this.settings.active.arDetect.canvasDimensions.sampleCanvas.height;
|
||||
cwidth = this.settings.active.aard.canvasDimensions.sampleCanvas.width;
|
||||
cheight = this.settings.active.aard.canvasDimensions.sampleCanvas.height;
|
||||
}
|
||||
|
||||
if (this.canvas) {
|
||||
@ -113,8 +113,8 @@ class ArDetector {
|
||||
this.canvas.width = cwidth;
|
||||
this.canvas.height = cheight;
|
||||
this.blackframeCanvas = document.createElement("canvas");
|
||||
this.blackframeCanvas.width = this.settings.active.arDetect.canvasDimensions.blackframeCanvas.width;
|
||||
this.blackframeCanvas.height = this.settings.active.arDetect.canvasDimensions.blackframeCanvas.height;
|
||||
this.blackframeCanvas.width = this.settings.active.aard.canvasDimensions.blackframeCanvas.width;
|
||||
this.blackframeCanvas.height = this.settings.active.aard.canvasDimensions.blackframeCanvas.height;
|
||||
|
||||
this.context = this.canvas.getContext("2d");
|
||||
this.blackframeContext = this.blackframeCanvas.getContext("2d");
|
||||
@ -129,8 +129,8 @@ class ArDetector {
|
||||
// [2] determine places we'll use to sample our main frame
|
||||
//
|
||||
|
||||
var ncol = this.settings.active.arDetect.sampling.staticCols;
|
||||
var nrow = this.settings.active.arDetect.sampling.staticRows;
|
||||
var ncol = this.settings.active.aard.sampling.staticCols;
|
||||
var nrow = this.settings.active.aard.sampling.staticRows;
|
||||
|
||||
var colSpacing = this.canvas.width / ncol;
|
||||
var rowSpacing = (this.canvas.height << 2) / nrow;
|
||||
@ -258,7 +258,7 @@ class ArDetector {
|
||||
|
||||
while (!this._exited && exitedRetries --> 0) {
|
||||
this.logger.log('warn', 'debug', `[ArDetect::main] <@${this.arid}> We are trying to start another instance of autodetection on current video, but the previous instance hasn't exited yet. Waiting for old instance to exit ...`);
|
||||
await sleep(this.settings.active.arDetect.timers.tickrate);
|
||||
await sleep(this.settings.active.aard.timers.tickrate);
|
||||
}
|
||||
if (!this._exited) {
|
||||
this.logger.log('error', 'debug', `[ArDetect::main] <@${this.arid}> Previous instance didn't exit in time. Not starting a new one.`);
|
||||
@ -272,7 +272,7 @@ class ArDetector {
|
||||
this._exited = false;
|
||||
|
||||
// set initial timestamps so frame check will trigger the first time we run the loop
|
||||
let lastFrameCheckStartTime = Date.now() - (this.settings.active.arDetect.timers.playing << 1);
|
||||
let lastFrameCheckStartTime = Date.now() - (this.settings.active.aard.timers.playing << 1);
|
||||
|
||||
const frameCheckTimes = new Array(10).fill(-1);
|
||||
let frameCheckBufferIndex = 0;
|
||||
@ -303,7 +303,7 @@ class ArDetector {
|
||||
}
|
||||
}
|
||||
|
||||
await sleep(this.settings.active.arDetect.timers.tickrate);
|
||||
await sleep(this.settings.active.aard.timers.tickrate);
|
||||
}
|
||||
|
||||
this.logger.log('info', 'debug', `%c[ArDetect::main] <@${this.arid}> Main autodetection loop exited. Halted? ${this._halted}`, _ard_console_stop);
|
||||
@ -319,15 +319,15 @@ class ArDetector {
|
||||
// we slow down if ended or pausing. Detecting is pointless.
|
||||
// we don't stop outright in case seeking happens during pause/after video was
|
||||
// ended and video gets into 'playing' state again
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.arDetect.timers.paused;
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.aard.timers.paused;
|
||||
}
|
||||
if (this.video.error){
|
||||
// če je video pavziran, še vedno skušamo zaznati razmerje stranic - ampak bolj poredko.
|
||||
// if the video is paused, we still do autodetection. We just do it less often.
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.arDetect.timers.error;
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.aard.timers.error;
|
||||
}
|
||||
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.arDetect.timers.playing;
|
||||
return Date.now() - lastFrameCheckStartTime > this.settings.active.aard.timers.playing;
|
||||
}
|
||||
|
||||
isRunning(){
|
||||
@ -445,7 +445,7 @@ class ArDetector {
|
||||
|
||||
var trueHeight = this.canvas.height * zoomFactor - letterbox;
|
||||
|
||||
if(edges.top > 1 && edges.top <= this.settings.active.arDetect.fallbackMode.noTriggerZonePx ){
|
||||
if(edges.top > 1 && edges.top <= this.settings.active.aard.fallbackMode.noTriggerZonePx ){
|
||||
this.logger.log('info', 'arDetect', `%c[ArDetect::calculateArFromEdges] <@${this.arid}> Edge is in the no-trigger zone. Aspect ratio change is not triggered.`)
|
||||
return;
|
||||
}
|
||||
@ -454,7 +454,7 @@ class ArDetector {
|
||||
// x2, ker je safetyBorderPx definiran za eno stran.
|
||||
// safety border so we can detect aspect ratio narrowing (21:9 -> 16:9).
|
||||
// x2 because safetyBorderPx is for one side.
|
||||
trueHeight += (this.settings.active.arDetect.fallbackMode.safetyBorderPx << 1);
|
||||
trueHeight += (this.settings.active.aard.fallbackMode.safetyBorderPx << 1);
|
||||
|
||||
return this.canvas.width * zoomFactor / trueHeight;
|
||||
}
|
||||
@ -483,7 +483,7 @@ class ArDetector {
|
||||
// is ar variance within acceptable levels? If yes -> we done
|
||||
this.logger.log('info', 'arDetect', `%c[ArDetect::processAr] <@${this.arid}> New aspect ratio varies from the old one by this much:\n`,"color: #aaf","old Ar", lastAr.ar, "current ar", trueAr, "arDiff (absolute):",arDiff,"ar diff (relative to new ar)", arDiff_percent);
|
||||
|
||||
if (arDiff < trueAr * this.settings.active.arDetect.allowedArVariance){
|
||||
if (arDiff < trueAr * this.settings.active.aard.allowedArVariance){
|
||||
this.logger.log('info', 'arDetect', `%c[ArDetect::processAr] <@${this.arid}> Aspect ratio change denied — diff %: ${arDiff_percent}`, "background: #740; color: #fa2");
|
||||
return;
|
||||
}
|
||||
@ -698,11 +698,11 @@ class ArDetector {
|
||||
} else {
|
||||
if (this.conf.player.dimensions){
|
||||
this.guardLine.setBlackbarManual({
|
||||
top: this.settings.active.arDetect.fallbackMode.noTriggerZonePx,
|
||||
bottom: this.conf.player.dimensions.height - this.settings.active.arDetect.fallbackMode.noTriggerZonePx - 1
|
||||
top: this.settings.active.aard.fallbackMode.noTriggerZonePx,
|
||||
bottom: this.conf.player.dimensions.height - this.settings.active.aard.fallbackMode.noTriggerZonePx - 1
|
||||
},{
|
||||
top: edgePost.guardLineTop + this.settings.active.arDetect.guardLine.edgeTolerancePx,
|
||||
bottom: edgePost.guardLineBottom - this.settings.active.arDetect.guardLine.edgeTolerancePx
|
||||
top: edgePost.guardLineTop + this.settings.active.aard.guardLine.edgeTolerancePx,
|
||||
bottom: edgePost.guardLineBottom - this.settings.active.aard.guardLine.edgeTolerancePx
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -724,7 +724,7 @@ class ArDetector {
|
||||
}
|
||||
|
||||
resetBlackLevel(){
|
||||
this.blackLevel = this.settings.active.arDetect.blackbar.blackLevel;
|
||||
this.blackLevel = this.settings.active.aard.blackbar.blackLevel;
|
||||
}
|
||||
|
||||
blackLevelTest_full() {
|
||||
@ -749,7 +749,7 @@ class ArDetector {
|
||||
let cumulativeValue = 0;
|
||||
let blackPixelCount = 0;
|
||||
const bfImageData = this.blackframeContext.getImageData(0, 0, cols, rows).data;
|
||||
const blackTreshold = this.blackLevel + this.settings.active.arDetect.blackbar.frameTreshold;
|
||||
const blackTreshold = this.blackLevel + this.settings.active.aard.blackbar.frameTreshold;
|
||||
|
||||
|
||||
// we do some recon for letterbox and pillarbox. While this can't determine whether letterbox/pillarbox exists
|
||||
@ -810,17 +810,17 @@ class ArDetector {
|
||||
}
|
||||
}
|
||||
|
||||
const hasSufficientVariance = Math.abs(var_r - var_g) / Math.max(var_r, var_g, 1) > this.settings.active.arDetect.blackframe.sufficientColorVariance
|
||||
|| Math.abs(var_r - var_b) / Math.max(var_r, var_b, 1) > this.settings.active.arDetect.blackframe.sufficientColorVariance
|
||||
|| Math.abs(var_b - var_g) / Math.max(var_b, var_g, 1) > this.settings.active.arDetect.blackframe.sufficientColorVariance
|
||||
const hasSufficientVariance = Math.abs(var_r - var_g) / Math.max(var_r, var_g, 1) > this.settings.active.aard.blackframe.sufficientColorVariance
|
||||
|| Math.abs(var_r - var_b) / Math.max(var_r, var_b, 1) > this.settings.active.aard.blackframe.sufficientColorVariance
|
||||
|| Math.abs(var_b - var_g) / Math.max(var_b, var_g, 1) > this.settings.active.aard.blackframe.sufficientColorVariance
|
||||
|
||||
let isBlack = (blackPixelCount/(cols * rows) > this.settings.active.arDetect.blackframe.blackPixelsCondition);
|
||||
let isBlack = (blackPixelCount/(cols * rows) > this.settings.active.aard.blackframe.blackPixelsCondition);
|
||||
|
||||
if (! isBlack) {
|
||||
if (hasSufficientVariance) {
|
||||
isBlack = cumulativeValue < this.settings.active.arDetect.blackframe.cumulativeThresholdLax;
|
||||
isBlack = cumulativeValue < this.settings.active.aard.blackframe.cumulativeThresholdLax;
|
||||
} else {
|
||||
isBlack = cumulativeValue < this.settings.active.arDetect.blackframe.cumulativeThresholdStrict;
|
||||
isBlack = cumulativeValue < this.settings.active.aard.blackframe.cumulativeThresholdStrict;
|
||||
}
|
||||
}
|
||||
|
||||
@ -842,13 +842,13 @@ class ArDetector {
|
||||
gb: Math.abs(var_b - var_g) / Math.max(var_b, var_g, 1),
|
||||
},
|
||||
relativePercent: {
|
||||
rg: Math.abs(var_r - var_g) / Math.max(var_r, var_g, 1) / this.settings.active.arDetect.blackframe.sufficientColorVariance,
|
||||
rb: Math.abs(var_r - var_b) / Math.max(var_r, var_b, 1) / this.settings.active.arDetect.blackframe.sufficientColorVariance,
|
||||
gb: Math.abs(var_b - var_g) / Math.max(var_b, var_g, 1) / this.settings.active.arDetect.blackframe.sufficientColorVariance,
|
||||
rg: Math.abs(var_r - var_g) / Math.max(var_r, var_g, 1) / this.settings.active.aard.blackframe.sufficientColorVariance,
|
||||
rb: Math.abs(var_r - var_b) / Math.max(var_r, var_b, 1) / this.settings.active.aard.blackframe.sufficientColorVariance,
|
||||
gb: Math.abs(var_b - var_g) / Math.max(var_b, var_g, 1) / this.settings.active.aard.blackframe.sufficientColorVariance,
|
||||
},
|
||||
varianceLimit: this.settings.active.arDetect.blackframe.sufficientColorVariance,
|
||||
varianceLimit: this.settings.active.aard.blackframe.sufficientColorVariance,
|
||||
},
|
||||
cumulativeValuePercent: cumulativeValue / (hasSufficientVariance ? this.settings.active.arDetect.blackframe.cumulativeThresholdLax : this.settings.active.arDetect.blackframe.cumulativeThresholdStrict),
|
||||
cumulativeValuePercent: cumulativeValue / (hasSufficientVariance ? this.settings.active.aard.blackframe.cumulativeThresholdLax : this.settings.active.aard.blackframe.cumulativeThresholdStrict),
|
||||
rowMax: rowMax,
|
||||
colMax: colMax,
|
||||
};
|
||||
@ -867,7 +867,7 @@ class ArDetector {
|
||||
|
||||
// If we detect anything darker than blackLevel, we modify blackLevel to the new lowest value
|
||||
const rowOffset = this.canvas.width * (this.canvas.height - 1);
|
||||
let currentMin = 255, currentMax = 0, colOffset_r, colOffset_g, colOffset_b, colOffset_rb, colOffset_gb, colOffset_bb, blthreshold = this.settings.active.arDetect.blackbar.threshold;
|
||||
let currentMin = 255, currentMax = 0, colOffset_r, colOffset_g, colOffset_b, colOffset_rb, colOffset_gb, colOffset_bb, blthreshold = this.settings.active.aard.blackbar.threshold;
|
||||
|
||||
// detect black level. if currentMax comes above blackbar + blackbar threshold, we know we aren't letterboxed
|
||||
|
||||
|
@ -28,8 +28,8 @@ class GuardLine {
|
||||
}
|
||||
|
||||
setBlackbar(bbconf){
|
||||
var bbTop = bbconf.top - this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
||||
var bbBottom = bbconf.bottom + this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
||||
var bbTop = bbconf.top - this.settings.active.aard.guardLine.edgeTolerancePx;
|
||||
var bbBottom = bbconf.bottom + this.settings.active.aard.guardLine.edgeTolerancePx;
|
||||
|
||||
// to odstrani vse neveljavne nastavitve in vse možnosti, ki niso smiselne
|
||||
// this removes any configs with invalid values or values that dont make sense
|
||||
@ -43,16 +43,16 @@ class GuardLine {
|
||||
}
|
||||
|
||||
this.imageBar = {
|
||||
top: bbconf.top + 1 + this.settings.active.arDetect.guardLine.edgeTolerancePx,
|
||||
bottom: bbconf.bottom - 1 - this.settings.active.arDetect.guardLine.edgeTolerancePx
|
||||
top: bbconf.top + 1 + this.settings.active.aard.guardLine.edgeTolerancePx,
|
||||
bottom: bbconf.bottom - 1 - this.settings.active.aard.guardLine.edgeTolerancePx
|
||||
}
|
||||
}
|
||||
|
||||
check(image, fallbackMode){
|
||||
// izračunaj enkrat in shrani na objekt
|
||||
// calculate once and save object-instance-wide
|
||||
this.blackbarThreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbar.threshold;
|
||||
this.imageThreshold = this.blackbarThreshold + this.settings.active.arDetect.blackbar.imageThreshold;
|
||||
this.blackbarThreshold = this.conf.blackLevel + this.settings.active.aard.blackbar.threshold;
|
||||
this.imageThreshold = this.blackbarThreshold + this.settings.active.aard.blackbar.imageThreshold;
|
||||
|
||||
// dejansko testiranje
|
||||
// actual checks
|
||||
@ -95,7 +95,7 @@ class GuardLine {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
var offset = parseInt(this.conf.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||
var offset = parseInt(this.conf.canvas.width * this.settings.active.aard.guardLine.ignoreEdgeMargin) << 2;
|
||||
|
||||
var offenders = [];
|
||||
var offenderCount = -1; // doing it this way means first offender has offenderCount==0. Ez index.
|
||||
@ -160,7 +160,7 @@ class GuardLine {
|
||||
if(!this.imageBar.top || !this.imageBar.bottom)
|
||||
return { success: false };
|
||||
|
||||
var offset = (this.conf.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||
var offset = (this.conf.canvas.width * this.settings.active.aard.guardLine.ignoreEdgeMargin) << 2;
|
||||
|
||||
// TODO: implement logo check.
|
||||
|
||||
@ -169,8 +169,8 @@ class GuardLine {
|
||||
// check both rows - by the rules and definitions, we shouldn't go out of bounds here. no need to check, then
|
||||
|
||||
// if(fallbackMode){
|
||||
// var edge_upper = this.settings.active.arDetect.fallbackMode.noTriggerZonePx;
|
||||
// var edge_lower = this.conf.canvas.height - this.settings.active.arDetect.fallbackMode.noTriggerZonePx - 1;
|
||||
// var edge_upper = this.settings.active.aard.fallbackMode.noTriggerZonePx;
|
||||
// var edge_lower = this.conf.canvas.height - this.settings.active.aard.fallbackMode.noTriggerZonePx - 1;
|
||||
// }
|
||||
// else{
|
||||
var edge_upper = this.imageBar.top;
|
||||
@ -181,7 +181,7 @@ class GuardLine {
|
||||
// robu (eden izmed robov je lahko v celoti črn)
|
||||
// how many non-black pixels we need to consider this check a success. We only need to detect enough pixels
|
||||
// on one edge (one of the edges can be black as long as both aren't)
|
||||
var successThreshold = (this.conf.canvas.width * this.settings.active.arDetect.guardLine.imageTestThreshold);
|
||||
var successThreshold = (this.conf.canvas.width * this.settings.active.aard.guardLine.imageTestThreshold);
|
||||
var rowStart, rowEnd;
|
||||
|
||||
|
||||
|
@ -15,10 +15,10 @@ class EdgeDetect{
|
||||
this.logger = ardConf.logger;
|
||||
this.settings = ardConf.settings;
|
||||
|
||||
this.sampleWidthBase = this.settings.active.arDetect.edgeDetection.sampleWidth << 2; // corrected so we can work on imageData
|
||||
this.sampleWidthBase = this.settings.active.aard.edgeDetection.sampleWidth << 2; // corrected so we can work on imageData
|
||||
this.halfSample = this.sampleWidthBase >> 1;
|
||||
|
||||
this.detectionThreshold = this.settings.active.arDetect.edgeDetection.detectionThreshold;
|
||||
this.detectionThreshold = this.settings.active.aard.edgeDetection.detectionThreshold;
|
||||
|
||||
this.init(); // initiate things that can change
|
||||
}
|
||||
@ -73,12 +73,12 @@ class EdgeDetect{
|
||||
const cols_b = cols_a.slice(0);
|
||||
const res_bottom = [];
|
||||
|
||||
this.colsThreshold = sampleCols.length * this.settings.active.arDetect.edgeDetection.minColsForSearch;
|
||||
this.colsThreshold = sampleCols.length * this.settings.active.aard.edgeDetection.minColsForSearch;
|
||||
if (this.colsThreshold == 0)
|
||||
this.colsThreshold = 1;
|
||||
|
||||
this.blackbarThreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbar.threshold;
|
||||
this.imageThreshold = this.blackbarThreshold + this.settings.active.arDetect.blackbar.imageThreshold;
|
||||
this.blackbarThreshold = this.conf.blackLevel + this.settings.active.aard.blackbar.threshold;
|
||||
this.imageThreshold = this.blackbarThreshold + this.settings.active.aard.blackbar.imageThreshold;
|
||||
|
||||
// if guardline didn't fail and imageDetect did, we don't have to check the upper few pixels
|
||||
// but only if upper and lower edge are defined. If they're not, we need to check full height
|
||||
@ -100,14 +100,14 @@ class EdgeDetect{
|
||||
lower_bottom = this.conf.canvas.height - 1;
|
||||
} else {
|
||||
upper_top = 0;
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * this.settings.active.aard.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * this.settings.active.aard.edgeDetection.middleIgnoredArea);*/
|
||||
lower_bottom = this.conf.canvas.height - 1;
|
||||
}
|
||||
} else{
|
||||
upper_top = 0;
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * this.settings.active.aard.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * this.settings.active.aard.edgeDetection.middleIgnoredArea);*/
|
||||
lower_bottom = this.conf.canvas.height - 1;
|
||||
}
|
||||
|
||||
@ -251,8 +251,8 @@ class EdgeDetect{
|
||||
sampleEnd = this.conf.canvasImageDataRowLength;
|
||||
|
||||
// calculate row offsets for imageData array
|
||||
sampleRow_black = (sample.black - this.settings.active.arDetect.edgeDetection.edgeTolerancePx - 1) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.black + this.settings.active.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_black = (sample.black - this.settings.active.aard.edgeDetection.edgeTolerancePx - 1) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.black + this.settings.active.aard.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
|
||||
// že ena kršitev črnega roba pomeni, da kandidat ni primeren
|
||||
// even a single black edge violation means the candidate is not an edge
|
||||
@ -294,8 +294,8 @@ class EdgeDetect{
|
||||
sampleEnd = this.conf.canvasImageDataRowLength;
|
||||
|
||||
// calculate row offsets for imageData array
|
||||
sampleRow_black = (sample.black + this.settings.active.arDetect.edgeDetection.edgeTolerancePx + 1) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.black - this.settings.active.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_black = (sample.black + this.settings.active.aard.edgeDetection.edgeTolerancePx + 1) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.black - this.settings.active.aard.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
|
||||
// že ena kršitev črnega roba pomeni, da kandidat ni primeren
|
||||
// even a single black edge violation means the candidate is not an edge
|
||||
@ -337,7 +337,7 @@ class EdgeDetect{
|
||||
edgePostprocess(edges){
|
||||
var edgesTop = [];
|
||||
var edgesBottom = [];
|
||||
var alignMargin = this.conf.canvas.height * this.settings.active.arDetect.allowedMisaligned;
|
||||
var alignMargin = this.conf.canvas.height * this.settings.active.aard.allowedMisaligned;
|
||||
|
||||
var missingEdge = edges.edgeCandidatesTopCount == 0 || edges.edgeCandidatesBottomCount == 0;
|
||||
|
||||
@ -391,8 +391,8 @@ class EdgeDetect{
|
||||
var blackbarWidth = edgesTop[0].distance > edgesBottom[0].distance ?
|
||||
edgesTop[0].distance : edgesBottom[0].distance;
|
||||
|
||||
if (edgesTop[0].count + edgesBottom[0].count > this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold
|
||||
|| ( edgesTop[0].count > this.settings.active.arDetect.edgeDetection.confirmationThreshold && edgesBottom[0].count > this.settings.active.arDetect.edgeDetection.confirmationThreshold) ){
|
||||
if (edgesTop[0].count + edgesBottom[0].count > this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold
|
||||
|| ( edgesTop[0].count > this.settings.active.aard.edgeDetection.confirmationThreshold && edgesBottom[0].count > this.settings.active.aard.edgeDetection.confirmationThreshold) ){
|
||||
return {
|
||||
status: EdgeStatus.AR_KNOWN,
|
||||
blackbarWidth: blackbarWidth,
|
||||
@ -409,7 +409,7 @@ class EdgeDetect{
|
||||
// it could be watermark. It could be a dark frame. Let's check for watermark first.
|
||||
if (edgesTop[0].distance < edgesBottom[0].distance &&
|
||||
edgesTop[0].count < edgesBottom[0].count &&
|
||||
edgesTop[0].count < this.conf.sampleCols.length * this.settings.active.arDetect.edgeDetection.logoThreshold){
|
||||
edgesTop[0].count < this.conf.sampleCols.length * this.settings.active.aard.edgeDetection.logoThreshold){
|
||||
// možno, da je watermark zgoraj. Preverimo, če se kateri od drugih potencialnih robov na zgornjem robu
|
||||
// ujema s prvim spodnjim (+/- variance). Če je temu tako, potem bo verjetno watermark. Logo mora imeti
|
||||
// manj vzorcev kot navaden rob.
|
||||
@ -425,8 +425,8 @@ class EdgeDetect{
|
||||
var blackbarWidth = edgesTop[i].distance > edgesBottom[0].distance ?
|
||||
edgesTop[i].distance : edgesBottom[0].distance;
|
||||
|
||||
if (edgesTop[i].count + edgesBottom[0].count > this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold
|
||||
|| (edgesTop[i].count > this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold && edgesBottom[0].count > this.settings.active.arDetect.edgeDetection.confirmationThreshold) ) {
|
||||
if (edgesTop[i].count + edgesBottom[0].count > this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold
|
||||
|| (edgesTop[i].count > this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold && edgesBottom[0].count > this.settings.active.aard.edgeDetection.confirmationThreshold) ) {
|
||||
return {
|
||||
status: EdgeStatus.AR_KNOWN,
|
||||
blackbarWidth: blackbarWidth,
|
||||
@ -443,7 +443,7 @@ class EdgeDetect{
|
||||
}
|
||||
if (edgesBottom[0].distance < edgesTop[0].distance &&
|
||||
edgesBottom[0].count < edgesTop[0].count &&
|
||||
edgesBottom[0].count < this.conf.sampleCols.length * this.settings.active.arDetect.edgeDetection.logoThreshold){
|
||||
edgesBottom[0].count < this.conf.sampleCols.length * this.settings.active.aard.edgeDetection.logoThreshold){
|
||||
|
||||
if(edgesBottom[0].length > 1){
|
||||
var lowMargin = edgesTop[0].distance - alignMargin;
|
||||
@ -456,8 +456,8 @@ class EdgeDetect{
|
||||
var blackbarWidth = edgesBottom[i].distance > edgesTop[0].distance ?
|
||||
edgesBottom[i].distance : edgesTop[0].distance;
|
||||
|
||||
if (edgesTop[0].count + edgesBottom[i].count > this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold
|
||||
|| (edgesTop[0].count > this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold && edgesBottom[i].count > this.settings.active.arDetect.edgeDetection.confirmationThreshold)) {
|
||||
if (edgesTop[0].count + edgesBottom[i].count > this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold
|
||||
|| (edgesTop[0].count > this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold && edgesBottom[i].count > this.settings.active.aard.edgeDetection.confirmationThreshold)) {
|
||||
return {
|
||||
status: EdgeStatus.AR_KNOWN,
|
||||
blackbarWidth: blackbarWidth,
|
||||
@ -479,7 +479,7 @@ class EdgeDetect{
|
||||
// either the top or the bottom edge remains undetected, but we have one more trick that we
|
||||
// can try. It also tries to work around logos.
|
||||
|
||||
const edgeDetectionThreshold = this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold;
|
||||
const edgeDetectionThreshold = this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold;
|
||||
|
||||
if (edges.edgeCandidatesTopCount == 0 && edges.edgeCandidatesBottomCount != 0){
|
||||
for(var edge of edgesBottom){
|
||||
@ -524,7 +524,7 @@ class EdgeDetect{
|
||||
// we also return true if we detect too much black
|
||||
|
||||
var blackbarThreshold, upper, lower;
|
||||
blackbarThreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbar.threshold;
|
||||
blackbarThreshold = this.conf.blackLevel + this.settings.active.aard.blackbar.threshold;
|
||||
|
||||
|
||||
var middleRowStart = (this.conf.canvas.height >> 1) * this.conf.canvas.width;
|
||||
@ -562,11 +562,11 @@ class EdgeDetect{
|
||||
|
||||
// če sta oba robova v mejah merske napake, potem vrnemo 'false'
|
||||
// if both edges resemble rounding error, we retunr 'false'
|
||||
if(edge_left < this.settings.active.arDetect.pillarTest.ignoreThinPillarsPx && edge_right < this.settings.active.arDetect.pillarTest.ignoreThinPillarsPx){
|
||||
if(edge_left < this.settings.active.aard.pillarTest.ignoreThinPillarsPx && edge_right < this.settings.active.aard.pillarTest.ignoreThinPillarsPx){
|
||||
return false;
|
||||
}
|
||||
|
||||
var edgeError = this.settings.active.arDetect.pillarTest.allowMisaligned;
|
||||
var edgeError = this.settings.active.aard.pillarTest.allowMisaligned;
|
||||
var error_low = 1 - edgeError;
|
||||
var error_hi = 1 + edgeError;
|
||||
|
||||
@ -646,7 +646,7 @@ class EdgeDetect{
|
||||
imageRow: -1,
|
||||
lastValue: -1,
|
||||
diffIndex: 0,
|
||||
diffs: new Array(this.settings.active.arDetect.blackbar.gradientSampleSize).fill(0)
|
||||
diffs: new Array(this.settings.active.aard.blackbar.gradientSampleSize).fill(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,7 +724,7 @@ class EdgeDetect{
|
||||
}
|
||||
|
||||
colsTmp[c].diffIndex++;
|
||||
if (colsTmp[c].diffIndex > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||
if (colsTmp[c].diffIndex > this.settings.active.aard.blackbar.gradientSampleSize) {
|
||||
colsTmp[c].imageFound = true;
|
||||
continue;
|
||||
}
|
||||
@ -737,11 +737,11 @@ class EdgeDetect{
|
||||
// let's process our results
|
||||
for (const c of colsTmp) {
|
||||
if (c.blackFound) {
|
||||
if (this.settings.active.arDetect.blackbar.antiGradientMode === AntiGradientMode.Disabled) {
|
||||
if (this.settings.active.aard.blackbar.antiGradientMode === AntiGradientMode.Disabled) {
|
||||
// if gradient detection is disabled, we treat such columns as detections/not gradient
|
||||
}
|
||||
if (c.imageFound) {
|
||||
if (c.imageRow - c.blackRow <= this.settings.active.arDetect.blackbar.gradientThreshold) {
|
||||
if (c.imageRow - c.blackRow <= this.settings.active.aard.blackbar.gradientThreshold) {
|
||||
// this is within our margin of error. Colums like this are auto-accepted
|
||||
colsOut.push({
|
||||
col: c.col,
|
||||
@ -757,7 +757,7 @@ class EdgeDetect{
|
||||
tmpVal += c.diffs[i];
|
||||
|
||||
// if difference is negative, we aren't looking at a gradient
|
||||
if (c.diffs[i] < this.settings.active.arDetect.blackbar.gradientNegativeTreshold) {
|
||||
if (c.diffs[i] < this.settings.active.aard.blackbar.gradientNegativeTreshold) {
|
||||
colsOut.push({
|
||||
col: c.col,
|
||||
black: c.blackRow
|
||||
@ -766,7 +766,7 @@ class EdgeDetect{
|
||||
}
|
||||
|
||||
// if difference is too big, we assume we aren't looking at a gradient
|
||||
if (c.diffs[i] > this.settings.active.arDetect.blackbar.maxGradient) {
|
||||
if (c.diffs[i] > this.settings.active.aard.blackbar.maxGradient) {
|
||||
colsOut.push({
|
||||
col: c.col,
|
||||
black: c.blackRow
|
||||
@ -789,7 +789,7 @@ class EdgeDetect{
|
||||
stdev = Math.sqrt((squareSum / (c.diffIndex - 1)));
|
||||
|
||||
// if standard deviation is too big, we're not on a gradient (prolly)
|
||||
if (stdev > this.settings.active.arDetect.blackbar.gradientMaxSD) {
|
||||
if (stdev > this.settings.active.aard.blackbar.gradientMaxSD) {
|
||||
colsOut.push({
|
||||
col: c.col,
|
||||
black: c.blackRow
|
||||
@ -821,7 +821,7 @@ class EdgeDetect{
|
||||
// we have blackbar but we haven't found a point that goes over imageTreshold.
|
||||
// how these cases are handled is determiend by what antiGradientMode we're using.
|
||||
// strict mode — treat as gradient. Lax mode — treat as not gradient
|
||||
if (this.settings.active.arDetect.blackbar.antiGradientMode === AntiGradientMode.Lax) {
|
||||
if (this.settings.active.aard.blackbar.antiGradientMode === AntiGradientMode.Lax) {
|
||||
colsOut.push({
|
||||
col: c.col,
|
||||
black: c.blackRow
|
||||
@ -852,7 +852,7 @@ class EdgeDetect{
|
||||
c.diffs = [];
|
||||
}
|
||||
if (reverseSearchDirection) {
|
||||
if (this.settings.active.arDetect.blackbar.antiGradientMode === AntiGradientMode.Disabled) {
|
||||
if (this.settings.active.aard.blackbar.antiGradientMode === AntiGradientMode.Disabled) {
|
||||
// todo: remove gradient detection code from this branch
|
||||
for(var i = bottom - this.conf.canvasImageDataRowLength; i >= top; i-= this.conf.canvasImageDataRowLength){
|
||||
for(let c = 0; c < colsIn.length; c++){
|
||||
@ -883,7 +883,7 @@ class EdgeDetect{
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (colsIn[c].blackFound++ > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||
if (colsIn[c].blackFound++ > this.settings.active.aard.blackbar.gradientSampleSize) {
|
||||
colsIn[c].imageFound = true;
|
||||
continue;
|
||||
}
|
||||
@ -961,7 +961,7 @@ class EdgeDetect{
|
||||
} else {
|
||||
// če smo dobili piksel, ki presega blackbar, preverimo do gradientSampleSize dodatnih pikslov.
|
||||
// ko dobimo piksel čez imageTreshold oz. gradientSampleSize, izračunamo ali gre za gradient.
|
||||
if (colsIn[c].blackFound++ > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||
if (colsIn[c].blackFound++ > this.settings.active.aard.blackbar.gradientSampleSize) {
|
||||
colsIn[c].imageFound = true;
|
||||
continue;
|
||||
}
|
||||
@ -1024,7 +1024,7 @@ class EdgeDetect{
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (colsIn[c].blackFound++ > this.settings.active.arDetect.blackbar.gradientSampleSize) {
|
||||
if (colsIn[c].blackFound++ > this.settings.active.aard.blackbar.gradientSampleSize) {
|
||||
colsIn[c].imageFound = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Generates shader that makes a sample that adds values of pixels within sampleRadius
|
||||
* and calculates how much they deviate from the average. sum of pixels is stored in
|
||||
* the red pixel and diff is stored in the green one. Blue component holds the grayscale
|
||||
* average of the sample. Alpha component can be ignored.
|
||||
*
|
||||
*
|
||||
* RGBA pixel data:
|
||||
*
|
||||
* | red | green | blue |
|
||||
* +-------------------+-------------------+-------------------+
|
||||
* | sum of all pixels | stdev of all | avg of all pixels |
|
||||
* | in a row | pixels | |
|
||||
* | (grayscale) | (grayscale) | (grayscale) |
|
||||
*
|
||||
* @param {number} sampleRadius sample width
|
||||
* @param {number} pixelSizeX size of a pixel on the texture (should be 1 / frameWidth)
|
||||
*/
|
||||
|
||||
export function generateHorizontalAdder(sampleRadius, pixelSizeX) {
|
||||
|
||||
if (sampleRadius < 1) {
|
||||
throw "Sample radius must be greater than 0!";
|
||||
}
|
||||
|
||||
// build adder kernel
|
||||
let adderStatements = 'vec4 rowSum =';
|
||||
for (let i = sampleRadius - 1; i > 0; i--) {
|
||||
adderStatements += `${i == sampleRadius - 1 ? '' : ' +'} texture2D(u_frame, v_textureCoords + vec2(${-i * pixelSizeX}, 0))`;
|
||||
}
|
||||
adderStatements += ` + texture2D(u_frame, v_textureCoords + vec2(0, 0))`;
|
||||
for (let i = 0; i < sampleRadius; i++) {
|
||||
adderStatements += ` + texture2D(u_frame, v_textureCoords + vec2(${i * pixelSizeX}, 0))`;
|
||||
}
|
||||
adderStatements += ';';
|
||||
|
||||
// build deviance kernel
|
||||
let stdDevStatements = `vec4 diffSum =`;
|
||||
for (let i = sampleRadius - 1; i > 0; i--) {
|
||||
stdDevStatements += `${i == sampleRadius - 1 ? '' : ' +'} abs(texture2D(u_frame, v_textureCoords + vec2(${-i * pixelSizeX}, 0)) - average)`;
|
||||
}
|
||||
stdDevStatements += `+ abs(texture2D(u_frame, v_textureCoords + vec2(0, 0)) - average)`;
|
||||
for (let i = sampleRadius - 1; i > 0; i--) {
|
||||
stdDevStatements += ` + abs(texture2D(u_frame, v_textureCoords + vec2(${i * pixelSizeX}, 0)) - average)`;
|
||||
}
|
||||
stdDevStatements += ';';
|
||||
|
||||
const shader = `
|
||||
precision mediump float;
|
||||
|
||||
// texture/frame stuffs:
|
||||
uniform sampler2D u_frame;
|
||||
uniform vec2 u_textureSize;
|
||||
|
||||
// texture coordinates passed from the vertex shader
|
||||
varying vec2 v_textureCoords;
|
||||
|
||||
void main() {
|
||||
${adderStatements}
|
||||
vec4 average = rowSum / ${sampleRadius * 2 + 1}.0;
|
||||
${stdDevStatements}
|
||||
vec4 diff = diffSum / ${sampleRadius * 2 + 1}.0;
|
||||
|
||||
float sumGrayscale = (rowSum.r + rowSum.g + rowSum.b) / 3.0;
|
||||
float diffGrayscale = (diff.r + diff.g + diff.b) / 3.0;
|
||||
|
||||
gl_FragColor = vec4(sumGrayscale, diffGrayscale, (average.r + average.g + average.b) / 3.0, 1.0);
|
||||
}
|
||||
`
|
||||
// btw don't forget: output "image" should be way smaller than input frame
|
||||
|
||||
return shader;
|
||||
}
|
19
src/ext/lib/ar-detect/gllib/shaders/vertex-shader.js
Normal file
19
src/ext/lib/ar-detect/gllib/shaders/vertex-shader.js
Normal file
@ -0,0 +1,19 @@
|
||||
export function getBasicVertexShader() {
|
||||
return `
|
||||
attribute vec2 a_position;
|
||||
attribute vec2 a_textureCoords;
|
||||
|
||||
uniform vec2 u_resolution;
|
||||
varying vec2 v_textureCoords;
|
||||
|
||||
void main() {
|
||||
// convert the position from pixels to uv coordinates
|
||||
vec2 uv = a_position / u_resolution;
|
||||
|
||||
gl_Position = vec4(uv, 0, 0);
|
||||
|
||||
// pass texture coordinates to fragment shader. GPU will
|
||||
// do interpolations
|
||||
v_textureCoords = a_textureCoords;
|
||||
}`;
|
||||
}
|
16
src/ext/lib/ar-detect/gllib/shaders/vertex-shader.vs
Normal file
16
src/ext/lib/ar-detect/gllib/shaders/vertex-shader.vs
Normal file
@ -0,0 +1,16 @@
|
||||
attribute vec2 a_position;
|
||||
attribute vec2 a_textureCoords;
|
||||
|
||||
uniform vec2 u_resolution;
|
||||
varying vec2 v_textureCoords;
|
||||
|
||||
void main() {
|
||||
// convert the position from pixels to uv coordinates
|
||||
vec2 uv = a_position / u_resolution;
|
||||
|
||||
gl_Position = vec4(uv, 0, 0);
|
||||
|
||||
// pass texture coordinates to fragment shader. GPU will
|
||||
// do interpolations
|
||||
v_textureCoords = a_textureCoords;
|
||||
}
|
@ -97,9 +97,9 @@ class CommsServer {
|
||||
(message) => {
|
||||
this.settings.active.sites['@global'].autoar = "disabled";
|
||||
if (message.reason){
|
||||
this.settings.active.arDetect.disabledReason = message.reason;
|
||||
this.settings.active.aard.disabledReason = message.reason;
|
||||
} else {
|
||||
this.settings.active.arDetect.disabledReason = 'User disabled';
|
||||
this.settings.active.aard.disabledReason = 'User disabled';
|
||||
}
|
||||
this.settings.save();
|
||||
this.logger.log('info', 'comms', "[uw-bg] autoar set to disabled. evidenz:", this.settings.active);
|
||||
@ -111,7 +111,7 @@ class CommsServer {
|
||||
|
||||
// set fairly liberal limit
|
||||
var timeout = message.timeout < 4 ? 4 : message.timeout;
|
||||
this.settings.active.arDetect.timer_playing = timeout;
|
||||
this.settings.active.aard.timer_playing = timeout;
|
||||
this.settings.save();
|
||||
}
|
||||
],
|
||||
|
@ -3,6 +3,7 @@ import PlayerData from './PlayerData';
|
||||
import Resizer from '../video-transform/Resizer';
|
||||
import ArDetector from '../ar-detect/ArDetector';
|
||||
import AspectRatio from '../../../common/enums/aspect-ratio.enum';
|
||||
import AardGl from '../ar-detect/AardGl';
|
||||
|
||||
class VideoData {
|
||||
|
||||
@ -47,7 +48,8 @@ class VideoData {
|
||||
};
|
||||
|
||||
|
||||
this.arDetector = new ArDetector(this); // this starts Ar detection. needs optional parameter that prevets ardetdctor from starting
|
||||
// this.arDetector = new ArDetector(this); // this starts Ar detection. needs optional parameter that prevets ardetdctor from starting
|
||||
this.arDetector = new AardGl(this);
|
||||
// player dimensions need to be in:
|
||||
// this.player.dimensions
|
||||
|
||||
@ -177,7 +179,8 @@ class VideoData {
|
||||
return;
|
||||
}
|
||||
if(! this.arSetupComplete){
|
||||
this.arDetector = new ArDetector(this);
|
||||
// this.arDetector = new ArDetector(this);
|
||||
this.arDetector = new AardGl(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +193,8 @@ class VideoData {
|
||||
this.arDetector.init();
|
||||
}
|
||||
else{
|
||||
this.arDetector = new ArDetector(this);
|
||||
// this.arDetector = new ArDetector(this);
|
||||
this.arDetector = new AardGl(this);
|
||||
this.arDetector.init();
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
<div class="flex flex-input">
|
||||
More often <small>(~60/s)</small>
|
||||
<input type="range"
|
||||
:value="Math.log(settings.active.arDetect.timers.playing)"
|
||||
:value="Math.log(settings.active.aard.timers.playing)"
|
||||
@change="setArCheckFrequency($event.target.value)"
|
||||
min="2.3"
|
||||
max="9.3"
|
||||
@ -88,7 +88,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.timers.playing"
|
||||
v-model="settings.active.aard.timers.playing"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -98,7 +98,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.timers.paused"
|
||||
v-model="settings.active.aard.timers.paused"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -108,7 +108,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.timers.error"
|
||||
v-model="settings.active.aard.timers.error"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -121,7 +121,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.timers.tickrate"
|
||||
v-model="settings.active.aard.timers.tickrate"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -147,7 +147,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="checkbox"
|
||||
v-model="settings.active.arDetect.fallbackMode.enabled"
|
||||
v-model="settings.active.aard.fallbackMode.enabled"
|
||||
/> Enable fallback mode <span v-if="!fallbackModeAvailable">because I'm super duper sure I'm using firefox right now.</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -158,7 +158,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.fallbackMode.safetyBorderPx"
|
||||
v-model="settings.active.aard.fallbackMode.safetyBorderPx"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -168,7 +168,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.fallbackMode.noTriggerZonePx"
|
||||
v-model="settings.active.aard.fallbackMode.noTriggerZonePx"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -185,7 +185,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.allowedMisaligned"
|
||||
v-model="settings.active.aard.allowedMisaligned"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -207,7 +207,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.sampling.staticCols"
|
||||
v-model="settings.active.aard.sampling.staticCols"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -217,7 +217,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.sampling.randomCols"
|
||||
v-model="settings.active.aard.sampling.randomCols"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -227,7 +227,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.sampling.staticRows"
|
||||
v-model="settings.active.aard.sampling.staticRows"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -237,7 +237,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.canvasDimensions.sampleCanvas.width"
|
||||
v-model="settings.active.aard.canvasDimensions.sampleCanvas.width"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -247,7 +247,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.canvasDimensions.sampleCanvas.height"
|
||||
v-model="settings.active.aard.canvasDimensions.sampleCanvas.height"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -279,7 +279,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackbar.blackLevel"
|
||||
v-model="settings.active.aard.blackbar.blackLevel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -289,7 +289,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackbar.threshold"
|
||||
v-model="settings.active.aard.blackbar.threshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -298,7 +298,7 @@
|
||||
Gradient detection:
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<select v-model="settings.active.arDetect.blackbar.antiGradientMode">
|
||||
<select v-model="settings.active.aard.blackbar.antiGradientMode">
|
||||
<option :value="0">Disabled</option>
|
||||
<option :value="1">Lax</option>
|
||||
<option :value="2">Strict</option>
|
||||
@ -311,7 +311,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackbar.imageThreshold"
|
||||
v-model="settings.active.aard.blackbar.imageThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -321,7 +321,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackbar.gradientThreshold"
|
||||
v-model="settings.active.aard.blackbar.gradientThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -331,7 +331,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackbar.gradientSampleSize"
|
||||
v-model="settings.active.aard.blackbar.gradientSampleSize"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -359,7 +359,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.canvasDimensions.blackframeCanvas.width"
|
||||
v-model="settings.active.aard.canvasDimensions.blackframeCanvas.width"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -369,7 +369,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.canvasDimensions.blackframeCanvas.height"
|
||||
v-model="settings.active.aard.canvasDimensions.blackframeCanvas.height"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -379,7 +379,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackframe.sufficientColorVariance"
|
||||
v-model="settings.active.aard.blackframe.sufficientColorVariance"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -389,7 +389,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackframe.cumulativeThresholdLax"
|
||||
v-model="settings.active.aard.blackframe.cumulativeThresholdLax"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -399,7 +399,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.blackframe.cumulativeThresholdStrict"
|
||||
v-model="settings.active.aard.blackframe.cumulativeThresholdStrict"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -409,7 +409,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type=""
|
||||
v-model="settings.active.arDetect.blackframe.blackPixelsCondition"
|
||||
v-model="settings.active.aard.blackframe.blackPixelsCondition"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -422,7 +422,7 @@
|
||||
<b>Sample width</b> — In a bid to detect "false" edges, we take two samples this many pixels wide near the point of our potential edge. One sample must be completely black, the other must contain a set
|
||||
amount of non-black pixels.<br/>
|
||||
<b>Detection threshold</b> — non-black sample mentioned above needs to contain at least this many non-black pixels.<br/>
|
||||
<b>Thickness quorum (per edge)</b> — amount of samples that agree on the thincknes of the blackbar that we need in order to establish aspect ratio. Every edge needs to have at least this many. Values higher than {{~~(settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold / 2)}} (quorum (total)/2) are pointless.<br/>
|
||||
<b>Thickness quorum (per edge)</b> — amount of samples that agree on the thincknes of the blackbar that we need in order to establish aspect ratio. Every edge needs to have at least this many. Values higher than {{~~(settings.active.aard.edgeDetection.singleSideConfirmationThreshold / 2)}} (quorum (total)/2) are pointless.<br/>
|
||||
<b>Thickness quorum (total)</b> — amount of samples that agree on the thinckess of the blackbar that we need in order to establish aspect ratio in case one of the edges doesn't contain enough samples to achieve quorum.<br/>
|
||||
<b>Logo threshold</b> — if edge candidate sits with count greater than this*all_samples, it can't be a logo or a watermark.<br/>
|
||||
<b>Ignore middle area</b> — When trying to detect area, ignore area between middle and canvasHeight * {this value} pixels towards the edge.<br/>
|
||||
@ -435,7 +435,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.edgeDetection.sampleWidth"
|
||||
v-model="settings.active.aard.edgeDetection.sampleWidth"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -445,7 +445,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.edgeDetection.detectionThreshold"
|
||||
v-model="settings.active.aard.edgeDetection.detectionThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -455,7 +455,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input
|
||||
v-model="settings.active.arDetect.edgeDetection.confirmationThreshold"
|
||||
v-model="settings.active.aard.edgeDetection.confirmationThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -465,7 +465,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input
|
||||
v-model="settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold"
|
||||
v-model="settings.active.aard.edgeDetection.singleSideConfirmationThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -475,7 +475,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input
|
||||
v-model="settings.active.arDetect.edgeDetection.logoThreshold"
|
||||
v-model="settings.active.aard.edgeDetection.logoThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -485,7 +485,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input
|
||||
v-model="settings.active.arDetect.edgeDetection.middleIgnoredArea"
|
||||
v-model="settings.active.aard.edgeDetection.middleIgnoredArea"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -495,7 +495,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input
|
||||
v-model="settings.active.arDetect.edgeDetection.minColsForSearch"
|
||||
v-model="settings.active.aard.edgeDetection.minColsForSearch"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -516,7 +516,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="checkbox"
|
||||
v-model="settings.active.arDetect.guardLine.enabled"
|
||||
v-model="settings.active.aard.guardLine.enabled"
|
||||
/> Enable guardline
|
||||
</div>
|
||||
</div>
|
||||
@ -526,7 +526,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.guardLine.ignoreEdgeMargin"
|
||||
v-model="settings.active.aard.guardLine.ignoreEdgeMargin"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -536,7 +536,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.guardLine.imageTestThreshold"
|
||||
v-model="settings.active.aard.guardLine.imageTestThreshold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -546,7 +546,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type="text"
|
||||
v-model="settings.active.arDetect.guardLine.edgeTolerancePx"
|
||||
v-model="settings.active.aard.guardLine.edgeTolerancePx"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -564,7 +564,7 @@
|
||||
</div>
|
||||
<div class="flex flex-input">
|
||||
<input type=""
|
||||
v-model="settings.active.arDetect.allowedMisaligned"
|
||||
v-model="settings.active.aard.allowedMisaligned"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -615,36 +615,36 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
setArCheckFrequency(event) {
|
||||
this.settings.active.arDetect.timers.playing = Math.floor(Math.pow(Math.E, event));
|
||||
this.settings.active.aard.timers.playing = Math.floor(Math.pow(Math.E, event));
|
||||
},
|
||||
getSensitivity() {
|
||||
if (this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold === 3 && this.settings.active.arDetect.edgeDetection.confirmationThreshold === 1) {
|
||||
if (this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold === 3 && this.settings.active.aard.edgeDetection.confirmationThreshold === 1) {
|
||||
return 'sensitive';
|
||||
}
|
||||
if (this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold === 5 && this.settings.active.arDetect.edgeDetection.confirmationThreshold === 2) {
|
||||
if (this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold === 5 && this.settings.active.aard.edgeDetection.confirmationThreshold === 2) {
|
||||
return 'balanced';
|
||||
}
|
||||
if (this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold === 7 && this.settings.active.arDetect.edgeDetection.confirmationThreshold === 3) {
|
||||
if (this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold === 7 && this.settings.active.aard.edgeDetection.confirmationThreshold === 3) {
|
||||
return 'accurate';
|
||||
}
|
||||
if (this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold === 16 && this.settings.active.arDetect.edgeDetection.confirmationThreshold === 8) {
|
||||
if (this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold === 16 && this.settings.active.aard.edgeDetection.confirmationThreshold === 8) {
|
||||
return 'strict';
|
||||
}
|
||||
return 'user-defined';
|
||||
},
|
||||
setConfirmationThresholds(sens) {
|
||||
if (sens === 'sensitive') {
|
||||
this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold = 3;
|
||||
this.settings.active.arDetect.edgeDetection.confirmationThreshold = 1;
|
||||
this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold = 3;
|
||||
this.settings.active.aard.edgeDetection.confirmationThreshold = 1;
|
||||
} else if (sens === 'balanced') {
|
||||
this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold = 5;
|
||||
this.settings.active.arDetect.edgeDetection.confirmationThreshold = 2;
|
||||
this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold = 5;
|
||||
this.settings.active.aard.edgeDetection.confirmationThreshold = 2;
|
||||
} else if (sens === 'accurate') {
|
||||
this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold = 7;
|
||||
this.settings.active.arDetect.edgeDetection.confirmationThreshold = 3;
|
||||
this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold = 7;
|
||||
this.settings.active.aard.edgeDetection.confirmationThreshold = 3;
|
||||
} else if (sens === 'strict') {
|
||||
this.settings.active.arDetect.edgeDetection.singleSideConfirmationThreshold = 16;
|
||||
this.settings.active.arDetect.edgeDetection.confirmationThreshold = 8;
|
||||
this.settings.active.aard.edgeDetection.singleSideConfirmationThreshold = 16;
|
||||
this.settings.active.aard.edgeDetection.confirmationThreshold = 8;
|
||||
}
|
||||
|
||||
this.sensitivity = this.getSensitivity();
|
||||
|
Loading…
Reference in New Issue
Block a user