mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-14 15:56:38 +03:00
4f62ce8b24
Ensure generated bundles contain a single license header instead of repeating the same notice across bundled modules. Normalize all copyright years to 2016 and remove duplicate license headers from generated bundles. This reduces the final bundle size while preserving license information in the distributed artifacts.
180 lines
4.1 KiB
JavaScript
180 lines
4.1 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.polyfill.VideoFrameCallback');
|
|
|
|
goog.require('shaka.polyfill');
|
|
|
|
|
|
/**
|
|
* @summary A polyfill for requestVideoFrameCallback.
|
|
* Uses requestAnimationFrame + getVideoPlaybackQuality.
|
|
* @export
|
|
*/
|
|
shaka.polyfill.VideoFrameCallback = class {
|
|
/**
|
|
* Install the polyfill if needed.
|
|
* @export
|
|
*/
|
|
static install() {
|
|
if (!window.HTMLVideoElement) {
|
|
return;
|
|
}
|
|
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
const proto = HTMLVideoElement.prototype;
|
|
|
|
if (proto.requestVideoFrameCallback) {
|
|
return;
|
|
}
|
|
|
|
if (!window.requestAnimationFrame) {
|
|
return;
|
|
}
|
|
|
|
if (!proto.getVideoPlaybackQuality) {
|
|
return;
|
|
}
|
|
|
|
proto.requestVideoFrameCallback =
|
|
shaka.polyfill.VideoFrameCallback.requestVideoFrameCallback_;
|
|
|
|
proto.cancelVideoFrameCallback =
|
|
shaka.polyfill.VideoFrameCallback.cancelVideoFrameCallback_;
|
|
}
|
|
|
|
/**
|
|
* @param {!HTMLVideoElement} video
|
|
* @return {!shaka.polyfill.VideoFrameCallback.CallbackData_}
|
|
* @private
|
|
*/
|
|
static getData_(video) {
|
|
let data = shaka.polyfill.VideoFrameCallback.callbackMap_.get(video);
|
|
|
|
if (!data) {
|
|
data = {
|
|
nextHandle: 1,
|
|
callbackHandlesToRafIds: new Map(),
|
|
presentedFrames: 0,
|
|
};
|
|
|
|
shaka.polyfill.VideoFrameCallback.callbackMap_.set(video, data);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* @this {HTMLVideoElement}
|
|
* @param {function(number, ?VideoFrameMetadata)} callback
|
|
* @return {number}
|
|
* @private
|
|
*/
|
|
static requestVideoFrameCallback_(callback) {
|
|
/** @type {!HTMLVideoElement} */
|
|
const video = this;
|
|
|
|
const data =
|
|
shaka.polyfill.VideoFrameCallback.getData_(video);
|
|
|
|
const handle = data.nextHandle++;
|
|
|
|
const checkFrame = (now) => {
|
|
if (!data.callbackHandlesToRafIds.has(handle)) {
|
|
return;
|
|
}
|
|
|
|
const quality = video.getVideoPlaybackQuality();
|
|
|
|
const presentedFrames = quality.totalVideoFrames || 0;
|
|
|
|
if (presentedFrames !== data.presentedFrames) {
|
|
data.presentedFrames = presentedFrames;
|
|
|
|
/** @type {!VideoFrameMetadata} */
|
|
const metadata = /** @type {!VideoFrameMetadata} */ ({
|
|
presentationTime: now,
|
|
expectedDisplayTime: now,
|
|
mediaTime: video.currentTime,
|
|
presentedFrames,
|
|
width: video.videoWidth,
|
|
height: video.videoHeight,
|
|
processingDuration: 0,
|
|
});
|
|
|
|
data.callbackHandlesToRafIds.delete(handle);
|
|
|
|
callback(now, metadata);
|
|
|
|
return;
|
|
}
|
|
|
|
const rafId = window.requestAnimationFrame(checkFrame);
|
|
|
|
data.callbackHandlesToRafIds.set(handle, rafId);
|
|
};
|
|
|
|
const rafId = window.requestAnimationFrame(checkFrame);
|
|
|
|
data.callbackHandlesToRafIds.set(handle, rafId);
|
|
|
|
return handle;
|
|
}
|
|
|
|
/**
|
|
* @this {HTMLVideoElement}
|
|
* @param {number} handle
|
|
* @private
|
|
*/
|
|
static cancelVideoFrameCallback_(handle) {
|
|
/** @type {!HTMLVideoElement} */
|
|
const video = this;
|
|
|
|
const data =
|
|
shaka.polyfill.VideoFrameCallback.callbackMap_.get(video);
|
|
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
const rafId = data.callbackHandlesToRafIds.get(handle);
|
|
|
|
if (rafId != null) {
|
|
window.cancelAnimationFrame(rafId);
|
|
data.callbackHandlesToRafIds.delete(handle);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @typedef {{
|
|
* nextHandle: number,
|
|
* callbackHandlesToRafIds: !Map<number, number>,
|
|
* presentedFrames: number
|
|
* }}
|
|
* @property {number} nextHandle
|
|
* @property {!Map<number, number>} callbackHandlesToRafIds
|
|
* Maps requestVideoFrameCallback handles to the corresponding
|
|
* requestAnimationFrame IDs so they can be cancelled later.
|
|
* @property {number} presentedFrames
|
|
* @private
|
|
*/
|
|
shaka.polyfill.VideoFrameCallback.CallbackData_;
|
|
|
|
|
|
/**
|
|
* @private {!WeakMap<
|
|
* !HTMLVideoElement,
|
|
* !shaka.polyfill.VideoFrameCallback.CallbackData_>}
|
|
*/
|
|
shaka.polyfill.VideoFrameCallback.callbackMap_ =
|
|
new WeakMap();
|
|
|
|
|
|
// Install at a low priority so that other Video polyfills go first.
|
|
shaka.polyfill.register(shaka.polyfill.VideoFrameCallback.install, -2);
|