Compare commits
No commits in common. "276a51b8c3baac5ed94f34aa1a4a6ee52c2c55a8" and "cd89cca984aebb81416db29ec1ce7d2ac613187c" have entirely different histories.
276a51b8c3
...
cd89cca984
@ -54,20 +54,12 @@ export type SettingsReloadFlags = true | SettingsReloadComponent;
|
|||||||
export interface AardSettings {
|
export interface AardSettings {
|
||||||
aardType: 'webgl' | 'legacy' | 'auto';
|
aardType: 'webgl' | 'legacy' | 'auto';
|
||||||
|
|
||||||
earlyStopOptions: {
|
|
||||||
stopAfterFirstDetection: boolean;
|
|
||||||
stopAfterTimeout: boolean;
|
|
||||||
stopTimeout: number;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
disabledReason: string, // if automatic aspect ratio has been disabled, show reason
|
disabledReason: string, // if automatic aspect ratio has been disabled, show reason
|
||||||
allowedMisaligned: number, // top and bottom letterbox thickness can differ by this much.
|
allowedMisaligned: number, // top and bottom letterbox thickness can differ by this much.
|
||||||
// Any more and we don't adjust ar.
|
// Any more and we don't adjust ar.
|
||||||
allowedArVariance: number, // amount by which old ar can differ from the new (1 = 100%)
|
allowedArVariance: number, // amount by which old ar can differ from the new (1 = 100%)
|
||||||
timers: { // autodetection frequency
|
timers: { // autodetection frequency
|
||||||
playing: number, // while playing
|
playing: number, // while playing
|
||||||
playingReduced: number, // while video/player element has insufficient size
|
|
||||||
paused: number, // while paused
|
paused: number, // while paused
|
||||||
error: number, // after error
|
error: number, // after error
|
||||||
minimumTimeout: number,
|
minimumTimeout: number,
|
||||||
@ -94,6 +86,51 @@ export interface AardSettings {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// NOTE: Black Frame is currently not in use.
|
||||||
|
blackframe: {
|
||||||
|
sufficientColorVariance: number, // calculate difference between average intensity and pixel, for every pixel for every color
|
||||||
|
// component. Average intensity is normalized to where 0 is black and 1 is biggest value for
|
||||||
|
// that component. If sum of differences between normalized average intensity and normalized
|
||||||
|
// component varies more than this % between color components, we can afford to use less strict
|
||||||
|
// cumulative threshold.
|
||||||
|
cumulativeThresholdLax: number,
|
||||||
|
cumulativeThresholdStrict: number,// if we add values of all pixels together and get more than this, the frame is bright enough.
|
||||||
|
// (note: blackframe is 16x9 px -> 144px total. cumulative threshold can be reached fast)
|
||||||
|
blackPixelsCondition: number, // How much pixels must be black (1 all, 0 none) before we consider frame as black. Takes
|
||||||
|
// precedence over cumulative threshold: if blackPixelsCondition is met, the frame is dark
|
||||||
|
// regardless of whether cumulative threshold has been reached.
|
||||||
|
},
|
||||||
|
|
||||||
|
// Used by old aspect ratio detection algorithm. Pls remove.
|
||||||
|
blackbar: {
|
||||||
|
blackLevel: number, // everything darker than 10/255 across all RGB components is considered black by
|
||||||
|
// default. blackLevel can decrease if we detect darker black.
|
||||||
|
threshold: number, // if pixel is darker than the sum of black level and this value, 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
|
||||||
|
frameThreshold: number, // threshold, but when doing blackframe test
|
||||||
|
imageThreshold: number, // in order to detect pixel as "not black", the pixel must be brighter than
|
||||||
|
// the sum of black level, threshold and this value.
|
||||||
|
gradientThreshold: number, // When trying to determine thickness of the black bars, we take 2 values: position of
|
||||||
|
// the last pixel that's darker than our threshold, and position of the first pixel that's
|
||||||
|
// brighter than our image threshold. If positions are more than this many pixels apart,
|
||||||
|
// we assume we aren't looking at letterbox and thus don't correct the aspect ratio.
|
||||||
|
gradientSampleSize: number, // How far do we look to find the gradient
|
||||||
|
maxGradient: number, // if two neighboring pixels in gradientSampleSize differ by more than this, then we aren't
|
||||||
|
// looking at a gradient
|
||||||
|
gradientNegativeTreshold: number,
|
||||||
|
gradientMaxSD: number, // reserved for future use
|
||||||
|
antiGradientMode: AntiGradientMode
|
||||||
|
},
|
||||||
|
// Also not in use, probs.
|
||||||
|
variableBlackbarThresholdOptions: { // In case of poor bitrate videos, jpeg artifacts may cause us issues
|
||||||
|
// FOR FUTURE USE
|
||||||
|
enabled: boolean, // allow increasing blackbar threshold
|
||||||
|
disableArDetectOnMax: boolean, // disable autodetection when threshold goes over max blackbar threshold
|
||||||
|
maxBlackbarThreshold: number, // max threshold (don't increase past this)
|
||||||
|
thresholdStep: number, // when failing to set aspect ratio, increase threshold by this much
|
||||||
|
increaseAfterConsecutiveResets: number // increase if AR resets this many times in a row
|
||||||
|
},
|
||||||
blackLevels: {
|
blackLevels: {
|
||||||
defaultBlack: number, // By default, pixels darker than this are considered black.
|
defaultBlack: number, // By default, pixels darker than this are considered black.
|
||||||
// (If detection algorithm detects darker blacks, black is considered darkest detected pixel)
|
// (If detection algorithm detects darker blacks, black is considered darkest detected pixel)
|
||||||
@ -107,6 +144,20 @@ export interface AardSettings {
|
|||||||
randomCols: number, // we add this many randomly selected columns to the static columns
|
randomCols: number, // we add this many randomly selected columns to the static columns
|
||||||
staticRows: number, // forms grid with staticSampleCols. Determined in the same way. For black frame checks,
|
staticRows: number, // forms grid with staticSampleCols. Determined in the same way. For black frame checks,
|
||||||
},
|
},
|
||||||
|
guardLine: { // all pixels on the guardline need to be black, or else we trigger AR recalculation
|
||||||
|
// (if AR fails to be recalculated, we reset AR)
|
||||||
|
enabled: boolean,
|
||||||
|
ignoreEdgeMargin: number, // we ignore anything that pokes over the black line this close to the edge
|
||||||
|
// (relative to width of the sample)
|
||||||
|
imageTestThreshold: number, // when testing for image, this much pixels must be over blackbarThreshold
|
||||||
|
edgeTolerancePx: number, // 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
|
||||||
|
},
|
||||||
|
arSwitchLimiter: { // to be implemented
|
||||||
|
switches: number, // we can switch this many times
|
||||||
|
period: number // per this period
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// pls deprecate and move things used
|
// pls deprecate and move things used
|
||||||
edgeDetection: {
|
edgeDetection: {
|
||||||
@ -122,7 +173,7 @@ export interface AardSettings {
|
|||||||
minQualitySecondEdge: number, // The other edge must reach this quality (must be smaller or equal to single edge quality)
|
minQualitySecondEdge: number, // The other edge must reach this quality (must be smaller or equal to single edge quality)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxLetterboxOffset: number, // Upper and lower letterbox can be different by this many (% of height)
|
maxLetterboxOffset: 0.1, // Upper and lower letterbox can be different by this many (% of height)
|
||||||
|
|
||||||
// Previous iteration variables VVVV
|
// Previous iteration variables VVVV
|
||||||
sampleWidth: number, // we take a sample this wide for edge detection
|
sampleWidth: number, // we take a sample this wide for edge detection
|
||||||
@ -132,14 +183,13 @@ export interface AardSettings {
|
|||||||
// to confirm an edge in case there's no edges on top or bottom (other
|
// to confirm an edge in case there's no edges on top or bottom (other
|
||||||
// than logo, of course)
|
// than logo, of course)
|
||||||
logoThreshold: number, // if edge candidate sits with count greater than this*all_samples, it can't be logo
|
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
|
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
|
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
|
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
|
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
|
// 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)
|
// 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: {
|
pillarTest: {
|
||||||
ignoreThinPillarsPx: number, // ignore pillars that are less than this many pixels thick.
|
ignoreThinPillarsPx: number, // ignore pillars that are less than this many pixels thick.
|
||||||
|
@ -321,107 +321,95 @@ export default {
|
|||||||
this.handleMessage(event);
|
this.handleMessage(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.eventBus.subscribeMulti(
|
this.eventBus.subscribe('uw-config-broadcast', {function: (data) => {
|
||||||
|
switch (data.type) {
|
||||||
|
case 'drm-status':
|
||||||
|
this.statusFlags.hasDrm = data.hasDrm;
|
||||||
|
break;
|
||||||
|
case 'aard-error':
|
||||||
|
this.statusFlags.aardErrors = data.aardErrors;
|
||||||
|
break;
|
||||||
|
case 'player-dimensions':
|
||||||
|
this.playerDimensionsUpdate(data.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
this.eventBus.subscribe('uw-set-ui-state', { function: (data) => {
|
||||||
|
if (data.globalUiVisible !== undefined) {
|
||||||
|
if (this.isGlobal) {
|
||||||
|
if (data.globalUiVisible) {
|
||||||
|
this.showUwWindow();
|
||||||
|
} else {
|
||||||
|
this.hideUwWindow(true);
|
||||||
|
}
|
||||||
|
// this.showPlayerUIAfterClose = data.showPlayerUIAfterClose;
|
||||||
|
} else {
|
||||||
|
// non global UIs are hidden while global overlay
|
||||||
|
// is visible and vice versa
|
||||||
|
// this.disabled = data.globalUiVisible;
|
||||||
|
this.saveState = {
|
||||||
|
uwWindowVisible: this.uwWindowVisible,
|
||||||
|
uwWindowFadeOutDisabled: this.uwWindowFadeOutDisabled,
|
||||||
|
uwWindowFadeOut: this.uwWindowFadeOut
|
||||||
|
};
|
||||||
|
this.uwWindowFadeOutDisabled = false;
|
||||||
|
this.hideUwWindow(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
this.eventBus.subscribe(
|
||||||
|
'uw-restore-ui-state',
|
||||||
{
|
{
|
||||||
'uw-config-broadcast': {
|
function: (data) => {
|
||||||
function:
|
if (this.saveState) {
|
||||||
(data) => {
|
if (this.saveState.uwWindowVisible) {
|
||||||
switch (data.type) {
|
this.showUwWindow();
|
||||||
case 'drm-status':
|
|
||||||
this.statusFlags.hasDrm = data.hasDrm;
|
|
||||||
break;
|
|
||||||
case 'aard-error':
|
|
||||||
this.statusFlags.aardErrors = data.aardErrors;
|
|
||||||
break;
|
|
||||||
case 'player-dimensions':
|
|
||||||
this.playerDimensionsUpdate(data.data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'uw-set-ui-state': {
|
|
||||||
function: (data) => {
|
|
||||||
if (data.globalUiVisible !== undefined) {
|
|
||||||
if (this.isGlobal) {
|
|
||||||
if (data.globalUiVisible) {
|
|
||||||
this.showUwWindow();
|
|
||||||
} else {
|
|
||||||
this.hideUwWindow(true);
|
|
||||||
}
|
|
||||||
// this.showPlayerUIAfterClose = data.showPlayerUIAfterClose;
|
|
||||||
} else {
|
|
||||||
// non global UIs are hidden while global overlay
|
|
||||||
// is visible and vice versa
|
|
||||||
// this.disabled = data.globalUiVisible;
|
|
||||||
this.saveState = {
|
|
||||||
uwWindowVisible: this.uwWindowVisible,
|
|
||||||
uwWindowFadeOutDisabled: this.uwWindowFadeOutDisabled,
|
|
||||||
uwWindowFadeOut: this.uwWindowFadeOut
|
|
||||||
};
|
|
||||||
this.uwWindowFadeOutDisabled = false;
|
|
||||||
this.hideUwWindow(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.uwWindowFadeOutDisabled = this.saveState.uwWindowFadeOutDisabled;
|
||||||
|
this.uwWindowFadeOut = this.saveState.uwWindowFadeOut;
|
||||||
}
|
}
|
||||||
},
|
this.saveState = {};
|
||||||
'uw-restore-ui-state': {
|
}
|
||||||
function: (data) => {
|
}
|
||||||
if (this.saveState) {
|
);
|
||||||
if (this.saveState.uwWindowVisible) {
|
|
||||||
this.showUwWindow();
|
this.eventBus.subscribe('ui-trigger-zone-update', {
|
||||||
}
|
function: (data) => {
|
||||||
this.uwWindowFadeOutDisabled = this.saveState.uwWindowFadeOutDisabled;
|
this.showTriggerZonePreview = data.previewZoneVisible;
|
||||||
this.uwWindowFadeOut = this.saveState.uwWindowFadeOut;
|
// this.;
|
||||||
}
|
}
|
||||||
this.saveState = {};
|
});
|
||||||
}
|
|
||||||
},
|
this.eventBus.subscribe(
|
||||||
'uw-restore-ui-state': {
|
'start-trigger-zone-edit',
|
||||||
function: (data) => {
|
{
|
||||||
if (this.saveState) {
|
function: () => {
|
||||||
if (this.saveState.uwWindowVisible) {
|
this.triggerZoneEditorVisible = true;
|
||||||
this.showUwWindow();
|
this.uwWindowVisible = false;
|
||||||
}
|
}
|
||||||
this.uwWindowFadeOutDisabled = this.saveState.uwWindowFadeOutDisabled;
|
}
|
||||||
this.uwWindowFadeOut = this.saveState.uwWindowFadeOut;
|
);
|
||||||
}
|
|
||||||
this.saveState = {};
|
this.eventBus.subscribe(
|
||||||
}
|
'finish-trigger-zone-edit',
|
||||||
},
|
{
|
||||||
'ui-trigger-zone-update': {
|
function: () => {
|
||||||
function: (data) => {
|
this.triggerZoneEditorVisible = false;
|
||||||
this.showTriggerZonePreview = data.previewZoneVisible;
|
this.showUwWindow('playerUiSettings');
|
||||||
// this.;
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
'start-trigger-zone-edit': {
|
|
||||||
function: () => {
|
|
||||||
this.triggerZoneEditorVisible = true;
|
|
||||||
this.uwWindowVisible = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'finish-trigger-zone-edit': {
|
|
||||||
function: () => {
|
|
||||||
this.triggerZoneEditorVisible = false;
|
|
||||||
this.showUwWindow('playerUiSettings');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
this
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.sendToParentLowLevel('uwui-get-role', null);
|
this.sendToParentLowLevel('uwui-get-role', null);
|
||||||
this.sendToParentLowLevel('uwui-get-theme', null);
|
this.sendToParentLowLevel('uwui-get-theme', null);
|
||||||
|
|
||||||
// console.log('player overlay created — get player dims:')
|
|
||||||
this.sendToParentLowLevel('uw-bus-tunnel', {
|
this.sendToParentLowLevel('uw-bus-tunnel', {
|
||||||
action: 'get-player-dimensions'
|
action: 'get-player-dimensions'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
|
||||||
this.eventBus.unsubscribeAll(this)
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* Gets URL of the browser settings page (i think?)
|
* Gets URL of the browser settings page (i think?)
|
||||||
|
@ -148,7 +148,6 @@ export default {
|
|||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe(
|
||||||
'set-current-site',
|
'set-current-site',
|
||||||
{
|
{
|
||||||
source: this,
|
|
||||||
function: (config, context) => {
|
function: (config, context) => {
|
||||||
if (this.site) {
|
if (this.site) {
|
||||||
if (!this.site.host) {
|
if (!this.site.host) {
|
||||||
@ -170,7 +169,7 @@ export default {
|
|||||||
this.loadFrames(this.site);
|
this.loadFrames(this.site);
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.comms = new CommsClient('popup-port', this.logger, this.eventBus);
|
this.comms = new CommsClient('popup-port', this.logger, this.eventBus);
|
||||||
|
@ -204,19 +204,13 @@ export default {
|
|||||||
|
|
||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe(
|
||||||
'uw-show-ui',
|
'uw-show-ui',
|
||||||
{
|
() => {
|
||||||
source: this,
|
if (this.inPlayer) {
|
||||||
function: () => {
|
return; // show-ui is only intended for global overlay
|
||||||
if (this.inPlayer) {
|
}
|
||||||
return; // show-ui is only intended for global overlay
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
destroyed() {
|
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* Gets URL of the browser settings page (i think?)
|
* Gets URL of the browser settings page (i think?)
|
||||||
|
@ -3,252 +3,222 @@
|
|||||||
<div class="flex flex-row flex-wrap">
|
<div class="flex flex-row flex-wrap">
|
||||||
|
|
||||||
<!-- AARD performance metrics -->
|
<!-- AARD performance metrics -->
|
||||||
<div>
|
<div class="sub-panel">
|
||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
<h1>Automatic Aspect Ratio Detection</h1>
|
<h1><mdicon name="television-play" :size="32" /> Automatic Aspect Ratio Detection</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="aard-settings-group">
|
<div class="sub-panel-content">
|
||||||
|
<p>
|
||||||
|
<b>Autodetection performance</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Automatic aspect ratio detection is a resource-hungry feature.
|
||||||
|
This page allows you to trade autodetection accuracy and/or frequency for
|
||||||
|
better performance.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note that some browsers <a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/now" target="_blank">limit the accuracy of time measurements</a>, though once the bars go past the blue line those limitations are largely inconsequential.
|
||||||
|
</p>
|
||||||
|
<div class="performance-graph-container">
|
||||||
|
<div class="performance-graph">
|
||||||
|
<div class="time-budget hz144"></div>
|
||||||
|
<div class="time-budget hz120"></div>
|
||||||
|
<div class="time-budget hz60"></div>
|
||||||
|
<div class="time-budget hz30"></div>
|
||||||
|
<div class="time-budget hz24"></div>
|
||||||
|
<div class="time-budget rest"></div>
|
||||||
|
|
||||||
<!-- the last time i tried to comment out this block, it didn't work properly — v-if="false" it is -->
|
<div class="bar-container">
|
||||||
<div v-if="false">
|
<div class="average-case">
|
||||||
<p>
|
<div class="stats">
|
||||||
<b>Autodetection performance</b>
|
<b>Average: </b>
|
||||||
</p>
|
<span class="draw">draw (main) {{(performanceData?.imageDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
<p>
|
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
Automatic aspect ratio detection is a resource-hungry feature.
|
<span class="processing">
|
||||||
This page allows you to trade autodetection accuracy and/or frequency for
|
processing {{
|
||||||
better performance.
|
Math.max(
|
||||||
</p>
|
(performanceData?.total?.averageTime ?? 0)
|
||||||
<p>
|
- (performanceData?.imageDraw?.averageTime ?? 0)
|
||||||
Note that some browsers <a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/now" target="_blank">limit the accuracy of time measurements</a>, though once the bars go past the blue line those limitations are largely inconsequential.
|
- (performanceData?.blackFrame?.averageTime ?? 0),
|
||||||
</p>
|
0
|
||||||
<div class="performance-graph-container">
|
|
||||||
<div class="performance-graph">
|
|
||||||
<div class="time-budget hz144"></div>
|
|
||||||
<div class="time-budget hz120"></div>
|
|
||||||
<div class="time-budget hz60"></div>
|
|
||||||
<div class="time-budget hz30"></div>
|
|
||||||
<div class="time-budget hz24"></div>
|
|
||||||
<div class="time-budget rest"></div>
|
|
||||||
|
|
||||||
<div class="bar-container">
|
|
||||||
<div class="average-case">
|
|
||||||
<div class="stats">
|
|
||||||
<b>Average: </b>
|
|
||||||
<span class="draw">draw (main) {{(performanceData?.imageDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
|
||||||
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
|
||||||
<span class="processing">
|
|
||||||
processing {{
|
|
||||||
Math.max(
|
|
||||||
(performanceData?.total?.averageTime ?? 0)
|
|
||||||
- (performanceData?.imageDraw?.averageTime ?? 0)
|
|
||||||
- (performanceData?.blackFrame?.averageTime ?? 0),
|
|
||||||
0
|
|
||||||
).toFixed(1)
|
|
||||||
}} ms
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="bar">
|
|
||||||
<div
|
|
||||||
class="draw"
|
|
||||||
:style="{'width': (performanceData?.imageDraw?.averageTime ?? 0) + '%'}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="draw-blackframe"
|
|
||||||
:style="{'width': (performanceData?.blackFrame?.averageTime ?? 0) + '%'}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="processing"
|
|
||||||
:style="{
|
|
||||||
'width': Math.max(
|
|
||||||
(performanceData?.total?.averageTime ?? 0)
|
|
||||||
- (performanceData?.imageDraw?.averageTime ?? 0)
|
|
||||||
- (performanceData?.blackFrame?.averageTime ?? 0),
|
|
||||||
0
|
|
||||||
) + '%'
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="worst-case">
|
|
||||||
<div class="stats">
|
|
||||||
<b>Worst: </b>
|
|
||||||
<span class="draw">draw (main) {{(performanceData?.imageDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
|
||||||
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
|
||||||
<span class="processing">
|
|
||||||
processing {{
|
|
||||||
Math.max(
|
|
||||||
(performanceData?.total?.worstTime ?? 0)
|
|
||||||
- (performanceData?.imageDraw?.worstTime ?? 0)
|
|
||||||
- (performanceData?.blackFrame?.worstTime ?? 0),
|
|
||||||
0
|
|
||||||
).toFixed(1)
|
|
||||||
}} ms
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="bar">
|
|
||||||
<div
|
|
||||||
class="draw"
|
|
||||||
:style="{'width': (performanceData?.imageDraw?.worstTime ?? 0) + '%'}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="draw-blackframe"
|
|
||||||
:style="{'width': (performanceData?.blackFrame?.worstTime ?? 0) + '%'}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="processing"
|
|
||||||
:style="{
|
|
||||||
'width': Math.max(
|
|
||||||
(performanceData?.total?.worstTime ?? 0)
|
|
||||||
- (performanceData?.imageDraw?.worstTime ?? 0)
|
|
||||||
- (performanceData?.blackFrame?.worstTime ?? 0),
|
|
||||||
0
|
|
||||||
) + '%'
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="average-case">
|
|
||||||
<div class="stats">
|
|
||||||
<b>AR change (average): </b>
|
|
||||||
<span class="draw">draw (main) {{(performanceData?.imageDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
|
||||||
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
|
||||||
<span class="processing">processing {{
|
|
||||||
(
|
|
||||||
(performanceData?.fastLetterbox?.averageTime ?? 0)
|
|
||||||
+ (performanceData?.edgeDetect?.averageTime ?? 0)
|
|
||||||
).toFixed(1)
|
).toFixed(1)
|
||||||
}} ms</span>
|
}} ms
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="bar">
|
||||||
|
<div
|
||||||
|
class="draw"
|
||||||
|
:style="{'width': (performanceData?.imageDraw?.averageTime ?? 0) + '%'}"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="bar">
|
<div
|
||||||
<div
|
class="draw-blackframe"
|
||||||
class="draw"
|
:style="{'width': (performanceData?.blackFrame?.averageTime ?? 0) + '%'}"
|
||||||
:style="{'width': (performanceData?.imageDraw?.averageTime ?? 0) + '%'}"
|
>
|
||||||
>
|
</div>
|
||||||
</div>
|
<div
|
||||||
<div
|
class="processing"
|
||||||
class="draw-blackframe"
|
:style="{
|
||||||
:style="{'width': (performanceData?.blackFrame?.averageTime ?? 0) + '%'}"
|
'width': Math.max(
|
||||||
>
|
(performanceData?.total?.averageTime ?? 0)
|
||||||
</div>
|
- (performanceData?.imageDraw?.averageTime ?? 0)
|
||||||
<div
|
- (performanceData?.blackFrame?.averageTime ?? 0),
|
||||||
class="processing"
|
0
|
||||||
:style="{
|
) + '%'
|
||||||
'width': (
|
}"
|
||||||
(performanceData?.fastLetterbox?.averageTime ?? 0)
|
>
|
||||||
+ (performanceData?.edgeDetect?.averageTime ?? 0)
|
|
||||||
) + '%'
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="worst-case">
|
</div>
|
||||||
<div class="stats">
|
<div class="worst-case">
|
||||||
<b>AR change (worst): </b>
|
<div class="stats">
|
||||||
<span class="draw">draw (main) {{(performanceData?.imageDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
<b>Worst: </b>
|
||||||
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
<span class="draw">draw (main) {{(performanceData?.imageDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
<span class="processing">processing {{
|
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
(
|
<span class="processing">
|
||||||
(performanceData?.fastLetterbox?.worstTime ?? 0)
|
processing {{
|
||||||
+ (performanceData?.edgeDetect?.worstTime ?? 0)
|
Math.max(
|
||||||
|
(performanceData?.total?.worstTime ?? 0)
|
||||||
|
- (performanceData?.imageDraw?.worstTime ?? 0)
|
||||||
|
- (performanceData?.blackFrame?.worstTime ?? 0),
|
||||||
|
0
|
||||||
).toFixed(1)
|
).toFixed(1)
|
||||||
}} ms</span>
|
}} ms
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="bar">
|
||||||
|
<div
|
||||||
|
class="draw"
|
||||||
|
:style="{'width': (performanceData?.imageDraw?.worstTime ?? 0) + '%'}"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="bar">
|
<div
|
||||||
<div
|
class="draw-blackframe"
|
||||||
class="draw"
|
:style="{'width': (performanceData?.blackFrame?.worstTime ?? 0) + '%'}"
|
||||||
:style="{'width': (performanceData?.imageDraw?.worstTime ?? 0) + '%'}"
|
>
|
||||||
>
|
</div>
|
||||||
</div>
|
<div
|
||||||
<div
|
class="processing"
|
||||||
class="draw-blackframe"
|
:style="{
|
||||||
:style="{'width': (performanceData?.blackFrame?.worstTime ?? 0) + '%'}"
|
'width': Math.max(
|
||||||
>
|
(performanceData?.total?.worstTime ?? 0)
|
||||||
</div>
|
- (performanceData?.imageDraw?.worstTime ?? 0)
|
||||||
<div
|
- (performanceData?.blackFrame?.worstTime ?? 0),
|
||||||
class="processing"
|
0
|
||||||
:style="{
|
) + '%'
|
||||||
'width': (
|
}"
|
||||||
(performanceData?.fastLetterbox?.worstTime ?? 0)
|
>
|
||||||
+ (performanceData?.edgeDetect?.worstTime ?? 0)
|
|
||||||
) + '%'
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="average-case">
|
||||||
|
<div class="stats">
|
||||||
|
<b>AR change (average): </b>
|
||||||
|
<span class="draw">draw (main) {{(performanceData?.imageDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
|
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.averageTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
|
<span class="processing">processing {{
|
||||||
|
(
|
||||||
|
(performanceData?.fastLetterbox?.averageTime ?? 0)
|
||||||
|
+ (performanceData?.edgeDetect?.averageTime ?? 0)
|
||||||
|
).toFixed(1)
|
||||||
|
}} ms</span>
|
||||||
|
</div>
|
||||||
|
<div class="bar">
|
||||||
|
<div
|
||||||
|
class="draw"
|
||||||
|
:style="{'width': (performanceData?.imageDraw?.averageTime ?? 0) + '%'}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="draw-blackframe"
|
||||||
|
:style="{'width': (performanceData?.blackFrame?.averageTime ?? 0) + '%'}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="processing"
|
||||||
|
:style="{
|
||||||
|
'width': (
|
||||||
|
(performanceData?.fastLetterbox?.averageTime ?? 0)
|
||||||
|
+ (performanceData?.edgeDetect?.averageTime ?? 0)
|
||||||
|
) + '%'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="worst-case">
|
||||||
|
<div class="stats">
|
||||||
|
<b>AR change (worst): </b>
|
||||||
|
<span class="draw">draw (main) {{(performanceData?.imageDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
|
<span class="draw-blackframe">blackframe {{(performanceData?.blackFrame?.worstTime ?? 0).toFixed(1)}} ms</span> |
|
||||||
|
<span class="processing">processing {{
|
||||||
|
(
|
||||||
|
(performanceData?.fastLetterbox?.worstTime ?? 0)
|
||||||
|
+ (performanceData?.edgeDetect?.worstTime ?? 0)
|
||||||
|
).toFixed(1)
|
||||||
|
}} ms</span>
|
||||||
|
</div>
|
||||||
|
<div class="bar">
|
||||||
|
<div
|
||||||
|
class="draw"
|
||||||
|
:style="{'width': (performanceData?.imageDraw?.worstTime ?? 0) + '%'}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="draw-blackframe"
|
||||||
|
:style="{'width': (performanceData?.blackFrame?.worstTime ?? 0) + '%'}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="processing"
|
||||||
|
:style="{
|
||||||
|
'width': (
|
||||||
|
(performanceData?.fastLetterbox?.worstTime ?? 0)
|
||||||
|
+ (performanceData?.edgeDetect?.worstTime ?? 0)
|
||||||
|
) + '%'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="settings-segment">
|
<div class="settings-segment">
|
||||||
<!-- <h2>Basic settings</h2> -->
|
<h2>Basic settings</h2>
|
||||||
|
|
||||||
<!-- <div class="field">
|
<div class="option">
|
||||||
<div class="label">
|
<div class="name">
|
||||||
Stop autodetection after first detection:
|
Autodetection frequency
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="description">
|
||||||
<input type="checkbox" v-model="settings.active.arDetect.earlyStopOptions.stopAfterFirstDetection" />
|
Shorter intervals (left side of the slider) are more responsive to changes in aspect ratio detections,
|
||||||
|
but requires more system resources.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="indent">
|
||||||
<div class="field">
|
<div class="flex flex-row row-padding">
|
||||||
<div class="label">
|
<div class="flex flex-input">
|
||||||
Stop detection after a period of time:
|
More often <small>(~60/s)</small>
|
||||||
</div>
|
<input type="range"
|
||||||
<div class="">
|
:value="Math.log(settings.active.arDetect.timers.playing)"
|
||||||
<input type="checkbox" v-model="settings.active.arDetect.earlyStopOptions.stopAfterTimeout" />
|
@change="setArCheckFrequency($event.target.value)"
|
||||||
</div>
|
min="2.3"
|
||||||
</div>
|
max="9.3"
|
||||||
<div class="field">
|
step="any"
|
||||||
<div class="label">
|
/>
|
||||||
Stop detection after:
|
Less often <small>(~1/10s)</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="input">
|
</div>
|
||||||
<input type="input" v-model="settings.active.arDetect.earlyStopOptions.stopTimeout" />
|
|
||||||
<div class="unit">seconds</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="label">Autodetection frequency (time between samples)</div>
|
|
||||||
<div class="range-input">
|
|
||||||
<input
|
|
||||||
type="range"
|
|
||||||
:value="Math.log(settings.active.arDetect.timers.playing)"
|
|
||||||
@change="setArCheckFrequency($event.target.value)"
|
|
||||||
min="2.3"
|
|
||||||
max="9.3"
|
|
||||||
step="0.01"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
v-model="settings.active.arDetect.timers.playing"
|
|
||||||
class="input"
|
|
||||||
type="text"
|
|
||||||
>
|
|
||||||
<div class="unit">ms</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="option">
|
||||||
<div class="label">Frame extraction canvas type:</div>
|
<div class="name">
|
||||||
<div class="select">
|
Autodetection sensitivity
|
||||||
<select v-model="settings.active.arDetect.aardType">
|
</div>
|
||||||
<option value="auto">Automatic</option>
|
<div class="description">
|
||||||
<option value="webgl">WebGL only</option>
|
|
||||||
<option value="fallback">Legacy / fallback</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -257,13 +227,30 @@
|
|||||||
<div class="input">
|
<div class="input">
|
||||||
<input v-model="settings.active.arDetect.allowedMisaligned" />
|
<input v-model="settings.active.arDetect.allowedMisaligned" />
|
||||||
</div>
|
</div>
|
||||||
<div class="hint">
|
<div class="description">
|
||||||
Ultrawidify detects letterbox only if video is vertically centered. Some people are bad at vertically
|
Ultrawidify detects letterbox only if video is vertically centered. Some people are bad at vertically
|
||||||
centering the content, though. This is how off-center the video can be before autodetection will
|
centering the content, though. This is how off-center the video can be before autodetection will
|
||||||
refuse to crop it (% of total height).
|
refuse to crop it.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="option">
|
||||||
|
<div class="name">Video sample size</div>
|
||||||
|
<div class="input">
|
||||||
|
<input v-model="settings.active.arDetect.canvasDimensions.sampleCanvas.width" /> x <input v-model="settings.active.arDetect.canvasDimensions.sampleCanvas.height" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<div class="label">Sample columns:</div>
|
||||||
|
<div class="input"><input v-model="settings.active.arDetect.sampling.staticCols" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="label">Sample rows:</div>
|
||||||
|
<div class="input"><input v-model="settings.active.arDetect.sampling.staticRows" /></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -298,16 +285,7 @@ export default {
|
|||||||
'site'
|
'site'
|
||||||
],
|
],
|
||||||
created() {
|
created() {
|
||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
||||||
'uw-config-broadcast',
|
|
||||||
{
|
|
||||||
source: this,
|
|
||||||
function: (config) => this.handleConfigBroadcast(config)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.eventBus.sendToTunnel('get-aard-timing');
|
this.eventBus.sendToTunnel('get-aard-timing');
|
||||||
@ -328,9 +306,6 @@ export default {
|
|||||||
async openOptionsPage() {
|
async openOptionsPage() {
|
||||||
BrowserDetect.runtime.openOptionsPage();
|
BrowserDetect.runtime.openOptionsPage();
|
||||||
},
|
},
|
||||||
setArCheckFrequency(event) {
|
|
||||||
this.settings.active.arDetect.timers.playing = Math.floor(Math.pow(Math.E, event));
|
|
||||||
},
|
|
||||||
refreshGraph() {
|
refreshGraph() {
|
||||||
this.eventBus.sendToTunnel('get-aard-timing');
|
this.eventBus.sendToTunnel('get-aard-timing');
|
||||||
},
|
},
|
||||||
@ -351,10 +326,6 @@ export default {
|
|||||||
<style lang="scss" scoped module>
|
<style lang="scss" scoped module>
|
||||||
@import '../res-common/variables';
|
@import '../res-common/variables';
|
||||||
|
|
||||||
// .aard-settings-group {
|
|
||||||
// max-width: 69rem;
|
|
||||||
// }
|
|
||||||
|
|
||||||
.performance-graph-container {
|
.performance-graph-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -373,20 +373,11 @@ export default({
|
|||||||
'isPopup'
|
'isPopup'
|
||||||
],
|
],
|
||||||
created() {
|
created() {
|
||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleElementStack(config)});
|
||||||
'uw-config-broadcast',
|
|
||||||
{
|
|
||||||
source: this,
|
|
||||||
function: (config) => this.handleElementStack(config)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getPlayerTree();
|
this.getPlayerTree();
|
||||||
},
|
},
|
||||||
destroyed() {
|
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
},
|
|
||||||
computed: {},
|
computed: {},
|
||||||
methods: {
|
methods: {
|
||||||
getPlayerTree() {
|
getPlayerTree() {
|
||||||
|
@ -241,7 +241,24 @@ export default {
|
|||||||
max-width: 24rem;
|
max-width: 24rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.range-input {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
input {
|
||||||
|
max-width: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=range] {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.trigger-zone-editor {
|
.trigger-zone-editor {
|
||||||
background-color: rgba(0,0,0,0.25);
|
background-color: rgba(0,0,0,0.25);
|
||||||
|
@ -66,6 +66,49 @@
|
|||||||
></StretchOptionsPanel>
|
></StretchOptionsPanel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col">
|
||||||
|
|
||||||
|
<!-- VIDEO ALIGNMENT -->
|
||||||
|
<div class="sub-panel">
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<mdicon name="align-horizontal-center" :size="32" />
|
||||||
|
<h1>Video alignment:</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row justify-center mt-4">
|
||||||
|
<alignment-options-control-component
|
||||||
|
:eventBus="eventBus"
|
||||||
|
>
|
||||||
|
</alignment-options-control-component>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="flex flex-row flex-wrap">
|
||||||
|
<div class="m-t-0-33em display-block">
|
||||||
|
<input id="_input_zoom_site_allow_pan"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
Pan with mouse
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ZOOM OPTIONS -->
|
||||||
|
<!-- <div class="sub-panel">
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<mdicon name="magnify-plus-outline" :size="32" />
|
||||||
|
<h1>Manual zoom:</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ZoomOptionsPanel
|
||||||
|
:settings="settings"
|
||||||
|
:siteSettings="siteSettings"
|
||||||
|
:eventBus="eventBus"
|
||||||
|
:isEditing="editMode"
|
||||||
|
></ZoomOptionsPanel>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -110,20 +153,11 @@ export default {
|
|||||||
'site'
|
'site'
|
||||||
],
|
],
|
||||||
created() {
|
created() {
|
||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
||||||
'uw-config-broadcast',
|
|
||||||
{
|
|
||||||
source: this,
|
|
||||||
function: (config) => this.handleConfigBroadcast(config)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.eventBus.sendToTunnel('get-ar');
|
this.eventBus.sendToTunnel('get-ar');
|
||||||
},
|
},
|
||||||
destroyed() {
|
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
ShortcutButton,
|
ShortcutButton,
|
||||||
EditShortcutButton,
|
EditShortcutButton,
|
||||||
|
@ -303,6 +303,8 @@ export default {
|
|||||||
return value.replaceAll(',', '.').split('.', 2).join('.').replace(/[^0-9.\-]/g, '');
|
return value.replaceAll(',', '.').split('.', 2).join('.').replace(/[^0-9.\-]/g, '');
|
||||||
},
|
},
|
||||||
setValue(key, originalValue, isTextInput) {
|
setValue(key, originalValue, isTextInput) {
|
||||||
|
console.log('trying to set value:', key, value, isTextInput);
|
||||||
|
|
||||||
let value = originalValue;
|
let value = originalValue;
|
||||||
if (isTextInput) {
|
if (isTextInput) {
|
||||||
value = (+this.forceNumber(value) / 100);
|
value = (+this.forceNumber(value) / 100);
|
||||||
@ -310,6 +312,8 @@ export default {
|
|||||||
value = +this.forceNumber(value);
|
value = +this.forceNumber(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('rocessed value:', value);
|
||||||
|
|
||||||
if (isNaN(+value)) {
|
if (isNaN(+value)) {
|
||||||
value = 0.5;
|
value = 0.5;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,28 @@
|
|||||||
<h1>Zoom:</h1>
|
<h1>Zoom:</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ZoomOptionsPanel
|
||||||
|
style="margin-top: -2rem"
|
||||||
|
:settings="settings"
|
||||||
|
:eventBus="eventBus"
|
||||||
|
:siteSettings="siteSettings"
|
||||||
|
:isEditing="false"
|
||||||
|
>
|
||||||
|
</ZoomOptionsPanel>
|
||||||
|
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<mdicon name="crop" :size="24" />
|
||||||
|
<h1>Video alignment:</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<alignment-options-control-component
|
||||||
|
:eventBus="eventBus"
|
||||||
|
>
|
||||||
|
</alignment-options-control-component>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@ -59,20 +81,11 @@ export default {
|
|||||||
CropOptionsPanel, StretchOptionsPanel, ZoomOptionsPanel
|
CropOptionsPanel, StretchOptionsPanel, ZoomOptionsPanel
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
|
||||||
'uw-config-broadcast',
|
|
||||||
{
|
|
||||||
source: this,
|
|
||||||
function: (config) => this.handleConfigBroadcast(config)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.eventBus.sendToTunnel('get-ar');
|
this.eventBus.sendToTunnel('get-ar');
|
||||||
},
|
},
|
||||||
destroyed() {
|
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -73,25 +73,18 @@ button, .button {
|
|||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&.l2 {
|
|
||||||
margin-left: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
flex: 0 0 25%;
|
flex: 0 0 25%;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
.input {
|
||||||
.input, .range-input {
|
|
||||||
flex: 0 0 70%;
|
flex: 0 0 70%;
|
||||||
max-width: 24rem;
|
|
||||||
background-color: rgba($blackBg, $normalTransparentOpacity);
|
background-color: rgba($blackBg, $normalTransparentOpacity);
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.5);
|
border-bottom: 1px solid rgba(255,255,255,0.5);
|
||||||
padding-top: 0.25rem;
|
padding-top: 0.25rem;
|
||||||
padding-bottom: 0.25rem;
|
padding-bottom: 0.25rem;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:active, &:focus, &:focus-within {
|
&:active, &:focus, &:focus-within {
|
||||||
border-bottom: 1px solid rgba($primary, 0.5);
|
border-bottom: 1px solid rgba($primary, 0.5);
|
||||||
@ -104,37 +97,7 @@ button, .button {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unit {
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0.69;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
top: 0;
|
|
||||||
transform: translateY(69%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.range-input {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
* {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
input {
|
|
||||||
max-width: 5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=range] {
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
padding-left: calc(25% + 1rem);
|
padding-left: calc(25% + 1rem);
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
@ -77,7 +77,6 @@ export default class UWContent {
|
|||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe(
|
||||||
'uw-restart',
|
'uw-restart',
|
||||||
{
|
{
|
||||||
source: this,
|
|
||||||
function: () => this.initPhase2()
|
function: () => this.initPhase2()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -122,7 +121,6 @@ export default class UWContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
if (this.pageInfo) {
|
if (this.pageInfo) {
|
||||||
this.pageInfo.destroy();
|
this.pageInfo.destroy();
|
||||||
}
|
}
|
||||||
|
@ -24,27 +24,27 @@ export default class UWServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eventBusCommands = {
|
eventBusCommands = {
|
||||||
'popup-set-selected-tab': {
|
'popup-set-selected-tab': [{
|
||||||
function: (message) => this.setSelectedTab(message.selectedMenu, message.selectedSubitem)
|
function: (message) => this.setSelectedTab(message.selectedMenu, message.selectedSubitem)
|
||||||
},
|
}],
|
||||||
'has-video': {
|
'has-video': [{
|
||||||
function: (message, context) => this.registerVideo(context.comms.sender)
|
function: (message, context) => this.registerVideo(context.comms.sender)
|
||||||
},
|
}],
|
||||||
'noVideo' : {
|
'noVideo' : [{
|
||||||
function: (message, context) => this.unregisterVideo(context.comms.sender)
|
function: (message, context) => this.unregisterVideo(context.comms.sender)
|
||||||
},
|
}],
|
||||||
'inject-css': {
|
'inject-css': [{
|
||||||
function: (message, context) => this.injectCss(message.cssString, context.comms.sender)
|
function: (message, context) => this.injectCss(message.cssString, context.comms.sender)
|
||||||
},
|
}],
|
||||||
'eject-css': {
|
'eject-css': [{
|
||||||
function: (message, context) => this.removeCss(message.cssString, context.comms.sender)
|
function: (message, context) => this.removeCss(message.cssString, context.comms.sender)
|
||||||
},
|
}],
|
||||||
'replace-css': {
|
'replace-css': [{
|
||||||
function: (message, context) => this.replaceCss(message.oldCssString, message.newCssString, context.comms.sender)
|
function: (message, context) => this.replaceCss(message.oldCssString, message.newCssString, context.comms.sender)
|
||||||
},
|
}],
|
||||||
'get-current-site': {
|
'get-current-site': [{
|
||||||
function: (message, context) => this.getCurrentSite()
|
function: (message, context) => this.getCurrentSite()
|
||||||
}
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
private gcTimeout: any;
|
private gcTimeout: any;
|
||||||
@ -84,8 +84,11 @@ export default class UWServer {
|
|||||||
|
|
||||||
this.eventBus = new EventBus({isUWServer: true});
|
this.eventBus = new EventBus({isUWServer: true});
|
||||||
|
|
||||||
this.eventBus.subscribeMulti(this.eventBusCommands, this);
|
for (const action in this.eventBusCommands) {
|
||||||
|
for (const command of this.eventBusCommands[action]) {
|
||||||
|
this.eventBus.subscribe(action, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.comms = new CommsServer(this);
|
this.comms = new CommsServer(this);
|
||||||
this.eventBus.setComms(this.comms);
|
this.eventBus.setComms(this.comms);
|
||||||
|
|
||||||
|
@ -16,20 +16,12 @@ if(Debug.debug)
|
|||||||
const ExtensionConf: SettingsInterface = {
|
const ExtensionConf: SettingsInterface = {
|
||||||
arDetect: {
|
arDetect: {
|
||||||
aardType: 'auto',
|
aardType: 'auto',
|
||||||
|
|
||||||
earlyStopOptions: {
|
|
||||||
stopAfterFirstDetection: false,
|
|
||||||
stopAfterTimeout: false,
|
|
||||||
stopTimeout: 30,
|
|
||||||
},
|
|
||||||
|
|
||||||
disabledReason: "", // if automatic aspect ratio has been disabled, show reason
|
disabledReason: "", // if automatic aspect ratio has been disabled, show reason
|
||||||
allowedMisaligned: 0.05, // top and bottom letterbox thickness can differ by this much.
|
allowedMisaligned: 0.05, // top and bottom letterbox thickness can differ by this much.
|
||||||
// Any more and we don't adjust ar.
|
// Any more and we don't adjust ar.
|
||||||
allowedArVariance: 0.0125,// amount by which old ar can differ from the new (1 = 100%)
|
allowedArVariance: 0.075, // amount by which old ar can differ from the new (1 = 100%)
|
||||||
timers: { // autodetection frequency
|
timers: { // autodetection frequency
|
||||||
playing: 333, // while playing
|
playing: 333, // while playing
|
||||||
playingReduced: 5000, // while playing at small sizes
|
|
||||||
paused: 3000, // while paused
|
paused: 3000, // while paused
|
||||||
error: 3000, // after error
|
error: 3000, // after error
|
||||||
minimumTimeout: 5,
|
minimumTimeout: 5,
|
||||||
@ -56,6 +48,48 @@ const ExtensionConf: SettingsInterface = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// samplingInterval: 10, // we sample at columns at (width/this) * [ 1 .. this - 1]
|
||||||
|
blackframe: {
|
||||||
|
sufficientColorVariance: 0.10, // calculate difference between average intensity and pixel, for every pixel for every color
|
||||||
|
// component. Average intensity is normalized to where 0 is black and 1 is biggest value for
|
||||||
|
// that component. If sum of differences between normalized average intensity and normalized
|
||||||
|
// component varies more than this % between color components, we can afford to use less strict
|
||||||
|
// cumulative threshold.
|
||||||
|
cumulativeThresholdLax: 1600,
|
||||||
|
cumulativeThresholdStrict: 2560,// if we add values of all pixels together and get more than this, the frame is bright enough.
|
||||||
|
// (note: blackframe is 16x9 px -> 144px total. cumulative threshold can be reached fast)
|
||||||
|
blackPixelsCondition: 0.6, // How much pixels must be black (1 all, 0 none) before we consider frame as black. Takes
|
||||||
|
// precedence over cumulative threshold: if blackPixelsCondition is met, the frame is dark
|
||||||
|
// regardless of whether cumulative threshold has been reached.
|
||||||
|
},
|
||||||
|
blackbar: {
|
||||||
|
blackLevel: 10, // everything darker than 10/255 across all RGB components is considered black by
|
||||||
|
// default. blackLevel can decrease if we detect darker black.
|
||||||
|
threshold: 16, // if pixel is darker than the sum of black level and this value, 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
|
||||||
|
frameThreshold: 4, // threshold, but when doing blackframe test
|
||||||
|
imageThreshold: 16, // in order to detect pixel as "not black", the pixel must be brighter than
|
||||||
|
// the sum of black level, threshold and this value.
|
||||||
|
gradientThreshold: 2, // When trying to determine thickness of the black bars, we take 2 values: position of
|
||||||
|
// the last pixel that's darker than our threshold, and position of the first pixel that's
|
||||||
|
// brighter than our image threshold. If positions are more than this many pixels apart,
|
||||||
|
// we assume we aren't looking at letterbox and thus don't correct the aspect ratio.
|
||||||
|
gradientSampleSize: 16, // How far do we look to find the gradient
|
||||||
|
maxGradient: 6, // if two neighboring pixels in gradientSampleSize differ by more than this, then we aren't
|
||||||
|
// looking at a gradient
|
||||||
|
gradientNegativeTreshold: -2,
|
||||||
|
gradientMaxSD: 6, // reserved for future use
|
||||||
|
antiGradientMode: AntiGradientMode.Lax,
|
||||||
|
},
|
||||||
|
variableBlackbarThresholdOptions: { // In case of poor bitrate videos, jpeg artifacts may cause us issues
|
||||||
|
// FOR FUTURE USE
|
||||||
|
enabled: true, // allow increasing blackbar threshold
|
||||||
|
disableArDetectOnMax: true, // disable autodetection when threshold goes over max blackbar threshold
|
||||||
|
maxBlackbarThreshold: 48, // max threshold (don't increase past this)
|
||||||
|
thresholdStep: 8, // when failing to set aspect ratio, increase threshold by this much
|
||||||
|
increaseAfterConsecutiveResets: 2 // increase if AR resets this many times in a row
|
||||||
|
},
|
||||||
blackLevels: {
|
blackLevels: {
|
||||||
defaultBlack: 16,
|
defaultBlack: 16,
|
||||||
blackTolerance: 4,
|
blackTolerance: 4,
|
||||||
@ -67,6 +101,19 @@ const ExtensionConf: SettingsInterface = {
|
|||||||
randomCols: 0, // we add this many randomly selected columns to the static columns
|
randomCols: 0, // we add this many randomly selected columns to the static columns
|
||||||
staticRows: 9, // forms grid with staticSampleCols. Determined in the same way. For black frame checks
|
staticRows: 9, // forms grid with staticSampleCols. Determined in the same way. For black frame checks
|
||||||
},
|
},
|
||||||
|
guardLine: { // all pixels on the guardline need to be black, or else we trigger AR recalculation
|
||||||
|
// (if AR fails to be recalculated, we reset AR)
|
||||||
|
enabled: true,
|
||||||
|
ignoreEdgeMargin: 0.20, // we ignore anything that pokes over the black line this close to the edge
|
||||||
|
// (relative to width of the sample)
|
||||||
|
imageTestThreshold: 0.1, // when testing for image, this much pixels must be over blackbarThreshold
|
||||||
|
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
|
||||||
|
},
|
||||||
|
arSwitchLimiter: { // to be implemented
|
||||||
|
switches: 2, // we can switch this many times
|
||||||
|
period: 2.0 // per this period
|
||||||
|
},
|
||||||
edgeDetection: {
|
edgeDetection: {
|
||||||
slopeTestWidth: 8,
|
slopeTestWidth: 8,
|
||||||
gradientTestSamples: 8,
|
gradientTestSamples: 8,
|
||||||
@ -75,7 +122,7 @@ const ExtensionConf: SettingsInterface = {
|
|||||||
gradientTestMinDelta: 8,
|
gradientTestMinDelta: 8,
|
||||||
|
|
||||||
thresholds: {
|
thresholds: {
|
||||||
edgeDetectionLimit: 12,
|
edgeDetectionLimit: 8,
|
||||||
minQualitySingleEdge: 6,
|
minQualitySingleEdge: 6,
|
||||||
minQualitySecondEdge: 3,
|
minQualitySecondEdge: 3,
|
||||||
},
|
},
|
||||||
@ -96,8 +143,6 @@ const ExtensionConf: SettingsInterface = {
|
|||||||
minColsForSearch: 0.5, // if we hit the edge of blackbars for all but this many columns (%-wise), we don't
|
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
|
// 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)
|
// 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: {
|
pillarTest: {
|
||||||
ignoreThinPillarsPx: 5, // ignore pillars that are less than this many pixels thick.
|
ignoreThinPillarsPx: 5, // ignore pillars that are less than this many pixels thick.
|
||||||
|
@ -4,7 +4,6 @@ import CommsServer from './comms/CommsServer';
|
|||||||
|
|
||||||
export interface EventBusCommand {
|
export interface EventBusCommand {
|
||||||
isGlobal?: boolean,
|
isGlobal?: boolean,
|
||||||
source?: any,
|
|
||||||
function: (commandData: any, context?: any) => void | Promise<void>
|
function: (commandData: any, context?: any) => void | Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +24,8 @@ export interface EventBusContext {
|
|||||||
export default class EventBus {
|
export default class EventBus {
|
||||||
|
|
||||||
private commands: { [x: string]: EventBusCommand[]} = {};
|
private commands: { [x: string]: EventBusCommand[]} = {};
|
||||||
|
private downstreamBuses: EventBus[] = [];
|
||||||
|
private upstreamBus?: EventBus;
|
||||||
private comms?: CommsClient | CommsServer;
|
private comms?: CommsClient | CommsServer;
|
||||||
|
|
||||||
private disableTunnel: boolean = false;
|
private disableTunnel: boolean = false;
|
||||||
@ -45,6 +46,9 @@ export default class EventBus {
|
|||||||
//#region lifecycle
|
//#region lifecycle
|
||||||
destroy() {
|
destroy() {
|
||||||
this.commands = null;
|
this.commands = null;
|
||||||
|
for (const bus of this.downstreamBuses) {
|
||||||
|
bus.destroy();
|
||||||
|
}
|
||||||
this.destroyIframeTunnelling();
|
this.destroyIframeTunnelling();
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
@ -53,6 +57,38 @@ export default class EventBus {
|
|||||||
this.comms = comms;
|
this.comms = comms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#region bus hierarchy management (single page)
|
||||||
|
setUpstreamBus(eventBus: EventBus, stopRecursing: boolean = false) {
|
||||||
|
this.upstreamBus = eventBus;
|
||||||
|
if (!stopRecursing) {
|
||||||
|
this.upstreamBus.addDownstreamBus(this, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsetUpstreamBus(stopRecursing: boolean = false) {
|
||||||
|
if (!stopRecursing) {
|
||||||
|
this.upstreamBus.removeDownstreamBus(this, false);
|
||||||
|
}
|
||||||
|
this.upstreamBus = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
addDownstreamBus(eventBus: EventBus, stopRecursing: boolean = false) {
|
||||||
|
if (!this.downstreamBuses.includes(eventBus)) {
|
||||||
|
this.downstreamBuses.push(eventBus);
|
||||||
|
|
||||||
|
if (!stopRecursing) {
|
||||||
|
eventBus.setUpstreamBus(this, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeDownstreamBus(eventBus: EventBus, stopRecursing: boolean = false) {
|
||||||
|
this.downstreamBuses = this.downstreamBuses.filter(x => x !== eventBus);
|
||||||
|
if (!stopRecursing) {
|
||||||
|
eventBus.unsetUpstreamBus(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subscribe(commandString: string, command: EventBusCommand) {
|
subscribe(commandString: string, command: EventBusCommand) {
|
||||||
if (!this.commands[commandString]) {
|
if (!this.commands[commandString]) {
|
||||||
this.commands[commandString] = [command];
|
this.commands[commandString] = [command];
|
||||||
@ -61,31 +97,8 @@ export default class EventBus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeMulti(commands: {[commandString: string]: EventBusCommand}, source?: any) {
|
|
||||||
for (const key in commands) {
|
|
||||||
this.subscribe(
|
|
||||||
key,
|
|
||||||
{
|
|
||||||
...commands[key],
|
|
||||||
source: source ?? commands[key].source
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all commands from a given source
|
|
||||||
* @param source
|
|
||||||
*/
|
|
||||||
unsubscribeAll(source: any) {
|
|
||||||
for (const commandString in this.commands) {
|
|
||||||
this.commands[commandString] = this.commands[commandString].filter(x => x.source !== source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
send(command: string, commandData: any, context?: EventBusContext) {
|
send(command: string, commandData: any, context?: EventBusContext) {
|
||||||
// execute commands we have subscriptions for
|
// execute commands we have subscriptions for
|
||||||
|
|
||||||
if (this.commands?.[command]) {
|
if (this.commands?.[command]) {
|
||||||
for (const eventBusCommand of this.commands[command]) {
|
for (const eventBusCommand of this.commands[command]) {
|
||||||
eventBusCommand.function(commandData, context);
|
eventBusCommand.function(commandData, context);
|
||||||
@ -101,6 +114,10 @@ export default class EventBus {
|
|||||||
if (context?.stopPropagation) {
|
if (context?.stopPropagation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// propagate commands across the bus
|
||||||
|
this.sendUpstream(command, commandData, context);
|
||||||
|
this.sendDownstream(command, commandData, context);
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
@ -110,7 +127,6 @@ export default class EventBus {
|
|||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
sendToTunnel(command: string, config: any) {
|
sendToTunnel(command: string, config: any) {
|
||||||
console.log('sending to tunnel from eventBus ....', this)
|
|
||||||
if (!this.disableTunnel) {
|
if (!this.disableTunnel) {
|
||||||
window.parent.postMessage(
|
window.parent.postMessage(
|
||||||
{
|
{
|
||||||
@ -129,6 +145,25 @@ export default class EventBus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sendDownstream(command: string, config: any, context?: EventBusContext, sourceEventBus?: EventBus) {
|
||||||
|
for (const eventBus of this.downstreamBuses) {
|
||||||
|
if (eventBus !== sourceEventBus) {
|
||||||
|
// prevent eventBus.send from auto-propagating the command
|
||||||
|
eventBus.send(command, config, {...context, stopPropagation: true});
|
||||||
|
eventBus.sendDownstream(command, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendUpstream(command: string, config: any, context?: EventBusContext) {
|
||||||
|
if (this.upstreamBus) {
|
||||||
|
// prevent eventBus.send from auto-propagating the command
|
||||||
|
this.upstreamBus.send(command, config, {...context, stopPropagation: true});
|
||||||
|
this.upstreamBus.sendUpstream(command, config, context);
|
||||||
|
this.upstreamBus.sendDownstream(command, config, context, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//#region iframe tunnelling
|
//#region iframe tunnelling
|
||||||
private setupIframeTunnelling() {
|
private setupIframeTunnelling() {
|
||||||
// forward messages coming from iframe tunnels
|
// forward messages coming from iframe tunnels
|
||||||
|
@ -10,7 +10,7 @@ import { GlCanvas } from './gl/GlCanvas';
|
|||||||
import { AardCanvasStore } from './interfaces/aard-canvas-store.interface';
|
import { AardCanvasStore } from './interfaces/aard-canvas-store.interface';
|
||||||
import { AardDetectionSample, generateSampleArray, resetSamples } from './interfaces/aard-detection-sample.interface';
|
import { AardDetectionSample, generateSampleArray, resetSamples } from './interfaces/aard-detection-sample.interface';
|
||||||
import { AardStatus, initAardStatus } from './interfaces/aard-status.interface';
|
import { AardStatus, initAardStatus } from './interfaces/aard-status.interface';
|
||||||
import { AardTestResults, initAardTestResults, resetAardTestResults, resetGuardLine } from './interfaces/aard-test-results.interface';
|
import { AardTestResults, initAardTestResults, resetAardTestResults } from './interfaces/aard-test-results.interface';
|
||||||
import { AardTimers, initAardTimers } from './interfaces/aard-timers.interface';
|
import { AardTimers, initAardTimers } from './interfaces/aard-timers.interface';
|
||||||
|
|
||||||
|
|
||||||
@ -222,9 +222,9 @@ export class Aard {
|
|||||||
private arid: string;
|
private arid: string;
|
||||||
|
|
||||||
private eventBusCommands = {
|
private eventBusCommands = {
|
||||||
// 'get-aard-timing': {
|
// 'get-aard-timing': [{
|
||||||
// function: () => this.handlePerformanceDataRequest()
|
// function: () => this.handlePerformanceDataRequest()
|
||||||
// }
|
// }]
|
||||||
};
|
};
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
@ -240,8 +240,6 @@ export class Aard {
|
|||||||
private canvasStore: AardCanvasStore;
|
private canvasStore: AardCanvasStore;
|
||||||
private testResults: AardTestResults;
|
private testResults: AardTestResults;
|
||||||
private canvasSamples: AardDetectionSample;
|
private canvasSamples: AardDetectionSample;
|
||||||
|
|
||||||
private forceFullRecheck: boolean = true;
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region getters
|
//#region getters
|
||||||
@ -269,8 +267,7 @@ export class Aard {
|
|||||||
this.settings = videoData.settings;
|
this.settings = videoData.settings;
|
||||||
this.eventBus = videoData.eventBus;
|
this.eventBus = videoData.eventBus;
|
||||||
|
|
||||||
this.eventBus.subscribeMulti(this.eventBusCommands, this);
|
this.initEventBus();
|
||||||
|
|
||||||
this.arid = (Math.random()*100).toFixed();
|
this.arid = (Math.random()*100).toFixed();
|
||||||
|
|
||||||
// we can tick manually, for debugging
|
// we can tick manually, for debugging
|
||||||
@ -279,12 +276,21 @@ export class Aard {
|
|||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initEventBus() {
|
||||||
|
for (const action in this.eventBusCommands) {
|
||||||
|
for (const command of this.eventBusCommands[action]) {
|
||||||
|
this.eventBus.subscribe(action, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes Aard with default values and starts autodetection loop.
|
* Initializes Aard with default values and starts autodetection loop.
|
||||||
* This method should only ever be called from constructor.
|
* This method should only ever be called from constructor.
|
||||||
*/
|
*/
|
||||||
private init() {
|
private init() {
|
||||||
|
|
||||||
|
|
||||||
this.canvasStore = {
|
this.canvasStore = {
|
||||||
main: this.createCanvas('main-gl')
|
main: this.createCanvas('main-gl')
|
||||||
};
|
};
|
||||||
@ -345,7 +351,6 @@ export class Aard {
|
|||||||
* Starts autodetection loop.
|
* Starts autodetection loop.
|
||||||
*/
|
*/
|
||||||
start() {
|
start() {
|
||||||
this.forceFullRecheck = true;
|
|
||||||
if (this.videoData.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
|
if (this.videoData.resizer.lastAr.type === AspectRatioType.AutomaticUpdate) {
|
||||||
// ensure first autodetection will run in any case
|
// ensure first autodetection will run in any case
|
||||||
this.videoData.resizer.lastAr = {type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr};
|
this.videoData.resizer.lastAr = {type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr};
|
||||||
@ -401,14 +406,11 @@ export class Aard {
|
|||||||
}
|
}
|
||||||
this.status.lastVideoStatus = videoState;
|
this.status.lastVideoStatus = videoState;
|
||||||
|
|
||||||
const now = Date.now();
|
if (Date.now() < this.timers.nextFrameCheckTime) {
|
||||||
|
|
||||||
if (now < (this.videoData.player.isTooSmall ? this.timers.reducedPollingNextCheckTime : this.timers.nextFrameCheckTime)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.timers.nextFrameCheckTime = now + this.settings.active.arDetect.timers.playing;
|
this.timers.nextFrameCheckTime = Date.now() + this.settings.active.arDetect.timers.playing;
|
||||||
this.timers.reducedPollingNextCheckTime = now + this.settings.active.arDetect.timers.playingReduced;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +419,6 @@ export class Aard {
|
|||||||
resetAardTestResults(this.testResults);
|
resetAardTestResults(this.testResults);
|
||||||
resetSamples(this.canvasSamples);
|
resetSamples(this.canvasSamples);
|
||||||
this.main();
|
this.main();
|
||||||
this.forceFullRecheck = false;
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
this.animationFrame = window.requestAnimationFrame( (ts: DOMHighResTimeStamp) => this.onAnimationFrame(ts));
|
this.animationFrame = window.requestAnimationFrame( (ts: DOMHighResTimeStamp) => this.onAnimationFrame(ts));
|
||||||
@ -476,13 +477,8 @@ export class Aard {
|
|||||||
);
|
);
|
||||||
if (this.testResults.notLetterbox) {
|
if (this.testResults.notLetterbox) {
|
||||||
// TODO: reset aspect ratio to "AR not applied"
|
// TODO: reset aspect ratio to "AR not applied"
|
||||||
|
console.log('NOT LETTERBOX!');
|
||||||
this.testResults.lastStage = 1;
|
this.testResults.lastStage = 1;
|
||||||
|
|
||||||
// we have a few things to do
|
|
||||||
// console.log('NOT LETTERBOX - resetting letterbox data')
|
|
||||||
this.testResults.letterboxWidth = 0;
|
|
||||||
this.testResults.letterboxOffset = 0;
|
|
||||||
resetGuardLine(this.testResults);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,36 +486,19 @@ export class Aard {
|
|||||||
// Check if previously detected aspect ratio is still gucci. If it is, then
|
// Check if previously detected aspect ratio is still gucci. If it is, then
|
||||||
// we can quit the loop without applying any aspect ratios (unless subtitle
|
// we can quit the loop without applying any aspect ratios (unless subtitle
|
||||||
// detection is enabled, in which case we still run the subtitle test)
|
// detection is enabled, in which case we still run the subtitle test)
|
||||||
// If we stopped autodetection because of manual aspect ratio input, then
|
this.checkLetterboxShrink(
|
||||||
// checkLetterboxShrink and checkLetterboxGrow may return invalid results.
|
imageData,
|
||||||
// This is why we skip this check and force full recheck if forceFullRecheck
|
this.settings.active.arDetect.canvasDimensions.sampleCanvas.width,
|
||||||
// flag is set.
|
this.settings.active.arDetect.canvasDimensions.sampleCanvas.height
|
||||||
if (this.forceFullRecheck) {
|
);
|
||||||
this.testResults.imageLine.invalidated = true;
|
console.log('LETTERBOX SHRINK CHECK RESULT — IS GUARDLINE INVALIDATED?', this.testResults.guardLine.invalidated)
|
||||||
this.testResults.guardLine.invalidated = true;
|
if (! this.testResults.guardLine.invalidated) {
|
||||||
} else {
|
this.checkLetterboxGrow(
|
||||||
this.checkLetterboxShrink(
|
|
||||||
imageData,
|
imageData,
|
||||||
this.settings.active.arDetect.canvasDimensions.sampleCanvas.width,
|
this.settings.active.arDetect.canvasDimensions.sampleCanvas.width,
|
||||||
this.settings.active.arDetect.canvasDimensions.sampleCanvas.height
|
this.settings.active.arDetect.canvasDimensions.sampleCanvas.height
|
||||||
);
|
);
|
||||||
|
|
||||||
// If guardline was invalidated, letterbox width and offset are unreliable.
|
|
||||||
// If guardLine is fine but imageLine is invalidated, we still keep last letterbox settings
|
|
||||||
if (this.testResults.guardLine.invalidated) {
|
|
||||||
// console.log('GUARD LINE INVALIDATED - resetting letterbox data')
|
|
||||||
|
|
||||||
this.testResults.letterboxWidth = 0;
|
|
||||||
this.testResults.letterboxOffset = 0;
|
|
||||||
} else {
|
|
||||||
this.checkLetterboxGrow(
|
|
||||||
imageData,
|
|
||||||
this.settings.active.arDetect.canvasDimensions.sampleCanvas.width,
|
|
||||||
this.settings.active.arDetect.canvasDimensions.sampleCanvas.height
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both need to be checked
|
// Both need to be checked
|
||||||
if (! (this.testResults.imageLine.invalidated || this.testResults.guardLine.invalidated)) {
|
if (! (this.testResults.imageLine.invalidated || this.testResults.guardLine.invalidated)) {
|
||||||
// TODO: ensure no aspect ratio changes happen
|
// TODO: ensure no aspect ratio changes happen
|
||||||
@ -543,21 +522,10 @@ export class Aard {
|
|||||||
// Also note that subtitle check should run on newest aspect ratio data, rather than lag one frame behind
|
// 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
|
// But implementation details are something for future Tam to figure out
|
||||||
|
|
||||||
// If forceFullRecheck is set, then 'not letterbox' should always force-reset the aspect ratio
|
// if detection is uncertain, we don't do anything at all
|
||||||
// (as aspect ratio may have been set manually while autodetection was off)
|
if (this.testResults.aspectRatioUncertain) {
|
||||||
if (this.testResults.notLetterbox) {
|
console.info('aspect ratio not cettain.');
|
||||||
// console.log('————not letterbox')
|
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');
|
||||||
this.updateAspectRatio(this.defaultAr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 && 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');
|
|
||||||
|
|
||||||
if (this.testResults.guardLine.invalidated) {
|
|
||||||
this.updateAspectRatio(this.defaultAr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -565,27 +533,22 @@ export class Aard {
|
|||||||
// TODO: emit debug values if debugging is enabled
|
// TODO: emit debug values if debugging is enabled
|
||||||
this.testResults.isFinished = true;
|
this.testResults.isFinished = true;
|
||||||
|
|
||||||
// console.warn(
|
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');
|
||||||
// `[${(+new Date() % 10000) / 100} | ${this.arid}]`,'check finished — aspect ratio updated:', this.testResults.aspectRatioUpdated,
|
|
||||||
// '\ndetected ar:', this.testResults.activeAspectRatio, '->', this.getAr(),
|
|
||||||
// '\nis video playing?', this.getVideoPlaybackState() === VideoPlaybackState.Playing,
|
|
||||||
// '\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 edge width changed, emit update event.
|
||||||
// except aspectRatioUpdated doesn't get set reliably, so we just call update every time, and update
|
if (this.testResults.aspectRatioUpdated) {
|
||||||
// if detected aspect ratio is different from the current aspect ratio
|
this.videoData.resizer.updateAr({
|
||||||
// if (this.testResults.aspectRatioUpdated) {
|
type: AspectRatioType.AutomaticUpdate,
|
||||||
this.updateAspectRatio();
|
ratio: this.getAr(),
|
||||||
// }
|
offset: this.testResults.letterboxOffset
|
||||||
|
});
|
||||||
// if we got "no letterbox" OR aspectRatioUpdated
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('[Ultrawidify] Aspect ratio autodetection crashed for some reason.\n\nsome reason:', 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});
|
this.videoData.resizer.setAr({type: AspectRatioType.AutomaticUpdate, ratio: this.defaultAr});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private getVideoPlaybackState(): VideoPlaybackState {
|
private getVideoPlaybackState(): VideoPlaybackState {
|
||||||
try {
|
try {
|
||||||
if (this.video.ended) {
|
if (this.video.ended) {
|
||||||
@ -714,8 +677,6 @@ export class Aard {
|
|||||||
// NOTE: but maybe we could, if blackLevel can only get lower than
|
// NOTE: but maybe we could, if blackLevel can only get lower than
|
||||||
// the default value.
|
// the default value.
|
||||||
if (this.testResults.notLetterbox) {
|
if (this.testResults.notLetterbox) {
|
||||||
this.testResults.aspectRatioUncertain = false;
|
|
||||||
|
|
||||||
if (min < this.testResults.blackLevel) {
|
if (min < this.testResults.blackLevel) {
|
||||||
this.testResults.blackLevel = min;
|
this.testResults.blackLevel = min;
|
||||||
this.testResults.blackThreshold = min + 16;
|
this.testResults.blackThreshold = min + 16;
|
||||||
@ -754,7 +715,6 @@ export class Aard {
|
|||||||
const segmentPixels = width * edgePosition;
|
const segmentPixels = width * edgePosition;
|
||||||
const edgeSegmentSize = segmentPixels * 4;
|
const edgeSegmentSize = segmentPixels * 4;
|
||||||
|
|
||||||
|
|
||||||
// check the top
|
// check the top
|
||||||
{
|
{
|
||||||
// no use in doing guardline tests if guardline hasn't been measured yet, or if
|
// no use in doing guardline tests if guardline hasn't been measured yet, or if
|
||||||
@ -765,7 +725,6 @@ export class Aard {
|
|||||||
const secondSegment = rowEnd - edgeSegmentSize;
|
const secondSegment = rowEnd - edgeSegmentSize;
|
||||||
|
|
||||||
let i = rowStart;
|
let i = rowStart;
|
||||||
|
|
||||||
while (i < firstSegment) {
|
while (i < firstSegment) {
|
||||||
if (
|
if (
|
||||||
imageData[i] > this.testResults.blackThreshold
|
imageData[i] > this.testResults.blackThreshold
|
||||||
@ -856,6 +815,8 @@ export class Aard {
|
|||||||
|
|
||||||
const maxViolations = segmentPixels * 0.20; // TODO: move the 0.2 threshold into settings
|
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
|
// we won't do a loop for this few elements
|
||||||
// corners with stuff in them will also be skipped in image test
|
// corners with stuff in them will also be skipped in image test
|
||||||
this.testResults.guardLine.cornerViolated[0] = this.testResults.guardLine.cornerPixelsViolated[0] > maxViolations;
|
this.testResults.guardLine.cornerViolated[0] = this.testResults.guardLine.cornerPixelsViolated[0] > maxViolations;
|
||||||
@ -863,9 +824,8 @@ export class Aard {
|
|||||||
this.testResults.guardLine.cornerViolated[2] = this.testResults.guardLine.cornerPixelsViolated[2] > maxViolations;
|
this.testResults.guardLine.cornerViolated[2] = this.testResults.guardLine.cornerPixelsViolated[2] > maxViolations;
|
||||||
this.testResults.guardLine.cornerViolated[3] = this.testResults.guardLine.cornerPixelsViolated[3] > maxViolations;
|
this.testResults.guardLine.cornerViolated[3] = this.testResults.guardLine.cornerPixelsViolated[3] > maxViolations;
|
||||||
|
|
||||||
const maxInvalidCorners = 0; // TODO: move this into settings — by default, we allow one corner to extend past the
|
const maxInvalidCorners = 1; // 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
|
// 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
|
// this works because +true converts to 1 and +false converts to 0
|
||||||
const dirtyCount = +this.testResults.guardLine.cornerViolated[0]
|
const dirtyCount = +this.testResults.guardLine.cornerViolated[0]
|
||||||
@ -1125,7 +1085,12 @@ export class Aard {
|
|||||||
// fact that it makes the 'if' statement governing gradient detection
|
// fact that it makes the 'if' statement governing gradient detection
|
||||||
// bit more nicely visible (instead of hidden among spagheti)
|
// bit more nicely visible (instead of hidden among spagheti)
|
||||||
this.edgeScan(imageData, width, height);
|
this.edgeScan(imageData, width, height);
|
||||||
|
|
||||||
|
console.log('edge scan:', JSON.parse(JSON.stringify(this.canvasSamples)));
|
||||||
|
|
||||||
this.validateEdgeScan(imageData, width, height);
|
this.validateEdgeScan(imageData, width, height);
|
||||||
|
console.log('edge scan post valid:', JSON.parse(JSON.stringify(this.canvasSamples)));
|
||||||
|
|
||||||
|
|
||||||
// TODO: _if gradient detection is enabled, then:
|
// TODO: _if gradient detection is enabled, then:
|
||||||
this.sampleForGradient(imageData, width, height);
|
this.sampleForGradient(imageData, width, height);
|
||||||
@ -1157,20 +1122,18 @@ export class Aard {
|
|||||||
* about where to find our letterbox. This test is all the data we need to check
|
* 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
|
* if valid guardLine has ever been set, since guardLine and imageLine are set
|
||||||
* in tandem (either both exist, or neither does (-1)).
|
* 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 (this.testResults.guardLine.top > 0) {
|
||||||
// // if guardLine is invalidated, then the new edge of image frame must be
|
// if guardLine is invalidated, then the new edge of image frame must be
|
||||||
// // above former guardline. Otherwise, it's below it.
|
// above former guardline. Otherwise, it's below it.
|
||||||
// if (this.testResults.guardLine.invalidated) {
|
if (this.testResults.guardLine.invalidated) {
|
||||||
// topEnd = this.testResults.guardLine.top;
|
topEnd = this.testResults.guardLine.top;
|
||||||
// bottomEnd = this.testResults.guardLine.bottom;
|
bottomEnd = this.testResults.guardLine.bottom;
|
||||||
// } else {
|
} else {
|
||||||
// topStart = this.testResults.imageLine.top;
|
topStart = this.testResults.imageLine.top;
|
||||||
// bottomStart = this.testResults.imageLine.bottom;
|
bottomStart = this.testResults.imageLine.bottom;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
let row: number, i: number, x: number, isImage: boolean, finishedRows: number;
|
let row: number, i: number, x: number, isImage: boolean, finishedRows: number;
|
||||||
|
|
||||||
@ -1393,6 +1356,7 @@ export class Aard {
|
|||||||
// didn't change meaningfully from the first, in which chance we aren't. If the brightness increased
|
// 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.
|
// anywhere between 'not enough' and 'too much', we mark the measurement as invalid.
|
||||||
if (lastSubpixel - firstSubpixel > this.settings.active.arDetect.edgeDetection.gradientTestMinDelta) {
|
if (lastSubpixel - firstSubpixel > this.settings.active.arDetect.edgeDetection.gradientTestMinDelta) {
|
||||||
|
console.log('sample invalidated cus gradient:');
|
||||||
this.canvasSamples.top[i] = -1;
|
this.canvasSamples.top[i] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1478,8 +1442,6 @@ export class Aard {
|
|||||||
// remember: array has two places per sample position — hence x2 on the results
|
// remember: array has two places per sample position — hence x2 on the results
|
||||||
const leftEdgeBoundary = ~~(fullFence * edgePosition) * 2;
|
const leftEdgeBoundary = ~~(fullFence * edgePosition) * 2;
|
||||||
const rightEdgeBoundary = (this.settings.active.arDetect.sampling.staticCols - leftEdgeBoundary) * 2;
|
const rightEdgeBoundary = (this.settings.active.arDetect.sampling.staticCols - leftEdgeBoundary) * 2;
|
||||||
const edgeTolerance = this.settings.active.arDetect.edgeDetection.edgeMismatchTolerancePx;
|
|
||||||
|
|
||||||
|
|
||||||
let i: number;
|
let i: number;
|
||||||
// Process top edge:
|
// Process top edge:
|
||||||
@ -1495,7 +1457,7 @@ export class Aard {
|
|||||||
|
|
||||||
while (i < leftEdgeBoundary) {
|
while (i < leftEdgeBoundary) {
|
||||||
if (this.canvasSamples.top[i] > -1) {
|
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.topRows[0] = this.canvasSamples.top[i];
|
||||||
this.testResults.aspectRatioCheck.topQuality[0] = 0;
|
this.testResults.aspectRatioCheck.topQuality[0] = 0;
|
||||||
} else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[0]) {
|
} else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[0]) {
|
||||||
@ -1507,7 +1469,7 @@ export class Aard {
|
|||||||
|
|
||||||
while (i < rightEdgeBoundary) {
|
while (i < rightEdgeBoundary) {
|
||||||
if (this.canvasSamples.top[i] > -1) {
|
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.topRows[1] = this.canvasSamples.top[i];
|
||||||
this.testResults.aspectRatioCheck.topQuality[1] = 0;
|
this.testResults.aspectRatioCheck.topQuality[1] = 0;
|
||||||
} else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[1]) {
|
} else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[1]) {
|
||||||
@ -1519,7 +1481,7 @@ export class Aard {
|
|||||||
|
|
||||||
while (i < this.canvasSamples.top.length) {
|
while (i < this.canvasSamples.top.length) {
|
||||||
if (this.canvasSamples.top[i] > -1) {
|
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.topRows[2] = this.canvasSamples.top[i];
|
||||||
this.testResults.aspectRatioCheck.topQuality[2] = 0;
|
this.testResults.aspectRatioCheck.topQuality[2] = 0;
|
||||||
} else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[2]) {
|
} else if (this.canvasSamples.top[i] === this.testResults.aspectRatioCheck.topRows[2]) {
|
||||||
@ -1528,17 +1490,6 @@ export class Aard {
|
|||||||
}
|
}
|
||||||
i += 2;
|
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
|
// Process bottom edge
|
||||||
@ -1554,7 +1505,7 @@ export class Aard {
|
|||||||
|
|
||||||
while (i < leftEdgeBoundary) {
|
while (i < leftEdgeBoundary) {
|
||||||
if (this.canvasSamples.bottom[i] > -1) {
|
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.bottomRows[0] = this.canvasSamples.bottom[i];
|
||||||
this.testResults.aspectRatioCheck.bottomQuality[0] = 0;
|
this.testResults.aspectRatioCheck.bottomQuality[0] = 0;
|
||||||
} else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[0]) {
|
} else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[0]) {
|
||||||
@ -1566,7 +1517,7 @@ export class Aard {
|
|||||||
|
|
||||||
while (i < rightEdgeBoundary) {
|
while (i < rightEdgeBoundary) {
|
||||||
if (this.canvasSamples.bottom[i] > -1) {
|
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.bottomRows[1] = this.canvasSamples.bottom[i];
|
||||||
this.testResults.aspectRatioCheck.bottomQuality[1] = 0;
|
this.testResults.aspectRatioCheck.bottomQuality[1] = 0;
|
||||||
} else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[1]) {
|
} else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[1]) {
|
||||||
@ -1578,7 +1529,7 @@ export class Aard {
|
|||||||
|
|
||||||
while (i < this.canvasSamples.bottom.length) {
|
while (i < this.canvasSamples.bottom.length) {
|
||||||
if (this.canvasSamples.bottom[i] > -1) {
|
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.bottomRows[2] = this.canvasSamples.bottom[i];
|
||||||
this.testResults.aspectRatioCheck.bottomQuality[2] = 0;
|
this.testResults.aspectRatioCheck.bottomQuality[2] = 0;
|
||||||
} else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[2]) {
|
} else if (this.canvasSamples.bottom[i] === this.testResults.aspectRatioCheck.bottomRows[2]) {
|
||||||
@ -1627,63 +1578,59 @@ export class Aard {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// TOP:
|
// TOP:
|
||||||
|
if (
|
||||||
// DifferenceMatrix:
|
this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[1]
|
||||||
// 0 - center <> left
|
&& this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[2]
|
||||||
// 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.topCandidate = this.testResults.aspectRatioCheck.topRows[0];
|
||||||
this.testResults.aspectRatioCheck.topCandidateQuality =
|
this.testResults.aspectRatioCheck.topCandidateQuality =
|
||||||
this.testResults.aspectRatioCheck.topQuality[0]
|
this.testResults.aspectRatioCheck.topQuality[0]
|
||||||
+ this.testResults.aspectRatioCheck.topQuality[1]
|
+ this.testResults.aspectRatioCheck.topQuality[1]
|
||||||
+ this.testResults.aspectRatioCheck.topQuality[2];
|
+ this.testResults.aspectRatioCheck.topQuality[2];
|
||||||
} else if ( // Second best: center matches one of the corners
|
} else if (this.testResults.aspectRatioCheck.topRows[0] === this.testResults.aspectRatioCheck.topRows[2]) {
|
||||||
this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[0] <= edgeTolerance
|
// Corners are the same, but different from center
|
||||||
|| this.testResults.aspectRatioCheck.topRowsDifferenceMatrix[1] <= edgeTolerance
|
if (this.testResults.aspectRatioCheck.topRows[0] > this.testResults.aspectRatioCheck.topRows[1]) {
|
||||||
) {
|
// Corners are above center.
|
||||||
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.topCandidate = this.testResults.aspectRatioCheck.topRows[0];
|
||||||
this.testResults.aspectRatioCheck.topCandidateQuality =
|
this.testResults.aspectRatioCheck.topCandidateQuality =
|
||||||
this.testResults.aspectRatioCheck.topQuality[0]
|
this.testResults.aspectRatioCheck.topQuality[0]
|
||||||
+ this.testResults.aspectRatioCheck.topQuality[2]
|
+ this.testResults.aspectRatioCheck.topQuality[2]
|
||||||
} else {
|
} else {
|
||||||
// Corners are below center - center authority
|
// Corners are below center
|
||||||
this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[1];
|
this.testResults.aspectRatioCheck.topCandidate = this.testResults.aspectRatioCheck.topRows[1];
|
||||||
this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[1]
|
this.testResults.aspectRatioCheck.topCandidateQuality = this.testResults.aspectRatioCheck.topQuality[1]
|
||||||
}
|
}
|
||||||
} else { // Worst: no matches, kinda like my tinder
|
} else {
|
||||||
this.testResults.topRowUncertain = true;
|
// Corners are different.
|
||||||
// we can second-wind this, so no returns yet.
|
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;
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
// Note that bottomRows candidates are measured from the top
|
// Note that bottomRows candidates are measured from the top
|
||||||
// Well have to invert our candidate after we're done
|
// Well have to invert our candidate after we're done
|
||||||
if ( // BEST: center matches both corners
|
if (
|
||||||
this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[0] <= edgeTolerance
|
this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[1]
|
||||||
&& this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[1] <= edgeTolerance
|
&& this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[2]
|
||||||
) {
|
) {
|
||||||
// All three detections are the same
|
// All three detections are the same
|
||||||
this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0];
|
this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0];
|
||||||
@ -1691,77 +1638,46 @@ export class Aard {
|
|||||||
this.testResults.aspectRatioCheck.bottomQuality[0]
|
this.testResults.aspectRatioCheck.bottomQuality[0]
|
||||||
+ this.testResults.aspectRatioCheck.bottomQuality[1]
|
+ this.testResults.aspectRatioCheck.bottomQuality[1]
|
||||||
+ this.testResults.aspectRatioCheck.bottomQuality[2];
|
+ this.testResults.aspectRatioCheck.bottomQuality[2];
|
||||||
} else if ( // Second best: center matches one of the corners
|
} else if (this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[2]) {
|
||||||
this.testResults.aspectRatioCheck.bottomRowsDifferenceMatrix[0] <= edgeTolerance
|
// Corners are the same, but different from center
|
||||||
|| 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]) {
|
if (this.testResults.aspectRatioCheck.bottomRows[0] > this.testResults.aspectRatioCheck.bottomRows[1]) {
|
||||||
// Corners closer to the edges than center. Note that bigger number = closer to edge
|
// Corners are above center.
|
||||||
this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0];
|
this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[0];
|
||||||
this.testResults.aspectRatioCheck.bottomCandidateQuality =
|
this.testResults.aspectRatioCheck.bottomCandidateQuality =
|
||||||
this.testResults.aspectRatioCheck.bottomQuality[0]
|
this.testResults.aspectRatioCheck.bottomQuality[0]
|
||||||
+ this.testResults.aspectRatioCheck.bottomQuality[2]
|
+ this.testResults.aspectRatioCheck.bottomQuality[2]
|
||||||
} else {
|
} else {
|
||||||
// Center is closer to the edge than corners
|
// Corners are below center
|
||||||
this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[1];
|
this.testResults.aspectRatioCheck.bottomCandidate = this.testResults.aspectRatioCheck.bottomRows[1];
|
||||||
this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[1]
|
this.testResults.aspectRatioCheck.bottomCandidateQuality = this.testResults.aspectRatioCheck.bottomQuality[1]
|
||||||
}
|
}
|
||||||
} else { // Worst: nothing matches
|
} else {
|
||||||
// We'll try to figure out aspect ratio later in second wind
|
// Corners are different.
|
||||||
this.testResults.bottomRowUncertain = true;
|
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;
|
||||||
|
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];
|
||||||
|
|
||||||
// console.log('BOTTOM ROW MISMATCH:', this.testResults.aspectRatioCheck.bottomRows[0], this.testResults.aspectRatioCheck.bottomRows[1], this.testResults.aspectRatioCheck.bottomRows[2]);
|
if (this.testResults.aspectRatioCheck.bottomRows[0] === this.testResults.aspectRatioCheck.bottomRows[1]) {
|
||||||
// return;
|
this.testResults.aspectRatioCheck.bottomCandidateQuality += this.testResults.aspectRatioCheck.bottomRows[0];
|
||||||
}
|
} else {
|
||||||
|
this.testResults.aspectRatioCheck.bottomCandidateQuality += this.testResults.aspectRatioCheck.bottomRows[2];
|
||||||
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
|
// Convert bottom candidate to letterbox width
|
||||||
this.testResults.aspectRatioCheck.bottomCandidateDistance = this.testResults.aspectRatioCheck.bottomCandidate === Infinity ? -1 : height - this.testResults.aspectRatioCheck.bottomCandidate;
|
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.
|
* Get final results.
|
||||||
* Let candidateA hold better-quality candidate, and let the candidateB hold the lower-quality candidate.
|
* Let candidateA hold better-quality candidate, and let the candidateB hold the lower-quality candidate.
|
||||||
@ -1781,16 +1697,15 @@ export class Aard {
|
|||||||
|| candidateB < this.settings.active.arDetect.edgeDetection.thresholds.minQualitySecondEdge
|
|| candidateB < this.settings.active.arDetect.edgeDetection.thresholds.minQualitySecondEdge
|
||||||
) {
|
) {
|
||||||
this.testResults.aspectRatioUncertain = true;
|
this.testResults.aspectRatioUncertain = true;
|
||||||
this.testResults.aspectRatioUncertainReason = 'INSUFFICIENT_EDGE_DETECTION_QUALITY';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxOffset = ~~(height * this.settings.active.arDetect.edgeDetection.maxLetterboxOffset)
|
||||||
const diff = this.testResults.aspectRatioCheck.topCandidate - this.testResults.aspectRatioCheck.bottomCandidateDistance;
|
const diff = this.testResults.aspectRatioCheck.topCandidate - this.testResults.aspectRatioCheck.bottomCandidateDistance;
|
||||||
const candidateAvg = ~~((this.testResults.aspectRatioCheck.topCandidate + this.testResults.aspectRatioCheck.bottomCandidateDistance) / 2);
|
const candidateAvg = ~~((this.testResults.aspectRatioCheck.topCandidate + this.testResults.aspectRatioCheck.bottomCandidateDistance) / 2);
|
||||||
|
|
||||||
if (diff > maxOffset) {
|
if (diff > maxOffset) {
|
||||||
this.testResults.aspectRatioUncertain = true;
|
this.testResults.aspectRatioUncertain = true;
|
||||||
this.testResults.aspectRatioUncertainReason = 'LETTERBOX_NOT_CENTERED_ENOUGH';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (maxOffset > 2) {
|
if (maxOffset > 2) {
|
||||||
@ -1799,35 +1714,12 @@ export class Aard {
|
|||||||
this.testResults.guardLine.top = Math.max(this.testResults.imageLine.top - 2, 0);
|
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.guardLine.bottom = Math.min(this.testResults.imageLine.bottom + 2, this.canvasStore.main.height - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.testResults.aspectRatioUncertain = false;
|
this.testResults.aspectRatioUncertain = false;
|
||||||
console.log('Updating letterboxWidth - as normal')
|
|
||||||
|
|
||||||
this.testResults.letterboxWidth = candidateAvg;
|
this.testResults.letterboxWidth = candidateAvg;
|
||||||
this.testResults.letterboxOffset = diff;
|
this.testResults.letterboxOffset = diff;
|
||||||
this.testResults.aspectRatioUpdated = true;
|
this.testResults.aspectRatioUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates aspect ratio if new aspect ratio is different enough from the old one
|
|
||||||
*/
|
|
||||||
private updateAspectRatio(overrideAr?: number) {
|
|
||||||
const ar = overrideAr ?? this.getAr();
|
|
||||||
|
|
||||||
// Calculate difference between two ratios
|
|
||||||
const maxRatio = Math.max(ar, this.testResults.activeAspectRatio);
|
|
||||||
const diff = Math.abs(ar - this.testResults.activeAspectRatio);
|
|
||||||
|
|
||||||
if (overrideAr || (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.
|
* Calculates video's current aspect ratio based on data in testResults.
|
||||||
* @returns
|
* @returns
|
||||||
@ -1838,23 +1730,24 @@ export class Aard {
|
|||||||
|
|
||||||
const compensatedWidth = fileAr === canvasAr ? this.canvasStore.main.width : this.canvasStore.main.width * fileAr;
|
const compensatedWidth = fileAr === canvasAr ? this.canvasStore.main.width : this.canvasStore.main.width * fileAr;
|
||||||
|
|
||||||
// console.log(`
|
|
||||||
// ———— ASPECT RATIO CALCULATION: —————
|
|
||||||
|
|
||||||
// canvas size: ${this.canvasStore.main.width} x ${this.canvasStore.main.height} (1:${this.canvasStore.main.width / this.canvasStore.main.height})
|
console.log(`
|
||||||
// file size: ${this.video.videoWidth} x ${this.video.videoHeight} (1:${this.video.videoWidth / this.video.videoHeight})
|
———— ASPECT RATIO CALCULATION: —————
|
||||||
|
|
||||||
// compensated size: ${compensatedWidth} x ${this.canvasStore.main.height} (1:${compensatedWidth / this.canvasStore.main.height})
|
canvas size: ${this.canvasStore.main.width} x ${this.canvasStore.main.height} (1:${this.canvasStore.main.width / this.canvasStore.main.height})
|
||||||
|
file size: ${this.video.videoWidth} x ${this.video.videoHeight} (1:${this.video.videoWidth / this.video.videoHeight})
|
||||||
|
|
||||||
// letterbox height: ${this.testResults.letterboxWidth}
|
compensated size: ${compensatedWidth} x ${this.canvasStore.main.height} (1:${compensatedWidth / this.canvasStore.main.height})
|
||||||
// net video height: ${this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)}
|
|
||||||
|
|
||||||
// calculated aspect ratio -----
|
letterbox height: ${this.testResults.letterboxWidth}
|
||||||
|
net video height: ${this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)}
|
||||||
|
|
||||||
// ${compensatedWidth} ${compensatedWidth} ${compensatedWidth}
|
calculated aspect ratio -----
|
||||||
// ——————————————— = —————————————— = —————— = ${compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2))}
|
|
||||||
// ${this.canvasStore.main.height} - 2 x ${this.testResults.letterboxWidth} ${this.canvasStore.main.height} - ${2 * this.testResults.letterboxWidth} ${this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)}
|
${compensatedWidth} ${compensatedWidth} ${compensatedWidth}
|
||||||
// `);
|
——————————————— = —————————————— = —————— = ${compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2))}
|
||||||
|
${this.canvasStore.main.height} - 2 x ${this.testResults.letterboxWidth} ${this.canvasStore.main.height} - ${2 * this.testResults.letterboxWidth} ${this.canvasStore.main.height - (this.testResults.letterboxWidth * 2)}
|
||||||
|
`);
|
||||||
|
|
||||||
|
|
||||||
return compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2));
|
return compensatedWidth / (this.canvasStore.main.height - (this.testResults.letterboxWidth * 2));
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
enum AardMode {
|
|
||||||
Continuous = 0,
|
|
||||||
UntilDetection = 1,
|
|
||||||
Timeout
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AardMode;
|
|
@ -2,7 +2,6 @@ import {VideoPlaybackState} from '../enums/video-playback-state.enum';
|
|||||||
|
|
||||||
export interface AardStatus {
|
export interface AardStatus {
|
||||||
aardActive: boolean,
|
aardActive: boolean,
|
||||||
aardReducedPolling: boolean,
|
|
||||||
checkInProgress: boolean,
|
checkInProgress: boolean,
|
||||||
lastVideoStatus: VideoPlaybackState,
|
lastVideoStatus: VideoPlaybackState,
|
||||||
|
|
||||||
@ -11,7 +10,6 @@ export interface AardStatus {
|
|||||||
export function initAardStatus(): AardStatus {
|
export function initAardStatus(): AardStatus {
|
||||||
return {
|
return {
|
||||||
aardActive: false,
|
aardActive: false,
|
||||||
aardReducedPolling: true,
|
|
||||||
checkInProgress: false,
|
checkInProgress: false,
|
||||||
lastVideoStatus: VideoPlaybackState.NotInitialized,
|
lastVideoStatus: VideoPlaybackState.NotInitialized,
|
||||||
}
|
}
|
||||||
|
@ -28,18 +28,12 @@ export interface AardTestResults {
|
|||||||
bottomCandidate: number,
|
bottomCandidate: number,
|
||||||
bottomCandidateDistance: number,
|
bottomCandidateDistance: number,
|
||||||
bottomCandidateQuality: number,
|
bottomCandidateQuality: number,
|
||||||
topRowsDifferenceMatrix: [number, number, number],
|
|
||||||
bottomRowsDifferenceMatrix: [number, number, number],
|
|
||||||
},
|
},
|
||||||
aspectRatioUncertain: boolean,
|
aspectRatioUncertain: boolean,
|
||||||
topRowUncertain: boolean,
|
|
||||||
bottomRowUncertain: boolean,
|
|
||||||
aspectRatioUpdated: boolean,
|
aspectRatioUpdated: boolean,
|
||||||
activeAspectRatio: number, // is cumulative
|
|
||||||
letterboxWidth: number,
|
letterboxWidth: number,
|
||||||
letterboxOffset: number,
|
letterboxOffset: number,
|
||||||
logoDetected: [boolean, boolean, boolean, boolean]
|
logoDetected: [boolean, boolean, boolean, boolean]
|
||||||
aspectRatioUncertainReason?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initAardTestResults(settings: AardSettings): AardTestResults {
|
export function initAardTestResults(settings: AardSettings): AardTestResults {
|
||||||
@ -71,35 +65,15 @@ export function initAardTestResults(settings: AardSettings): AardTestResults {
|
|||||||
bottomCandidate: 0,
|
bottomCandidate: 0,
|
||||||
bottomCandidateDistance: 0,
|
bottomCandidateDistance: 0,
|
||||||
bottomCandidateQuality: 0,
|
bottomCandidateQuality: 0,
|
||||||
topRowsDifferenceMatrix: [0, 0, 0],
|
|
||||||
bottomRowsDifferenceMatrix: [0, 0, 0],
|
|
||||||
},
|
},
|
||||||
aspectRatioUncertain: false,
|
aspectRatioUncertain: false,
|
||||||
topRowUncertain: false,
|
|
||||||
bottomRowUncertain: false,
|
|
||||||
aspectRatioUpdated: false,
|
aspectRatioUpdated: false,
|
||||||
activeAspectRatio: 0,
|
|
||||||
letterboxWidth: 0,
|
letterboxWidth: 0,
|
||||||
letterboxOffset: 0,
|
letterboxOffset: 0,
|
||||||
logoDetected: [false, false, false, false]
|
logoDetected: [false, false, false, false]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetGuardLine(results: AardTestResults) {
|
|
||||||
results.guardLine.top = -1;
|
|
||||||
results.guardLine.bottom = -1;
|
|
||||||
results.imageLine.invalidated = false;
|
|
||||||
results.guardLine.invalidated = false;
|
|
||||||
results.guardLine.cornerViolated[0] = false;
|
|
||||||
results.guardLine.cornerViolated[1] = false;
|
|
||||||
results.guardLine.cornerViolated[2] = false;
|
|
||||||
results.guardLine.cornerViolated[3] = false;
|
|
||||||
results.guardLine.cornerPixelsViolated[0] = 0;
|
|
||||||
results.guardLine.cornerPixelsViolated[1] = 0;
|
|
||||||
results.guardLine.cornerPixelsViolated[2] = 0;
|
|
||||||
results.guardLine.cornerPixelsViolated[3] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resetAardTestResults(results: AardTestResults): void {
|
export function resetAardTestResults(results: AardTestResults): void {
|
||||||
results.isFinished = false;
|
results.isFinished = false;
|
||||||
results.lastStage = 0;
|
results.lastStage = 0;
|
||||||
@ -114,10 +88,7 @@ export function resetAardTestResults(results: AardTestResults): void {
|
|||||||
results.guardLine.cornerPixelsViolated[1] = 0;
|
results.guardLine.cornerPixelsViolated[1] = 0;
|
||||||
results.guardLine.cornerPixelsViolated[2] = 0;
|
results.guardLine.cornerPixelsViolated[2] = 0;
|
||||||
results.guardLine.cornerPixelsViolated[3] = 0;
|
results.guardLine.cornerPixelsViolated[3] = 0;
|
||||||
// results.letterboxWidth = 0;
|
results.letterboxWidth = 0;
|
||||||
// results.letterboxOffset = 0;
|
results.letterboxOffset = 0;
|
||||||
results.aspectRatioUpdated = false;
|
results.aspectRatioUpdated = false;
|
||||||
results.aspectRatioUncertainReason = null;
|
|
||||||
results.topRowUncertain = false;
|
|
||||||
results.bottomRowUncertain = false;
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
export interface AardTimers {
|
export interface AardTimers {
|
||||||
nextFrameCheckTime: number;
|
nextFrameCheckTime: number;
|
||||||
reducedPollingNextCheckTime: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initAardTimers(): AardTimers {
|
export function initAardTimers(): AardTimers {
|
||||||
return {
|
return {
|
||||||
nextFrameCheckTime: 0,
|
nextFrameCheckTime: 0
|
||||||
reducedPollingNextCheckTime: 0,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
1141
src/ext/lib/ar-detect/ArDetector.ts
Normal file
1141
src/ext/lib/ar-detect/ArDetector.ts
Normal file
File diff suppressed because it is too large
Load Diff
129
src/ext/lib/ar-detect/DebugCanvas.js
Normal file
129
src/ext/lib/ar-detect/DebugCanvas.js
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
class DebugCanvas {
|
||||||
|
constructor(ardConf){
|
||||||
|
this.conf = ardConf;
|
||||||
|
this.targetWidth = 1280;
|
||||||
|
this.targetHeight = 720;
|
||||||
|
this.targetOffsetTop = 1080;
|
||||||
|
this.targetOffsetLeft = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
init(canvasSize, canvasPosition, targetCanvasSize) {
|
||||||
|
console.log("initiating DebugCanvas")
|
||||||
|
|
||||||
|
var body = document.getElementsByTagName('body')[0];
|
||||||
|
|
||||||
|
if(!canvasPosition){
|
||||||
|
canvasPosition = {
|
||||||
|
top: 1200,
|
||||||
|
left: 800
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!this.canvas){
|
||||||
|
this.canvas = document.createElement("canvas");
|
||||||
|
body.appendChild(this.canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(targetCanvasSize){
|
||||||
|
this.targetWidth = targetCanvasSize.width;
|
||||||
|
this.targetHeight = targetCanvasSize.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canvas.style.position = "absolute";
|
||||||
|
this.canvas.style.left = `${canvasPosition.left}px`;
|
||||||
|
this.canvas.style.top = `${canvasPosition.top}px`;
|
||||||
|
this.canvas.style.zIndex = 10002;
|
||||||
|
// this.canvas.id = "uw_debug_canvas";
|
||||||
|
|
||||||
|
this.context = this.canvas.getContext("2d");
|
||||||
|
|
||||||
|
this.canvas.width = canvasSize.width;
|
||||||
|
this.canvas.height = canvasSize.height;
|
||||||
|
|
||||||
|
this.calculateCanvasZoom();
|
||||||
|
|
||||||
|
console.log("debug canvas is:", this.canvas, "context:", this.context)
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateCanvasZoom(){
|
||||||
|
var canvasZoom = this.targetWidth / this.canvas.width;
|
||||||
|
var translateX = (this.canvas.width - this.targetWidth)/2;
|
||||||
|
var translateY = (this.canvas.height - this.targetHeight)/2;
|
||||||
|
|
||||||
|
this.canvas.style.transform = `scale(${canvasZoom},${canvasZoom}) translateX(${translateX}px) translateY(${translateY}px)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(){
|
||||||
|
if(this.canvas)
|
||||||
|
this.canvas.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
setBuffer(buffer) {
|
||||||
|
// this.imageBuffer = buffer.splice(0);
|
||||||
|
this.imageBuffer = new Uint8ClampedArray(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
trace(arrayIndex, colorClass) {
|
||||||
|
this.imageBuffer[arrayIndex ] = colorClass.colorRgb[0];
|
||||||
|
this.imageBuffer[arrayIndex+1] = colorClass.colorRgb[1];
|
||||||
|
this.imageBuffer[arrayIndex+2] = colorClass.colorRgb[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
var start = performance.now();
|
||||||
|
try{
|
||||||
|
if(this.context && this.imageBuffer instanceof Uint8ClampedArray){
|
||||||
|
try{
|
||||||
|
var idata = new ImageData(this.imageBuffer, this.canvas.width, this.canvas.height);
|
||||||
|
} catch (ee) {
|
||||||
|
console.log("[DebugCanvas.js::update] can't create image data. Trying to correct canvas size. Error was:", ee);
|
||||||
|
this.canvas.width = this.conf.canvas.width;
|
||||||
|
this.canvas.height = this.conf.canvas.height;
|
||||||
|
|
||||||
|
this.calculateCanvasZoom();
|
||||||
|
// this.context = this.canvas.getContext("2d");
|
||||||
|
var idata = new ImageData(this.imageBuffer, this.canvas.width, this.canvas.height);
|
||||||
|
}
|
||||||
|
this.putImageData(this.context, idata, 0, 0, 0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log("[DebugCanvas.js::update] updating canvas failed.", e);
|
||||||
|
}
|
||||||
|
console.log("[DebugCanvas.js::update] update took", (performance.now() - start), "ms.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugCanvasClasses = {
|
||||||
|
VIOLATION: {color: '#ff0000', colorRgb: [255, 0, 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)'},
|
||||||
|
|
||||||
|
EDGEDETECT_ONBLACK: {color: '#444444', colorRgb: [68, 68, 68], text: 'edge detect - perpendicular (to edge)'},
|
||||||
|
EDGEDETECT_CANDIDATE: {color: '#FFFFFF', colorRgb: [255, 255, 255], text: 'edge detect - edge candidate'},
|
||||||
|
EDGEDETECT_CANDIDATE_SECONDARY: {color: '#OOOOOO', colorRgb: [0, 0, 0], text: 'edge detect - edge candidate, but for when candidate is really bright'},
|
||||||
|
EDGEDETECT_BLACKBAR: {color: '#07ac93', colorRgb: [7, 172, 147], text: 'edge detect - parallel, black test'},
|
||||||
|
EDGEDETECT_IMAGE: {color: '#046c5c', colorRgb: [4, 108, 92], text: 'edge detect - parallel, image test'}
|
||||||
|
}
|
291
src/ext/lib/ar-detect/GuardLine.ts
Normal file
291
src/ext/lib/ar-detect/GuardLine.ts
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
import Debug from '../../conf/Debug';
|
||||||
|
import Settings from '../Settings';
|
||||||
|
import ArDetector from './ArDetector';
|
||||||
|
|
||||||
|
export type GuardLineBar = {
|
||||||
|
top?: number;
|
||||||
|
bottom?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ImageCheckResult = {
|
||||||
|
success: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GuardLine {
|
||||||
|
blackbar: GuardLineBar;
|
||||||
|
imageBar: GuardLineBar;
|
||||||
|
|
||||||
|
aard: ArDetector;
|
||||||
|
settings: Settings;
|
||||||
|
|
||||||
|
blackbarThreshold: number;
|
||||||
|
imageThreshold: number;
|
||||||
|
|
||||||
|
|
||||||
|
// ardConf — reference to ArDetector that has current GuardLine instance
|
||||||
|
constructor (ardConf){
|
||||||
|
this.blackbar = {top: undefined, bottom: undefined};
|
||||||
|
this.imageBar = {top: undefined, bottom: undefined};
|
||||||
|
|
||||||
|
this.aard = ardConf;
|
||||||
|
this.settings = ardConf.settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.blackbar = {top: undefined, bottom: undefined};
|
||||||
|
this.imageBar = {top: undefined, bottom: undefined};
|
||||||
|
}
|
||||||
|
|
||||||
|
setBlackbar(bbconf){
|
||||||
|
let bbTop = bbconf.top - this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
||||||
|
let bbBottom = bbconf.bottom + this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
||||||
|
|
||||||
|
// to odstrani vse neveljavne nastavitve in vse možnosti, ki niso smiselne
|
||||||
|
// this removes any configs with invalid values or values that dont make sense
|
||||||
|
if (bbTop < 0 || bbBottom >= this.aard.glCanvas.height ){
|
||||||
|
throw {error: "INVALID_SETTINGS_IN_GUARDLINE", bbTop, bbBottom}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blackbar = {
|
||||||
|
top: bbTop,
|
||||||
|
bottom: bbBottom
|
||||||
|
}
|
||||||
|
|
||||||
|
this.imageBar = {
|
||||||
|
top: bbconf.top + 1 + this.settings.active.arDetect.guardLine.edgeTolerancePx,
|
||||||
|
bottom: bbconf.bottom - 1 - this.settings.active.arDetect.guardLine.edgeTolerancePx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check(image){
|
||||||
|
// calculate once and save object-instance-wide
|
||||||
|
this.blackbarThreshold = this.aard.blackLevel + this.settings.active.arDetect.blackbar.threshold;
|
||||||
|
this.imageThreshold = this.blackbarThreshold + this.settings.active.arDetect.blackbar.imageThreshold;
|
||||||
|
|
||||||
|
// actual checks
|
||||||
|
let guardLineResult = this.guardLineCheck(image);
|
||||||
|
|
||||||
|
// blackbar violation detected. We don't even need to check for presence of image
|
||||||
|
// as aspect ratio just decreased
|
||||||
|
if(! guardLineResult.success) {
|
||||||
|
return {
|
||||||
|
blackbarFail: true,
|
||||||
|
offenders: guardLineResult.offenders,
|
||||||
|
imageFail: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageCheckResult = this.imageCheck(image);
|
||||||
|
|
||||||
|
return {
|
||||||
|
blackbarFail: false,
|
||||||
|
imageFail: ! imageCheckResult.success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// don't use methods below this line outside this class
|
||||||
|
guardLineCheck(image){
|
||||||
|
// this test tests for whether we crop too aggressively
|
||||||
|
|
||||||
|
// if this test is passed, then aspect ratio probably didn't change from wider to narrower. However, further
|
||||||
|
// checks are needed to determine whether aspect ratio got wider.
|
||||||
|
// if this test fails, it returns a list of offending points.
|
||||||
|
|
||||||
|
// if the upper edge is null, then edge hasn't been detected before. This test is pointless, therefore it
|
||||||
|
// should succeed by default. Also need to check bottom, for cases where only one edge is known
|
||||||
|
|
||||||
|
if (!this.blackbar.top || !this.blackbar.bottom) {
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset = (this.aard.glCanvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||||
|
|
||||||
|
let offenders = [];
|
||||||
|
let offenderCount = -1; // doing it this way means first offender has offenderCount==0. Ez index.
|
||||||
|
|
||||||
|
// TODO: implement logo check.
|
||||||
|
|
||||||
|
// preglejmo obe vrstici
|
||||||
|
// check both rows
|
||||||
|
let edge_lower, edge_upper;
|
||||||
|
|
||||||
|
edge_upper = this.blackbar.top;
|
||||||
|
edge_lower = this.blackbar.bottom;
|
||||||
|
|
||||||
|
let rowStart, rowEnd;
|
||||||
|
|
||||||
|
// <<<=======| checking upper row |========>>>
|
||||||
|
|
||||||
|
rowStart = ((edge_upper * this.aard.glCanvas.width) << 2) + offset;
|
||||||
|
rowEnd = rowStart + ( this.aard.glCanvas.width << 2 ) - (offset * 2);
|
||||||
|
|
||||||
|
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
|
||||||
|
// offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
||||||
|
} else {
|
||||||
|
offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
||||||
|
}
|
||||||
|
// <<<=======| checking lower row |========>>>
|
||||||
|
|
||||||
|
rowStart = ((edge_lower * this.aard.glCanvas.width) << 2) + offset;
|
||||||
|
rowEnd = rowStart + ( this.aard.glCanvas.width << 2 ) - (offset * 2);
|
||||||
|
|
||||||
|
if (Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine) {
|
||||||
|
// offenderCount = this._gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
||||||
|
} else {
|
||||||
|
offenderCount = this._gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// če nismo našli nobenih prekrškarjev, vrnemo uspeh. Drugače vrnemo seznam prekrškarjev
|
||||||
|
// vrnemo tabelo, ki vsebuje sredinsko točko vsakega prekrškarja (x + width*0.5)
|
||||||
|
//
|
||||||
|
// if we haven't found any offenders, we return success. Else we return list of offenders
|
||||||
|
// we return array of middle points of offenders (x + (width * 0.5) for every offender)
|
||||||
|
|
||||||
|
if(offenderCount == -1){
|
||||||
|
return {success: true};
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = new Array(offenders.length);
|
||||||
|
for(let o in offenders){
|
||||||
|
ret[o] = offenders[o].x + (offenders[o].width * 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {success: false, offenders: ret};
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCheck(image): ImageCheckResult {
|
||||||
|
if(!this.imageBar.top || !this.imageBar.bottom)
|
||||||
|
return { success: false };
|
||||||
|
|
||||||
|
let offset = (this.aard.glCanvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||||
|
|
||||||
|
// TODO: implement logo check.
|
||||||
|
|
||||||
|
let edge_upper = this.imageBar.top;
|
||||||
|
let edge_lower = this.imageBar.bottom;
|
||||||
|
|
||||||
|
// how many non-black pixels we need to consider this check a success. We only need to detect enough pixels
|
||||||
|
// on one edge (one of the edges can be black as long as both aren't)
|
||||||
|
let successThreshold = (this.aard.glCanvas.width * this.settings.active.arDetect.guardLine.imageTestThreshold);
|
||||||
|
let rowStart, rowEnd;
|
||||||
|
|
||||||
|
|
||||||
|
// <<<=======| checking upper row |========>>>
|
||||||
|
|
||||||
|
rowStart = ((edge_upper * this.aard.glCanvas.width) << 2) + offset;
|
||||||
|
rowEnd = rowStart + ( this.aard.glCanvas.width << 2 ) - (offset * 2);
|
||||||
|
|
||||||
|
let res = false;
|
||||||
|
|
||||||
|
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
|
||||||
|
// res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold);
|
||||||
|
} else {
|
||||||
|
res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
return {success: true};
|
||||||
|
}
|
||||||
|
|
||||||
|
// <<<=======| checking lower row |========>>>
|
||||||
|
|
||||||
|
rowStart = ((edge_lower * this.aard.glCanvas.width) << 2) + offset;
|
||||||
|
// rowEnd = rowStart + ( this.conf.canvas.width << 2 ) - (offset * 2);
|
||||||
|
|
||||||
|
|
||||||
|
if(Debug.debugCanvas.enabled && Debug.debugCanvas.guardLine){
|
||||||
|
// res = this._ti_debugCheckRow(image, rowStart, rowEnd, successThreshold);
|
||||||
|
} else {
|
||||||
|
res = this._ti_checkRow(image, rowStart, rowEnd,successThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {success: res};
|
||||||
|
}
|
||||||
|
|
||||||
|
// pomožne metode
|
||||||
|
// helper methods
|
||||||
|
|
||||||
|
|
||||||
|
_gl_rowCheck(image, rowStart, rowEnd, offenders, offenderCount){
|
||||||
|
let firstOffender = -1;
|
||||||
|
for(let 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] > this.blackbarThreshold || image[i+1] > this.blackbarThreshold || image[i+2] > this.blackbarThreshold){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _gl_debugRowCheck(image, rowStart, rowEnd, offenders, offenderCount){
|
||||||
|
// let firstOffender = -1;
|
||||||
|
// for(let 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] > this.blackbarThreshold || image[i+1] > this.blackbarThreshold || image[i+2] > this.blackbarThreshold){
|
||||||
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.VIOLATION);
|
||||||
|
// if(firstOffender < 0){
|
||||||
|
// firstOffender = (i - rowStart) >> 2;
|
||||||
|
// offenderCount++;
|
||||||
|
// offenders.push({x: firstOffender, width: 1});
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// offenders[offenderCount].width++
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_BLACKBAR);
|
||||||
|
// // is that a black pixel again? Let's reset the 'first offender'
|
||||||
|
// firstOffender = -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return offenderCount;
|
||||||
|
// }
|
||||||
|
|
||||||
|
_ti_checkRow(image, rowStart, rowEnd, successThreshold): boolean {
|
||||||
|
for(let i = rowStart; i < rowEnd; i+=4){
|
||||||
|
if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){
|
||||||
|
if(successThreshold --<= 0){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ti_debugCheckRow(image, rowStart, rowEnd, successThreshold) {
|
||||||
|
// for(let i = rowStart; i < rowEnd; i+=4){
|
||||||
|
// if(image[i] > this.imageThreshold || image[i+1] > this.imageThreshold || image[i+2] > this.imageThreshold){
|
||||||
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.GUARDLINE_IMAGE);
|
||||||
|
// if(successThreshold --<= 0){
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// this.aard.debugCanvas.trace(i, DebugCanvasClasses.WARN);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GuardLine;
|
1241
src/ext/lib/ar-detect/edge-detect/EdgeDetect.ts
Normal file
1241
src/ext/lib/ar-detect/edge-detect/EdgeDetect.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
|||||||
|
enum EdgeDetectPrimaryDirection {
|
||||||
|
Vertical = 0,
|
||||||
|
Horizontal = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EdgeDetectPrimaryDirection;
|
@ -0,0 +1,6 @@
|
|||||||
|
enum EdgeDetectQuality {
|
||||||
|
Fast = 0,
|
||||||
|
Improved = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EdgeDetectQuality;
|
@ -0,0 +1,6 @@
|
|||||||
|
enum EdgeStatus {
|
||||||
|
ARUnknown = 0,
|
||||||
|
ARKnown = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EdgeStatus;
|
@ -137,7 +137,7 @@ class CommsClient {
|
|||||||
try {
|
try {
|
||||||
return this.port.postMessage(message);
|
return this.port.postMessage(message);
|
||||||
} catch (e) {
|
} 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});
|
const port = chrome.runtime.connect(null, {name: this.name});
|
||||||
port.onMessage.addListener(this._listener);
|
port.onMessage.addListener(this._listener);
|
||||||
return port.postMessage(message);
|
return port.postMessage(message);
|
||||||
@ -152,7 +152,7 @@ class CommsClient {
|
|||||||
* @param receivedMessage
|
* @param receivedMessage
|
||||||
*/
|
*/
|
||||||
private processReceivedMessage(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
|
// when sending between frames, message will be enriched with two new properties
|
||||||
const {_sourceFrame, _sourcePort, ...message} = receivedMessage;
|
const {_sourceFrame, _sourcePort, ...message} = receivedMessage;
|
||||||
|
|
||||||
|
@ -148,7 +148,14 @@ class UI {
|
|||||||
|
|
||||||
initMessaging() {
|
initMessaging() {
|
||||||
// subscribe to events coming back to us. Unsubscribe if iframe vanishes.
|
// subscribe to events coming back to us. Unsubscribe if iframe vanishes.
|
||||||
window.addEventListener('message', this.messageHandlerFn);
|
const messageHandlerFn = (message) => {
|
||||||
|
if (!this.uiIframe?.contentWindow) {
|
||||||
|
window.removeEventListener('message', messageHandlerFn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.handleMessage(message);
|
||||||
|
}
|
||||||
|
window.addEventListener('message', messageHandlerFn);
|
||||||
|
|
||||||
|
|
||||||
/* set up event bus tunnel from content script to UI — necessary if we want to receive
|
/* set up event bus tunnel from content script to UI — necessary if we want to receive
|
||||||
@ -156,44 +163,39 @@ class UI {
|
|||||||
* necessary for UI display in the popup.
|
* necessary for UI display in the popup.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.eventBus.subscribeMulti(
|
this.eventBus.subscribe(
|
||||||
|
'uw-config-broadcast',
|
||||||
{
|
{
|
||||||
'uw-config-broadcast': {
|
function: (config, routingData) => {
|
||||||
function: (config, routingData) => {
|
this.sendToIframe('uw-config-broadcast', config, routingData);
|
||||||
this.sendToIframe('uw-config-broadcast', config, routingData);
|
}
|
||||||
}
|
}
|
||||||
},
|
);
|
||||||
'uw-set-ui-state': {
|
this.eventBus.subscribe(
|
||||||
function: (config, routingData) => {
|
'uw-set-ui-state',
|
||||||
if (config.globalUiVisible !== undefined) {
|
{
|
||||||
if (this.isGlobal) {
|
function: (config, routingData) => {
|
||||||
this.setUiVisibility(config.globalUiVisible);
|
if (config.globalUiVisible !== undefined) {
|
||||||
} else {
|
if (this.isGlobal) {
|
||||||
this.setUiVisibility(!config.globalUiVisible);
|
this.setUiVisibility(config.globalUiVisible);
|
||||||
}
|
} else {
|
||||||
|
this.setUiVisibility(!config.globalUiVisible);
|
||||||
}
|
}
|
||||||
this.sendToIframe('uw-set-ui-state', {...config, isGlobal: this.isGlobal}, routingData);
|
|
||||||
}
|
}
|
||||||
},
|
this.sendToIframe('uw-set-ui-state', {...config, isGlobal: this.isGlobal}, routingData);
|
||||||
'uw-restore-ui-state': {
|
}
|
||||||
function: (config, routingData) => {
|
}
|
||||||
if (!this.isGlobal) {
|
)
|
||||||
this.setUiVisibility(true);
|
this.eventBus.subscribe(
|
||||||
this.sendToIframe('uw-restore-ui-state', config, routingData);
|
'uw-restore-ui-state', {
|
||||||
}
|
function: (config, routingData) => {
|
||||||
|
if (!this.isGlobal) {
|
||||||
|
this.setUiVisibility(true);
|
||||||
|
this.sendToIframe('uw-restore-ui-state', config, routingData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
this
|
)
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
messageHandlerFn = (message) => {
|
|
||||||
if (!this.uiIframe?.contentWindow) {
|
|
||||||
window.removeEventListener('message', this.messageHandlerFn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.handleMessage(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setUiVisibility(visible) {
|
setUiVisibility(visible) {
|
||||||
@ -358,8 +360,6 @@ class UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
window.removeEventListener('message', this.messageHandlerFn);
|
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
// this.comms?.destroy();
|
// this.comms?.destroy();
|
||||||
this.uiIframe?.remove();
|
this.uiIframe?.remove();
|
||||||
this.element?.remove();
|
this.element?.remove();
|
||||||
|
@ -36,24 +36,18 @@ export default class IframeManager {
|
|||||||
|
|
||||||
if (this.isIframe) {
|
if (this.isIframe) {
|
||||||
window.addEventListener('beforeunload', this.destroy);
|
window.addEventListener('beforeunload', this.destroy);
|
||||||
|
|
||||||
this.eventBus.subscribe(
|
this.eventBus.subscribe(
|
||||||
'uw-frame-ping',
|
'uw-frame-ping', {function: (cmd, context) => this.handleIframePing(context)}
|
||||||
{
|
|
||||||
source: this,
|
|
||||||
function: (cmd, context) => this.handleIframePing(context)
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
this.eventBus.send(
|
this.eventBus.send(
|
||||||
'uw-frame-register', {host: window.location.hostname}, {comms: {forwardTo: 'all-frames'}}
|
'uw-frame-register', {host: window.location.hostname}, {comms: {forwardTo: 'all-frames'}}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.eventBus.subscribeMulti(
|
this.eventBus.subscribe(
|
||||||
{
|
'uw-frame-register', {function: (data, context) => this.handleIframeRegister(data, context)}
|
||||||
'uw-frame-register': {function: (data, context) => this.handleIframeRegister(data, context)},
|
);
|
||||||
'uw-frame-destroyed': {function: (cmd, context) => this.handleFrameDestroyed(context)}
|
this.eventBus.subscribe(
|
||||||
},
|
'uw-frame-destroyed', {function: (cmd, context) => this.handleFrameDestroyed(context)}
|
||||||
this
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// register all frames to re-register themselves
|
// register all frames to re-register themselves
|
||||||
@ -75,7 +69,6 @@ export default class IframeManager {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
this.eventBus.unsubscribeAll(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleIframePing(context) {
|
private handleIframePing(context) {
|
||||||
|
@ -112,7 +112,7 @@ class PageInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
// this.logger.log('info', ['debug', 'init'], "[PageInfo::destroy] destroying all videos!")
|
this.logger.log('info', ['debug', 'init'], "[PageInfo::destroy] destroying all videos!")
|
||||||
if(this.rescanTimer){
|
if(this.rescanTimer){
|
||||||
clearTimeout(this.rescanTimer);
|
clearTimeout(this.rescanTimer);
|
||||||
}
|
}
|
||||||
@ -179,22 +179,16 @@ class PageInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideos(): HTMLVideoElement[] {
|
getVideos(host) {
|
||||||
const videoQs = this.siteSettings.getCustomDOMQuerySelector('video');
|
const videoQs = this.siteSettings.getCustomDOMQuerySelector('video');
|
||||||
let videos: HTMLVideoElement[] = [];
|
|
||||||
|
|
||||||
if (videoQs){
|
if (videoQs){
|
||||||
videos = Array.from(document.querySelectorAll(videoQs) as NodeListOf<HTMLVideoElement> ?? []);
|
const videos = document.querySelectorAll(videoQs) as NodeListOf<HTMLVideoElement>;
|
||||||
} else{
|
|
||||||
videos = Array.from(document.getElementsByTagName('video') ?? []);
|
if (videos.length) {
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return document.getElementsByTagName('video');
|
||||||
// filter out videos that aren't big enough
|
|
||||||
videos = videos.filter(
|
|
||||||
(v: HTMLVideoElement) => v.clientHeight > 720 && v.clientWidth > 1208
|
|
||||||
);
|
|
||||||
|
|
||||||
return videos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasVideo() {
|
hasVideo() {
|
||||||
@ -212,7 +206,6 @@ class PageInfo {
|
|||||||
// is there any video data objects that had their HTML elements removed but not yet
|
// is there any video data objects that had their HTML elements removed but not yet
|
||||||
// destroyed? We clean that up here.
|
// destroyed? We clean that up here.
|
||||||
const orphans = this.videos.filter(x => !document.body.contains(x.element));
|
const orphans = this.videos.filter(x => !document.body.contains(x.element));
|
||||||
|
|
||||||
for (const orphan of orphans) {
|
for (const orphan of orphans) {
|
||||||
orphan.videoData.destroy();
|
orphan.videoData.destroy();
|
||||||
}
|
}
|
||||||
@ -222,7 +215,7 @@ class PageInfo {
|
|||||||
|
|
||||||
// add new videos
|
// add new videos
|
||||||
try{
|
try{
|
||||||
let vids = this.getVideos();
|
let vids = this.getVideos(window.location.hostname);
|
||||||
|
|
||||||
if(!vids || vids.length == 0){
|
if(!vids || vids.length == 0){
|
||||||
this.hasVideos = false;
|
this.hasVideos = false;
|
||||||
|
@ -80,7 +80,6 @@ class PlayerData {
|
|||||||
halted: boolean = true;
|
halted: boolean = true;
|
||||||
isFullscreen: boolean = !!document.fullscreenElement;
|
isFullscreen: boolean = !!document.fullscreenElement;
|
||||||
isTheaterMode: boolean = false; // note: fullscreen mode will count as theaterMode if player was in theater mode before fs switch. This is desired, so far.
|
isTheaterMode: boolean = false; // note: fullscreen mode will count as theaterMode if player was in theater mode before fs switch. This is desired, so far.
|
||||||
isTooSmall: boolean = true;
|
|
||||||
|
|
||||||
//#region misc stuff
|
//#region misc stuff
|
||||||
extensionMode: any;
|
extensionMode: any;
|
||||||
@ -88,8 +87,6 @@ class PlayerData {
|
|||||||
private playerIdElement: any;
|
private playerIdElement: any;
|
||||||
private observer: ResizeObserver;
|
private observer: ResizeObserver;
|
||||||
|
|
||||||
private trackChangesTimeout: any;
|
|
||||||
|
|
||||||
private ui: UI;
|
private ui: UI;
|
||||||
|
|
||||||
elementStack: any[] = [];
|
elementStack: any[] = [];
|
||||||
@ -102,7 +99,7 @@ class PlayerData {
|
|||||||
}],
|
}],
|
||||||
'get-player-dimensions': [{
|
'get-player-dimensions': [{
|
||||||
function: () => {
|
function: () => {
|
||||||
this.eventBus.send('—————————————————————————— uw-config-broadcast', {
|
this.eventBus.send('uw-config-broadcast', {
|
||||||
type: 'player-dimensions',
|
type: 'player-dimensions',
|
||||||
data: this.dimensions
|
data: this.dimensions
|
||||||
});
|
});
|
||||||
@ -160,12 +157,20 @@ class PlayerData {
|
|||||||
// do the rest
|
// do the rest
|
||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
this.element = this.getPlayer();
|
this.element = this.getPlayer();
|
||||||
this.isTooSmall = (this.element.clientWidth < 1208 || this.element.clientHeight < 720);
|
|
||||||
|
|
||||||
this.initEventBus();
|
this.initEventBus();
|
||||||
|
|
||||||
// we defer UI creation until player element is big enough
|
// this.notificationService = new PlayerNotificationUi(this.element, this.settings, this.eventBus);
|
||||||
// this happens in trackDimensionChanges!
|
if (this.videoData.settings.active.ui?.inPlayer?.enabled) {
|
||||||
|
this.ui = new UI(
|
||||||
|
'ultrawidifyUi',
|
||||||
|
{
|
||||||
|
parentElement: this.element,
|
||||||
|
eventBus: this.eventBus,
|
||||||
|
playerData: this,
|
||||||
|
uiSettings: this.videoData.settings.active.ui
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.dimensions = undefined;
|
this.dimensions = undefined;
|
||||||
this.overlayNode = undefined;
|
this.overlayNode = undefined;
|
||||||
@ -228,46 +233,10 @@ class PlayerData {
|
|||||||
destroy() {
|
destroy() {
|
||||||
document.removeEventListener('fullscreenchange', this.dimensionChangeListener);
|
document.removeEventListener('fullscreenchange', this.dimensionChangeListener);
|
||||||
this.stopChangeDetection();
|
this.stopChangeDetection();
|
||||||
this.ui?.destroy();
|
|
||||||
this.notificationService?.destroy();
|
this.notificationService?.destroy();
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
deferredUiInitialization(playerDimensions) {
|
|
||||||
if (this.ui || ! this.videoData.settings.active.ui?.inPlayer?.enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
this.isFullscreen
|
|
||||||
|| (
|
|
||||||
playerDimensions.width > 1208
|
|
||||||
&& playerDimensions.height > 720
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.ui = new UI(
|
|
||||||
'ultrawidifyUi',
|
|
||||||
{
|
|
||||||
parentElement: this.element,
|
|
||||||
eventBus: this.eventBus,
|
|
||||||
playerData: this,
|
|
||||||
uiSettings: this.videoData.settings.active.ui
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.runLevel < RunLevel.UIOnly) {
|
|
||||||
this.ui?.disable();
|
|
||||||
}
|
|
||||||
if (this.runLevel >= RunLevel.UIOnly) {
|
|
||||||
this.ui?.enable();
|
|
||||||
this.startChangeDetection();
|
|
||||||
}
|
|
||||||
if (this.runLevel >= RunLevel.CustomCSSActive) {
|
|
||||||
this.element.classList.add(this.playerCssClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets extension runLevel and sets or unsets appropriate css classes as necessary
|
* Sets extension runLevel and sets or unsets appropriate css classes as necessary
|
||||||
* @param runLevel
|
* @param runLevel
|
||||||
@ -284,11 +253,11 @@ class PlayerData {
|
|||||||
this.element.classList.remove(this.playerCssClass);
|
this.element.classList.remove(this.playerCssClass);
|
||||||
}
|
}
|
||||||
if (runLevel < RunLevel.UIOnly) {
|
if (runLevel < RunLevel.UIOnly) {
|
||||||
this.ui?.disable();
|
this.ui.disable();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (runLevel >= RunLevel.UIOnly) {
|
if (runLevel >= RunLevel.UIOnly) {
|
||||||
this.ui?.enable();
|
this.ui.enable();
|
||||||
this.startChangeDetection();
|
this.startChangeDetection();
|
||||||
}
|
}
|
||||||
if (runLevel >= RunLevel.CustomCSSActive) {
|
if (runLevel >= RunLevel.CustomCSSActive) {
|
||||||
@ -344,20 +313,12 @@ class PlayerData {
|
|||||||
this.detectTheaterMode();
|
this.detectTheaterMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// defer creating UI
|
|
||||||
this.deferredUiInitialization(currentPlayerDimensions);
|
|
||||||
|
|
||||||
// if dimensions of the player box are the same as the last known
|
// if dimensions of the player box are the same as the last known
|
||||||
// dimensions, we don't have to do anything ... in theory. In practice,
|
// dimensions, we don't have to do anything
|
||||||
// sometimes restore-ar doesn't appear to register the first time, and
|
|
||||||
// this function doesn't really run often enough to warrant finding a
|
|
||||||
// real, optimized fix.
|
|
||||||
if (
|
if (
|
||||||
this.dimensions?.width == currentPlayerDimensions.width
|
this.dimensions?.width == currentPlayerDimensions.width
|
||||||
&& this.dimensions?.height == currentPlayerDimensions.height
|
&& this.dimensions?.height == currentPlayerDimensions.height
|
||||||
) {
|
) {
|
||||||
this.eventBus.send('restore-ar', null);
|
|
||||||
this.eventBus.send('delayed-restore-ar', {delay: 500});
|
|
||||||
this.dimensions = currentPlayerDimensions;
|
this.dimensions = currentPlayerDimensions;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -365,7 +326,7 @@ class PlayerData {
|
|||||||
// in every other case, we need to check if the player is still
|
// in every other case, we need to check if the player is still
|
||||||
// big enough to warrant our extension running.
|
// big enough to warrant our extension running.
|
||||||
this.handleSizeConstraints(currentPlayerDimensions);
|
this.handleSizeConstraints(currentPlayerDimensions);
|
||||||
// this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
||||||
|
|
||||||
// Save current dimensions to avoid triggering this function pointlessly
|
// Save current dimensions to avoid triggering this function pointlessly
|
||||||
this.dimensions = currentPlayerDimensions;
|
this.dimensions = currentPlayerDimensions;
|
||||||
@ -377,15 +338,19 @@ class PlayerData {
|
|||||||
* @param currentPlayerDimensions
|
* @param currentPlayerDimensions
|
||||||
*/
|
*/
|
||||||
private handleSizeConstraints(currentPlayerDimensions: PlayerDimensions) {
|
private handleSizeConstraints(currentPlayerDimensions: PlayerDimensions) {
|
||||||
|
console.log('handling resize constraints');
|
||||||
// Check if extension is allowed to run in current combination of theater + full screen
|
// 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;
|
const canEnable = this.siteSettings.isEnabledForEnvironment(this.isFullscreen, this.isTheaterMode) === ExtensionMode.Enabled;
|
||||||
|
|
||||||
if (this.runLevel === RunLevel.Off && canEnable) {
|
if (this.runLevel === RunLevel.Off && canEnable) {
|
||||||
|
console.log('runLevel: off -> [anything]');
|
||||||
this.eventBus.send('restore-ar', null);
|
this.eventBus.send('restore-ar', null);
|
||||||
// must be called after
|
// must be called after
|
||||||
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
||||||
} else if (!canEnable && this.runLevel !== RunLevel.Off) {
|
} else if (!canEnable && this.runLevel !== RunLevel.Off) {
|
||||||
// must be called before
|
// must be called before
|
||||||
|
console.log('runLevel: [anything] -> off');
|
||||||
|
|
||||||
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
this.handleDimensionChanges(currentPlayerDimensions, this.dimensions);
|
||||||
this.setRunLevel(RunLevel.Off);
|
this.setRunLevel(RunLevel.Off);
|
||||||
}
|
}
|
||||||
@ -393,6 +358,7 @@ class PlayerData {
|
|||||||
|
|
||||||
|
|
||||||
private handleDimensionChanges(newDimensions: PlayerDimensions, oldDimensions: PlayerDimensions) {
|
private handleDimensionChanges(newDimensions: PlayerDimensions, oldDimensions: PlayerDimensions) {
|
||||||
|
console.log('handling dimension changes\n\nold dimensions:', oldDimensions, '\nnew dimensions:', newDimensions, '\n\nis enabled:', this.enabled, this.runLevel, RunLevel);
|
||||||
if (this.runLevel === RunLevel.Off ) {
|
if (this.runLevel === RunLevel.Off ) {
|
||||||
this.logger.log('info', 'debug', "[PlayerDetect] player size changed, but PlayerDetect is in disabled state. The player element is probably too small.");
|
this.logger.log('info', 'debug', "[PlayerDetect] player size changed, but PlayerDetect is in disabled state. The player element is probably too small.");
|
||||||
return;
|
return;
|
||||||
@ -408,6 +374,7 @@ class PlayerData {
|
|||||||
|| newDimensions?.height != oldDimensions?.height
|
|| newDimensions?.height != oldDimensions?.height
|
||||||
|| newDimensions?.fullscreen != oldDimensions?.fullscreen
|
|| newDimensions?.fullscreen != oldDimensions?.fullscreen
|
||||||
){
|
){
|
||||||
|
console.log('dimensions changed + we are enabled. Sending restore-ar ...');
|
||||||
// If player size changes, we restore aspect ratio
|
// If player size changes, we restore aspect ratio
|
||||||
this.eventBus.send('restore-ar', null);
|
this.eventBus.send('restore-ar', null);
|
||||||
this.eventBus.send('delayed-restore-ar', {delay: 500});
|
this.eventBus.send('delayed-restore-ar', {delay: 500});
|
||||||
@ -416,9 +383,6 @@ class PlayerData {
|
|||||||
type: 'player-dimensions',
|
type: 'player-dimensions',
|
||||||
data: newDimensions
|
data: newDimensions
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.isTooSmall = !newDimensions.fullscreen && (newDimensions.width < 1208 || newDimensions.height < 720);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,15 +515,20 @@ class PlayerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if mode is given, we follow the preference
|
// 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) {
|
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') {
|
if (this.siteSettings.data.currentDOMConfig?.elements?.player?.mode === 'qs') {
|
||||||
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
|
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
|
||||||
|
console.log('got qs player candidate');
|
||||||
} else {
|
} else {
|
||||||
playerCandidate = elementStack[playerIndex];
|
playerCandidate = elementStack[playerIndex];
|
||||||
playerCandidate.heuristics['manualElementByParentIndex'] = true;
|
playerCandidate.heuristics['manualElementByParentIndex'] = true;
|
||||||
|
console.log('got index player candidate')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.log('no preference.')
|
||||||
// try to figure it out based on what we have, with playerQs taking priority
|
// try to figure it out based on what we have, with playerQs taking priority
|
||||||
if (playerQs) {
|
if (playerQs) {
|
||||||
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
|
playerCandidate = this.getPlayerQs(playerQs, elementStack, videoWidth, videoHeight);
|
||||||
@ -733,10 +702,10 @@ class PlayerData {
|
|||||||
* Lists elements between video and DOM root for display in player selector (UI)
|
* Lists elements between video and DOM root for display in player selector (UI)
|
||||||
*/
|
*/
|
||||||
private handlePlayerTreeRequest() {
|
private handlePlayerTreeRequest() {
|
||||||
|
console.log('aya')
|
||||||
// this populates this.elementStack fully
|
// this populates this.elementStack fully
|
||||||
this.getPlayer({verbose: true});
|
this.getPlayer({verbose: true});
|
||||||
console.log('tree:', JSON.parse(JSON.stringify(this.elementStack)));
|
console.log('tree:', JSON.parse(JSON.stringify(this.elementStack)));
|
||||||
console.log('————————————————————— handling player tree request!')
|
|
||||||
this.eventBus.send('uw-config-broadcast', {type: 'player-tree', config: JSON.parse(JSON.stringify(this.elementStack))});
|
this.eventBus.send('uw-config-broadcast', {type: 'player-tree', config: JSON.parse(JSON.stringify(this.elementStack))});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,15 +88,15 @@ class VideoData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private eventBusCommands = {
|
private eventBusCommands = {
|
||||||
'get-drm-status': {
|
'get-drm-status': [{
|
||||||
function: () => {
|
function: () => {
|
||||||
this.hasDrm = hasDrm(this.video);
|
this.hasDrm = hasDrm(this.video);
|
||||||
this.eventBus.send('uw-config-broadcast', {type: 'drm-status', hasDrm: this.hasDrm});
|
this.eventBus.send('uw-config-broadcast', {type: 'drm-status', hasDrm: this.hasDrm});
|
||||||
}
|
}
|
||||||
},
|
}],
|
||||||
'set-run-level': {
|
'set-run-level': [{
|
||||||
function: (runLevel: RunLevel) => this.setRunLevel(runLevel)
|
function: (runLevel: RunLevel) => this.setRunLevel(runLevel)
|
||||||
}
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,18 +128,19 @@ class VideoData {
|
|||||||
height: this.video.offsetHeight,
|
height: this.video.offsetHeight,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!pageInfo.eventBus) {
|
this.eventBus = new EventBus();
|
||||||
this.eventBus = new EventBus();
|
|
||||||
} else {
|
|
||||||
this.eventBus = pageInfo.eventBus;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.extensionStatus = new ExtensionStatus(siteSettings, pageInfo.eventBus, pageInfo.fsStatus);
|
this.extensionStatus = new ExtensionStatus(siteSettings, pageInfo.eventBus, pageInfo.fsStatus);
|
||||||
|
|
||||||
this.eventBus.subscribeMulti(
|
if (pageInfo.eventBus) {
|
||||||
this.eventBusCommands,
|
this.eventBus.setUpstreamBus(pageInfo.eventBus);
|
||||||
this
|
|
||||||
);
|
for (const action in this.eventBusCommands) {
|
||||||
|
for (const command of this.eventBusCommands[action]) {
|
||||||
|
this.eventBus.subscribe(action, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setupEventListeners();
|
this.setupEventListeners();
|
||||||
}
|
}
|
||||||
@ -242,8 +243,10 @@ class VideoData {
|
|||||||
}
|
}
|
||||||
this.resizer = new Resizer(this);
|
this.resizer = new Resizer(this);
|
||||||
|
|
||||||
|
console.log('before init aard');
|
||||||
try {
|
try {
|
||||||
this.aard = new Aard(this); // this starts Ar detection. needs optional parameter that prevents ArDetector from starting
|
this.aard = new Aard(this); // this starts Ar detection. needs optional parameter that prevents ArDetector from starting
|
||||||
|
console.log('after init aard');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to start Aard!', e);
|
console.error('Failed to start Aard!', e);
|
||||||
}
|
}
|
||||||
@ -267,6 +270,7 @@ class VideoData {
|
|||||||
* Must be triggered on first action. TODO
|
* Must be triggered on first action. TODO
|
||||||
*/
|
*/
|
||||||
preparePage() {
|
preparePage() {
|
||||||
|
console.log('preparing page ...')
|
||||||
this.injectBaseCss();
|
this.injectBaseCss();
|
||||||
this.pageInfo.initMouseActionHandler(this);
|
this.pageInfo.initMouseActionHandler(this);
|
||||||
|
|
||||||
@ -361,7 +365,7 @@ class VideoData {
|
|||||||
|
|
||||||
this.eventBus.send('set-run-level', RunLevel.Off);
|
this.eventBus.send('set-run-level', RunLevel.Off);
|
||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
this.eventBus.unsubscribeAll(this);
|
this.eventBus?.unsetUpstreamBus();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.aard.stop();
|
this.aard.stop();
|
||||||
@ -385,12 +389,16 @@ class VideoData {
|
|||||||
|
|
||||||
|
|
||||||
setRunLevel(runLevel: RunLevel, options?: {fromPlayer?: boolean}) {
|
setRunLevel(runLevel: RunLevel, options?: {fromPlayer?: boolean}) {
|
||||||
|
console.log('setting new runlevel for videodata. current:', this.runLevel, 'new', runLevel)
|
||||||
if (this.runLevel === runLevel) {
|
if (this.runLevel === runLevel) {
|
||||||
return; // also no need to propagate to the player
|
return; // also no need to propagate to the player
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('setting run level ...')
|
||||||
|
|
||||||
// Run level decreases towards 'off'
|
// Run level decreases towards 'off'
|
||||||
if (this.runLevel > runLevel) {
|
if (this.runLevel > runLevel) {
|
||||||
|
console.log('decreasing css.')
|
||||||
if (runLevel < RunLevel.CustomCSSActive) {
|
if (runLevel < RunLevel.CustomCSSActive) {
|
||||||
this.video.classList.remove(this.baseCssName);
|
this.video.classList.remove(this.baseCssName);
|
||||||
this.video.classList.remove(this.userCssClassName);
|
this.video.classList.remove(this.userCssClassName);
|
||||||
|
@ -63,11 +63,9 @@ class Resizer {
|
|||||||
|
|
||||||
_lastAr: Ar = {type: AspectRatioType.Initial};
|
_lastAr: Ar = {type: AspectRatioType.Initial};
|
||||||
set lastAr(x: Ar) {
|
set lastAr(x: Ar) {
|
||||||
// emit updates for UI when setting lastAr, but only if AR really changed
|
|
||||||
if (this._lastAr?.type !== x.type || this._lastAr?.ratio !== x.ratio) {
|
|
||||||
this.eventBus.send('uw-config-broadcast', {type: 'ar', config: x});
|
|
||||||
}
|
|
||||||
this._lastAr = x;
|
this._lastAr = x;
|
||||||
|
// emit updates for UI when setting lastAr
|
||||||
|
this.eventBus.send('uw-config-broadcast', {type: 'ar', config: x})
|
||||||
}
|
}
|
||||||
get lastAr() {
|
get lastAr() {
|
||||||
return this._lastAr;
|
return this._lastAr;
|
||||||
|
@ -297,6 +297,8 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video);
|
|||||||
playerAr
|
playerAr
|
||||||
).xFactor;
|
).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.xFactor = Math.min(stretchFactors.xFactor, maxSafeStretchFactor);
|
||||||
stretchFactors.yFactor = Math.min(stretchFactors.yFactor, maxSafeStretchFactor);
|
stretchFactors.yFactor = Math.min(stretchFactors.yFactor, maxSafeStretchFactor);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user