Skip to content

Commit c4451dc

Browse files
author
Matthew Shotton
committed
added initial mobile support by default, closes #14 & #16
1 parent 51e77a6 commit c4451dc

8 files changed

+586
-248
lines changed

dist/videocontext.commonjs2.js

+235-48
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/videocontext.commonjs2.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/videocontext.js

+259-124
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/videocontext.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "videocontext",
3-
"version": "0.26.0",
3+
"version": "0.27.0",
44
"description": "A WebGL & HTML5 graph based video composition library",
55
"contributors": [
66
{

src/SourceNodes/videonode.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ export default class VideoNode extends SourceNode {
66
* Initialise an instance of a VideoNode.
77
* This should not be called directly, but created through a call to videoContext.createVideoNode();
88
*/
9-
constructor(src, gl, renderGraph, currentTime, globalPlaybackRate=1.0, sourceOffset=0, preloadTime = 4, usingVideoElementCache=false, attributes = {}){
9+
constructor(src, gl, renderGraph, currentTime, globalPlaybackRate=1.0, sourceOffset=0, preloadTime = 4, videoElementCache=undefined, attributes = {}){
1010
super(src, gl, renderGraph, currentTime);
1111
this._preloadTime = preloadTime;
1212
this._sourceOffset = sourceOffset;
1313
this._globalPlaybackRate = globalPlaybackRate;
14-
this._usingVideoElementCache = usingVideoElementCache;
15-
if (this._usingVideoElementCache){
14+
this._videoElementCache = videoElementCache;
15+
if (this._videoElementCache){
1616
this._isResponsibleForElementLifeCycle = true;
17-
this._element.currentTime = this._sourceOffset;
17+
//this._element.currentTime = this._sourceOffset;
1818
}
1919
this._playbackRate = 1.0;
2020
this._playbackRateUpdated = true;
@@ -81,11 +81,15 @@ export default class VideoNode extends SourceNode {
8181
return;
8282
}
8383
if (this._isResponsibleForElementLifeCycle){
84-
this._element = document.createElement("video");
85-
this._element.setAttribute("crossorigin", "anonymous");
86-
this._element.setAttribute("webkit-playsinline", "");
84+
if (this._videoElementCache){
85+
this._element = this._videoElementCache.get();
86+
}else{
87+
this._element = document.createElement("video");
88+
this._element.setAttribute("crossorigin", "anonymous");
89+
this._element.setAttribute("webkit-playsinline", "");
90+
this._playbackRateUpdated = true;
91+
}
8792
this._element.src = this._elementURL;
88-
this._playbackRateUpdated = true;
8993

9094
for (let key in this._attributes) {
9195
this._element[key] = this._attributes[key];
@@ -98,8 +102,11 @@ export default class VideoNode extends SourceNode {
98102
super._destroy();
99103
if (this._isResponsibleForElementLifeCycle && this._element !== undefined){
100104
this._element.src = "";
105+
for (let key in this._attributes){
106+
this._element.removeAttribute(key);
107+
}
101108
this._element = undefined;
102-
if(!this._usingVideoElementCache) delete this._element;
109+
if(!this._videoElementCache) delete this._element;
103110
}
104111
this._ready = false;
105112
}

src/videocontext.js

+9-64
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import DestinationNode from "./DestinationNode/destinationnode.js";
1010
import EffectNode from "./ProcessingNodes/effectnode.js";
1111
import TransitionNode from "./ProcessingNodes/transitionnode.js";
1212
import RenderGraph from "./rendergraph.js";
13+
import VideoElementCache from "./videoelementcache.js";
1314
import { createSigmaGraphDataFromRenderGraph, visualiseVideoContextTimeline, visualiseVideoContextGraph, createControlFormForNode, UpdateablesManager, exportToJSON } from "./utils.js";
1415
import DEFINITIONS from "./Definitions/definitions.js";
1516

@@ -29,7 +30,7 @@ export default class VideoContext{
2930
* ctx.play();
3031
*
3132
*/
32-
constructor(canvas, initErrorCallback, options={"preserveDrawingBuffer":true, "manualUpdate":false, "endOnLastSourceEnd":true, useVideoElementCache:false, videoElementCacheSize:5, webglContextAttributes: {preserveDrawingBuffer: true, alpha: false }}){
33+
constructor(canvas, initErrorCallback, options={"preserveDrawingBuffer":true, "manualUpdate":false, "endOnLastSourceEnd":true, useVideoElementCache:true, videoElementCacheSize:6, webglContextAttributes: {preserveDrawingBuffer: true, alpha: false }}){
3334
this._canvas = canvas;
3435
let manualUpdate = false;
3536
this.endOnLastSourceEnd = true;
@@ -53,19 +54,11 @@ export default class VideoContext{
5354
}
5455

5556
// Initialise the video element cache
57+
if(!options.useVideoElementCache) options.useVideoElementCache = true;
5658
this._useVideoElementCache = options.useVideoElementCache;
5759
if (this._useVideoElementCache){
58-
this._videoElementCache = [];
59-
if (options.videoElementCacheSize === undefined) options.videoElementCacheSize = 5;
60-
console.log("USING VIDEO CACHE");
61-
console.log(options.videoElementCacheSize);
62-
for (var i = 0; i < options.videoElementCacheSize; i++) {
63-
let videoElement = document.createElement("video");
64-
videoElement.setAttribute("crossorigin", "anonymous");
65-
videoElement.setAttribute("webkit-playsinline", "");
66-
videoElement.src = "";
67-
this._videoElementCache.push(videoElement);
68-
}
60+
if (!options.videoElementCacheSize) options.videoElementCacheSize = 5;
61+
this._videoElementCache = new VideoElementCache(options.videoElementCacheSize);
6962
}
7063

7164

@@ -351,22 +344,9 @@ export default class VideoContext{
351344
*/
352345
play(){
353346
console.debug("VideoContext - playing");
354-
355-
//Mark the elements in the video element cache as being able to be controlled programattically.
356-
if (this._videoElementCache){
357-
for (var i = 0; i < this._videoElementCache.length; i++) {
358-
let videoElement = this._videoElementCache[i];
359-
videoElement.play().then(()=>{
360-
try {
361-
videoElement.pause();
362-
} catch(e) {
363-
//catch the inevitable DOM exception.
364-
}
365-
});
366-
}
367-
}
368-
369-
347+
//Initialise the video elemnt cache
348+
if (this._videoElementCache)this._videoElementCache.init();
349+
// set the state.
370350
this._state = VideoContext.STATE.PLAYING;
371351
return true;
372352
}
@@ -391,34 +371,6 @@ export default class VideoContext{
391371
}
392372

393373

394-
_getVideoElementCacheRemaining(){
395-
let cacheCount = 0;
396-
if (this._useVideoElementCache){
397-
for (var i = 0; i < this._videoElementCache.length; i++) {
398-
let videoElement = this._videoElementCache[i];
399-
// For some reason an uninitialised videoElement has its sr attribute set to the windows href. Hence the below check.
400-
if (videoElement.src === "" || videoElement.src === undefined || videoElement.src === window.location.href)cacheCount += 1;
401-
}
402-
}
403-
return cacheCount;
404-
}
405-
406-
_getCachedVideoElement(){
407-
if (this._useVideoElementCache){
408-
for (var i = 0; i < this._videoElementCache.length; i++) {
409-
let videoElement = this._videoElementCache[i];
410-
// For some reason an uninitialised videoElement has its sr attribute set to the windows href. Hence the below check.
411-
if (videoElement.src === "" || videoElement.src === undefined || videoElement.src === window.location.href) return videoElement;
412-
}
413-
} else {
414-
console.error("Video element cache not enabled, pass {useVideoElementCache:true} into the VideoContext constructor.");
415-
return;
416-
}
417-
console.error("No available video element in the cache");
418-
return;
419-
}
420-
421-
422374
/**
423375
* Create a new node representing a video source
424376
*
@@ -436,14 +388,7 @@ export default class VideoContext{
436388
* var videoNode = ctx.video(videoElement);
437389
*/
438390
video(src, sourceOffset=0, preloadTime=4, videoElementAttributes={}){
439-
let videoNode;
440-
if (this._useVideoElementCache && typeof src === "string"){
441-
let videoElement = this._getCachedVideoElement();
442-
videoElement.src = src;
443-
videoNode = new VideoNode(videoElement, this._gl, this._renderGraph, this._currentTime, this._playbackRate, sourceOffset, preloadTime, this._useVideoElementCache, videoElementAttributes);
444-
} else{
445-
videoNode = new VideoNode(src, this._gl, this._renderGraph, this._currentTime, this._playbackRate, sourceOffset, preloadTime, this._useVideoElementCache, videoElementAttributes);
446-
}
391+
let videoNode = new VideoNode(src, this._gl, this._renderGraph, this._currentTime, this._playbackRate, sourceOffset, preloadTime, this._videoElementCache, videoElementAttributes);
447392
this._sourceNodes.push(videoNode);
448393
return videoNode;
449394
}

src/videoelementcache.js

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
class VideoElementCache {
2+
3+
constructor(cache_size = 3) {
4+
this._elements = [];
5+
this._elementsInitialised = false;
6+
for (let i = 0; i < cache_size; i++) {
7+
let element = this._createElement();
8+
this._elements.push(element);
9+
}
10+
}
11+
12+
13+
_createElement(){
14+
let videoElement = document.createElement("video");
15+
videoElement.setAttribute("crossorigin", "anonymous");
16+
videoElement.setAttribute("webkit-playsinline", "");
17+
videoElement.src = "";
18+
return videoElement;
19+
}
20+
21+
init(){
22+
if (!this._elementsInitialised){
23+
for(let element of this._elements){
24+
element.play().then(()=>{
25+
element.pause();
26+
}, (e)=>{
27+
if (e.name !== "NotSupportedError")throw(e);
28+
});
29+
}
30+
}
31+
this._elementsInitialised = true;
32+
}
33+
34+
get() {
35+
console.log("GETTING FORM CACHE");
36+
//Try and get an already intialised element.
37+
for (let element of this._elements) {
38+
// For some reason an uninitialised videoElement has its sr attribute set to the windows href. Hence the below check.
39+
if (element.src === "" || element.src === undefined || element.src === window.location.href) return element;
40+
}
41+
//Fallback to creating a new element if non exists.
42+
console.debug("No available video element in the cache, creating a new one. This may break mobile, make your initial cache larger.");
43+
let element = this._createElement();
44+
this._elements.push(element);
45+
this._elementsInitialised = false;
46+
return element;
47+
}
48+
49+
get length(){
50+
return this._elements.length;
51+
}
52+
53+
get unused(){
54+
let count = 0;
55+
for (let element of this._elements) {
56+
// For some reason an uninitialised videoElement has its sr attribute set to the windows href. Hence the below check.
57+
if (element.src === "" || element.src === undefined || element.src === window.location.href) count += 1;
58+
}
59+
return count;
60+
}
61+
62+
}
63+
64+
export default VideoElementCache;

0 commit comments

Comments
 (0)