Skip to content

Commit

Permalink
fix: Properly size region anchor from LINE units (#5941)
Browse files Browse the repository at this point in the history
CEA708 captions may set windows in LINE units, this needs to be
converted to percentages to be properly displayed. In addition, adjust
by the region anchor.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
  • Loading branch information
gkatsev and avelad committed Nov 29, 2023
1 parent 2fcc2f8 commit 8b6602e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS
Expand Up @@ -55,6 +55,7 @@ Esteban Dosztal <edosztal@gmail.com>
Fadomire <fadomire@gmail.com>
Fernando Neira <slocomber@gmail.com>
François Beaufort <fbeaufort@google.com>
Gary Katsevman <git@gkatsev.com>
Gerardo Meola <meola.gerardo@gmail.com>
Gil Gonen <gil.gonen@gmail.com>
Giorgio Gamberoni <giorgio.gamberoni@gmail.com>
Expand Down
54 changes: 50 additions & 4 deletions lib/text/ui_text_displayer.js
Expand Up @@ -44,6 +44,9 @@ shaka.text.UITextDisplayer = class {
/** @private {HTMLElement} */
this.videoContainer_ = videoContainer;

/** @private {?number} */
this.aspectRatio_ = null;

/** @type {HTMLElement} */
this.textContainer_ = shaka.util.Dom.createHTMLElement('div');
this.textContainer_.classList.add('shaka-text-container');
Expand Down Expand Up @@ -90,6 +93,23 @@ shaka.text.UITextDisplayer = class {
this.updateCaptions_(/* forceUpdate= */ true);
});

// From: https://html.spec.whatwg.org/multipage/media.html#dom-video-videowidth
// Whenever the natural width or natural height of the video changes
// (including, for example, because the selected video track was changed),
// if the element's readyState attribute is not HAVE_NOTHING, the user
// agent must queue a media element task given the media element to fire an
// event named resize at the media element.
this.eventManager_.listen(this.video_, 'resize', () => {
const element = /** @type {!HTMLVideoElement} */ (this.video_);
const width = element.videoWidth;
const height = element.videoHeight;
if (width && height) {
this.aspectRatio_ = width / height;
} else {
this.aspectRatio_ = null;
}
});

/** @private {ResizeObserver} */
this.resizeObserver_ = null;
if ('ResizeObserver' in window) {
Expand Down Expand Up @@ -400,6 +420,10 @@ shaka.text.UITextDisplayer = class {
*/
getRegionElement_(cue) {
const region = cue.region;
// from https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#caption-window-size
// if aspect ratio is 4/3, use that value, otherwise, use the 16:9 value
const lineWidthMultiple = this.aspectRatio_ === 4/3 ? 2.5 : 1.9;
const lineHeightMultiple = 5.33;

const regionId = this.generateRegionId_(region);
if (this.regionElements_.has(regionId)) {
Expand All @@ -417,11 +441,33 @@ shaka.text.UITextDisplayer = class {
regionElement.id = 'shaka-text-region---' + regionId;
regionElement.classList.add('shaka-text-region');

regionElement.style.height = region.height + heightUnit;
regionElement.style.width = region.width + widthUnit;
regionElement.style.position = 'absolute';
regionElement.style.top = region.viewportAnchorY + viewportAnchorUnit;
regionElement.style.left = region.viewportAnchorX + viewportAnchorUnit;

const linesUnit = shaka.text.CueRegion.units.LINES;
if (region.heightUnits === linesUnit && region.widthUnits === linesUnit) {
regionElement.style.height = region.height * lineHeightMultiple + '%';
regionElement.style.width = region.width * lineWidthMultiple + '%';
} else {
regionElement.style.height = region.height + heightUnit;
regionElement.style.width = region.width + widthUnit;
}

if (region.viewportAnchorUnits === linesUnit) {
// from https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-708
let top = region.viewportAnchorY / 75 * 100;
const windowWidth = this.aspectRatio_ === 4/3 ? 160 : 210;
let left = region.viewportAnchorX / windowWidth * 100;
// adjust top and left values based on the region anchor and window size
top -= region.regionAnchorY * region.height * lineHeightMultiple / 100;
left -= region.regionAnchorX * region.width * lineWidthMultiple / 100;
regionElement.style.top = top + '%';
regionElement.style.left = left + '%';
} else {
regionElement.style.top = region.viewportAnchorY -
region.regionAnchorY * region.height / 100 + viewportAnchorUnit;
regionElement.style.left = region.viewportAnchorX -
region.regionAnchorX * region.width / 100 + viewportAnchorUnit;
}

regionElement.style.display = 'flex';
regionElement.style.flexDirection = 'column';
Expand Down

0 comments on commit 8b6602e

Please sign in to comment.