2018-05-08 23:35:16 +02:00
class ArDetector {
2018-05-09 00:34:22 +02:00
2018-05-08 23:35:16 +02:00
constructor ( videoData ) {
2018-05-14 20:39:15 +02:00
this . conf = videoData ;
2018-05-08 23:35:16 +02:00
this . video = videoData . video ;
this . setupTimer = null ;
this . timer = null ;
2018-05-14 20:39:15 +02:00
this . sampleCols = [ ] ;
2018-05-09 00:34:22 +02:00
// todo: dynamically detect the following two
this . canFallback = true ;
this . fallbackMode = false ;
2018-05-12 02:51:58 +02:00
2018-05-14 20:39:15 +02:00
this . blackLevel = ExtensionConf . arDetect . blackLevel _default ;
2018-05-09 00:34:22 +02:00
}
2018-05-08 23:35:16 +02:00
init ( ) {
2018-05-14 20:39:15 +02:00
if ( Debug . debug ) {
console . log ( "[ArDetect::init] Initializing autodetection" )
}
2018-05-13 21:05:11 +02:00
this . setup ( ExtensionConf . arDetect . hSamples , ExtensionConf . arDetect . vSamples ) ;
2018-05-08 23:35:16 +02:00
}
2018-05-16 23:26:47 +02:00
destroy ( ) {
this . debugCanvas . destroy ( ) ;
}
2018-05-08 23:35:16 +02:00
setup ( cwidth , cheight ) {
2018-05-17 23:09:04 +02:00
this . guardLine = new GuardLine ( this ) ;
this . edgeDetector = new EdgeDetect ( this ) ;
this . debugCanvas = new DebugCanvas ( this ) ;
2018-05-14 20:39:15 +02:00
if ( Debug . debug ) {
console . log ( "[ArDetect::setup] Starting autodetection setup" ) ;
}
if ( ! cwidth ) {
cwidth = ExtensionConf . arDetect . hSamples ;
cheight = ExtensionConf . arDetect . vSamples ;
}
2018-05-09 00:03:22 +02:00
try {
2018-05-15 20:36:22 +02:00
if ( Debug . debug ) {
2018-05-22 00:19:50 +02:00
console . log ( "[ArDetect::setup] Trying to setup automatic aspect ratio detector. Choice config bits:\ncanvas dimensions:" , cwidth , "× " , cheight , "\nvideoData:" , this . conf ) ;
2018-05-15 20:36:22 +02:00
}
2018-05-09 00:03:22 +02:00
2018-05-09 00:34:22 +02:00
this . _halted = false ;
2018-05-09 00:03:22 +02:00
this . detectionTimeoutEventCount = 0 ;
2018-05-15 20:36:22 +02:00
// // vstavimo začetne stolpce v this.sampleCols. - NE!
// // let's insert initial columns to this.sampleCols - NO!!! do it later dow
// this.sampleCols = [];
2018-05-09 00:03:22 +02:00
2018-05-15 20:36:22 +02:00
// var samplingIntervalPx = parseInt(cheight / ExtensionConf.arDetect.samplingInterval)
// for(var i = 1; i < ExtensionConf.arDetect.samplingInterval; i++){
// this.sampleCols.push(i * samplingIntervalPx);
// }
2018-05-09 00:03:22 +02:00
if ( this . canvas ) {
if ( Debug . debug )
2018-05-20 23:17:09 +02:00
console . log ( "[ArDetect::setup] existing canvas found. REMOVING KEBAB removing kebab\n\n\n\n(im hungry and you're not authorized to have it)" ) ;
2018-05-09 00:03:22 +02:00
this . canvas . remove ( ) ;
if ( Debug . debug )
2018-05-20 23:17:09 +02:00
console . log ( "[ArDetect::setup] canvas removed" ) ;
2018-05-09 00:03:22 +02:00
}
// imamo video, pa tudi problem. Ta problem bo verjetno kmalu popravljen, zato setup začnemo hitreje kot prej
// we have a video, but also a problem. This problem will prolly be fixed very soon, so setup is called with
// less delay than before
if ( this . video . videoWidth === 0 || this . video . videoHeight === 0 ) {
2018-05-20 23:17:09 +02:00
if ( Debug . debug ) {
console . log ( "[ArDetector::setup] video has no width or height!" , this . video . videoWidth , "× " , this . video . videoHeight )
}
this . scheduleInitRestart ( ) ;
2018-05-09 00:03:22 +02:00
return ;
}
// 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 . context = this . canvas . getContext ( "2d" ) ;
// do setup once
// tho we could do it for every frame
2018-05-14 20:39:15 +02:00
this . canvasScaleFactor = cheight / this . video . videoHeight ;
2018-05-09 00:03:22 +02:00
try {
// determine where to sample
var ncol = ExtensionConf . arDetect . staticSampleCols ;
var nrow = ExtensionConf . arDetect . staticSampleRows ;
2018-05-15 20:36:22 +02:00
var colSpacing = this . canvas . width / ncol ;
var rowSpacing = ( this . canvas . height << 2 ) / nrow ;
2018-05-09 00:03:22 +02:00
this . sampleLines = [ ] ;
this . sampleCols = [ ] ;
for ( var i = 0 ; i < ncol ; i ++ ) {
if ( i < ncol - 1 )
this . sampleCols . push ( Math . round ( colSpacing * i ) ) ;
else {
this . sampleCols . push ( Math . round ( colSpacing * i ) - 1 ) ;
}
}
2018-05-15 20:36:22 +02:00
2018-05-09 00:03:22 +02:00
for ( var i = 0 ; i < nrow ; i ++ ) {
if ( i < ncol - 5 )
this . sampleLines . push ( Math . round ( rowSpacing * i ) ) ;
else {
this . sampleLines . push ( Math . round ( rowSpacing * i ) - 4 ) ;
}
}
}
catch ( ex ) {
console . log ( "%c[ArDetect::_arSetup] something went terribly wrong when calcuating sample colums." , ExtensionConf . colors . criticalFail ) ;
console . log ( "settings object:" , Settings ) ;
console . log ( "error:" , ex ) ;
}
// we're also gonna reset this
this . guardLine . top = null ;
this . guardLine . bottom = null ;
2018-05-14 20:39:15 +02:00
this . resetBlackLevel ( ) ;
2018-05-09 00:03:22 +02:00
this . _forcehalt = false ;
// if we're restarting ArDetect, we need to do this in order to force-recalculate aspect ratio
2018-05-14 20:39:15 +02:00
this . conf . resizer . setLastAr ( { type : "auto" , ar : null } ) ;
2018-05-08 23:35:16 +02:00
2018-05-09 00:03:22 +02:00
this . canvasImageDataRowLength = cwidth << 2 ;
this . noLetterboxCanvasReset = false ;
this . start ( ) ;
}
catch ( ex ) {
console . log ( ex ) ;
}
if ( Debug . debugCanvas . enabled ) {
2018-05-14 20:39:15 +02:00
this . debugCanvas . init ( { width : cwidth , height : cheight } ) ;
2018-05-09 00:03:22 +02:00
// DebugCanvas.draw("test marker","test","rect", {x:5, y:5}, {width: 5, height: 5});
}
2018-05-16 23:26:47 +02:00
this . conf . arSetupComplete = true ;
2018-05-08 23:35:16 +02:00
}
start ( ) {
2018-05-22 00:19:50 +02:00
console . log ( "%c[ArDetect::setup] Starting automatic aspect ratio detection." , _ard _console _start ) ;
2018-05-12 01:51:43 +02:00
this . _halted = false ;
2018-05-09 00:34:22 +02:00
this . scheduleFrameCheck ( 0 , true ) ;
2018-05-08 23:35:16 +02:00
}
stop ( ) {
if ( Debug . debug ) {
console . log ( "%c[ArDetect::_ard_stop] Stopping automatic aspect ratio detection" , _ard _console _stop ) ;
}
this . _forcehalt = true ;
this . _halted = true ;
clearTimeout ( this . setupTimer ) ;
clearTimeout ( this . timer ) ;
}
2018-05-12 01:51:43 +02:00
isRunning ( ) {
return ! this . _halted ;
}
2018-05-20 23:17:09 +02:00
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 . init ( ) ;
} catch ( e ) { console . log ( "[ArDetector::scheduleInitRestart] Failed to start init(). Error:" , e ) }
ths = null ;
} ,
timeout
) ;
}
2018-05-15 20:36:22 +02:00
scheduleFrameCheck ( timeout , force _reset ) {
if ( ! timeout ) {
this . frameCheck ( ) ;
return ;
}
// run anything that needs to be run after frame check
this . postFrameCheck ( ) ;
// don't allow more than 1 instance
if ( this . timer ) {
clearTimeout ( this . timer ) ;
}
var ths = this ;
2018-05-22 00:19:50 +02:00
// console.log(this.video, "this.video | ths.video", ths.video)
// console.log(this.conf.video, "this.conf | ths.conf", ths.conf.video)
// console.log("resizer conf&vid",
// this.conf.resizer, this.conf.resizer.conf, this.conf.resizer.video, this.conf.resizer.conf.video )
// debugger;
2018-05-15 20:36:22 +02:00
this . timer = setTimeout ( function ( ) {
ths . timer = null ;
2018-05-17 23:09:04 +02:00
try {
2018-05-15 20:36:22 +02:00
ths . frameCheck ( ) ;
2018-05-17 23:09:04 +02:00
} catch ( e ) { console . log ( "Frame check failed. Error:" , e ) }
2018-05-15 20:36:22 +02:00
ths = null ;
} ,
timeout
) ;
}
2018-05-09 00:34:22 +02:00
2018-05-12 01:51:43 +02:00
postFrameCheck ( ) {
if ( Debug . debugCanvas . enabled ) {
this . debugCanvas . update ( ) ;
}
}
2018-05-09 00:34:22 +02:00
//#region helper functions (general)
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 ( ) {
if ( Debug . debug )
console . log ( "%c[ArDetect::_ard_canvasReadyForDrawWindow] (?)" , "color: #44f" , this . canvas . height == window . innerHeight , "(ard_height:" , this . canvas . height , "| window height:" , window . innerHeight , ")" ) ;
return this . canvas . height == window . innerHeight
}
2018-05-09 00:58:50 +02:00
getTimeout ( baseTimeout , startTime ) {
var execTime = ( performance . now ( ) - startTime ) ;
if ( execTime > ExtensionConf . arDetect . autoDisable . maxExecutionTime ) {
this . detectionTimeoutEventCount ++ ;
if ( Debug . debug ) {
2018-05-17 23:09:04 +02:00
console . log ( "[ArDetect::getTimeout] Exec time exceeded maximum allowed execution time. This has now happened " + this . detectionTimeoutEventCount + " times in a row." ) ;
2018-05-09 00:58:50 +02:00
}
2018-05-15 20:36:22 +02:00
// if( this.detectionTimeoutEventCount >= ExtensionConf.arDetect.autoDisable.consecutiveTimeoutCount ){
// if (Debug.debug){
// console.log("[ArDetect::getTimeout] Maximum execution time was exceeded too many times. Automatic aspect ratio detection has been disabled.");
// }
2018-05-09 00:58:50 +02:00
2018-05-15 20:36:22 +02:00
// Comms.sendToBackgroundScript({cmd: 'disable-autoar', reason: 'Automatic aspect ratio detection was taking too much time and has been automatically disabled in order to avoid lag.'});
// _ard_stop();
// return 999999;
// }
2018-05-09 00:58:50 +02:00
} else {
this . detectionTimeoutEventCount = 0 ;
}
// return baseTimeout > ExtensionConf.arDetect.minimumTimeout ? baseTimeout : ExtensionConf.arDetect.minimumTimeout;
return baseTimeout ;
}
2018-05-09 00:34:22 +02:00
//#endregion
2018-05-13 21:05:11 +02:00
processAr ( edges ) {
2018-05-09 00:34:22 +02:00
if ( Debug . debug && Debug . debugArDetect ) {
console . log ( "[ArDetect::_ard_processAr] processing ar. sample width:" , this . canvas . width , "; sample height:" , this . canvas . height , "; edge top:" , edges . top ) ;
}
// if we don't specify these things, they'll have some default values.
if ( edges . top === undefined ) {
edges . top = 0 ;
edges . bottom = 0 ;
edge . left = 0 ;
edges . right = 0 ;
}
var letterbox = edges . top + edges . bottom ;
var trueHeight = this . canvas . height - letterbox ;
if ( this . fallbackMode ) {
2018-05-18 23:26:20 +02:00
if ( edges . top > 1 && edges . top <= ExtensionConf . arDetect . fallbackMode . noTriggerZonePx ) {
console . log ( "Edge is in the no-trigger zone. Aspect ratio change is not triggered." )
2018-05-09 00:34:22 +02:00
return ;
2018-05-18 23:26:20 +02:00
}
2018-05-09 00:34:22 +02:00
// 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 += ( ExtensionConf . arDetect . fallbackMode . safetyBorderPx << 1 ) ;
}
2018-05-15 21:40:53 +02:00
var trueAr = this . canvas . width / trueHeight ;
2018-05-09 00:34:22 +02:00
this . detectedAr = trueAr ;
// poglejmo, če se je razmerje stranic spremenilo
// check if aspect ratio is changed:
2018-05-15 21:40:53 +02:00
var lastAr = this . conf . resizer . getLastAr ( ) ;
2018-05-09 00:34:22 +02:00
if ( lastAr . type == "auto" && lastAr . ar != 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
if ( Debug . debug && Debug . debugArDetect )
console . log ( "%c[ArDetect::_ard_processAr] 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 * ExtensionConf . arDetect . allowedArVariance ) {
if ( Debug . debug && Debug . debugArDetect )
console . log ( "%c[ArDetect::_ard_processAr] aspect ratio change denied — diff %:" , "background: #740; color: #fa2" , arDiff _percent )
return ;
}
else if ( Debug . debug && Debug . debugArDetect ) {
console . log ( "%c[ArDetect::_ard_processAr] aspect ratio change accepted — diff %:" , "background: #153; color: #4f9" , arDiff _percent )
}
}
if ( Debug . debug )
console . log ( "[ArDetect::_ard_processAr] attempting to fix aspect ratio. New aspect ratio: " , trueAr ) ;
// POMEMBNO: GlobalVars.lastAr je potrebno nastaviti šele po tem, ko kličemo _res_setAr(). _res_setAr() predvideva,
// da želimo nastaviti statično (type: 'static') razmerje stranic — tudi, če funkcijo kličemo tu oz. v ArDetect.
//
// IMPORTANT NOTE: GlobalVars.lastAr needs to be set after _res_setAr() is called, as _res_setAr() assumes we're
// setting a static aspect ratio (even if the function is called from here or ArDetect).
2018-05-14 20:39:15 +02:00
this . conf . resizer . setAr ( trueAr , { type : "auto" , ar : trueAr } ) ;
2018-05-09 00:34:22 +02:00
}
frameCheck ( ) {
2018-05-22 00:19:50 +02:00
// console.log("this.video:", this.video, this.conf.video);
// debugger;
2018-05-09 00:58:50 +02:00
if ( this . _halted )
return ;
2018-05-09 00:34:22 +02:00
2018-05-09 00:58:50 +02:00
if ( ! this . video ) {
if ( Debug . debug || Debug . warnings _critical )
2018-05-16 23:26:47 +02:00
console . log ( "[ArDetect::_ard_vdraw] Video went missing. Destroying current instance of videoData." )
this . conf . destroy ( ) ;
2018-05-09 00:58:50 +02:00
return ;
}
var fallbackMode = false ;
var startTime = performance . now ( ) ;
var baseTimeout = ExtensionConf . arDetect . timer _playing ;
var triggerTimeout ;
var guardLineResult = true ; // true if success, false if fail. true by default
var imageDetectResult = false ; // true if we detect image along the way. false by default
2017-12-29 23:34:40 +01:00
2018-05-15 20:36:22 +02:00
var sampleCols = this . sampleCols . slice ( 0 ) ;
2018-05-09 00:58:50 +02:00
var how _far _treshold = 8 ; // how much can the edge pixel vary (*4)
2018-05-16 23:26:47 +02:00
if ( this . video . ended ) {
// we slow down if ended. Detecting is pointless.
2018-05-09 00:58:50 +02:00
this . scheduleFrameCheck ( ExtensionConf . arDetect . timer _paused ) ;
return false ;
}
if ( this . video . paused ) {
// č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.
baseTimeout = ExtensionConf . arDetect . timer _paused ;
}
try {
this . context . drawImage ( this . video , 0 , 0 , this . canvas . width , this . canvas . height ) ;
}
catch ( ex ) {
if ( Debug . debug )
console . log ( "%c[ArDetect::_ard_vdraw] can't draw image on canvas. Trying canvas.drawWindow instead" , "color:#000; backgroud:#f51;" , ex ) ;
try {
if ( ! ExtensionConf . arDetect . fallbackMode . enabled )
throw "fallbackMode is disabled." ;
if ( this . canvasReadyForDrawWindow ( ) ) {
2018-05-17 23:09:04 +02:00
this . context . drawWindow ( window , this . canvasDrawWindowHOffset , 0 , this . canvas . width , this . canvas . height , "rgba(0,0,128,1)" ) ;
2018-05-09 00:58:50 +02:00
if ( Debug . debug )
console . log ( "%c[ArDetect::_ard_vdraw] canvas.drawImage seems to have worked" , "color:#000; backgroud:#2f5;" ) ;
this . fallbackMode = true ;
}
else {
// canvas needs to be resized, so let's change setup
this . stop ( ) ;
2018-05-17 23:09:04 +02:00
var newCanvasWidth = window . innerHeight * ( this . video . videoWidth / this . video . videoHeight ) ;
2018-05-09 00:58:50 +02:00
var newCanvasHeight = window . innerHeight ;
if ( ExtensionConf . miscFullscreenSettings . videoFloat == "center" )
this . canvasDrawWindowHOffset = Math . round ( ( window . innerWidth - newCanvasWidth ) * 0.5 ) ;
else if ( ExtensionConf . miscFullscreenSettings . videFloat == "left" )
this . canvasDrawWindowHOffset = 0 ;
else
this . canvasDrawWindowHOffset = window . innerWidth - newCanvasWidth ;
this . setup ( newCanvasWidth , newCanvasHeight ) ;
return ;
}
}
catch ( ex ) {
if ( Debug . debug )
console . log ( "%c[ArDetect::_ard_vdraw] okay this didnt work either" , "color:#000; backgroud:#f51;" , ex ) ;
this . scheduleFrameCheck ( ExtensionConf . arDetect . timer _error ) ;
return ;
}
}
2017-09-27 02:26:47 +02:00
2018-05-09 00:58:50 +02:00
if ( ! this . blackLevel ) {
if ( Debug . debugArDetect )
console . log ( "[ArDetect::_ard_vdraw] black level undefined, resetting" ) ;
2018-05-14 20:39:15 +02:00
this . resetBlackLevel ( ) ;
2018-05-09 00:58:50 +02:00
}
// we get the entire frame so there's less references for garbage collection to catch
var image = this . context . getImageData ( 0 , 0 , this . canvas . width , this . canvas . height ) . data ;
if ( Debug . debugCanvas . enabled ) {
2018-05-12 01:51:43 +02:00
this . debugCanvas . setBuffer ( image ) ;
2018-05-09 00:58:50 +02:00
}
2017-09-27 02:26:47 +02:00
2018-05-09 00:58:50 +02:00
//#region black level detection
2018-02-26 22:38:17 +01:00
2018-05-09 00:58:50 +02:00
// fast test to see if aspect ratio is correct. If we detect anything darker than blackLevel, we modify
// blackLevel to the new lowest value
var isLetter = true ;
var currentMaxVal = 0 ;
var currentMax _a ;
var currentMinVal = 48 ; // not 255 cos safety, even this is prolly too high
var currentMin _a ;
var rowOffset = 0 ;
var colOffset _r , colOffset _g , colOffset _b ;
// detect black level. if currentMax and currentMin vary too much, we automatically know that
// black level is bogus and that we aren't letterboxed. We still save the darkest value as black level,
// though — as black bars will never be brighter than that.
for ( var i = 0 ; i < sampleCols . length ; ++ i ) {
colOffset _r = sampleCols [ i ] << 2 ;
colOffset _g = colOffset _r + 1 ;
colOffset _b = colOffset _r + 2 ;
currentMax _a = image [ colOffset _r ] > image [ colOffset _g ] ? image [ colOffset _r ] : image [ colOffset _g ] ;
currentMax _a = currentMax _a > image [ colOffset _b ] ? currentMax _a : image [ colOffset _b ] ;
currentMaxVal = currentMaxVal > currentMax _a ? currentMaxVal : currentMax _a ;
currentMin _a = image [ colOffset _r ] < image [ colOffset _g ] ? image [ colOffset _r ] : image [ colOffset _g ] ;
currentMin _a = currentMin _a < image [ colOffset _b ] ? currentMin _a : image [ colOffset _b ] ;
currentMinVal = currentMinVal < currentMin _a ? currentMinVal : currentMin _a ;
}
2018-02-28 23:54:32 +01:00
2018-05-09 00:58:50 +02:00
// we'll shift the sum. math says we can do this
rowOffset = this . canvas . width * ( this . canvas . height - 1 ) ;
for ( var i = 0 ; i < sampleCols . length ; ++ i ) {
colOffset _r = ( rowOffset + sampleCols [ i ] ) << 2 ;
colOffset _g = colOffset _r + 1 ;
colOffset _b = colOffset _r + 2 ;
currentMax _a = image [ colOffset _r ] > image [ colOffset _g ] ? image [ colOffset _r ] : image [ colOffset _g ] ;
currentMax _a = currentMax _a > image [ colOffset _b ] ? currentMax _a : image [ colOffset _b ] ;
currentMaxVal = currentMaxVal > currentMax _a ? currentMaxVal : currentMax _a ;
currentMin _a = image [ colOffset _r ] < image [ colOffset _g ] ? image [ colOffset _r ] : image [ colOffset _g ] ;
currentMin _a = currentMin _a < image [ colOffset _b ] ? currentMin _a : image [ colOffset _b ] ;
if ( currentMinVal == undefined && currenMinVal != undefined )
currentMinVal = currentMin _a ;
else if ( currentMin _a != undefined )
currentMinVal = currentMinVal < currentMin _a ? currentMinVal : currentMin _a ;
}
// save black level only if defined
if ( currentMinVal )
this . blackLevel = this . blackLevel < currentMinVal ? this . blackLevel : currentMinVal ;
2017-09-24 01:54:46 +02:00
2018-05-09 00:58:50 +02:00
//#endregion
2017-12-31 18:26:59 +01:00
2018-05-09 00:58:50 +02:00
// this means we don't have letterbox
if ( currentMaxVal > ( this . blackLevel + ExtensionConf . arDetect . blackbarTreshold ) || ( currentMaxVal - currentMinVal ) > ExtensionConf . arDetect . blackbarTreshold ) {
// Če ne zaznamo letterboxa, kličemo reset. Lahko, da je bilo razmerje stranic popravljeno na roke. Možno je tudi,
// da je letterbox izginil.
// If we don't detect letterbox, we reset aspect ratio to aspect ratio of the video file. The aspect ratio could
// have been corrected manually. It's also possible that letterbox (that was there before) disappeared.
if ( Debug . debug ) {
console . log ( "%c[ArDetect::_ard_vdraw] no edge detected. canvas has no edge." , "color: #aaf" ) ;
}
// Pogledamo, ali smo že kdaj ponastavili CSS. Če še nismo, potem to storimo. Če smo že, potem ne.
// Ponastavimo tudi guardline (na null).
// let's chec if we ever reset CSS. If we haven't, then we do so. If we did, then we don't.
// while resetting the CSS, we also reset guardline top and bottom back to null.
2018-05-16 23:26:47 +02:00
if ( ! this . noLetterboxCanvasReset ) {
2018-05-14 20:39:15 +02:00
this . conf . resizer . reset ( { type : "auto" , ar : null } ) ;
2018-05-09 00:58:50 +02:00
this . guardLine . top = null ;
this . guardLine . bottom = null ;
this . noLetterboxCanvasReset = true ;
}
2018-05-11 00:49:50 +02:00
2018-05-09 00:58:50 +02:00
triggerTimeout = this . getTimeout ( baseTimeout , startTime ) ;
this . scheduleFrameCheck ( triggerTimeout ) ; //no letterbox, no problem
2017-12-31 18:26:59 +01:00
return ;
2018-05-09 00:58:50 +02:00
}
2017-12-31 18:26:59 +01:00
2018-05-09 00:58:50 +02:00
// Če preverjamo naprej, potem moramo postaviti to vrednost nazaj na 'false'. V nasprotnem primeru se bo
// css resetiral enkrat na video/pageload namesto vsakič, ko so za nekaj časa obrobe odstranejene
// if we look further we need to reset this value back to false. Otherwise we'll only get CSS reset once
// per video/pageload instead of every time letterbox goes away (this can happen more than once per vid)
2018-05-16 23:26:47 +02:00
this . noLetterboxCanvasReset = false ;
2018-02-12 23:28:31 +01:00
2018-05-09 00:58:50 +02:00
// let's do a quick test to see if we're on a black frame
// TODO: reimplement but with less bullshit
// poglejmo, če obrežemo preveč.
// let's check if we're cropping too much (or whatever)
var guardLineOut ;
2018-02-12 23:28:31 +01:00
2018-05-14 20:39:15 +02:00
guardLineOut = this . guardLine . check ( image , fallbackMode ) ;
2018-05-11 00:49:50 +02:00
if ( guardLineOut . blackbarFail ) { // add new ssamples to our sample columns
for ( var col of guardLineOut . offenders ) {
sampleCols . push ( col )
2018-05-09 00:58:50 +02:00
}
2018-05-11 00:49:50 +02:00
}
2018-05-09 00:58:50 +02:00
2018-05-11 00:49:50 +02:00
// če ni padla nobena izmed funkcij, potem se razmerje stranic ni spremenilo
// if both succeed, then aspect ratio hasn't changed.
// if we're in fallback mode and blackbar test failed, we restore CSS
if ( fallbackMode && guardLineOut . blackbarFail ) {
2018-05-14 20:39:15 +02:00
this . conf . resizer . reset ( { type : "auto" , ar : null } ) ;
2018-05-11 00:49:50 +02:00
this . guardLine . reset ( ) ;
2018-05-16 23:26:47 +02:00
this . noLetterboxCanvasReset = true ;
2018-05-09 00:58:50 +02:00
2018-05-11 00:49:50 +02:00
triggerTimeout = this . getTimeout ( baseTimeout , startTime ) ;
2018-05-12 01:51:43 +02:00
this . scheduleFrameCheck ( triggerTimeout ) ; //no letterbox, no problem
2018-05-11 00:49:50 +02:00
return ;
2018-02-12 23:28:31 +01:00
}
2018-05-09 00:58:50 +02:00
2018-05-11 00:49:50 +02:00
if ( ! guardLineOut . imageFail && ! guardLineOut . blackbarFail ) {
triggerTimeout = this . getTimeout ( baseTimeout , startTime ) ;
this . scheduleFrameCheck ( triggerTimeout ) ; //no letterbox, no problem
return ;
}
2018-05-09 00:58:50 +02:00
// će se razmerje stranic spreminja iz ožjega na širšega, potem najprej poglejmo za prisotnostjo navpičnih črnih obrob.
// če so prisotne navpične obrobe tudi na levi in desni strani, potlej obstaja možnost, da gre za logo na črnem ozadju.
// v tem primeru obstaja nevarnost, da porežemo preveč. Ker obstaja dovolj velika možnost, da bi porezali preveč, rajši
// ne naredimo ničesar.
//
// če je pillarbox zaznan v primeru spremembe iz ožjega na širše razmerje stranice, razmerje povrnemo na privzeto vrednost.
//
// If aspect ratio changes from narrower to wider, we first check for presence of pillarbox. Presence of pillarbox indicates
// a chance of a logo on black background. We could cut easily cut too much. Because there's a somewhat significant chance
// that we will cut too much, we rather avoid doing anything at all. There's gonna be a next chance.
2018-05-16 23:26:47 +02:00
try {
2018-05-11 00:49:50 +02:00
if ( guardLineOut . blackbarFail || guardLineOut . imageFail ) {
2018-05-14 20:39:15 +02:00
if ( this . edgeDetector . findBars ( image , null , EdgeDetectPrimaryDirection . HORIZONTAL ) . status === 'ar_known' ) {
2017-09-24 01:54:46 +02:00
2018-05-11 00:49:50 +02:00
if ( Debug . debug && guardLineOut . blackbarFail ) {
2018-05-09 00:58:50 +02:00
console . log ( "[ArDetect::_ard_vdraw] Detected blackbar violation and pillarbox. Resetting to default aspect ratio." ) ;
}
2018-05-16 23:26:47 +02:00
if ( guardLineOut . blackbarFail ) {
2018-05-14 20:39:15 +02:00
this . conf . resizer . reset ( { type : "auto" , ar : null } ) ;
2018-05-11 00:49:50 +02:00
this . guardLine . reset ( ) ;
2018-05-09 00:58:50 +02:00
}
2018-03-04 23:07:11 +01:00
2018-05-09 00:58:50 +02:00
triggerTimeout = this . getTimeout ( baseTimeout , startTime ) ;
2018-05-11 00:49:50 +02:00
this . scheduleFrameCheck ( triggerTimeout ) ;
2018-05-09 00:58:50 +02:00
return ;
}
}
2018-05-16 23:26:47 +02:00
} catch ( e ) { console . log ( "deeee" , e ) }
2018-03-04 23:07:11 +01:00
2018-05-09 00:58:50 +02:00
// pa poglejmo, kje se končajo črne letvice na vrhu in na dnu videa.
// let's see where black bars end.
2018-05-15 20:36:22 +02:00
this . sampleCols _current = sampleCols . length ;
2018-05-09 00:58:50 +02:00
// blackSamples -> {res_top, res_bottom}
2018-05-14 20:39:15 +02:00
var edgePost = this . edgeDetector . findBars ( image , sampleCols , EdgeDetectPrimaryDirection . VERTICAL , EdgeDetectQuality . IMPROVED , guardLineOut ) ;
2018-05-09 00:58:50 +02:00
// console.log("SAMPLES:", blackbarSamples, "candidates:", edgeCandidates, "post:", edgePost,"\n\nblack level:",GlobalVars.arDetect.blackLevel, "tresh:", this.blackLevel + ExtensionConf.arDetect.blackbarTreshold);
if ( edgePost . status == "ar_known" ) {
// zaznali smo rob — vendar pa moramo pred obdelavo še preveriti, ali ni "rob" slučajno besedilo. Če smo kot rob pofočkali
// besedilo, potem to ni veljaven rob. Razmerja stranic se zato ne bomo pipali.
// we detected an edge — but before we process it, we need to check if the "edge" isn't actually some text. If the detected
// edge is actually some text on black background, we shouldn't touch the aspect ratio. Whatever we detected is invalid.
2018-05-12 01:51:43 +02:00
// var textEdge = false;;
2018-03-04 23:07:11 +01:00
2018-05-12 01:51:43 +02:00
// if(edgePost.guardLineTop != null){
// var row = edgePost.guardLineTop + ~~(this.canvas.height * ExtensionConf.arDetect.textLineTest.testRowOffset);
// textEdge |= textLineTest(image, row);
// }
// if(edgePost.guardLineTop != null){
// var row = edgePost.guardLineTop - ~~(this.canvas.height * ExtensionConf.arDetect.textLineTest.testRowOffset);
// textEdge |= textLineTest(image, row);
// }
2018-03-04 23:07:11 +01:00
2018-05-12 01:51:43 +02:00
// if(!textEdge){
2018-05-15 21:40:53 +02:00
this . processAr ( edgePost ) ;
2018-05-09 00:58:50 +02:00
// we also know edges for guardline, so set them
2018-05-12 01:51:43 +02:00
this . guardLine . setBlackbar ( { top : edgePost . guardLineTop , bottom : edgePost . guardLineBottom } ) ;
// }
// else{
// console.log("detected text on edges, dooing nothing")
// }
2018-03-04 23:07:11 +01:00
2018-05-09 00:58:50 +02:00
triggerTimeout = this . getTimeout ( baseTimeout , startTime ) ;
2018-05-12 01:51:43 +02:00
this . scheduleFrameCheck ( triggerTimeout ) ; //no letterbox, no problem
2018-05-09 00:58:50 +02:00
return ;
2018-05-12 01:51:43 +02:00
} else {
2018-05-09 00:58:50 +02:00
triggerTimeout = this . getTimeout ( baseTimeout , startTime ) ;
2018-05-12 01:51:43 +02:00
this . scheduleFrameCheck ( triggerTimeout ) ; //no letterbox, no problem
2018-05-09 00:58:50 +02:00
return ;
}
}
2018-03-04 23:07:11 +01:00
2018-05-14 20:39:15 +02:00
resetBlackLevel ( ) {
this . blackLevel = ExtensionConf . arDetect . blackLevel _default ;
}
2018-05-09 00:58:50 +02:00
}
if ( Debug . debug )
console . log ( "Loading: ArDetect" ) ;
2018-03-04 23:07:11 +01:00
2018-05-09 00:58:50 +02:00
var _ard _console _stop = "background: #000; color: #f41" ;
var _ard _console _start = "background: #000; color: #00c399" ;
2018-03-04 23:07:11 +01:00
2018-04-10 21:35:34 +02:00
2018-04-11 00:19:44 +02:00
var textLineTest = function ( image , row ) {
// preverimo, če vrstica vsebuje besedilo na črnem ozadju. Če ob pregledu vrstice naletimo na veliko sprememb
// iz črnega v ne-črno, potem obstaja možnost, da gledamo besedilo. Prisotnost take vrstice je lahko znak, da
// zaznano razmerje stranic ni veljavno
//
// vrne 'true' če zazna text, 'false' drugače.
//
//
// check if line contains any text. If line scan reveals a lot of changes from black to non-black there's a
// chance we're looking at text on a black background. If we detect text near what we think is an edge of the
// video, there's a good chance we're about to incorrectly adjust the aspect ratio.
//
// returns 'true' if text is detected, 'false' otherwise
2018-05-09 00:58:50 +02:00
var blackbarTreshold = this . blackLevel + ExtensionConf . arDetect . blackbarTreshold ;
var nontextTreshold = this . canvas . width * ExtensionConf . arDetect . textLineTest . nonTextPulse ;
2018-04-11 00:19:44 +02:00
2018-05-09 00:58:50 +02:00
var rowStart = ( row * this . canvas . width ) << 2 ;
var rowEnd = rowStart + ( this . canvas . width << 2 ) ;
2018-04-11 00:19:44 +02:00
var pulse = false ;
var currentPulseLength = 0 , pulseCount = 0 ;
var pulses = [ ] ;
var longestBlack = 0 ;
// preglejmo vrstico
// analyse the row
for ( var i = rowStart ; i < rowEnd ; i += 4 ) {
if ( pulse ) {
if ( image [ i ] < blackbarTreshold || image [ i + 1 ] < blackbarTreshold || image [ i + 2 ] < blackbarTreshold ) {
// pulses.push(currentPulseLength);
pulseCount ++ ;
pulse = false ;
currentPulseLength = 0 ;
2018-04-10 21:35:34 +02:00
}
else {
2018-04-11 00:19:44 +02:00
currentPulseLength ++ ;
// če najdemo dovolj dolgo zaporedje ne-črnih točk, potem vrnemo 'false' — dobili smo legitimen rob
// if we find long enough uninterrupted line of non-black point, we fail the test. We found a legit edge.
if ( currentPulseLength > nontextTreshold ) {
return false ;
}
2018-04-10 21:35:34 +02:00
}
}
else {
2018-04-11 00:19:44 +02:00
if ( image [ i ] > blackbarTreshold || image [ i + 1 ] > blackbarTreshold || image [ i + 2 ] > blackbarTreshold ) {
if ( currentPulseLength > longestBlack ) {
longestBlack = currentPulseLength ;
}
pulse = true ;
currentPulseLength = 0 ;
}
else {
currentPulseLength ++ ;
}
2018-04-10 21:35:34 +02:00
}
}
2018-04-11 00:19:44 +02:00
if ( pulse ) {
pulseCount ++ ;
// pulses.push(currentPulseLength);
}
2018-03-04 23:07:11 +01:00
2018-04-11 00:19:44 +02:00
// pregledamo rezultate:
// analyse the results
2018-05-02 17:52:25 +02:00
// console.log("pulse test:\n\npulses:", pulseCount, "longest black:", longestBlack);
2018-04-11 00:19:44 +02:00
// če smo zaznali dovolj pulzov, potem vrnemo res
// if we detected enough pulses, we return true
if ( pulseCount > ExtensionConf . arDetect . textLineTest . pulsesToConfirm ) {
return true ;
}
// če je najdaljša neprekinjena črta črnih pikslov širša od polovice širine je merilo za zaznavanje
// besedila rahlo milejše
// if the longest uninterrupted line of black pixels is wider than half the width, we use a more
// forgiving standard for determining if we found text
2018-05-09 00:58:50 +02:00
if ( longestBlack > ( this . canvas . width >> 1 ) &&
2018-04-11 00:19:44 +02:00
pulseCount > ExtensionConf . arDetect . textLineTest . pulsesToConfirmIfHalfBlack ) {
return true ;
}
// če pridemo do sem, potem besedilo ni bilo zaznano
// if we're here, no text was detected
return false ;
}
2018-03-04 23:07:11 +01:00