monitor autodetection performance

This commit is contained in:
Tamius Han 2022-07-13 00:21:21 +02:00
parent f94f6ec956
commit 1556506bd7
3 changed files with 498 additions and 8 deletions

View File

@ -116,6 +116,13 @@
:site="site"
>
</PlayerDetectionPanel>
<AutodetectionSettingsPanel
v-if="selectedTab === 'autodetectionSettings'"
:settings="settings"
:eventBus="eventBus"
:site="site"
>
</AutodetectionSettingsPanel>
<!-- <ResizerDebugPanel :debugData="debugData">
</ResizerDebugPanel> -->
</template>
@ -127,6 +134,7 @@
<script>
import VideoSettings from './src/PlayerUiPanels/VideoSettings.vue'
import AutodetectionSettingsPanel from './src/PlayerUiPanels/AutodetectionSettingsPanel.vue'
import PlayerDetectionPanel from './src/PlayerUiPanels/PlayerDetectionPanel.vue'
import { mapState } from 'vuex';
// import Icon from '../common/components/Icon';
@ -142,7 +150,8 @@ export default {
// Icon,
ResizerDebugPanel,
VideoSettings,
PlayerDetectionPanel
PlayerDetectionPanel,
AutodetectionSettingsPanel,
},
data() {
return {

View File

@ -0,0 +1,420 @@
<template>
<div class="flex flex-column tab-root">
<div class="flex flex-row flex-wrap">
<!-- AARD performance metrics -->
<div class="sub-panel">
<div class="flex flex-row">
<h1><mdicon name="television-play" :size="32" /> Automatic Aspect Ratio Detection</h1>
</div>
<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>.
</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>
<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">draw (blackframe) {{(performanceData?.blackFrameDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">
processing {{
Math.max(
(performanceData?.total?.averageTime ?? 0)
- (performanceData?.imageDraw?.averageTime ?? 0)
- (performanceData?.imageDraw?.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?.blackFrameDraw?.averageTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': Math.max(
(performanceData?.total?.averageTime ?? 0)
- (performanceData?.imageDraw?.averageTime ?? 0)
- (performanceData?.imageDraw?.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">draw (blackframe) {{(performanceData?.blackFrameDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">
processing {{
Math.max(
(performanceData?.total?.worstTime ?? 0)
- (performanceData?.imageDraw?.worstTime ?? 0)
- (performanceData?.blackFrameDraw?.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?.blackFrameDraw?.worstTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': Math.max(
(performanceData?.total?.worstTime ?? 0)
- (performanceData?.imageDraw?.worstTime ?? 0)
- (performanceData?.blackFrameDraw?.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">draw (blackframe) {{(performanceData?.blackFrameDraw?.averageTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">processing {{
(
(performanceData?.blackFrame?.averageTime ?? 0)
+ (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?.blackFrameDraw?.averageTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': (
(performanceData?.blackFrame?.averageTime ?? 0)
+ (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">draw (blackframe) {{(performanceData?.blackFrameDraw?.worstTime ?? 0).toFixed(1)}} ms</span> |
<span class="processing">processing {{
(
(performanceData?.blackFrame?.worstTime ?? 0)
+ (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?.blackFrameDraw?.worstTime ?? 0) + '%'}"
>
</div>
<div
class="processing"
:style="{
'width': (
(performanceData?.blackFrame?.worstTime ?? 0)
+ (performanceData?.fastLetterbox?.worstTime ?? 0)
+ (performanceData?.edgeDetect?.worstTime ?? 0)
) + '%'
}"
>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Button from '../../../common/components/Button.vue'
import KeyboardShortcutParser from '../../../common/js/KeyboardShortcutParser';
import ShortcutButton from '../../../common/components/ShortcutButton';
import EditShortcutButton from '../../../common/components/EditShortcutButton';
import ExecAction from '../ui-libs/ExecAction';
import BrowserDetect from '../../../ext/conf/BrowserDetect';
import AspectRatioType from '../../../common/enums/AspectRatioType.enum';
import StretchType from '../../../common/enums/StretchType.enum';
import CropModePersistence from '../../../common/enums/CropModePersistence.enum';
import AlignmentOptionsControlComponent from './AlignmentOptionsControlComponent.vue';
export default {
data() {
return {
exec: null,
performanceData: {},
graphRefreshInterval: undefined,
}
},
mixins: [
],
props: [
'settings',
'frame',
'eventBus',
'site'
],
created() {
this.exec = new ExecAction(this.settings, window.location.hostname);
this.eventBus.subscribe('uw-config-broadcast', {function: (config) => this.handleConfigBroadcast(config)});
},
mounted() {
this.eventBus.sendToTunnel('get-aard-timing');
this.graphRefreshInterval = setInterval(() => this.eventBus.sendToTunnel('get-aard-timing'), 500);
},
destroyed() {
clearInterval(this.graphRefreshInterval);
},
components: {
ShortcutButton,
EditShortcutButton,
Button,
AlignmentOptionsControlComponent
},
computed: {
},
methods: {
async openOptionsPage() {
BrowserDetect.runtime.openOptionsPage();
},
refreshGraph() {
this.eventBus.sendToTunnel('get-aard-timing');
},
handleConfigBroadcast(data) {
console.log('GOT CONFIG BROADCAST!', data);
if (data.type === 'aard-performance-data') {
this.performanceData = data.performanceData;
this.$nextTick( () => this.$forceUpdate() );
}
},
}
}
</script>
<style lang="scss" src="../../../res/css/flex.scss" scoped module></style>
<style lang="scss" src="../res-common/panels.scss" scoped module></style>
<style lang="scss" src="../res-common/common.scss" scoped module></style>
<style lang="scss" scoped module>
@import '../res-common/variables';
.performance-graph-container {
position: relative;
width: 100%;
height: 8rem;
padding: 1rem;
.performance-graph {
border: 1px solid #fa6;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
// graph is 100 ms wide
.time-budget {
height: 100%;
display: inline-block;
position: relative;
box-sizing: border-box;
z-index: 100;
&.hz144 {
width: 6.9%;
// background-color: rgba(143, 143, 235, 0.47);
}
&.hz120 {
width: 1.39%;
// background-color: rgba(108, 108, 211, 0.441);
}
&.hz60 {
width: 8.33%;
// background-color: rgba(78, 78, 182, 0.327);
border-right: 2px solid rgb(96, 96, 227);
&::after {
content: '60fps';
position: absolute;
top: 0;
right: -2px;
border-right: 2px solid rgb(96, 96, 227);
transform: translateY(-100%);
font-size: 0.6rem;
padding-right: 0.25rem;
text-transform: small-caps;
}
}
&.hz30 {
width: 16.67%;
// background-color: rgba(56, 56, 151, 0.308);
border-right: 2px solid #fb772a;
&::after {
content: '30fps';
position: absolute;
top: 0;
right: -2px;
border-right: 2px solid #fb772a;
transform: translateY(-100%);
font-size: 0.6rem;
padding-right: 0.25rem;
text-transform: small-caps;
}
}
&.hz24 {
width: 8.33%;
// background-color: rgba(37, 37, 118, 0.269);
}
}
.bar-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
> div {
height: 2.5rem;
}
.stats {
background-color: rgba(0, 0, 0, 0.544);
font-size: 0.75rem;
font-family: 'Overpass Mono';
z-index: 11010;
span {
font-size: 0.75rem;
z-index: 11011;
&::before {
content: '';
display: inline-block;
width: 0.75rem;
height: 0.75rem;
margin-top: 0.25rem;
margin-right: 0.5rem;
}
&.draw::before {
background-color: #fb772a;
}
&.draw-blackframe::before {
background-color: #e70c0c;
}
&.processing::before {
background-color: rgb(176, 167, 239);
}
}
}
.bar {
width: 100%;
height: 0.69rem;
background-color: #000;
overflow: hidden;
* {
display: inline-block;
height: 100%;
}
.draw {
background-color: #fb772a;
}
.draw-blackframe {
background-color: #e70c0c;
}
.processing {
background-color: rgb(176, 167, 239);
}
}
}
}
}
</style>

View File

@ -31,6 +31,7 @@ export interface AardPerformanceMeasurement {
export interface AardPerformanceData {
total: AardPerformanceMeasurement,
theoretical: AardPerformanceMeasurement,
imageDraw: AardPerformanceMeasurement
blackFrameDraw: AardPerformanceMeasurement,
blackFrame: AardPerformanceMeasurement,
@ -136,6 +137,8 @@ class ArDetector {
this.settings = videoData.settings;
this.eventBus = videoData.eventBus;
this.initEventBus();
this.sampleCols = [];
this.blackLevel = this.settings.active.arDetect.blackbar.blackLevel;
@ -146,6 +149,15 @@ class ArDetector {
this.logger.log('info', 'init', `[ArDetector::ctor] creating new ArDetector. arid: ${this.arid}`);
}
private initEventBus() {
for (const action in this.eventBusCommands) {
for (const command of this.eventBusCommands[action]) {
this.eventBus.subscribe(action, command);
}
}
}
init(){
this.logger.log('info', 'init', `[ArDetect::init] <@${this.arid}> Initializing autodetection.`);
this.setup();
@ -471,6 +483,10 @@ class ArDetector {
let totalWorst = 0;
let totalStDev = 0;
let theoreticalAverage = 0;
let theoreticalWorst = 0;
let theoreticalStDev = 0;
for (const sample of this.performance.samples) {
if (sample.imageDrawTime) {
imageDrawCount++;
@ -511,12 +527,39 @@ class ArDetector {
if (execTime > totalWorst) {
totalWorst = execTime;
}
const partialExecTime =
sample.imageDrawTime ?? 0
+ sample.blackFrameDrawTime ?? 0
+ sample.blackFrameProcessTime ?? 0;
if (partialExecTime > theoreticalWorst) {
theoreticalWorst = partialExecTime;
}
}
imageDrawAverage /= imageDrawCount;
blackFrameDrawAverage /= blackFrameDrawCount;
blackFrameProcessAverage /= blackFrameProcessCount;
totalAverage /= this.performance.samples.length;
if (imageDrawCount) {
imageDrawAverage /= imageDrawCount;
} else {
imageDrawAverage = 0;
}
if (blackFrameDrawCount) {
blackFrameDrawAverage /= blackFrameDrawCount;
} else {
blackFrameDrawAverage = 0;
}
if (blackFrameProcessCount) {
blackFrameProcessAverage /= blackFrameProcessCount;
} else {
blackFrameProcessAverage = 0;
}
if (this.performance.samples.length) {
totalAverage /= this.performance.samples.length;
} else {
totalAverage = 0;
}
theoreticalAverage = imageDrawAverage + blackFrameDrawAverage + blackFrameProcessAverage;
for (const sample of this.performance.lastMeasurements.fastLetterbox.samples) {
fastLetterboxAverage += sample;
@ -533,8 +576,19 @@ class ArDetector {
fastLetterboxCount = this.performance.lastMeasurements.fastLetterbox.samples.length;
edgeDetectCount = this.performance.lastMeasurements.edgeDetect.samples.length;
fastLetterboxAverage /= fastLetterboxCount;
edgeDetectAverage /= edgeDetectCount;
if (fastLetterboxCount) {
fastLetterboxAverage /= fastLetterboxCount;
} else {
fastLetterboxAverage = 0;
}
if (edgeDetectCount) {
edgeDetectAverage /= edgeDetectCount;
} else {
edgeDetectAverage = 0;
}
theoreticalWorst += fastLetterboxWorst + edgeDetectWorst;
theoreticalAverage += fastLetterboxAverage + edgeDetectAverage;
for (const sample of this.performance.samples) {
if (sample.imageDrawTime) {
@ -599,6 +653,7 @@ class ArDetector {
totalStDev = Math.sqrt(totalStDev / (this.performance.samples.length - 1));
}
const res: AardPerformanceData = {
total: {
sampleCount: this.performance.samples.length,
@ -606,6 +661,12 @@ class ArDetector {
worstTime: totalWorst,
stDev: totalStDev,
},
theoretical: {
sampleCount: -1,
averageTime: theoreticalAverage,
worstTime: theoreticalWorst,
stDev: theoreticalStDev
},
imageDraw: {
sampleCount: imageDrawCount,
averageTime: imageDrawAverage,
@ -644,7 +705,7 @@ class ArDetector {
edgeDetectCount
}
this.eventBus.send('uw-config-broadcast', {type: 'aard-performance-data', config: res});
this.eventBus.send('uw-config-broadcast', {type: 'aard-performance-data', performanceData: res});
}
//#endregion