1017 lines
25 KiB
JavaScript
Executable File
1017 lines
25 KiB
JavaScript
Executable File
var AVProVideoWebGL =
|
|
{
|
|
/*isNumber: function (item) {
|
|
return typeof(item) === "number" && !isNaN(item);
|
|
},
|
|
assert: function (equality, message) {
|
|
if (!equality)
|
|
console.log(message);
|
|
},*/
|
|
count: 0,
|
|
players: [],
|
|
|
|
isSafari: function() {
|
|
return navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && navigator.userAgent && navigator.userAgent.indexOf('CriOS') == -1 && navigator.userAgent.indexOf('FxiOS') == -1;
|
|
},
|
|
|
|
is_iOS: function() {
|
|
return [
|
|
'iPad Simulator',
|
|
'iPhone Simulator',
|
|
'iPod Simulator',
|
|
'iPad',
|
|
'iPhone',
|
|
'iPod'
|
|
].includes(navigator.platform)
|
|
// iPad on iOS 13 detection
|
|
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document);
|
|
},
|
|
|
|
hasPlayer__deps: ["players"],
|
|
hasPlayer: function (videoIndex)
|
|
{
|
|
if (videoIndex)
|
|
{
|
|
if (videoIndex == -1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (_players)
|
|
{
|
|
if (_players[videoIndex])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_players)
|
|
{
|
|
if (_players.length > 0)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
AVPPlayerInsertVideoElement__deps: ["count", "players", "isSafari", "is_iOS"],
|
|
AVPPlayerInsertVideoElement: function (path, idValues, externalLibrary)
|
|
{
|
|
if (!path) { return false; }
|
|
|
|
// NOTE: When loading from the indexedDB (Application.persistentDataPath),
|
|
// URL.createObjectURL() must be used get a valid URL. See:
|
|
// http://www.misfitgeek.com/html5-off-line-storing-and-retrieving-videos-with-indexeddb/
|
|
path = Pointer_stringify(path);
|
|
_count++;
|
|
|
|
var vid = document.createElement("video");
|
|
var useNativeSrcPath = true;
|
|
var hls = null;
|
|
|
|
if (externalLibrary == 1)
|
|
{
|
|
useNativeSrcPath = false;
|
|
var player = dashjs.MediaPlayer().create();
|
|
player.initialize(vid, path, true);
|
|
}
|
|
else if (externalLibrary == 2 && !(_is_iOS() || _isSafari()))
|
|
{
|
|
useNativeSrcPath = false;
|
|
hls = new Hls();
|
|
hls.loadSource(path);
|
|
hls.attachMedia(vid);
|
|
hls.on(Hls.Events.MANIFEST_PARSED, function()
|
|
{
|
|
//video.play();
|
|
});
|
|
}
|
|
else if (externalLibrary == 3)
|
|
{
|
|
//useNativeSrcPath = false;
|
|
}
|
|
|
|
// Some sources say that this is the proper way to catch errors...
|
|
/*vid.addEventListener('error', function(event) {
|
|
console.log("Error: " + event);
|
|
}, true);*/
|
|
|
|
var hasSetCanPlay = false;
|
|
var playerIndex;
|
|
var id = _count;
|
|
|
|
var vidData = {
|
|
id: id,
|
|
video: vid,
|
|
ready: false,
|
|
hasMetadata: false,
|
|
isStalled: false,
|
|
buffering: false,
|
|
lastErrorCode: 0,
|
|
hlsjs: hls
|
|
};
|
|
|
|
_players.push(vidData);
|
|
playerIndex = (_players.length > 0) ? _players.length - 1 : 0;
|
|
|
|
/*const frameCounterCallback = function (timeNow, metadata) {
|
|
console.log("got a frame! " + metadata.presentedFrames + " " + metadata.presentationTime);
|
|
vid.requestVideoFrameCallback(frameCounterCallback);
|
|
};
|
|
|
|
if (HTMLVideoElement.prototype.requestVideoFrameCallback)
|
|
{
|
|
console.log("has frame callback support");
|
|
vid.requestVideoFrameCallback(frameCounterCallback);
|
|
}*/
|
|
|
|
vid.oncanplay = function()
|
|
{
|
|
if (!hasSetCanPlay)
|
|
{
|
|
hasSetCanPlay = true;
|
|
vidData.ready = true;
|
|
}
|
|
};
|
|
|
|
vid.onloadedmetadata = function()
|
|
{
|
|
vidData.hasMetadata = true;
|
|
};
|
|
|
|
vid.oncanplaythrough = function()
|
|
{
|
|
vidData.buffering = false;
|
|
};
|
|
|
|
vid.onplaying = function()
|
|
{
|
|
vidData.buffering = false;
|
|
vidData.isStalled = false;
|
|
//console.log("PLAYING");
|
|
};
|
|
|
|
vid.onwaiting = function()
|
|
{
|
|
vidData.buffering = true;
|
|
//console.log("WAITING");
|
|
};
|
|
|
|
vid.onstalled = function()
|
|
{
|
|
vidData.isStalled = true;
|
|
//console.log("STALLED");
|
|
}
|
|
|
|
/*vid.onpause = function() {
|
|
};*/
|
|
|
|
vid.onended = function()
|
|
{
|
|
vidData.buffering = false;
|
|
vidData.isStalled = false;
|
|
//console.log("ENDED");
|
|
};
|
|
|
|
vid.ontimeupdate = function()
|
|
{
|
|
vidData.buffering = false;
|
|
vidData.isStalled = false;
|
|
//console.log("vid current time: ", this.currentTime);
|
|
};
|
|
|
|
vid.onerror = function(texture)
|
|
{
|
|
var err = "unknown error";
|
|
|
|
switch (vid.error.code) {
|
|
case 1:
|
|
err = "video loading aborted";
|
|
break;
|
|
case 2:
|
|
err = "network loading error";
|
|
break;
|
|
case 3:
|
|
err = "video decoding failed / corrupted data or unsupported codec";
|
|
break;
|
|
case 4:
|
|
err = "video not supported";
|
|
break;
|
|
}
|
|
|
|
vidData.lastErrorCode = vid.error.code;
|
|
|
|
console.log("Error: " + err + " (errorcode=" + vid.error.code + ")", "color:red;");
|
|
};
|
|
|
|
vid.crossOrigin = "anonymous";
|
|
vid.preload = 'auto';
|
|
vid.autoplay = false;
|
|
|
|
if (_is_iOS())
|
|
{
|
|
vid.autoplay = true;
|
|
vid.playsInline = true;
|
|
}
|
|
|
|
if (useNativeSrcPath)
|
|
{
|
|
vid.src = path;
|
|
}
|
|
|
|
HEAP32[(idValues>>2)] = playerIndex;
|
|
HEAP32[(idValues>>2)+1] = id;
|
|
|
|
return true;
|
|
},
|
|
|
|
AVPPlayerGetLastError__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetLastError: function(playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
var ret = _players[playerIndex].lastErrorCode
|
|
_players[playerIndex].lastErrorCode = 0;
|
|
|
|
return ret;
|
|
},
|
|
|
|
AVPPlayerCreateVideoTexture__deps: ["players", "hasPlayer"],
|
|
AVPPlayerCreateVideoTexture: function (textureId)
|
|
{
|
|
const texture = GLctx.createTexture();
|
|
GL.textures[textureId] = texture;
|
|
|
|
//console.log("creating textureId " +textureId + " : " + GL.textures[textureId]);
|
|
GLctx.bindTexture(GLctx.TEXTURE_2D, texture);
|
|
},
|
|
|
|
AVPPlayerDestroyVideoTexture__deps: ["players", "hasPlayer"],
|
|
AVPPlayerDestroyVideoTexture: function (textureId)
|
|
{
|
|
GLctx.deleteTexture(GL.textures[textureId]);
|
|
},
|
|
|
|
AVPPlayerFetchVideoTexture__deps: ["players", "hasPlayer"],
|
|
AVPPlayerFetchVideoTexture: function (playerIndex, textureId, init)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
//console.log("updating textureId " +textureId + " : " + GL.textures[textureId]);
|
|
GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[textureId]);
|
|
|
|
//GLctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
if (!init)
|
|
{
|
|
//GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA, GLctx.UNSIGNED_BYTE, _players[playerIndex].video);
|
|
GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, _players[playerIndex].video);
|
|
}
|
|
else
|
|
{
|
|
GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA, GLctx.UNSIGNED_BYTE, _players[playerIndex].video);
|
|
}
|
|
|
|
//NB: This line causes the texture to not show unless something else is rendered (not sure why)
|
|
//GLctx.bindTexture(GLctx.TEXTURE_2D, null);
|
|
GLctx.texParameteri(GLctx.TEXTURE_2D, GLctx.TEXTURE_WRAP_S, GLctx.CLAMP_TO_EDGE);
|
|
GLctx.texParameteri(GLctx.TEXTURE_2D, GLctx.TEXTURE_WRAP_T, GLctx.CLAMP_TO_EDGE);
|
|
GLctx.pixelStorei(GLctx.UNPACK_FLIP_Y_WEBGL, false);
|
|
},
|
|
|
|
AVPPlayerUpdatePlayerIndex__deps: ["players", "hasPlayer"],
|
|
AVPPlayerUpdatePlayerIndex: function (id)
|
|
{
|
|
var result = -1;
|
|
|
|
if (!_hasPlayer()) { return result; }
|
|
|
|
_players.forEach(function (currentVid, index)
|
|
{
|
|
if (currentVid != null && currentVid.id == id)
|
|
{
|
|
result = index;
|
|
}
|
|
});
|
|
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerWidth__deps: ["players", "hasPlayer"],
|
|
AVPPlayerWidth: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
return _players[playerIndex].video.videoWidth;
|
|
},
|
|
|
|
AVPPlayerHeight__deps: ["players", "hasPlayer"],
|
|
AVPPlayerHeight: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
return _players[playerIndex].video.videoHeight;
|
|
},
|
|
|
|
AVPPlayerReady__deps: ["players", "hasPlayer"],
|
|
AVPPlayerReady: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
if (_players)
|
|
{
|
|
if (_players.length > 0)
|
|
{
|
|
if (_players[playerIndex])
|
|
{
|
|
return _players[playerIndex].ready;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//return _players[playerIndex].video.readyState >= _players[playerIndex].video.HAVE_CURRENT_DATA;
|
|
},
|
|
|
|
AVPPlayerClose__deps: ["players", "hasPlayer"],
|
|
AVPPlayerClose: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
var vid = _players[playerIndex].video;
|
|
|
|
// Setting 'src' to an empty string results in the onerror handler being invoked and producing log noise on Chrome.
|
|
// Removing the src attribute and invoking load is a recommended best practice in the HTML Standard.
|
|
// See https://html.spec.whatwg.org/multipage/media.html#best-practices-for-authors-using-media-elements
|
|
vid.pause();
|
|
vid.removeAttribute("src"); // Previous: vid.src = "";
|
|
vid.load();
|
|
|
|
if (_players[playerIndex].hlsjs != null)
|
|
{
|
|
_players[playerIndex].hlsjs.destroy();
|
|
_players[playerIndex].hlsjs = null;
|
|
}
|
|
|
|
_players[playerIndex].video = null;
|
|
_players[playerIndex] = null;
|
|
|
|
var allEmpty = true;
|
|
for (i = 0; i < _players.length; i++) {
|
|
if (_players[i] != null) {
|
|
allEmpty = false;
|
|
break;
|
|
}
|
|
}
|
|
if (allEmpty)
|
|
{
|
|
_players = [];
|
|
}
|
|
//_players = _players.splice(playerIndex, 1);
|
|
|
|
// Remove from DOM
|
|
//vid.parentNode.removeChild(vid);
|
|
},
|
|
|
|
AVPPlayerSetLooping__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSetLooping: function (playerIndex, loop)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
_players[playerIndex].video.loop = loop;
|
|
},
|
|
|
|
AVPPlayerIsLooping__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsLooping: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].video.loop;
|
|
},
|
|
|
|
AVPPlayerHasMetadata__deps: ["players", "hasPlayer"],
|
|
AVPPlayerHasMetadata: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return (_players[playerIndex].video.readyState >= 1);
|
|
},
|
|
|
|
AVPPlayerIsPlaying__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsPlaying: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var video = _players[playerIndex].video;
|
|
|
|
return (!video.paused && !video.ended);// || video.seeking || video.readyState < video.HAVE_FUTURE_DATA);
|
|
},
|
|
|
|
AVPPlayerIsSeeking__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsSeeking: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].video.seeking;
|
|
},
|
|
|
|
AVPPlayerIsPaused__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsPaused: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].video.paused;
|
|
},
|
|
|
|
AVPPlayerIsFinished__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsFinished: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].video.ended;
|
|
},
|
|
|
|
AVPPlayerIsBuffering__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsBuffering: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].buffering;
|
|
},
|
|
|
|
AVPPlayerIsPlaybackStalled__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsPlaybackStalled: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].isStalled;
|
|
},
|
|
|
|
AVPPlayerPlay__deps: ["players", "hasPlayer"],
|
|
AVPPlayerPlay: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
// https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/
|
|
// https://developers.google.com/web/updates/2017/06/play-request-was-interrupted
|
|
var playPromise = _players[playerIndex].video.play();
|
|
if (playPromise !== undefined)
|
|
{
|
|
playPromise.then(function()
|
|
{
|
|
// Automatic playback started!
|
|
// Show playing UI.
|
|
})
|
|
.catch(function(error)
|
|
{
|
|
// Auto-play was prevented
|
|
// Show paused UI.
|
|
return false;
|
|
});
|
|
}
|
|
return true;
|
|
},
|
|
|
|
AVPPlayerPause__deps: ["players", "hasPlayer"],
|
|
AVPPlayerPause: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
_players[playerIndex].video.pause();
|
|
},
|
|
|
|
AVPPlayerSeekToTime__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSeekToTime: function (playerIndex, timeSec, fast)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
var vid = _players[playerIndex].video;
|
|
|
|
if (vid.seekable && vid.seekable.length > 0)
|
|
{
|
|
var timeNorm = 0.0;
|
|
if (vid.duration > 0.0)
|
|
{
|
|
timeNorm = timeSec / vid.duration;
|
|
}
|
|
for (i = 0; i < vid.seekable.length; i++)
|
|
{
|
|
if (timeNorm >= vid.seekable.start(i) && timeNorm <= vid.seekable.end(i))
|
|
{
|
|
if (fast && vid.fastSeek)
|
|
{
|
|
vid.fastSeek(timeNorm);
|
|
}
|
|
else
|
|
{
|
|
vid.currentTime = timeSec;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (timeSec == 0.0)
|
|
{
|
|
vid.load();
|
|
}
|
|
else
|
|
{
|
|
vid.currentTime = timeSec;
|
|
}
|
|
}
|
|
},
|
|
|
|
AVPPlayerGetCurrentTime__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetCurrentTime: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0.0; }
|
|
|
|
return _players[playerIndex].video.currentTime;
|
|
},
|
|
|
|
AVPPlayerGetDuration__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetDuration: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0.0; }
|
|
|
|
return _players[playerIndex].video.duration;
|
|
},
|
|
|
|
AVPPlayerGetPlaybackRate__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetPlaybackRate: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0.0; }
|
|
|
|
return _players[playerIndex].video.playbackRate;
|
|
},
|
|
|
|
AVPPlayerSetPlaybackRate__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSetPlaybackRate: function (playerIndex, rate)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
_players[playerIndex].video.playbackRate = rate;
|
|
},
|
|
|
|
AVPPlayerSetMuted__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSetMuted: function (playerIndex, mute)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
_players[playerIndex].video.muted = mute;
|
|
},
|
|
|
|
AVPPlayerIsMuted__deps: ["players", "hasPlayer"],
|
|
AVPPlayerIsMuted: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].video.muted;
|
|
},
|
|
|
|
AVPPlayerSetVolume__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSetVolume: function (playerIndex, volume)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return; }
|
|
|
|
_players[playerIndex].video.volume = volume;
|
|
},
|
|
|
|
AVPPlayerGetVolume__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetVolume: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0.0; }
|
|
|
|
return _players[playerIndex].video.volume;
|
|
},
|
|
|
|
AVPPlayerHasVideo__deps: ["players", "hasPlayer"],
|
|
AVPPlayerHasVideo: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var isChrome = !!window.chrome && !!window.chrome.webstore;
|
|
|
|
if (isChrome)
|
|
{
|
|
return Boolean(_players[playerIndex].video.webkitVideoDecodedByteCount > 0);
|
|
}
|
|
|
|
if (_players[playerIndex].video.videoTracks)
|
|
{
|
|
return Boolean(_players[playerIndex].video.videoTracks.length > 0);
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
AVPPlayerHasAudio__deps: ["players", "hasPlayer"],
|
|
AVPPlayerHasAudio: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
return _players[playerIndex].video.mozHasAudio || Boolean(_players[playerIndex].video.webkitAudioDecodedByteCount) ||
|
|
Boolean(_players[playerIndex].video.audioTracks && _players[playerIndex].video.audioTracks.length);
|
|
},
|
|
|
|
AVPPlayerGetDecodedFrameCount__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetDecodedFrameCount: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
var vid = _players[playerIndex].video;
|
|
if (vid.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA) { return 0; }
|
|
|
|
var frameCount = 0;
|
|
|
|
if (vid.mozPresentedFrames)
|
|
{
|
|
frameCount = vid.mozPresentedFrames;
|
|
}
|
|
else if (vid.mozDecodedFrames)
|
|
{
|
|
frameCount = vid.mozDecodedFrames;
|
|
}
|
|
else if (vid.webkitDecodedFrameCount)
|
|
{
|
|
frameCount = vid.webkitDecodedFrameCount;
|
|
}
|
|
|
|
/*var q = vid.getVideoPlaybackQuality();
|
|
if (q)
|
|
{
|
|
console.log("frames: " + q.totalVideoFrames + " " + q.droppedVideoFrames);
|
|
}*/
|
|
|
|
return frameCount;
|
|
},
|
|
|
|
AVPPlayerSupportedDecodedFrameCount__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSupportedDecodedFrameCount: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var vid = _players[playerIndex].video;
|
|
|
|
if (vid.mozPresentedFrames)
|
|
{
|
|
return true;
|
|
}
|
|
else if (vid.mozDecodedFrames)
|
|
{
|
|
return true;
|
|
}
|
|
else if (vid.webkitDecodedFrameCount)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
AVPPlayerGetNumBufferedTimeRanges__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetNumBufferedTimeRanges: function(playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
if (_players[playerIndex].video.buffered)
|
|
{
|
|
return _players[playerIndex].video.buffered.length;
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
AVPPlayerGetTimeRangeStart__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetTimeRangeStart: function(playerIndex, rangeIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0.0; }
|
|
|
|
if (_players[playerIndex].video.buffered)
|
|
{
|
|
if(rangeIndex >= _players[playerIndex].video.buffered.length)
|
|
{
|
|
return 0.0;
|
|
}
|
|
return _players[playerIndex].video.buffered.start(rangeIndex);
|
|
}
|
|
return 0.0;
|
|
},
|
|
|
|
AVPPlayerGetTimeRangeEnd__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetTimeRangeEnd: function(playerIndex, rangeIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0.0; }
|
|
|
|
if (_players[playerIndex].video.buffered)
|
|
{
|
|
if(rangeIndex >= _players[playerIndex].video.buffered.length)
|
|
{
|
|
return 0.0;
|
|
}
|
|
return _players[playerIndex].video.buffered.end(rangeIndex);
|
|
}
|
|
return 0.0;
|
|
},
|
|
|
|
AVPPlayerGetVideoTrackCount__deps: ["players", "hasPlayer", "AVPPlayerHasVideo"],
|
|
AVPPlayerGetVideoTrackCount: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
var result = 0;
|
|
var tracks = _players[playerIndex].video.videoTracks;
|
|
if (tracks)
|
|
{
|
|
result = tracks.length;
|
|
}
|
|
else
|
|
{
|
|
if (_AVPPlayerHasVideo(playerIndex))
|
|
{
|
|
result = 1;
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetAudioTrackCount__deps: ["players", "hasPlayer", "AVPPlayerHasAudio"],
|
|
AVPPlayerGetAudioTrackCount: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
var result = 0;
|
|
var tracks = _players[playerIndex].video.audioTracks;
|
|
if (tracks)
|
|
{
|
|
result = tracks.length;
|
|
}
|
|
else
|
|
{
|
|
if (_AVPPlayerHasAudio(playerIndex))
|
|
{
|
|
result = 1;
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetTextTrackCount__deps: ["players", "hasPlayer"],
|
|
AVPPlayerGetTextTrackCount: function (playerIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return 0; }
|
|
|
|
var result = 0;
|
|
var tracks = _players[playerIndex].video.textTracks;
|
|
if (tracks)
|
|
{
|
|
result = tracks.length;
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerSetActiveVideoTrack__deps: ["players", "hasPlayer"],
|
|
AVPPlayerSetActiveVideoTrack: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = false;
|
|
if (_players[playerIndex].video.videoTracks)
|
|
{
|
|
var tracks = _players[playerIndex].video.videoTracks;
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
tracks[trackIndex].selected = true;
|
|
result = true;
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerSetActiveAudioTrack: ["players", "hasPlayer"],
|
|
AVPPlayerSetActiveAudioTrack: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = false;
|
|
if (_players[playerIndex].video.audioTracks)
|
|
{
|
|
var tracks = _players[playerIndex].video.audioTracks;
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
for (i = 0; i < tracks.length; i++)
|
|
{
|
|
tracks[i].enabled = (i === trackIndex);
|
|
}
|
|
result = true;
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerSetActiveTextTrack: ["players", "hasPlayer"],
|
|
AVPPlayerSetActiveTextTrack: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = false;
|
|
if (_players[playerIndex].video.textTracks)
|
|
{
|
|
var tracks = _players[playerIndex].video.textTracks;
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
for (i = 0; i < tracks.length; i++)
|
|
{
|
|
tracks[i].mode = (i === trackIndex)?"showing":"disabled";
|
|
}
|
|
result = true;
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerStringToBuffer: [],
|
|
AVPPlayerStringToBuffer: function (text)
|
|
{
|
|
// Get size of the string
|
|
var bufferSize = lengthBytesUTF8(text) + 1;
|
|
// Allocate memory space
|
|
var buffer = _malloc(bufferSize);
|
|
// Copy old data to the new one then return it
|
|
stringToUTF8(text, buffer, bufferSize);
|
|
return buffer;
|
|
},
|
|
|
|
AVPPlayerGetVideoTrackName: ["players", "hasPlayer", "AVPPlayerStringToBuffer"],
|
|
AVPPlayerGetVideoTrackName: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = null;
|
|
var tracks = _players[playerIndex].video.videoTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = _AVPPlayerStringToBuffer(tracks[trackIndex].label);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetAudioTrackName: ["players", "hasPlayer", "AVPPlayerStringToBuffer"],
|
|
AVPPlayerGetAudioTrackName: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = null;
|
|
var tracks = _players[playerIndex].video.audioTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = _AVPPlayerStringToBuffer(tracks[trackIndex].label);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetTextTrackName: ["players", "hasPlayer", "AVPPlayerStringToBuffer"],
|
|
AVPPlayerGetTextTrackName: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = null;
|
|
var tracks = _players[playerIndex].video.textTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = _AVPPlayerStringToBuffer(tracks[trackIndex].label);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetVideoTrackLanguage: ["players", "hasPlayer", "AVPPlayerStringToBuffer"],
|
|
AVPPlayerGetVideoTrackLanguage: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = null;
|
|
var tracks = _players[playerIndex].video.videoTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = _AVPPlayerStringToBuffer(tracks[trackIndex].language);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetAudioTrackLanguage: ["players", "hasPlayer", "AVPPlayerStringToBuffer"],
|
|
AVPPlayerGetAudioTrackLanguage: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = null;
|
|
var tracks = _players[playerIndex].video.audioTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = _AVPPlayerStringToBuffer(tracks[trackIndex].language);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerGetTextTrackLanguage: ["players", "hasPlayer", "AVPPlayerStringToBuffer"],
|
|
AVPPlayerGetTextTrackLanguage: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = null;
|
|
var tracks = _players[playerIndex].video.textTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = _AVPPlayerStringToBuffer(tracks[trackIndex].language);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerIsVideoTrackActive: ["players", "hasPlayer", "AVPPlayerHasVideo"],
|
|
AVPPlayerIsVideoTrackActive: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = false;
|
|
var tracks = _players[playerIndex].video.videoTracks;
|
|
if (tracks)
|
|
{
|
|
result = (tracks.selectedIndex === trackIndex);
|
|
}
|
|
else
|
|
{
|
|
result = _AVPPlayerHasVideo(playerIndex);
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerIsAudioTrackActive: ["players", "hasPlayer", "AVPPlayerHasAudio"],
|
|
AVPPlayerIsAudioTrackActive: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = false;
|
|
var tracks = _players[playerIndex].video.audioTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = tracks[trackIndex].enabled;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = _AVPPlayerHasAudio(playerIndex);
|
|
}
|
|
return result;
|
|
},
|
|
|
|
AVPPlayerIsTextTrackActive: ["players", "hasPlayer"],
|
|
AVPPlayerIsTextTrackActive: function (playerIndex, trackIndex)
|
|
{
|
|
if (!_hasPlayer(playerIndex)) { return false; }
|
|
|
|
var result = false;
|
|
var tracks = _players[playerIndex].video.textTracks;
|
|
if (tracks)
|
|
{
|
|
if (trackIndex >=0 && trackIndex < tracks.length)
|
|
{
|
|
result = (tracks[trackIndex].mode === "showing");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
|
|
autoAddDeps(AVProVideoWebGL, 'count');
|
|
autoAddDeps(AVProVideoWebGL, 'players');
|
|
autoAddDeps(AVProVideoWebGL, 'hasPlayer');
|
|
autoAddDeps(AVProVideoWebGL, 'AVPPlayerHasVideo');
|
|
autoAddDeps(AVProVideoWebGL, 'AVPPlayerHasAudio');
|
|
autoAddDeps(AVProVideoWebGL, 'AVPPlayerStringToBuffer');
|
|
mergeInto(LibraryManager.library, AVProVideoWebGL); |