diff --git a/src/common/interfaces/SettingsInterface.ts b/src/common/interfaces/SettingsInterface.ts index 34f5c19..28be02a 100644 --- a/src/common/interfaces/SettingsInterface.ts +++ b/src/common/interfaces/SettingsInterface.ts @@ -122,7 +122,7 @@ export interface AardSettings { minQualitySecondEdge: number, // The other edge must reach this quality (must be smaller or equal to single edge quality) } - maxLetterboxOffset: 0.1, // Upper and lower letterbox can be different by this many (% of height) + maxLetterboxOffset: number, // Upper and lower letterbox can be different by this many (% of height) // Previous iteration variables VVVV sampleWidth: number, // we take a sample this wide for edge detection @@ -132,13 +132,14 @@ export interface AardSettings { // to confirm an edge in case there's no edges on top or bottom (other // than logo, of course) logoThreshold: number, // if edge candidate sits with count greater than this*all_samples, it can't be logo - // or watermark. + // or watermark. edgeTolerancePx?: number, // we check for black edge violation this far from detection point edgeTolerancePercent?: number, // we check for black edge detection this % of height from detection point. unused middleIgnoredArea: number, // we ignore this % of canvas height towards edges while detecting aspect ratios minColsForSearch: number, // if we hit the edge of blackbars for all but this many columns (%-wise), we don't - // continue with search. It's pointless, because black edge is higher/lower than we - // are now. (NOTE: keep this less than 1 in case we implement logo detection) + // continue with search. It's pointless, because black edge is higher/lower than we + // are now. (NOTE: keep this less than 1 in case we implement logo detection) + edgeMismatchTolerancePx: number,// corners and center are considered equal if they differ by at most this many px }, pillarTest: { ignoreThinPillarsPx: number, // ignore pillars that are less than this many pixels thick. diff --git a/src/csui/PlayerOverlay.vue b/src/csui/PlayerOverlay.vue index b747818..d64f541 100644 --- a/src/csui/PlayerOverlay.vue +++ b/src/csui/PlayerOverlay.vue @@ -413,7 +413,7 @@ export default { this.sendToParentLowLevel('uwui-get-role', null); this.sendToParentLowLevel('uwui-get-theme', null); - console.log('player overlay created — get player dims:') + // console.log('player overlay created — get player dims:') this.sendToParentLowLevel('uw-bus-tunnel', { action: 'get-player-dimensions' }); diff --git a/src/ext/conf/ExtensionConf.ts b/src/ext/conf/ExtensionConf.ts index ddda4e9..a0f92b4 100644 --- a/src/ext/conf/ExtensionConf.ts +++ b/src/ext/conf/ExtensionConf.ts @@ -26,7 +26,7 @@ const ExtensionConf: SettingsInterface = { 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%) + allowedArVariance: 0.0125,// amount by which old ar can differ from the new (1 = 100%) timers: { // autodetection frequency playing: 333, // while playing playingReduced: 5000, // while playing at small sizes @@ -75,7 +75,7 @@ const ExtensionConf: SettingsInterface = { gradientTestMinDelta: 8, thresholds: { - edgeDetectionLimit: 8, + edgeDetectionLimit: 12, minQualitySingleEdge: 6, minQualitySecondEdge: 3, }, @@ -96,6 +96,8 @@ const ExtensionConf: SettingsInterface = { minColsForSearch: 0.5, // if we hit the edge of blackbars for all but this many columns (%-wise), we don't // continue with search. It's pointless, because black edge is higher/lower than we // are now. (NOTE: keep this less than 1 in case we implement logo detection) + + edgeMismatchTolerancePx: 3, // corners and center are considered equal if they differ by at most this many px }, pillarTest: { ignoreThinPillarsPx: 5, // ignore pillars that are less than this many pixels thick. diff --git a/src/ext/lib/aard/Aard.ts b/src/ext/lib/aard/Aard.ts index 92988e2..934ae8a 100644 --- a/src/ext/lib/aard/Aard.ts +++ b/src/ext/lib/aard/Aard.ts @@ -477,6 +477,8 @@ export class Aard { if (this.testResults.notLetterbox) { // TODO: reset aspect ratio to "AR not applied" this.testResults.lastStage = 1; + this.testResults.letterboxWidth = 0; + this.testResults.letterboxOffset = 0; break; } @@ -512,6 +514,10 @@ export class Aard { // TODO: ensure no aspect ratio changes happen this.testResults.lastStage = 2; break; + } else { + // our current letterbox width is now no longer accurate. Time to wipe. + this.testResults.letterboxWidth = 0; + this.testResults.letterboxOffset = 0; } // STEP 3: @@ -540,7 +546,7 @@ export class Aard { } // if detection is uncertain, we don't do anything at all (unless if guardline was broken, in which case we reset) - if (this.testResults.aspectRatioUncertain) { + if (this.testResults.aspectRatioUncertain && this.testResults.guardLine.invalidated) { console.info('aspect ratio not certain:', this.testResults.aspectRatioUncertainReason); console.warn('check finished:', JSON.parse(JSON.stringify(this.testResults)), JSON.parse(JSON.stringify(this.canvasSamples)), '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'); @@ -560,13 +566,11 @@ export class Aard { '\n\n', JSON.parse(JSON.stringify(this.testResults)), JSON.parse(JSON.stringify(this.canvasSamples)), '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'); // if edge width changed, emit update event. - if (this.testResults.aspectRatioUpdated) { - this.videoData.resizer.updateAr({ - type: AspectRatioType.AutomaticUpdate, - ratio: this.getAr(), - offset: this.testResults.letterboxOffset - }); - } + // except aspectRatioUpdated doesn't get set reliably, so we just call update every time, and update + // if detected aspect ratio is different from the current aspect ratio + // if (this.testResults.aspectRatioUpdated) { + this.updateAspectRatio(); + // } // if we got "no letterbox" OR aspectRatioUpdated } catch (e) { @@ -844,8 +848,6 @@ export class Aard { const maxViolations = segmentPixels * 0.20; // TODO: move the 0.2 threshold into settings - console.log('Corner violations counts — segment px & max violations,', segmentPixels, maxViolations ) - // we won't do a loop for this few elements // corners with stuff in them will also be skipped in image test this.testResults.guardLine.cornerViolated[0] = this.testResults.guardLine.cornerPixelsViolated[0] > maxViolations; @@ -853,8 +855,9 @@ export class Aard { this.testResults.guardLine.cornerViolated[2] = this.testResults.guardLine.cornerPixelsViolated[2] > maxViolations; this.testResults.guardLine.cornerViolated[3] = this.testResults.guardLine.cornerPixelsViolated[3] > maxViolations; - const maxInvalidCorners = 1; // TODO: move this into settings — by default, we allow one corner to extend past the + const maxInvalidCorners = 0; // TODO: move this into settings — by default, we allow one corner to extend past the // guard line in order to prevent watermarks/logos from preventing cropping the video + // .... _except_ this doesn't really work because https://youtu.be/-YJwPXipJbo?t=459 // this works because +true converts to 1 and +false converts to 0 const dirtyCount = +this.testResults.guardLine.cornerViolated[0] @@ -1114,12 +1117,7 @@ export class Aard { // fact that it makes the 'if' statement governing gradient detection // bit more nicely visible (instead of hidden among spagheti) this.edgeScan(imageData, width, height); - - console.log('edge scan:', JSON.parse(JSON.stringify(this.canvasSamples))); - this.validateEdgeScan(imageData, width, height); - console.log('edge scan post valid:', JSON.parse(JSON.stringify(this.canvasSamples))); - // TODO: _if gradient detection is enabled, then: this.sampleForGradient(imageData, width, height); @@ -1151,18 +1149,20 @@ export class Aard { * about where to find our letterbox. This test is all the data we need to check * if valid guardLine has ever been set, since guardLine and imageLine are set * in tandem (either both exist, or neither does (-1)). + * + * But maybe we _can't really_, because https://youtu.be/-YJwPXipJbo?t=460 is having problems detecting change */ - if (this.testResults.guardLine.top > 0) { - // if guardLine is invalidated, then the new edge of image frame must be - // above former guardline. Otherwise, it's below it. - if (this.testResults.guardLine.invalidated) { - topEnd = this.testResults.guardLine.top; - bottomEnd = this.testResults.guardLine.bottom; - } else { - topStart = this.testResults.imageLine.top; - bottomStart = this.testResults.imageLine.bottom; - } - } + // if (this.testResults.guardLine.top > 0) { + // // if guardLine is invalidated, then the new edge of image frame must be + // // above former guardline. Otherwise, it's below it. + // if (this.testResults.guardLine.invalidated) { + // topEnd = this.testResults.guardLine.top; + // bottomEnd = this.testResults.guardLine.bottom; + // } else { + // topStart = this.testResults.imageLine.top; + // bottomStart = this.testResults.imageLine.bottom; + // } + // } let row: number, i: number, x: number, isImage: boolean, finishedRows: number; @@ -1385,7 +1385,6 @@ export class Aard { // didn't change meaningfully from the first, in which chance we aren't. If the brightness increased // anywhere between 'not enough' and 'too much', we mark the measurement as invalid. if (lastSubpixel - firstSubpixel > this.settings.active.arDetect.edgeDetection.gradientTestMinDelta) { - console.log('sample invalidated cus gradient:'); this.canvasSamples.top[i] = -1; } } @@ -1471,6 +1470,8 @@ export class Aard { // remember: array has two places per sample position — hence x2 on the results const leftEdgeBoundary = ~~(fullFence * edgePosition) * 2; const rightEdgeBoundary = (this.settings.active.arDetect.sampling.staticCols - leftEdgeBoundary) * 2; + const edgeTolerance = this.settings.active.arDetect.edgeDetection.edgeMismatchTolerancePx; + let i: number; // Process top edge: @@ -1486,7 +1487,7 @@ export class Aard { while (i < leftEdgeBoundary) { if (this.canvasSamples.top[i] > -1) { - if (this.canvasSamples.top[i] <= this.testResults.aspectRatioCheck.topRows[0]) { + if (this.canvasSamples.top[i] < this.testResults.aspectRatioCheck.topRows[0]) { this.testResults.aspectRatioCheck.topRows[0] = this.canvasSamples.top[i]; this.testResults.aspectRatioCheck.topQuality[0] = 0; } else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[0]) { @@ -1498,7 +1499,7 @@ export class Aard { while (i < rightEdgeBoundary) { if (this.canvasSamples.top[i] > -1) { - if (this.canvasSamples.top[i] <= this.testResults.aspectRatioCheck.topRows[1]) { + if (this.canvasSamples.top[i] < this.testResults.aspectRatioCheck.topRows[1]) { this.testResults.aspectRatioCheck.topRows[1] = this.canvasSamples.top[i]; this.testResults.aspectRatioCheck.topQuality[1] = 0; } else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[1]) { @@ -1510,7 +1511,7 @@ export class Aard { while (i < this.canvasSamples.top.length) { if (this.canvasSamples.top[i] > -1) { - if (this.canvasSamples.top[i] <= this.testResults.aspectRatioCheck.topRows[2]) { + if (this.canvasSamples.top[i] < this.testResults.aspectRatioCheck.topRows[2]) { this.testResults.aspectRatioCheck.topRows[2] = this.canvasSamples.top[i]; this.testResults.aspectRatioCheck.topQuality[2] = 0; } else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[2]) { @@ -1519,6 +1520,17 @@ export class Aard { } i += 2; } + + // remove any stray infinities + if (this.testResults.aspectRatioCheck.topRows[0] === Infinity) { + this.testResults.aspectRatioCheck.topRows[0] = 0; + } + if (this.testResults.aspectRatioCheck.topRows[1] === Infinity) { + this.testResults.aspectRatioCheck.topRows[1] = 0; + } + if (this.testResults.aspectRatioCheck.topRows[2] === Infinity) { + this.testResults.aspectRatioCheck.topRows[2] = 0; + } } // Process bottom edge @@ -1534,7 +1546,7 @@ export class Aard { while (i < leftEdgeBoundary) { if (this.canvasSamples.bottom[i] > -1) { - if (this.canvasSamples.bottom[i] <= this.testResults.aspectRatioCheck.bottomRows[0]) { + if (this.canvasSamples.bottom[i] < this.testResults.aspectRatioCheck.bottomRows[0]) { this.testResults.aspectRatioCheck.bottomRows[0] = this.canvasSamples.bottom[i]; this.testResults.aspectRatioCheck.bottomQuality[0] = 0; } else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[0]) { @@ -1546,7 +1558,7 @@ export class Aard { while (i < rightEdgeBoundary) { if (this.canvasSamples.bottom[i] > -1) { - if (this.canvasSamples.bottom[i] <= this.testResults.aspectRatioCheck.bottomRows[1]) { + if (this.canvasSamples.bottom[i] < this.testResults.aspectRatioCheck.bottomRows[1]) { this.testResults.aspectRatioCheck.bottomRows[1] = this.canvasSamples.bottom[i]; this.testResults.aspectRatioCheck.bottomQuality[1] = 0; } else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[1]) { @@ -1558,7 +1570,7 @@ export class Aard { while (i < this.canvasSamples.bottom.length) { if (this.canvasSamples.bottom[i] > -1) { - if (this.canvasSamples.bottom[i] <= this.testResults.aspectRatioCheck.bottomRows[2]) { + if (this.canvasSamples.bottom[i] < this.testResults.aspectRatioCheck.bottomRows[2]) { this.testResults.aspectRatioCheck.bottomRows[2] = this.canvasSamples.bottom[i]; this.testResults.aspectRatioCheck.bottomQuality[2] = 0; } else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[2]) { @@ -1607,60 +1619,63 @@ export class Aard { */ // TOP: - if ( - this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[1] - && this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[2] + + // DifferenceMatrix: + // 0 - center <> left + // 1 - center <> right + // 2 - left <> right + this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[0] = Math.abs(this.testResults.aspectRatioCheck.topRows[1] - this.testResults.aspectRatioCheck.topRows[0]); + this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[1] = Math.abs(this.testResults.aspectRatioCheck.topRows[1] - this.testResults.aspectRatioCheck.topRows[2]); + this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[2] = Math.abs(this.testResults.aspectRatioCheck.topRows[0] - this.testResults.aspectRatioCheck.topRows[2]); + this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[0] = Math.abs(this.testResults.aspectRatioCheck.bottomRows[0] - this.testResults.aspectRatioCheck.bottomRows[1]); + this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[1] = Math.abs(this.testResults.aspectRatioCheck.bottomRows[1] - this.testResults.aspectRatioCheck.bottomRows[2]); + this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[2] = Math.abs(this.testResults.aspectRatioCheck.bottomRows[0] - this.testResults.aspectRatioCheck.bottomRows[2]); + + // We need to write if-statements in order of importance. + if ( // BEST: center matches both corners + this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[0] <= edgeTolerance + && this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[1] <= edgeTolerance ) { - // All three detections are the same this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[0]; this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[0] + this.testResults.aspectRatioCheck.topQuality[1] + this.testResults.aspectRatioCheck.topQuality[2]; - } else if (this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[2]) { - // Corners are the same, but different from center - if (this.testResults.aspectRatioCheck.topRows[0] > this.testResults.aspectRatioCheck.topRows[1]) { - // Corners are above center. + } else if ( // Second best: center matches one of the corners + this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[0] <= edgeTolerance + || this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[1] <= edgeTolerance + ) { + this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[1]; + this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[1]; + + if (this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[1]) { + this.testResults.aspectRatioCheck.topCandidateQuality += this.testResults.aspectRatioCheck.topQuality[0]; + } else { + this.testResults.aspectRatioCheck.topCandidateQuality += this.testResults.aspectRatioCheck.topQuality[2]; + } + } else if (this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[2] <= edgeTolerance) { // Third best: corners match, but are different from center + if (this.testResults.aspectRatioCheck.topRows[0] < this.testResults.aspectRatioCheck.topRows[1]) { + // Corners are above center -> corner authority this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[0]; this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[0] + this.testResults.aspectRatioCheck.topQuality[2] } else { - // Corners are below center + // Corners are below center - center authority this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[1]; this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[1] } - } else { - // Corners are different. - if ( - this.testResults.aspectRatioCheck.topRows[0] !== this.testResults.aspectRatioCheck.topRows[1] - && this.testResults.aspectRatioCheck.topRows[2] !== this.testResults.aspectRatioCheck.topRows[1] - ) { - // Center and matches neither of the corners. - // TODO: maybe we can figure out to guess aspect ratio in scenarios like this. - // But for the time being, just slap it with "inconclusive". - this.testResults.aspectRatioUncertain = true; - this.testResults.aspectRatioUncertainReason = 'TOP_ROW_MISMATCH'; - return; - } else { - // center matches one of the corners - this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[1]; - this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[1]; - - if (this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[1]) { - this.testResults.aspectRatioCheck.topCandidateQuality += this.testResults.aspectRatioCheck.topRows[0]; - } else { - this.testResults.aspectRatioCheck.topCandidateQuality += this.testResults.aspectRatioCheck.topRows[2]; - } - } + } else { // Worst: no matches, kinda like my tinder + this.testResults.topRowUncertain = true; + // we can second-wind this, so no returns yet. } // BOTTOM // Note that bottomRows candidates are measured from the top // Well have to invert our candidate after we're done - if ( - this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[1] - && this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[2] + if ( // BEST: center matches both corners + this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[0] <= edgeTolerance + && this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[1] <= edgeTolerance ) { // All three detections are the same this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0]; @@ -1668,47 +1683,77 @@ export class Aard { this.testResults.aspectRatioCheck.bottomQuality[0] + this.testResults.aspectRatioCheck.bottomQuality[1] + this.testResults.aspectRatioCheck.bottomQuality[2]; - } else if (this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[2]) { - // Corners are the same, but different from center + } else if ( // Second best: center matches one of the corners + this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[0] <= edgeTolerance + || this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[1] <= edgeTolerance + ) { + this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[1]; + this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[1]; + + if (this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[1]) { + this.testResults.aspectRatioCheck.bottomCandidateQuality += this.testResults.aspectRatioCheck.bottomQuality[0]; + } else { + this.testResults.aspectRatioCheck.bottomCandidateQuality += this.testResults.aspectRatioCheck.bottomQuality[2]; + } + } else if (this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[2] <= edgeTolerance) { // Third best: corners match, but are different from center if (this.testResults.aspectRatioCheck.bottomRows[0] > this.testResults.aspectRatioCheck.bottomRows[1]) { - // Corners are above center. + // Corners closer to the edges than center. Note that bigger number = closer to edge this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0]; this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[0] + this.testResults.aspectRatioCheck.bottomQuality[2] } else { - // Corners are below center + // Center is closer to the edge than corners this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[1]; this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[1] } - } else { - // Corners are different. - if ( - this.testResults.aspectRatioCheck.bottomRows[0] !== this.testResults.aspectRatioCheck.bottomRows[1] - && this.testResults.aspectRatioCheck.bottomRows[2] !== this.testResults.aspectRatioCheck.bottomRows[1] - ) { - // Center and matches neither of the corners. - // TODO: maybe we can figure out to guess aspect ratio in scenarios like this. - // But for the time being, just slap it with "inconclusive". - this.testResults.aspectRatioUncertain = true; - this.testResults.aspectRatioUncertainReason += 'BOTTOM_ROW_MISMATCH'; - return; - } else { - // center matches one of the corners - this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[1]; - this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[1]; + } else { // Worst: nothing matches + // We'll try to figure out aspect ratio later in second wind + this.testResults.bottomRowUncertain = true; - if (this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[1]) { - this.testResults.aspectRatioCheck.bottomCandidateQuality += this.testResults.aspectRatioCheck.bottomRows[0]; - } else { - this.testResults.aspectRatioCheck.bottomCandidateQuality += this.testResults.aspectRatioCheck.bottomRows[2]; - } - } + // console.log('BOTTOM ROW MISMATCH:', this.testResults.aspectRatioCheck.bottomRows[0], this.testResults.aspectRatioCheck.bottomRows[1], this.testResults.aspectRatioCheck.bottomRows[2]); + // return; + } + + if (this.testResults.topRowUncertain && this.testResults.bottomRowUncertain) { + this.testResults.aspectRatioUncertain = true; + this.testResults.aspectRatioUncertainReason = 'TOP_AND_BOTTOM_ROW_MISMATCH'; } // Convert bottom candidate to letterbox width this.testResults.aspectRatioCheck.bottomCandidateDistance = this.testResults.aspectRatioCheck.bottomCandidate === Infinity ? -1 : height - this.testResults.aspectRatioCheck.bottomCandidate; + const maxOffset = ~~(height * this.settings.active.arDetect.edgeDetection.maxLetterboxOffset) + + // attempt second-wind: + // if any of the top candidates matches the best bottom candidate sufficiently, + // we'll just promote it to the candidate status + if (this.testResults.topRowUncertain) { + if (this.testResults.aspectRatioCheck.bottomCandidateDistance - this.testResults.aspectRatioCheck.topRows[0] < edgeTolerance + maxOffset) { + this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[0]; + this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[0] + this.testResults.aspectRatioCheck.bottomCandidateQuality; + } else if (this.testResults.aspectRatioCheck.bottomCandidateDistance - this.testResults.aspectRatioCheck.topRows[1] < edgeTolerance + maxOffset) { + this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[1]; + this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[1] + this.testResults.aspectRatioCheck.bottomCandidateQuality; + } else if (this.testResults.aspectRatioCheck.bottomCandidateDistance - this.testResults.aspectRatioCheck.topRows[2] < edgeTolerance + maxOffset) { + this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[2]; + this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[2] + this.testResults.aspectRatioCheck.bottomCandidateQuality; + } + } else if (this.testResults.bottomRowUncertain) { + const bottomEdgeEquivalent = height - this.testResults.aspectRatioCheck.topCandidate; + + if (bottomEdgeEquivalent - this.testResults.aspectRatioCheck.bottomRows[0] < edgeTolerance + maxOffset) { + this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0]; + this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[0] + this.testResults.aspectRatioCheck.topCandidateQuality; + } else if (bottomEdgeEquivalent - this.testResults.aspectRatioCheck.bottomRows[1] < edgeTolerance + maxOffset) { + this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[1]; + this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[1] + this.testResults.aspectRatioCheck.topCandidateQuality; + } else if (bottomEdgeEquivalent - this.testResults.aspectRatioCheck.bottomRows[2] < edgeTolerance + maxOffset) { + this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[2]; + this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[2] + this.testResults.aspectRatioCheck.topCandidateQuality; + } + } + /** * Get final results. * Let candidateA hold better-quality candidate, and let the candidateB hold the lower-quality candidate. @@ -1732,7 +1777,6 @@ export class Aard { return; } - const maxOffset = ~~(height * this.settings.active.arDetect.edgeDetection.maxLetterboxOffset) const diff = this.testResults.aspectRatioCheck.topCandidate - this.testResults.aspectRatioCheck.bottomCandidateDistance; const candidateAvg = ~~((this.testResults.aspectRatioCheck.topCandidate + this.testResults.aspectRatioCheck.bottomCandidateDistance) / 2); @@ -1747,12 +1791,33 @@ export class Aard { this.testResults.guardLine.top = Math.max(this.testResults.imageLine.top - 2, 0); this.testResults.guardLine.bottom = Math.min(this.testResults.imageLine.bottom + 2, this.canvasStore.main.height - 1); } + this.testResults.aspectRatioUncertain = false; this.testResults.letterboxWidth = candidateAvg; this.testResults.letterboxOffset = diff; this.testResults.aspectRatioUpdated = true; } + /** + * Updates aspect ratio if new aspect ratio is different enough from the old one + */ + private updateAspectRatio() { + const ar = this.getAr(); + + // Calculate difference between two ratios + const maxRatio = Math.max(ar, this.testResults.activeAspectRatio); + const diff = Math.abs(ar - this.testResults.activeAspectRatio); + + if ((diff / maxRatio) > this.settings.active.arDetect.allowedArVariance) { + this.videoData.resizer.updateAr({ + type: AspectRatioType.AutomaticUpdate, + ratio: this.getAr(), + offset: this.testResults.letterboxOffset + }); + this.testResults.activeAspectRatio = ar; + } + } + /** * Calculates video's current aspect ratio based on data in testResults. * @returns diff --git a/src/ext/lib/aard/interfaces/aard-test-results.interface.ts b/src/ext/lib/aard/interfaces/aard-test-results.interface.ts index 4c33831..4464dba 100644 --- a/src/ext/lib/aard/interfaces/aard-test-results.interface.ts +++ b/src/ext/lib/aard/interfaces/aard-test-results.interface.ts @@ -28,9 +28,14 @@ export interface AardTestResults { bottomCandidate: number, bottomCandidateDistance: number, bottomCandidateQuality: number, + topRowsDifferenceMatrix: [number, number, number], + bottomRowsDifferenceMatrix: [number, number, number], }, aspectRatioUncertain: boolean, + topRowUncertain: boolean, + bottomRowUncertain: boolean, aspectRatioUpdated: boolean, + activeAspectRatio: number, // is cumulative letterboxWidth: number, letterboxOffset: number, logoDetected: [boolean, boolean, boolean, boolean] @@ -66,9 +71,14 @@ export function initAardTestResults(settings: AardSettings): AardTestResults { bottomCandidate: 0, bottomCandidateDistance: 0, bottomCandidateQuality: 0, + topRowsDifferenceMatrix: [0, 0, 0], + bottomRowsDifferenceMatrix: [0, 0, 0], }, aspectRatioUncertain: false, + topRowUncertain: false, + bottomRowUncertain: false, aspectRatioUpdated: false, + activeAspectRatio: 0, letterboxWidth: 0, letterboxOffset: 0, logoDetected: [false, false, false, false] @@ -89,8 +99,10 @@ export function resetAardTestResults(results: AardTestResults): void { results.guardLine.cornerPixelsViolated[1] = 0; results.guardLine.cornerPixelsViolated[2] = 0; results.guardLine.cornerPixelsViolated[3] = 0; - results.letterboxWidth = 0; - results.letterboxOffset = 0; + // results.letterboxWidth = 0; + // results.letterboxOffset = 0; results.aspectRatioUpdated = false; results.aspectRatioUncertainReason = null; + results.topRowUncertain = false; + results.bottomRowUncertain = false; } diff --git a/src/ext/lib/comms/CommsClient.ts b/src/ext/lib/comms/CommsClient.ts index 42a8cfc..141127f 100644 --- a/src/ext/lib/comms/CommsClient.ts +++ b/src/ext/lib/comms/CommsClient.ts @@ -137,7 +137,7 @@ class CommsClient { try { return this.port.postMessage(message); } catch (e) { - console.log('chrome is shit, lets try to bruteforce ...', e); + // console.log('chrome is shit, lets try to bruteforce ...', e); const port = chrome.runtime.connect(null, {name: this.name}); port.onMessage.addListener(this._listener); return port.postMessage(message); @@ -152,7 +152,7 @@ class CommsClient { * @param receivedMessage */ private processReceivedMessage(receivedMessage){ - console.log('message popped out of the comms', receivedMessage, 'event bus:', this.eventBus); + // console.log('message popped out of the comms', receivedMessage, 'event bus:', this.eventBus); // when sending between frames, message will be enriched with two new properties const {_sourceFrame, _sourcePort, ...message} = receivedMessage; diff --git a/src/ext/lib/uwui/UI.js b/src/ext/lib/uwui/UI.js index 4c6f31b..8f94718 100644 --- a/src/ext/lib/uwui/UI.js +++ b/src/ext/lib/uwui/UI.js @@ -160,7 +160,6 @@ class UI { { 'uw-config-broadcast': { function: (config, routingData) => { - console.log('sending config broadcast from eventBus subscription:', this.eventBus) this.sendToIframe('uw-config-broadcast', config, routingData); } }, @@ -279,7 +278,6 @@ class UI { this.eventBus.send(busCommand.action, busCommand.config, busCommand.routingData); break; case 'uwui-get-role': - console.log('handle get role!'); this.sendToIframeLowLevel('uwui-set-role', {role: this.isGlobal ? 'global' : 'player'}); break; case 'uwui-interface-ready': @@ -306,7 +304,6 @@ class UI { // because existence of UI is not guaranteed — UI is not shown when extension is inactive. // If extension is inactive due to "player element isn't big enough to justify it", however, // we can still receive eventBus messages. - console.log('sending to iframe - low level.') if (this.element && this.uiIframe) { this.uiIframe.contentWindow?.postMessage( { @@ -336,7 +333,6 @@ class UI { // } // routingData.crossedConnections.push(EventBusConnector.IframeBoundaryIn); - console.warn('send to iframe — uw bus tunnel. Action:', action, actionConfig) this.sendToIframeLowLevel( 'uw-bus-tunnel', { diff --git a/src/ext/lib/video-data/PlayerData.ts b/src/ext/lib/video-data/PlayerData.ts index 2bb218d..cad4552 100644 --- a/src/ext/lib/video-data/PlayerData.ts +++ b/src/ext/lib/video-data/PlayerData.ts @@ -102,7 +102,6 @@ class PlayerData { }], 'get-player-dimensions': [{ function: () => { - console.log('got get-player-dimensions'); this.eventBus.send('—————————————————————————— uw-config-broadcast', { type: 'player-dimensions', data: this.dimensions @@ -378,7 +377,6 @@ class PlayerData { * @param currentPlayerDimensions */ private handleSizeConstraints(currentPlayerDimensions: PlayerDimensions) { - console.log('handling resize constraints'); // Check if extension is allowed to run in current combination of theater + full screen const canEnable = this.siteSettings.isEnabledForEnvironment(this.isFullscreen, this.isTheaterMode) === ExtensionMode.Enabled; @@ -553,20 +551,15 @@ class PlayerData { } // if mode is given, we follow the preference - console.log('we prefer manual mode:', this.siteSettings, this.siteSettings.data.currentDOMConfig?.elements?.player); if (this.siteSettings.data.currentDOMConfig?.elements?.player?.manual && this.siteSettings.data.currentDOMConfig?.elements?.player?.mode) { - console.log('we prefer manual mode:', this.siteSettings.data.currentDOMConfig?.elements?.player?.mode); if (this.siteSettings.data.currentDOMConfig?.elements?.player?.mode === 'qs') { playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight); - console.log('got qs player candidate'); } else { playerCandidate = elementStack[playerIndex]; playerCandidate.heuristics['manualElementByParentIndex'] = true; - console.log('got index player candidate') } } else { - console.log('no preference.') // try to figure it out based on what we have, with playerQs taking priority if (playerQs) { playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight); @@ -740,7 +733,6 @@ class PlayerData { * Lists elements between video and DOM root for display in player selector (UI) */ private handlePlayerTreeRequest() { - console.log('aya') // this populates this.elementStack fully this.getPlayer({verbose: true}); console.log('tree:', JSON.parse(JSON.stringify(this.elementStack))); diff --git a/src/ext/lib/video-data/VideoData.ts b/src/ext/lib/video-data/VideoData.ts index f768c38..a0daf00 100644 --- a/src/ext/lib/video-data/VideoData.ts +++ b/src/ext/lib/video-data/VideoData.ts @@ -242,10 +242,8 @@ class VideoData { } this.resizer = new Resizer(this); - console.log('before init aard'); try { this.aard = new Aard(this); // this starts Ar detection. needs optional parameter that prevents ArDetector from starting - console.log('after init aard'); } catch (e) { console.error('Failed to start Aard!', e); } diff --git a/src/ext/lib/video-transform/Stretcher.ts b/src/ext/lib/video-transform/Stretcher.ts index b8af79b..f79a1da 100644 --- a/src/ext/lib/video-transform/Stretcher.ts +++ b/src/ext/lib/video-transform/Stretcher.ts @@ -297,8 +297,6 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video); playerAr ).xFactor; - // console.info('Stretch factors before:', stretchFactors.xFactor, stretchFactors.yFactor, "max safe:", maxSafeStretchFactor, "max safe ar:", maxSafeAr); - stretchFactors.xFactor = Math.min(stretchFactors.xFactor, maxSafeStretchFactor); stretchFactors.yFactor = Math.min(stretchFactors.yFactor, maxSafeStretchFactor);