Fix aspect ratio calculations on height-compensated videos, episode 1

This commit is contained in:
Tamius Han 2020-12-19 03:18:14 +01:00
parent be82c4dae6
commit a9f99d93be
2 changed files with 25 additions and 16 deletions

View File

@ -71,7 +71,13 @@ class Scaler {
* *
* Video width is normalized based on 100% of the parent. That means if the player AR * Video width is normalized based on 100% of the parent. That means if the player AR
* is narrower than video ar, we need to pre-downscale the video. This scaling already * is narrower than video ar, we need to pre-downscale the video. This scaling already
* undoes any zoom that style="height:123%" on the video element adds. * undoes any zoom that style="height:123%" on the video element adds.
*
* There are few exceptions and additional caveatss:
* * AspectRatio.FitHeight: we don't want to pre-downscale the video at all, as things
* will be scaled to fit height as-is.
* * When player is wider than stream, we want to undo any height compensations site
* tacks on the video tag.
* *
* Quick notes: * Quick notes:
* * when I say 'video AR', I actually mean aspect ratio after we've compensated for * * when I say 'video AR', I actually mean aspect ratio after we've compensated for
@ -81,11 +87,14 @@ class Scaler {
*/ */
const streamAr = this.conf.video.videoWidth / this.conf.video.videoHeight; const streamAr = this.conf.video.videoWidth / this.conf.video.videoHeight;
const playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height; const playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height;
const compensatedStreamAr = streamAr * this.conf.getHeightCompensationFactor(); const heightCompensationFactor = this.conf.getHeightCompensationFactor();
const compensatedStreamAr = streamAr * heightCompensationFactor;
let arCorrectionFactor = 1; let arCorrectionFactor = 1;
if (playerAr < compensatedStreamAr) { if (playerAr < compensatedStreamAr) {
arCorrectionFactor = this.conf.player.dimensions.width / this.conf.video.offsetWidth; arCorrectionFactor = this.conf.player.dimensions.width / this.conf.video.offsetWidth;
} else if (ar.type !== AspectRatio.Reset) {
arCorrectionFactor /= heightCompensationFactor;
} }
if(!this.conf.video){ if(!this.conf.video){

View File

@ -138,15 +138,14 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video);
const playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height; const playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height;
let arCorrectionFactor = 1; let arCorrectionFactor = 1;
if (playerAr < streamAr) { arCorrectionFactor = this.conf.player.dimensions.width / this.conf.video.offsetWidth;
arCorrectionFactor = this.conf.player.dimensions.width / this.conf.video.offsetWidth;
}
return arCorrectionFactor; return arCorrectionFactor;
} }
calculateStretch(actualAr, playerArOverride) { calculateStretch(actualAr, playerArOverride) {
const playerAr = playerArOverride || this.conf.player.dimensions.width / this.conf.player.dimensions.height; const playerAr = playerArOverride || this.conf.player.dimensions.width / this.conf.player.dimensions.height;
const videoAr = this.conf.video.videoWidth / this.conf.video.videoHeight; const streamAr = this.conf.video.videoWidth / this.conf.video.videoHeight;
if (! actualAr){ if (! actualAr){
actualAr = playerAr; actualAr = playerAr;
@ -157,7 +156,7 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video);
yFactor: 1 yFactor: 1
}; };
if (playerAr >= videoAr){ if (playerAr >= streamAr){
// player adds PILLARBOX // player adds PILLARBOX
if(actualAr >= playerAr){ if(actualAr >= playerAr){
@ -166,18 +165,18 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video);
// actual > player > video — video is letterboxed // actual > player > video — video is letterboxed
// solution: horizontal stretch according to difference between video and player AR // solution: horizontal stretch according to difference between video and player AR
// vertical stretch according to difference between actual AR and player AR // vertical stretch according to difference between actual AR and player AR
stretchFactors.xFactor = playerAr / videoAr; stretchFactors.xFactor = playerAr / streamAr;
stretchFactors.yFactor = actualAr / videoAr; stretchFactors.yFactor = actualAr / streamAr;
this.logger.log('info', 'stretcher', "[Stretcher.js::calculateStretch] stretching strategy 1") this.logger.log('info', 'stretcher', "[Stretcher.js::calculateStretch] stretching strategy 1")
} else if ( actualAr >= videoAr) { } else if ( actualAr >= streamAr) {
// VERIFIED WORKS // VERIFIED WORKS
// player > actual > video — video is still letterboxed // player > actual > video — video is still letterboxed
// we need vertical stretch to remove black bars in video // we need vertical stretch to remove black bars in video
// we need horizontal stretch to make video fit width // we need horizontal stretch to make video fit width
stretchFactors.xFactor = playerAr / videoAr; stretchFactors.xFactor = playerAr / streamAr;
stretchFactors.yFactor = actualAr / videoAr; stretchFactors.yFactor = actualAr / streamAr;
this.logger.log('info', 'stretcher', "[Stretcher.js::calculateStretch] stretching strategy 2") this.logger.log('info', 'stretcher', "[Stretcher.js::calculateStretch] stretching strategy 2")
} else { } else {
@ -197,10 +196,10 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video);
// video > player > actual // video > player > actual
// video is PILLARBOXED // video is PILLARBOXED
stretchFactors.xFactor = actualAr / playerAr; stretchFactors.xFactor = actualAr / playerAr;
stretchFactors.yFactor = videoAr / playerAr; stretchFactors.yFactor = streamAr / playerAr;
this.logger.log('info', 'stretcher', "[Stretcher.js::calculateStretch] stretching strategy 4") this.logger.log('info', 'stretcher', "[Stretcher.js::calculateStretch] stretching strategy 4")
} else if ( actualAr < videoAr ) { } else if ( actualAr < streamAr ) {
// NEEDS CHECKING // NEEDS CHECKING
// video > actual > player // video > actual > player
@ -222,10 +221,11 @@ squeezeFactor: ${squeezeFactor}`, '\nvideo', this.conf.video);
} }
} }
// correct factors
const arCorrectionFactor = this.getArCorrectionFactor(); const arCorrectionFactor = this.getArCorrectionFactor();
// correct factors, unless we're trying to reset
stretchFactors.xFactor *= arCorrectionFactor; stretchFactors.xFactor *= arCorrectionFactor;
stretchFactors.yFactor *= arCorrectionFactor; stretchFactors.yFactor *= arCorrectionFactor;
stretchFactors.arCorrectionFactor = this.getArCorrectionFactor();
return stretchFactors; return stretchFactors;
} }