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
2 people authored and joeyparrish committed Feb 17, 2024
1 parent 30a71f2 commit f0a07bc
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Enson Choy <enson.choy@harmonicinc.com>
Esteban Dosztal <edosztal@gmail.com>
Fadomire <fadomire@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
Original file line number Diff line number Diff line change
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 f0a07bc

Please sign in to comment.