Fixes to aspect ratio detection: guardline/black line now works properly-ish. By accident also managed to correct the bug where aspect ratio detection was mildly screwed in theater mode?

This commit is contained in:
Tamius Han 2018-05-01 23:09:58 +02:00
parent bf7dce2482
commit 9a5f586eaf
6 changed files with 210 additions and 132 deletions

View File

@ -18,7 +18,6 @@ Debug = {
debugDetection: true
},
debugCanvas: {
enable: true,
enabled: true,
guardLine: true
}

View File

@ -14,7 +14,7 @@ var ExtensionConf = {
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%)
timer_playing: 1000, // we trigger ar this often (in ms) under this conditions
timer_playing: 666, // we trigger ar this often (in ms) under this conditions
timer_paused: 3000,
timer_error: 3000,
timer_minimumTimeout: 5, // but regardless of above, we wait this many msec before retriggering
@ -23,7 +23,7 @@ var ExtensionConf = {
samplingInterval: 10, // we sample at columns at (width/this) * [ 1 .. this - 1]
blackLevel_default: 10, // everything darker than 10/255 across all RGB components is considered black by
// default. GlobalVars.blackLevel can decrease if we detect darker black.
blackbarTreshold: 8, // if pixel is darker than blackLevel + blackbarTreshold, we count it as black
blackbarTreshold: 16, // if pixel is darker than blackLevel + blackbarTreshold, 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
staticSampleCols: 9, // we take a column at [0-n]/n-th parts along the width and sample it

View File

@ -138,8 +138,13 @@ var _pd_checkPlayerSizeChange = function(){
console.log("[PlayerDetect] player size changed. reason: exited fullscreen");
}
}
if(GlobalVars.playerDimensions.width != GlobalVars.playerDimensions.element.offsetWidth || GlobalVars.playerDimensions.height != GlobalVars.playerDimensions.element.offsetHeight ){
if(! GlobalVars.playerDimensions.element)
console.log("[PlayerDetect] player element isnt defined");
if ( GlobalVars.playerDimensions.element &&
( GlobalVars.playerDimensions.width != GlobalVars.playerDimensions.element.offsetWidth ||
GlobalVars.playerDimensions.height != GlobalVars.playerDimensions.element.offsetHeight )
){
console.log("[PlayerDetect] player size changed. reason: dimension change. Old dimensions?", GlobalVars.playerDimensions.width, GlobalVars.playerDimensions.height, "new dimensions:", GlobalVars.playerDimensions.element.offsetWidth, GlobalVars.playerDimensions.element.offsetHeight);
}
}

View File

