Autodetection persists over multiple videos

This commit is contained in:
Tamius Han 2018-05-16 23:26:47 +02:00
parent 82abee42bd
commit 4fe5ce6bcb
7 changed files with 169 additions and 60 deletions

View File

@ -41,7 +41,7 @@ var ExtensionConf = {
ignoreEdgeMargin: 0.20, // we ignore anything that pokes over the black line this close to the edge
// (relative to width of the sample)
imageTestTreshold: 0.1, // when testing for image, this much pixels must be over blackbarTreshold
edgeTolerancePx: 3, // black edge violation is performed this far from reported 'last black pixel'
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: {

View File

@ -1,6 +1,7 @@
class VideoData {
constructor(video){
this.arSetupComplete = false;
this.video = video;
// POZOR: VRSTNI RED JE POMEMBEN (arDetect mora bit zadnji)
@ -14,8 +15,17 @@ class VideoData {
// this.player.dimensions
}
firstTimeArdInit(){
if(! this.arSetupComplete){
this.arDetector = new ArDetector(this);
}
}
initArDetection() {
this.arDetector.init();
if(ths.arDetector)
this.arDetector.init();
else
this.arDetector = new ArDetector(this);
}
startArDetection() {
@ -23,7 +33,15 @@ class VideoData {
}
destroy() {
this.arDetector.stop();
if(this.arDetector){
this.arDetector.stop();
this.arDetector.destroy();
}
this.arDetector = null;
if(this.resizer){
this.resizer.destroy();
}
this.video = null;
}
setLastAr(lastAr){

View File

@ -28,6 +28,10 @@ class ArDetector {
this.setup(ExtensionConf.arDetect.hSamples, ExtensionConf.arDetect.vSamples);
}
destroy(){
this.debugCanvas.destroy();
}
setup(cwidth, cheight){
if(Debug.debug){
console.log("[ArDetect::setup] Starting autodetection setup");
@ -73,7 +77,7 @@ class ArDetector {
if(this.video.videoWidth === 0 || this.video.videoHeight === 0 ){
if(! this.timer)
this.setupTimer = setTimeout(_arSetup, 100);
this.setupTimer = setTimeout(this.init(), 100);
return;
}
@ -145,6 +149,8 @@ class ArDetector {
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;
}
start(){
@ -332,8 +338,8 @@ class ArDetector {
if(! this.video){
if(Debug.debug || Debug.warnings_critical)
console.log("[ArDetect::_ard_vdraw] Video went missing. Stopping current instance of automatic detection.")
this.stop();
console.log("[ArDetect::_ard_vdraw] Video went missing. Destroying current instance of videoData.")
this.conf.destroy();
return;
}
@ -350,8 +356,8 @@ class ArDetector {
var how_far_treshold = 8; // how much can the edge pixel vary (*4)
if(this.video == null || this.video.ended ){
// we slow down if ended or null. Detecting is pointless.
if(this.video.ended ){
// we slow down if ended. Detecting is pointless.
this.scheduleFrameCheck(ExtensionConf.arDetect.timer_paused);
return false;
@ -502,7 +508,7 @@ class ArDetector {
// 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.
if(! GlobalVars.arDetect.noLetterboxCanvasReset){
if(! this.noLetterboxCanvasReset){
this.conf.resizer.reset({type: "auto", ar: null});
this.guardLine.top = null;
this.guardLine.bottom = null;
@ -518,7 +524,7 @@ class ArDetector {
// 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)
GlobalVars.arDetect.noLetterboxCanvasReset = false;
this.noLetterboxCanvasReset = false;
// let's do a quick test to see if we're on a black frame
// TODO: reimplement but with less bullshit
@ -542,7 +548,7 @@ class ArDetector {
if (fallbackMode && guardLineOut.blackbarFail) {
this.conf.resizer.reset({type: "auto", ar: null});
this.guardLine.reset();
this.arDetect.noLetterboxCanvasReset = true;
this.noLetterboxCanvasReset = true;
triggerTimeout = this.getTimeout(baseTimeout, startTime);
this.scheduleFrameCheck(triggerTimeout); //no letterbox, no problem
@ -565,7 +571,7 @@ class ArDetector {
// 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.
try{
if(guardLineOut.blackbarFail || guardLineOut.imageFail){
if(this.edgeDetector.findBars(image, null, EdgeDetectPrimaryDirection.HORIZONTAL).status === 'ar_known'){
@ -573,7 +579,7 @@ class ArDetector {
console.log("[ArDetect::_ard_vdraw] Detected blackbar violation and pillarbox. Resetting to default aspect ratio.");
}
if(! guardLineResult){
if(guardLineOut.blackbarFail){
this.conf.resizer.reset({type: "auto", ar: null});
this.guardLine.reset();
}
@ -584,6 +590,7 @@ class ArDetector {
return;
}
}
}catch(e) {console.log("deeee",e)}
// pa poglejmo, kje se končajo črne letvice na vrhu in na dnu videa.
// let's see where black bars end.

View File

@ -34,6 +34,10 @@ class DebugCanvas {
console.log("debug canvas is:", this.canvas, "context:", this.context)
}
destroy(){
this.canvas.remove();
}
setBuffer(buffer) {
// this.imageBuffer = buffer.splice(0);
this.imageBuffer = new Uint8ClampedArray(buffer);
@ -77,8 +81,8 @@ class DebugCanvas {
}
DebugCanvasClasses = {
VIOLATION: {color: '#ff4400', colorRgb: [255, 68, 0], text: 'violation (general)'},
WARN: {color: '#d08539', colorRgb: [208, 133, 57], text: 'lesser violation (general)'},
VIOLATION: {color: '#ff0000', colorRgb: [255, 00, 0], text: 'violation (general)'},
WARN: {color: '#d0d039', colorRgb: [208, 208, 57], text: 'lesser violation (general)'},
GUARDLINE_BLACKBAR: {color: '#3333FF', colorRgb: [51, 51, 255], text: 'guardline/blackbar (expected value)'},
GUARDLINE_IMAGE: {color: '#000088', colorRgb: [0, 0, 136], text: 'guardline/image (expected value)'},

View File

@ -12,33 +12,69 @@ class PageInfo {
}
rescan(count){
try{
var vids = document.getElementsByTagName('video');
if(!vids || vids.length == 0){
this.hasVideos = false;
this.scheduleRescan();
return;
}
// debugger;
// add new videos
for(var video of vids){
var existing = this.videos.find( (x) => {
if (x == video.video)
return x;
if (x.currentSrc == video.video.currentSrc){
return x;
}
})
// for(var video of vids){
// var existing = this.videos.find( (x) => {
// if (video && x == video.video)
// return x;
// if (video && x.currentSrc == video.video.currentSrc){
// return x;
// }
// })
if(existing){
video.video = existing;
// if(existing){
// video.video = existing;
// } else {
// this.videos.push(
// new VideoData(video)
// );
// }
// }
if(this.videos.length > 0){
if(vids[0] == this.videos[0].video){
// do nothing
} else {
this.videos.push(
new VideoData(video)
);
this.videos[0].destroy();
this.videos[0] = new VideoData(vids[0]);
}
} else {
this.videos.push(new VideoData(vids[0]));
}
console.log("Rescan complete. Total videos?", this.videos.length)
}catch(e){
console.log("rescan error:",e)
}
this.scheduleRescan();
}
scheduleRescan(){
try{
if(this.rescanTimer){
clearTimeout(this.rescanTimer);
}
var ths = this;
this.rescanTimer = setTimeout(function(){
ths.rescanTimer = null;
ths.rescan();
ths = null;
}, 1000)
}catch(e){console.log("eee",e)}
}
initArDetection(){

View File

@ -30,8 +30,13 @@ class Resizer {
this.restore_wd = false;
this.lastAr = {type: 'original'};
this.destroyed = false;
}
destroy(){
this.destroyed = true;
this.stopCssWatcher();
}
setAr(ar, lastAr){
if(Debug.debug){
@ -50,15 +55,17 @@ class Resizer {
if (! this.video) {
// console.log("No video detected.")
// this.videoData.destroy();
this.videoData.destroy();
}
var dimensions = Scaler.calculateCrop(ar, this.video, this.conf.player.dimensions);
if(dimensions.error){
if(! dimensions || dimensions.error){
if(Debug.debug){
console.log("[Resizer::setAr] failed to set AR due to problem with calculating crop. Error:", dimensions.error)
console.log("[Resizer::setAr] failed to set AR due to problem with calculating crop. Error:", (dimensions ? dimensions.error : dimensions));
}
if(dimensions.error === 'no_video'){
this.conf.destroy();
}
return;
}
@ -75,6 +82,9 @@ class Resizer {
var cssOffsets = this.computeOffsets(dimensions);
this.applyCss(cssOffsets, stretchFactors);
if(! this.destroyed)
this.startCssWatcher();
}
setLastAr(override){
@ -101,10 +111,18 @@ class Resizer {
}
startCssWatcher(){
this.cssWatcherTimeout = setInterval(this.cssWatcher, 200);
// this.haltCssWatcher = false;
if(!this.cssWatcherTimeout){
if(Debug.debug)
console.log("[Resizer.js] STARTING CSS WATCHER")
this.cssWatcherTimeout = setInterval(this.cssWatcher, 200, this);
}
}
stopCssWatcher(){
if(Debug.debug) console.log("[Resizer.js] STOPPING CSS WATCHER!")
clearInterval(this.cssWatcherTimeout);
}
@ -190,12 +208,20 @@ class Resizer {
applyCss(dimensions, stretchFactors){
if(this.video == undefined || this.video == null){
if (! this.video ){
if(Debug.debug)
console.log("[Resizer::_res_applyCss] Video went missing, doing nothing.");
this.conf.destroy();
return;
}
// save stuff for quick tests (before we turn numbers into css values):
this.currentVideoSettings = {
validFor: this.conf.player.dimensions,
videoWidth: dimensions.width,
videoHeight: dimensions.height
}
if(Debug.debug)
console.log("[Resizer::_res_applyCss] Starting to apply css. this is what we're getting in:", dimensions);
@ -284,6 +310,9 @@ class Resizer {
styleString += styleArray[i] + "; ";
this.setStyleString(styleString);
}
setStyleString (styleString, count = 0) {
@ -322,21 +351,31 @@ class Resizer {
}
}
cssWatcher(){
cssWatcher(ths){
// this means we haven't set our CSS yet, or that we changed video.
if(! this.currentCss.top)
if(! ths.currentCss.top)
return;
// this means video went missing.
if(! this.video)
// this means video went missing. videoData will be re-initialized when the next video is found
if(! ths.video){
ths.conf.destroy();
return;
}
// // our current css is fucky? Null, undefined and 0 are invalid values.
// if(! GlobalVars.currentCss.width || ! GlobalVars.currentCss.height )
// return;
// first, a quick test:
if (ths.currentVideoSettings.validFor == ths.conf.player.dimensions ){
if (ths.currentVideoSettings.videoWidth != ths.video.offsetWidth ||
ths.currentVideoSettings.videoHeight != ths.video.offsetHeight){
ths.restore();
return;
}
}
var styleArrayStr = this.video.getAttribute('style');
var styleArrayStr = ths.video.getAttribute('style');
if (styleArrayStr){
var styleArray = styleArrayStr.split(";");
@ -349,24 +388,24 @@ class Resizer {
if (styleArray[i].startsWith("top:")){
// don't force css restore if currentCss.top is not defined
if(this.currentCss.top && styleArray[i] != this.currentCss.top){
if(ths.currentCss.top && styleArray[i] != ths.currentCss.top){
if(Debug.debug){
console.log("[Resizer::_res_antiCssOverride] SOMEBODY TOUCHED MA SPAGHETT (our CSS got overriden, restoring our css)");
console.log("[Resizer::_res_antiCssOverride] MA SPAGHETT: top:", this.currentCss.top, "left:", this.currentCss.left, "thing that touched ma spaghett", styleArrayStr);
console.log("[Resizer::_res_antiCssOverride] MA SPAGHETT: top:", ths.currentCss.top, "left:", ths.currentCss.left, "thing that touched ma spaghett", styleArrayStr);
}
_res_restore();
ths.restore();
return;
}
stuffChecked++;
}
else if(styleArray[i].startsWith("left:")){
// don't force css restore if currentCss.left is not defined
if(this.currentCss.left && styleArray[i] != this.currentCss.left){
if(ths.currentCss.left && styleArray[i] != ths.currentCss.left){
if(Debug.debug){
console.log("[Resizer::_res_antiCssOverride] SOMEBODY TOUCHED MA SPAGHETT (our CSS got overriden, restoring our css)");
console.log("[Resizer::_res_antiCssOverride] MA SPAGHETT: width:", this.currentCss.width, "height:", this.currentCss.height, "thing that touched ma spaghett", styleArrayStr);
console.log("[Resizer::_res_antiCssOverride] MA SPAGHETT: width:", ths.currentCss.width, "height:", ths.currentCss.height, "thing that touched ma spaghett", styleArrayStr);
}
_res_restore();
ths.restore();
return;
}
stuffChecked++;

View File

@ -57,21 +57,7 @@ class Scaler {
}
static calculateCrop(mode, video, playerDimensions) {
// if 'ar' is string, we'll handle that in legacy wrapper
var ar = 0;
if(isNaN(mode)){
ar = this.modeToAr(mode);
} else {
ar = mode;
}
// handle fuckie-wuckies
if (! ar){
return null;
}
if(Debug.debug)
console.log("[Scaler::calculateCrop] trying to set ar. args are: ar->",ar,"; playerDimensions->",playerDimensions.width, "×", playerDimensions.height, "| obj:", playerDimensions);
if(!video || video.videoWidth == 0 || video.videoHeight == 0){
if(Debug.debug)
@ -79,6 +65,25 @@ class Scaler {
return {error: "no_video"};
}
// if 'ar' is string, we'll handle that in legacy wrapper
var ar = 0;
if(isNaN(mode)){
ar = Scaler.modeToAr(mode);
} else {
ar = mode;
}
// handle fuckie-wuckies
if (! ar){
if(Debug.debug)
console.log("[Scaler::calculateCrop] no ar?", ar, " -- we were given this mode:", mode);
return {error: "no_ar", ar: ar};
}
if(Debug.debug)
console.log("[Scaler::calculateCrop] trying to set ar. args are: ar->",ar,"; playerDimensions->",playerDimensions.width, "×", playerDimensions.height, "| obj:", playerDimensions);
if( (! playerDimensions) || playerDimensions.width === 0 || playerDimensions.height === 0 ){
if(Debug.debug)
console.log("[Scaler::calculateCrop] ERROR — no (or invalid) playerDimensions:",playerDimensions);