Aard should be nominally complete. Probably.
This commit is contained in:
parent
7c5e4101b0
commit
bf182c65ad
@ -8,7 +8,7 @@ import { GlCanvas } from './gl/GlCanvas';
|
||||
import { AardCanvasStore } from './interfaces/aard-canvas-store.interface';
|
||||
import { AardDetectionSample, generateSampleArray } from './interfaces/aard-detection-sample.interface';
|
||||
import { AardStatus, initAardStatus } from './interfaces/aard-status.interface';
|
||||
import { AardTestResults, initAardTestResults } from './interfaces/aard-test-results.interface';
|
||||
import { AardTestResults, initAardTestResults, resetAardTestResults } from './interfaces/aard-test-results.interface';
|
||||
import { AardTimers, initAardTimers } from './interfaces/aard-timers.interface';
|
||||
|
||||
|
||||
@ -214,7 +214,7 @@ class Aard {
|
||||
|
||||
//#region configuration parameters
|
||||
private logger: Logger;
|
||||
private conf: VideoData;
|
||||
private videoData: VideoData;
|
||||
private settings: Settings;
|
||||
private eventBus: EventBus;
|
||||
private arid: string;
|
||||
@ -256,7 +256,7 @@ class Aard {
|
||||
//#region lifecycle
|
||||
constructor(videoData: VideoData){
|
||||
this.logger = videoData.logger;
|
||||
this.conf = videoData;
|
||||
this.videoData = videoData;
|
||||
this.video = videoData.video;
|
||||
this.settings = videoData.settings;
|
||||
this.eventBus = videoData.eventBus;
|
||||
@ -284,6 +284,10 @@ class Aard {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes Aard with default values and starts autodetection loop.
|
||||
* This method should only ever be called from constructor.
|
||||
*/
|
||||
private init() {
|
||||
this.canvasStore = {
|
||||
main: new GlCanvas(new GlCanvas(this.settings.active.arDetect.canvasDimensions.sampleCanvas)),
|
||||
@ -300,16 +304,17 @@ class Aard {
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
this.start();
|
||||
}
|
||||
|
||||
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* Starts autodetection loop.
|
||||
*/
|
||||
start() {
|
||||
if (this.conf.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
|
||||
if (this.videoData.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
|
||||
// ensure first autodetection will run in any case
|
||||
this.conf.resizer.lastAr = {type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr};
|
||||
this.videoData.resizer.lastAr = {type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr};
|
||||
}
|
||||
|
||||
if (this.animationFrame) {
|
||||
@ -318,15 +323,63 @@ class Aard {
|
||||
|
||||
this.status.aardActive = true;
|
||||
this.animationFrame = window.requestAnimationFrame( (ts: DOMHighResTimeStamp) => this.onAnimationFrame(ts));
|
||||
// this.logger.log('info', 'debug', `"%c[ArDetect::startLoop] <@${this.arid}> AARD loop started.`, _ard_console_start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs autodetection ONCE.
|
||||
* If autodetection loop is running, this will also stop autodetection loop.
|
||||
*/
|
||||
step() {
|
||||
this.stop();
|
||||
this.main();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops autodetection.
|
||||
*/
|
||||
stop() {
|
||||
if (this.animationFrame) {
|
||||
window.cancelAnimationFrame(this.animationFrame);
|
||||
}
|
||||
}
|
||||
|
||||
//#region animationFrame, scheduling, and other shit
|
||||
/**
|
||||
* Checks whether conditions for granting a frame check are fulfilled
|
||||
* @returns
|
||||
*/
|
||||
private canTriggerFrameCheck() {
|
||||
// if (this._paused || this._halted || this._exited) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if video was paused & we know that we already checked that frame,
|
||||
// we will not check it again.
|
||||
const videoState = this.getVideoPlaybackState();
|
||||
|
||||
if (videoState !== VideoPlaybackState.Playing) {
|
||||
if (this.status.lastVideoStatus === videoState) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.status.lastVideoStatus = videoState;
|
||||
|
||||
if (Date.now() < this.timers.nextFrameCheckTime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.timers.nextFrameCheckTime = Date.now() + this.settings.active.arDetect.timers.playing;
|
||||
return true;
|
||||
}
|
||||
|
||||
private onAnimationFrame(ts: DOMHighResTimeStamp) {
|
||||
if (this.canTriggerFrameCheck()) {
|
||||
resetAardTestResults(this.testResults);
|
||||
this.main();
|
||||
}
|
||||
this.animationFrame = window.requestAnimationFrame( (ts: DOMHighResTimeStamp) => this.onAnimationFrame(ts));
|
||||
}
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* Main loop for scanning aspect ratio changes
|
||||
@ -390,42 +443,33 @@ class Aard {
|
||||
|
||||
} while (false);
|
||||
|
||||
// TODO: subtitle check goes here.
|
||||
// Note that subtitle check should reset aspect ratio outright, regardless of what other tests revealed.
|
||||
// Also note that subtitle check should run on newest aspect ratio data, rather than lag one frame behind
|
||||
// But implementation details are something for future Tam to figure out
|
||||
|
||||
// if detection is uncertain, we don't do anything at all
|
||||
if (this.testResults.aspectRatioUncertain) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: emit debug values if debugging is enabled
|
||||
this.testResults.isFinished = true;
|
||||
|
||||
// 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
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[Ultrawidify] Aspect ratio autodetection crashed for some reason.\n\nsome reason:', e);
|
||||
this.videoData.resizer.setAr({type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether conditions for granting a frame check are fulfilled
|
||||
* @returns
|
||||
*/
|
||||
private canTriggerFrameCheck() {
|
||||
// if (this._paused || this._halted || this._exited) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if video was paused & we know that we already checked that frame,
|
||||
// we will not check it again.
|
||||
const videoState = this.getVideoPlaybackState();
|
||||
|
||||
if (videoState !== VideoPlaybackState.Playing) {
|
||||
if (this.status.lastVideoStatus === videoState) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.status.lastVideoStatus = videoState;
|
||||
|
||||
if (Date.now() < this.timers.nextFrameCheckTime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.timers.nextFrameCheckTime = Date.now() + this.settings.active.arDetect.timers.playing;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private getVideoPlaybackState(): VideoPlaybackState {
|
||||
try {
|
||||
if (this.video.ended) {
|
||||
@ -1568,7 +1612,22 @@ class Aard {
|
||||
this.testResults.aspectRatioUncertain = false;
|
||||
this.testResults.letterboxWidth = candidateAvg;
|
||||
this.testResults.letterboxOffset = diff;
|
||||
this.testResults.aspectRatioUpdated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates video's current aspect ratio based on data in testResults.
|
||||
* @returns
|
||||
*/
|
||||
private getAr() {
|
||||
const fileAr = this.video.videoWidth / this.video.videoHeight;
|
||||
const canvasAr = this.canvasStore.main.width / this.canvasStore.main.height;
|
||||
|
||||
const compensatedWidth = fileAr === canvasAr ? this.canvasStore.main.width : this.canvasStore.main.width * fileAr;
|
||||
|
||||
return compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2));
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ export interface AardTestResults {
|
||||
bottomCandidateQuality: number,
|
||||
},
|
||||
aspectRatioUncertain: boolean,
|
||||
aspectRatioUpdated: boolean,
|
||||
letterboxWidth: number,
|
||||
letterboxOffset: number,
|
||||
logoDetected: [boolean, boolean, boolean, boolean]
|
||||
@ -61,10 +62,11 @@ export function initAardTestResults(settings: AardSettings): AardTestResults {
|
||||
bottomCandidate: 0,
|
||||
bottomCandidateQuality: 0,
|
||||
},
|
||||
aspectRatioUncertain: false,
|
||||
aspectRatioUpdated: false,
|
||||
letterboxWidth: 0,
|
||||
letterboxOffset: 0,
|
||||
logoDetected: [false, false, false, false]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,4 +79,7 @@ export function resetAardTestResults(results: AardTestResults): void {
|
||||
results.guardLine.cornerViolations[1] = false;
|
||||
results.guardLine.cornerViolations[2] = false;
|
||||
results.guardLine.cornerViolations[3] = false;
|
||||
results.letterboxWidth = 0;
|
||||
results.letterboxOffset = 0;
|
||||
results.aspectRatioUpdated = false;
|
||||
}
|
||||
|
@ -709,39 +709,12 @@ class VideoData {
|
||||
//#endregion
|
||||
|
||||
//#region shit that gets propagated to resizer and should be removed. Implement an event bus instead
|
||||
|
||||
panHandler(event, forcePan?: boolean) {
|
||||
if (this.invalid) {
|
||||
return;
|
||||
}
|
||||
if(this.destroyed) {
|
||||
// throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
|
||||
return;
|
||||
}
|
||||
if(!this.resizer) {
|
||||
this.destroy();
|
||||
return;
|
||||
}
|
||||
this.resizer.panHandler(event, forcePan);
|
||||
}
|
||||
|
||||
setPanMode(mode) {
|
||||
if (this.invalid) {
|
||||
return;
|
||||
}
|
||||
this.resizer.setPanMode(mode);
|
||||
}
|
||||
|
||||
restoreAr(){
|
||||
if (this.invalid) {
|
||||
return;
|
||||
}
|
||||
this.resizer.restore();
|
||||
}
|
||||
|
||||
isPlaying() {
|
||||
return this.video && this.video.currentTime > 0 && !this.video.paused && !this.video.ended;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
checkVideoSizeChange(){
|
||||
|
Loading…
Reference in New Issue
Block a user