mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-14 15:56:38 +03:00
85 lines
2.0 KiB
JavaScript
85 lines
2.0 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.util.VideoFrameCallbackHandler');
|
|
|
|
goog.require('shaka.util.IReleasable');
|
|
|
|
|
|
/**
|
|
* Handles video frame callbacks using requestVideoFrameCallback.
|
|
*
|
|
* Note: Only one active callback can be registered at a time. Calling `start`
|
|
* will cancel any previously scheduled callback before registering a new one.
|
|
*
|
|
* @implements {shaka.util.IReleasable}
|
|
*/
|
|
shaka.util.VideoFrameCallbackHandler = class {
|
|
/**
|
|
* @param {!HTMLVideoElement} video
|
|
*/
|
|
constructor(video) {
|
|
/** @private {?HTMLVideoElement} */
|
|
this.video_ = video;
|
|
|
|
/** @private {?number} */
|
|
this.callbackHandle_ = null;
|
|
|
|
/** @private {?VideoFrameRequestCallback} */
|
|
this.boundCallback_ = null;
|
|
}
|
|
|
|
/**
|
|
* @param {!function(number, ?VideoFrameMetadata)} callback
|
|
* @param {boolean=} once
|
|
* @return {boolean}
|
|
*/
|
|
start(callback, once = false) {
|
|
this.cancelPending_();
|
|
|
|
if (!this.video_ ||
|
|
!('requestVideoFrameCallback' in this.video_)) {
|
|
return false;
|
|
}
|
|
|
|
const loopCallback = (now, metadata) => {
|
|
if (this.video_ && this.boundCallback_ === loopCallback) {
|
|
callback(now, metadata);
|
|
}
|
|
// Note: the callback can take some time, so we need to check again
|
|
// that the video and callback are still valid before scheduling another
|
|
// frame.
|
|
if (this.video_ && this.boundCallback_ === loopCallback && !once) {
|
|
this.callbackHandle_ =
|
|
this.video_.requestVideoFrameCallback(loopCallback);
|
|
}
|
|
};
|
|
|
|
this.boundCallback_ = loopCallback;
|
|
this.callbackHandle_ = this.video_.requestVideoFrameCallback(loopCallback);
|
|
|
|
return true;
|
|
}
|
|
|
|
/** @override */
|
|
release() {
|
|
this.cancelPending_();
|
|
this.video_ = null;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
cancelPending_() {
|
|
if (this.callbackHandle_ !== null) {
|
|
this.video_?.cancelVideoFrameCallback?.(this.callbackHandle_);
|
|
this.callbackHandle_ = null;
|
|
}
|
|
|
|
this.boundCallback_ = null;
|
|
}
|
|
};
|