Compare commits

...

30 Commits

Author SHA1 Message Date
0e4b75746d Additional AardGL fixes 2020-06-28 21:33:02 +02:00
41db18e1ed launch.json update 2020-06-27 19:28:55 +02:00
836bf6240e Get webgl setup to not fail and periodic functions to trigger periodically 2020-06-27 19:28:02 +02:00
831e6b8541 Update packages 2020-06-25 02:53:21 +02:00
81195e7b48 add .nvmrc 2020-06-25 02:51:37 +02:00
40e1effa2d Further fixes to AardGl 2020-06-18 20:57:00 +02:00
56456bddda Always init AardGL 2020-06-18 20:56:47 +02:00
b1257a4c51 Fix logger 2020-06-18 20:55:38 +02:00
fb7d7735be WIP aardgl work, before switching back to master 2020-05-29 21:25:08 +02:00
b296552e35 error logging 2020-05-27 01:08:02 +02:00
689e75d3d8 fix # of sample cols 2020-05-27 01:07:32 +02:00
557a0eef46 fix, pt. 3 2020-05-26 23:55:11 +02:00
172f67c7ca i swear I renamed arDetect to aard yesterday already 2020-05-26 23:53:37 +02:00
8d6367d16c fix find/replace gone wrong 2020-05-26 23:51:00 +02:00
3eeef5410f changed regular aard with aardGl in videodata 2020-05-26 01:41:06 +02:00
6400f4cfd6 fix shaders ... to an extent 2020-05-26 01:40:42 +02:00
75a214962c switch arDetect with aard 2020-05-26 01:40:25 +02:00
124dc33828 remove dead code 2020-05-26 01:40:04 +02:00
45a2e5894d add redraw function 2020-05-26 01:39:21 +02:00
d238b1fffe Merge branch 'master' into feature/opengl-test 2020-05-25 22:12:57 +02:00
ee57799005 remove dead code from aardgl, basic settings for aardGl 2020-05-14 00:00:49 +02:00
43709cef34 Start using settings.aardGl where appropriate 2020-04-30 02:08:04 +02:00
b950fef806 keep conf for aardGl and legacy arDetect separate 2020-04-30 02:07:47 +02:00
96803e9b66 dict 2020-04-30 02:07:25 +02:00
1f4bb40b44 Documentation intensifies 2020-04-30 01:32:18 +02:00
02ca4bdd8e Reorganize ardGL 2020-04-30 01:14:04 +02:00
d3754e7a86 piggy-back off requestAnimationFrame 2020-04-30 00:52:48 +02:00
f9c86b2832 webgl setup 2020-04-30 00:43:10 +02:00
e84a1346b4 Start working on webgl-based aspect ratio detection 2020-04-30 00:43:10 +02:00
f13aca1c7f Merge branch 'master' into stable 2020-04-30 00:41:11 +02:00
16 changed files with 2796 additions and 2552 deletions

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
14.4.0

8
.vscode/launch.json vendored
View File

@ -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": {

View File

@ -43,6 +43,7 @@
"tabitem",
"tablist",
"tamius",
"stdev",
"textbox",
"ultrawidify",
"unmark",

4045
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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,

View File

@ -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 ) {

View 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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View 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;
}`;
}

View 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;
}

View File

@ -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();
}
],

View File

@ -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();
}
}

View File

@ -14,7 +14,7 @@
<div class="flex flex-input">
More often&nbsp;<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&nbsp;<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();