@ -153,20 +153,20 @@ var _arSetup = function(cwidth, cheight){
GlobalVars.canvas.imageDataRowLength = canvasWidth << 2;
GlobalVars.arDetect.noLetterboxCanvasReset = false;
// GlobalVars.correctedVideoDimensions.height = null;
// GlobalVars.correctedVideoDimensions.width = null;
// GlobalVars.correctedVideoDimensions.top = null;
// GlobalVars.correctedVideoDimensions.left = null;
//
// GlobalVars.correctedVideoDimensions.height = null;
// GlobalVars.correctedVideoDimensions.width = null;
// GlobalVars.correctedVideoDimensions.top = null;
// GlobalVars.correctedVideoDimensions.left = null;
//
_ard_vdraw(0);
}
catch(ex){
console.log(ex);
}
if(Debug.debugCanvas.enable){
if(Debug.debugCanvas.enabled){
DebugCanvas.init({width: canvasWidth, height: canvasHeight});
DebugCanvas.draw("test marker","test","rect", {x:5, y:5}, {width: 5, height: 5});
// DebugCanvas.draw("test marker","test","rect", {x:5, y:5}, {width: 5, height: 5});
}
};
@ -383,6 +383,11 @@ var _ard_vdraw_but_for_reals = function() {
// we get the entire frame so there's less references for garbage collection to catch
var image = GlobalVars.canvas.context.getImageData(0,0,GlobalVars.canvas.width,GlobalVars.canvas.height).data;
if(Debug.debugCanvas.enabled){
DebugCanvas.showTraces();
DebugCanvas.setBuffer(image);
}
// 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;
@ -485,51 +490,7 @@ var _ard_vdraw_but_for_reals = function() {
var guardLineOut;
var imageDetectOut;
if(ExtensionConf.arDetect.guardLine.enabled){
console.log("GUARDLINE ENABLED")
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
var xOffset = parseInt(GlobalVars.canvas.width * ExtensionConf.arDetect.guardLine.ignoreEdgeMargin);
var dbgc_w = GlobalVars.canvas.width - (xOffset * 2);
if(GlobalVars.arDetect.guardLine.top){
DebugCanvas.draw(
"",
"guardLine_blackbar",
"rect",
{x: xOffset, y: GlobalVars.arDetect.guardLine.top - ExtensionConf.arDetect.guardLine.edgeTolerancePx},
{width: dbgc_w, height: 1},
ExtensionConf.arDetect.timer_playing
);
DebugCanvas.draw(
"",
"guardLine_imageTest",
"rect",
{x: xOffset, y: GlobalVars.arDetect.guardLine.top + ExtensionConf.arDetect.guardLine.edgeTolerancePx},
{width: dbgc_w, height: 1},
ExtensionConf.arDetect.timer_playing
);
}
if(GlobalVars.arDetect.guardLine.bottom){
DebugCanvas.draw(
"",
"guardLine_blackbar",
"rect",
{x: xOffset, y: GlobalVars.arDetect.guardLine.bottom + ExtensionConf.arDetect.guardLine.edgeTolerancePx},
{width: dbgc_w, height: 1},
ExtensionConf.arDetect.timer_playing
);
DebugCanvas.draw(
"",
"guardLine_imageTest",
"rect",
{x: xOffset, y: GlobalVars.arDetect.guardLine.bottom - ExtensionConf.arDetect.guardLine.edgeTolerancePx},
{width: dbgc_w, height: 1},
ExtensionConf.arDetect.timer_playing
);
}
}
if(ExtensionConf.arDetect.guardLine.enabled){
guardLineOut = _ard_guardLineCheck(image, fallbackMode);
guardLineResult = guardLineOut.success;
@ -538,7 +499,9 @@ var _ard_vdraw_but_for_reals = function() {
sampleCols.push(col)
}
}
console.log("GUARDLINE RESULT:", guardLineResult, guardLineOut)
imageDetectOut = _ard_guardLineImageDetect(image, fallbackMode);
imageDetectResult = imageDetectOut.success;
@ -574,12 +537,23 @@ var _ard_vdraw_but_for_reals = function() {
// 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.
if(! imageDetectResult){
if(! imageDetectResult || ! guardLineResult){
if(pillarTest(image)){
console.log("pillarboxing, doing jack shit")
if(Debug.debug && ! guardLineResult){
console.log("[ArDetect::_ard_vdraw] Detected blackbar violation and pillarbox. Resetting to default aspect ratio.");
}
if(! guardLineResult){
Resizer.reset();
}
delete image;
triggerTimeout = _ard_getTimeout(baseTimeout, startTime);
_ard_vdraw(triggerTimeout);
@ -597,7 +571,7 @@ var _ard_vdraw_but_for_reals = function() {
var edgeCandidates = _ard_edgeDetect(image, blackbarSamples);
var edgePost = _ard_edgePostprocess(edgeCandidates, GlobalVars.canvas.height);
// console.log("SAMPLES:", blackbarSamples, "candidates:", edgeCandidates, "post:", edgePost,"\n\nblack level:",GlobalVars.arDetect.blackLevel, "tresh:", GlobalVars.arDetect.blackLevel + ExtensionConf.arDetect.blackbarTreshold);
// console.log("SAMPLES:", blackbarSamples, "candidates:", edgeCandidates, "post:", edgePost,"\n\nblack level:",GlobalVars.arDetect.blackLevel, "tresh:", GlobalVars.arDetect.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
@ -849,58 +823,20 @@ var _ard_guardLineCheck = function(image, fallbackMode){
rowStart = ((edge_upper * GlobalVars.canvas.width) << 2) + offset;
rowEnd = rowStart + ( GlobalVars.canvas.width << 2 ) - (offset * 2);
for(var i = rowStart; i < rowEnd; i+=4){
// we track sections that go over what's supposed to be a black line, so we can suggest more
// columns to sample
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
if(firstOffender < 0){
firstOffender = (i >> 2) - rowStart;
offenderCount++;
offenders.push({x: firstOffender, width: 1})
if(Debug.debugCanvas.enable && Debug.debugCanvas.guardLine){
DebugCanvas.draw('','guardLine_blackbar_violation', 'rect', {x: i>>2, y: edge_upper}, {width: 3, height: 3}, 1000)
}
}
else{
offenders[offenderCount].width++
}
}
else{
// is that a black pixel again? Let's reset the 'first offender'
firstOffender = -1;
}
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
offenderCount = _ard_gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount, blackbarTreshold);
} else {
offenderCount = _ard_gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount, blackbarTreshold);
}
// <<<=======| checking lower row |========>>>
rowStart = ((edge_lower * GlobalVars.canvas.width) << 2) + offset;
rowEnd = rowStart + ( GlobalVars.canvas.width << 2 ) - (offset * 2);
for(var i = rowStart; i < rowEnd; i+=4){
// we track sections that go over what's supposed to be a black line, so we can suggest more
// columns to sample
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
if(firstOffender < 0){
firstOffender = (i >> 2) - rowStart;
offenderCount++;
offenders.push({x: firstOffender, width: 1})
if(Debug.debugCanvas.enable && Debug.debugCanvas.blackBar){
DebugCanvas.draw('','guardLine_blackbar_violation', 'rect', {x: i>>2, y: edge_lower}, {width: 3, height: 3}, 1000)
}
}
else{
offenders[offenderCount].width++
}
}
else{
// is that a black pixel again? Let's reset the 'first offender'
firstOffender = -1;
}
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
offenderCount = _ard_gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount, blackbarTreshold);
} else {
offenderCount = _ard_gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount, blackbarTreshold);
}
// če nismo našli nobenih prekrškarjev, vrnemo uspeh. Drugače vrnemo seznam prekrškarjev
@ -920,6 +856,59 @@ var _ard_guardLineCheck = function(image, fallbackMode){
return {success: false, offenders: ret};
}
var _ard_gl_rowCheck = function(image, rowStart, rowEnd, offenders, offenderCount, blackbarTreshold){
var firstOffender = -1;
for(var i = rowStart; i < rowEnd; i+=4){
// we track sections that go over what's supposed to be a black line, so we can suggest more
// columns to sample
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
if(firstOffender < 0){
firstOffender = (i - rowStart) >> 2;
offenderCount++;
offenders.push({x: firstOffender, width: 1});
}
else{
offenders[offenderCount].width++
}
}
else{
// is that a black pixel again? Let's reset the 'first offender'
firstOffender = -1;
}
}
return offenderCount;
}
var _ard_gl_debugRowCheck = function(image, rowStart, rowEnd, offenders, offenderCount, blackbarTreshold){
var firstOffender = -1;
for(var i = rowStart; i < rowEnd; i+=4){
// we track sections that go over what's supposed to be a black line, so we can suggest more
// columns to sample
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
DebugCanvas.trace('guardLine_blackbar_violation', i);
if(firstOffender < 0){
firstOffender = (i - rowStart) >> 2;
offenderCount++;
offenders.push({x: firstOffender, width: 1});
}
else{
offenders[offenderCount].width++
}
}
else{
DebugCanvas.trace('guardLine_blackbar', i);
// is that a black pixel again? Let's reset the 'first offender'
firstOffender = -1;
}
}
return offenderCount;
}
var _ard_edgeDetect = function(image, samples){
var edgeCandidatesTop = {};
var edgeCandidatesBottom = {};
@ -1167,7 +1156,7 @@ var _ard_findBlackbarLimits = function(image, cols, guardLineResult, imageDetect
return {res_top: res_top, res_bottom: res_bottom};
}
var _ard_guardLineImageDetect = function(image, fallbackMode){
function _ard_guardLineImageDetect(image, fallbackMode){
if(GlobalVars.arDetect.guardLine.top == null || GlobalVars.arDetect.guardLine.bottom == null)
return { success: false };
@ -1204,33 +1193,57 @@ var _ard_guardLineImageDetect = function(image, fallbackMode){
rowStart = ((edge_upper * GlobalVars.canvas.width) << 2) + offset;
rowEnd = rowStart + ( GlobalVars.canvas.width << 2 ) - (offset * 2);
var res = false;
for(var i = rowStart; i < rowEnd; i+=4){
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
if(successTreshold --<= 0){
return {success: true}
}
}
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
res = _ard_ti_debugCheckRow(image, rowStart, rowEnd, successTreshold, blackbarTreshold);
} else {
res = _ard_ti_checkRow(image, rowStart, rowEnd,successTreshold, blackbarTreshold);
}
if(res)
return {success: true};
// <<<=======| checking lower row |========>>>
rowStart = ((edge_lower * GlobalVars.canvas.width) << 2) + offset;
rowEnd = rowStart + ( GlobalVars.canvas.width << 2 ) - (offset * 2);
// rowEnd = rowStart + ( GlobalVars.canvas.width << 2 ) - (offset * 2);
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
res = _ard_ti_debugCheckRow(image, rowStart, rowEnd, successTreshold);
} else {
res = _ard_ti_checkRow(image, rowStart, rowEnd,successTreshold);
}
return {success: res};
}
function _ard_ti_checkRow(image, rowStart, rowEnd, successTreshold, blackbarTreshold) {
for(var i = rowStart; i < rowEnd; i+=4){
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
if(successTreshold --<= 0){
return {success: true}
return true;
}
}
}
}
return {success: false};
return false;
}
function _ard_ti_debugCheckRow(image, rowStart, rowEnd, successTreshold, blackbarTreshold) {
for(var i = rowStart; i < rowEnd; i+=4){
if(image[i] > blackbarTreshold || image[i+1] > blackbarTreshold || image[i+2] > blackbarTreshold){
DebugCanvas.trace('guardLine_imageTest', i);
if(successTreshold --<= 0){
return true;
}
} else {
DebugCanvas.trace('guardLine_imageTest_noimage', i);
}
}
return false;
}
var _ard_edgePostprocess = function(edges, canvasHeight){

View File

@ -2,6 +2,7 @@ var _dbgc_canvas;
var _dbgc_context;
var _dbgc_timer;
var _dbgc_clearTimeoutCount = 0;
var _dbgc_imageBuffer;
// drawQueue vsebuje stvari, ki jih bomo risali na platno
// Je tabela objektov, ki naj bi zgledali takole:
@ -20,11 +21,18 @@ var _dbgc_drawQueue = [];
var _dbgc_classes = {
guardLine_blackbar: "#000099",
guardLine_imageTest: "#5555FF",
guardLine_blackbar_violation: "#2222FF",
guardLine_blackbar_violation: "#FF0000",
test: "#FF0000"
}
var _dbgc_traceColors = {
guardLine_blackbar: [0, 0, 96],
guardLine_imageTest: [72, 72, 255],
guardLine_blackbar_violation: [255, 0, 0],
guardLine_imageTest_noimage: [69, 42, 42]
}
var _dbgc_init = async function(canvasSize, canvasPosition){
console.log("initiating DebugCanvas")
@ -53,9 +61,9 @@ var _dbgc_init = async function(canvasSize, canvasPosition){
_dbgc_canvas.width = canvasSize.width;
_dbgc_canvas.height = canvasSize.height;
console.log("debug canvas is:", _dbgc_canvas)
console.log("debug canvas is:", _dbgc_canvas, "context:", _dbgc_context)
_dbgc_start();
// _dbgc_start();
}
var _dbgc_removeFromQueue = function(element){
@ -154,15 +162,59 @@ var _dbgc_update = function(){
_dbgc_scheduleUpdate(100);
}
var _dbgc_setBuffer = function(buffer) {
// _dbgc_imageBuffer = buffer.splice(0);
_dbgc_imageBuffer = new Uint8ClampedArray(buffer);
// console.log(buffer, "<--buf")
}
var _dbgc_trace = function(className, arrayIndex){
_dbgc_imageBuffer[arrayIndex ] = _dbgc_traceColors[className][0];
_dbgc_imageBuffer[arrayIndex+1] = _dbgc_traceColors[className][1];
_dbgc_imageBuffer[arrayIndex+2] = _dbgc_traceColors[className][2];
}
// because (context.putImageData) doesnt work
function putImageData(ctx, imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) {
var data = imageData.data;
var height = imageData.height;
var width = imageData.width;
dirtyX = dirtyX || 0;
dirtyY = dirtyY || 0;
dirtyWidth = dirtyWidth !== undefined? dirtyWidth: width;
dirtyHeight = dirtyHeight !== undefined? dirtyHeight: height;
var limitBottom = Math.min(dirtyHeight, height);
var limitRight = Math.min(dirtyWidth, width);
for (var y = dirtyY; y < limitBottom; y++) {
for (var x = dirtyX; x < limitRight; x++) {
var pos = y * width + x;
ctx.fillStyle = 'rgba(' + data[pos*4+0]
+ ',' + data[pos*4+1]
+ ',' + data[pos*4+2]
+ ',' + (data[pos*4+3]/255) + ')';
ctx.fillRect(x + dx, y + dy, 1, 1);
}
}
}
var _dbgc_showTraces = function(){
if(_dbgc_context && _dbgc_imageBuffer instanceof Uint8ClampedArray){
var idata = new ImageData(_dbgc_imageBuffer, _dbgc_canvas.width, _dbgc_canvas.height);
putImageData(_dbgc_context, idata, 0, 0);
}
}
var DebugCanvas = {
events: {
},
init: _dbgc_init,
start: _dbgc_start,
draw: _dbgc_draw,
remove: _dbgc_remove,
removeClass: _dbgc_removeClass
// start: _dbgc_start,
// draw: _dbgc_draw,
// remove: _dbgc_remove,
// removeClass: _dbgc_removeClass,
setBuffer: _dbgc_setBuffer,
trace: _dbgc_trace,
showTraces: _dbgc_showTraces
}

View File

@ -48,11 +48,16 @@ var _res_char = function(newAr, video, player){
// Približevanje opuščeno.
// handles "legacy" options, such as 'fit to widht', 'fit to height' and 'reset'. No zoom tho
var _res_legacyAr = function(action){
if (!vid) {
return;
}
var vid = GlobalVars.video;
var ar;
if (!vid) {
if(Debug.debug){
console.log("[Resizer.js::_res_legacyAr] No video??",vid)
}
return;
}
if(! GlobalVars.playerDimensions ){
ar = screen.width / screen.height;
@ -76,6 +81,10 @@ var _res_legacyAr = function(action){
_res_setAr( ar < fileAr ? ar : fileAr);
}
else if(action == "reset"){
if(Debug.debug){
console.log("[Resizer.js::_res_legacyAr] Resetting aspect ratio to", fileAr)
}
_res_setAr(fileAr);
GlobalVars.lastAr = {type: "original"};
return;