@createjs/easeljs
Version:
The Easel JavaScript library provides a full, hierarchical display list, a core interaction model, and helper classes to make working with the HTML5 Canvas element much easier. Part of the CreateJS suite of libraries.
107 lines (95 loc) • 3.31 kB
JavaScript
/**
* @license VideoBuffer
* Visit http://createjs.com/ for documentation, updates and examples.
*
* Copyright (c) 2010 gskinner.com, inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
import createCanvas from "./Canvas";
/**
* When an HTML video seeks, including when looping, there is an indeterminate period before a new frame is available.
* This can result in the video blinking or flashing when it is drawn to a canvas. The VideoBuffer class resolves
* this issue by drawing each frame to an off-screen canvas and preserving the prior frame during a seek.
*
* @example
* let buffer = new VideoBuffer(video);
* let bitmap = new Bitmap(buffer);
*
* @param {HTMLVideoElement} video The HTML video element to buffer.
*/
export default class VideoBuffer {
constructor (video) {
/**
* Used by Bitmap to determine when the video buffer is ready to be drawn. Not intended for general use.
* @protected
* @type {Number}
*/
this.readyState = video.readyState;
/**
* @protected
* @type {HTMLVideoElement}
*/
this._video = video;
/**
* @protected
* @type {HTMLCanvasElement}
*/
this._canvas = null;
/**
* @protected
* @type {Number}
* @default -1
*/
this._lastTime = -1;
if (this.readyState < 2) {
video.addEventListener("canplaythrough", this._videoReady.bind(this));
}
// {once: true} isn't supported everywhere, but its a non-critical optimization here.
}
/**
* Gets an HTML canvas element showing the current video frame, or the previous frame if in a seek / loop.
* Primarily for use by {@link easeljs.Bitmap}.
*/
getImage () {
if (this.readyState < 2) { return; }
let canvas = this._canvas, video = this._video;
if (!canvas) {
canvas = this._canvas = createCanvas();
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
}
if (video.readyState >= 2 && video.currentTime !== this._lastTime) {
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
this._lastTime = video.currentTime;
}
return canvas;
}
/**
* @protected
*/
_videoReady () {
this.readyState = 2;
}
}