609 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			609 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
var AVProVideoWebGL = {
 | 
						|
    /*isNumber: function (item) {
 | 
						|
        return typeof(item) === "number" && !isNaN(item);
 | 
						|
    },
 | 
						|
    assert: function (equality, message) {
 | 
						|
        if (!equality)
 | 
						|
            console.log(message);
 | 
						|
    },*/
 | 
						|
    count: 0,
 | 
						|
    videos: [],
 | 
						|
    hasVideos__deps: ["videos"],
 | 
						|
    hasVideos: function (videoIndex) {
 | 
						|
        if (videoIndex) {
 | 
						|
            if (videoIndex == -1) {
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
 | 
						|
            if (_videos) {
 | 
						|
                if (_videos[videoIndex]) {
 | 
						|
                    return true;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            if (_videos) {
 | 
						|
                if (_videos.length > 0) {
 | 
						|
                    return true;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return false;
 | 
						|
    },
 | 
						|
    AVPPlayerInsertVideoElement__deps: ["count", "videos"],
 | 
						|
    AVPPlayerInsertVideoElement: function (path, idValues, externalLibrary) {
 | 
						|
        if (!path) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        // NOTE: When loading from the indexedDB (Application.persistantDataPath), 
 | 
						|
        //       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;
 | 
						|
 | 
						|
        if (externalLibrary == 1)
 | 
						|
        {
 | 
						|
            useNativeSrcPath = false;
 | 
						|
            var player = dashjs.MediaPlayer().create();
 | 
						|
            player.initialize(vid, path, true);
 | 
						|
        }
 | 
						|
        else if (externalLibrary == 2)
 | 
						|
        {
 | 
						|
            useNativeSrcPath = false;
 | 
						|
            var 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
 | 
						|
        };
 | 
						|
 | 
						|
        _videos.push(vidData);
 | 
						|
        playerIndex = (_videos.length > 0) ? _videos.length - 1 : 0;
 | 
						|
 | 
						|
        vid.oncanplay = function () {
 | 
						|
            if (!hasSetCanPlay) {
 | 
						|
                hasSetCanPlay = true;
 | 
						|
                vidData.ready = true;
 | 
						|
            }
 | 
						|
            //console.log("ONCANPLAY");
 | 
						|
        };
 | 
						|
 | 
						|
        vid.onloadedmetadata = function () {
 | 
						|
            vidData.hasMetadata = true;
 | 
						|
        };
 | 
						|
 | 
						|
        vid.oncanplaythrough = function () {
 | 
						|
            vidData.buffering = false;
 | 
						|
            //console.log("CANPLAYTHROUGH");
 | 
						|
        };
 | 
						|
 | 
						|
        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.autoplay = false;
 | 
						|
        if (useNativeSrcPath)
 | 
						|
        {
 | 
						|
            vid.src = path;
 | 
						|
        }
 | 
						|
 | 
						|
		HEAP32[(idValues>>2)] = playerIndex;
 | 
						|
		HEAP32[(idValues>>2)+1] = id;
 | 
						|
 | 
						|
		return true;
 | 
						|
    },
 | 
						|
    AVPPlayerGetLastError__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetLastError: function(playerIndex){
 | 
						|
        if(!_hasVideos(playerIndex))
 | 
						|
        {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        var ret = _videos[playerIndex].lastErrorCode
 | 
						|
        _videos[playerIndex].lastErrorCode = 0;
 | 
						|
 | 
						|
        return ret;
 | 
						|
    },
 | 
						|
    AVPPlayerFetchVideoTexture__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerFetchVideoTexture: function (playerIndex, texture, init) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[texture]);
 | 
						|
        if (!init)
 | 
						|
        {
 | 
						|
        	GLctx.texSubImage2D(GLctx.TEXTURE_2D, 0, 0, 0, GLctx.RGBA, GLctx.UNSIGNED_BYTE, _videos[playerIndex].video);
 | 
						|
        }
 | 
						|
        else
 | 
						|
		{
 | 
						|
        	GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA, GLctx.UNSIGNED_BYTE, _videos[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);
 | 
						|
	},
 | 
						|
    AVPPlayerUpdatePlayerIndex__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerUpdatePlayerIndex: function (id) {
 | 
						|
        var result = -1;
 | 
						|
 | 
						|
        if (!_hasVideos()) {
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        _videos.forEach(function (currentVid, index)
 | 
						|
        {
 | 
						|
        	if (currentVid != null && currentVid.id == id)
 | 
						|
        	{
 | 
						|
                result = index;
 | 
						|
            }
 | 
						|
        });
 | 
						|
 | 
						|
        return result;
 | 
						|
    },
 | 
						|
    AVPPlayerWidth__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerWidth: function (playerIndex) {
 | 
						|
    	if (!_hasVideos(playerIndex)) {
 | 
						|
    		return 0;
 | 
						|
    	}
 | 
						|
 | 
						|
    	return _videos[playerIndex].video.videoWidth;
 | 
						|
    },
 | 
						|
    AVPPlayerHeight__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerHeight: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.videoHeight;
 | 
						|
    },
 | 
						|
    AVPPlayerReady__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerReady: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        if (_videos) {
 | 
						|
            if (_videos.length > 0) {
 | 
						|
                if (_videos[playerIndex]) {
 | 
						|
                    return _videos[playerIndex].ready;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        //return _videos[playerIndex].video.readyState >= _videos[playerIndex].video.HAVE_CURRENT_DATA;
 | 
						|
    },
 | 
						|
    AVPPlayerClose__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerClose: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        var vid = _videos[playerIndex].video;
 | 
						|
 | 
						|
        vid.src = "";
 | 
						|
        vid.load();
 | 
						|
 | 
						|
        _videos[playerIndex].video = null;
 | 
						|
        _videos[playerIndex] = null;
 | 
						|
 | 
						|
        var allEmpty = true;
 | 
						|
        for (i = 0; i < _videos.length; i++) {
 | 
						|
        	if (_videos[i] != null) {
 | 
						|
        		allEmpty = false;
 | 
						|
        		break;
 | 
						|
        	}
 | 
						|
        }
 | 
						|
        if (allEmpty)
 | 
						|
        {
 | 
						|
        	_videos = [];
 | 
						|
        }
 | 
						|
        //_videos = _videos.splice(playerIndex, 1);
 | 
						|
 | 
						|
		// Remove from DOM
 | 
						|
        //vid.parentNode.removeChild(vid);
 | 
						|
    },
 | 
						|
    AVPPlayerSetLooping__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSetLooping: function (playerIndex, loop) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        _videos[playerIndex].video.loop = loop;
 | 
						|
    },
 | 
						|
    AVPPlayerIsLooping__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsLooping: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.loop;
 | 
						|
    },
 | 
						|
    AVPPlayerHasMetadata__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerHasMetadata: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return (_videos[playerIndex].video.readyState >= 1);
 | 
						|
        //return _videos[playerIndex].video.hasMetadata;
 | 
						|
    },
 | 
						|
    AVPPlayerIsPlaying__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsPlaying: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        var video = _videos[playerIndex].video;
 | 
						|
 | 
						|
        return !(video.paused || video.ended || video.seeking || video.readyState < video.HAVE_FUTURE_DATA);
 | 
						|
    },
 | 
						|
    AVPPlayerIsSeeking__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsSeeking: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.seeking;
 | 
						|
    },
 | 
						|
    AVPPlayerIsPaused__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsPaused: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.paused;
 | 
						|
    },
 | 
						|
    AVPPlayerIsFinished__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsFinished: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.ended;
 | 
						|
    },
 | 
						|
    AVPPlayerIsBuffering__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsBuffering: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].buffering;
 | 
						|
    },
 | 
						|
    AVPPlayerIsPlaybackStalled__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsPlaybackStalled: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].isStalled;
 | 
						|
    },
 | 
						|
    AVPPlayerPlay__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerPlay: function (playerIndex) {
 | 
						|
        if (!_hasVideos(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 = _videos[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: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerPause: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        _videos[playerIndex].video.pause();
 | 
						|
    },
 | 
						|
    AVPPlayerSeekToTime__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSeekToTime: function (playerIndex, timeSec, fast) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        var vid = _videos[playerIndex].video;
 | 
						|
 | 
						|
        if (vid.seekable && vid.seekable.length > 0) {
 | 
						|
        	for (i = 0; i < vid.seekable.length; i++) {
 | 
						|
            	if (timeSec >= vid.seekable.start(i) && timeSec <= vid.seekable.end(i)) {
 | 
						|
            		vid.currentTime = timeSec;
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (timeSec == 0) {
 | 
						|
                _videos[playerIndex].video.load();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    },
 | 
						|
    AVPPlayerGetCurrentTime__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetCurrentTime: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.currentTime;
 | 
						|
    },
 | 
						|
    AVPPlayerGetPlaybackRate__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetPlaybackRate: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.playbackRate;
 | 
						|
    },
 | 
						|
    AVPPlayerSetPlaybackRate__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSetPlaybackRate: function (playerIndex, rate) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        _videos[playerIndex].video.playbackRate = rate;
 | 
						|
    },
 | 
						|
    AVPPlayerSetMuted__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSetMuted: function (playerIndex, mute) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        _videos[playerIndex].video.muted = mute;
 | 
						|
    },
 | 
						|
    AVPPlayerGetDuration__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetDuration: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.duration;
 | 
						|
    },
 | 
						|
    AVPPlayerIsMuted__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerIsMuted: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.muted;
 | 
						|
    },
 | 
						|
    AVPPlayerSetVolume__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSetVolume: function (playerIndex, volume) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        _videos[playerIndex].video.volume = volume;
 | 
						|
    },
 | 
						|
    AVPPlayerGetVolume__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetVolume: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.volume;
 | 
						|
    },
 | 
						|
    AVPPlayerHasVideo__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerHasVideo: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        var isChrome = !!window.chrome && !!window.chrome.webstore;
 | 
						|
 | 
						|
        if(isChrome){
 | 
						|
            return Boolean(_videos[playerIndex].video.webkitVideoDecodedByteCount);
 | 
						|
        }
 | 
						|
        
 | 
						|
        if(_videos[playerIndex].video.videoTracks){
 | 
						|
            return Boolean(_videos[playerIndex].video.videoTracks.length);
 | 
						|
        }
 | 
						|
        
 | 
						|
        return true;
 | 
						|
    },
 | 
						|
    AVPPlayerHasAudio__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerHasAudio: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.mozHasAudio || Boolean(_videos[playerIndex].video.webkitAudioDecodedByteCount) || Boolean(_videos[playerIndex].video.audioTracks && _videos[playerIndex].video.audioTracks.length);
 | 
						|
    },
 | 
						|
    AVPPlayerAudioTrackCount__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerAudioTrackCount: function (playerIndex) {
 | 
						|
    	if (!_hasVideos(playerIndex)) {
 | 
						|
    		return 0;
 | 
						|
    	}
 | 
						|
    	var result = 0;
 | 
						|
    	if (_videos[playerIndex].video.audioTracks)
 | 
						|
    	{
 | 
						|
    		result = _videos[playerIndex].video.audioTracks.length;
 | 
						|
    	}
 | 
						|
    	return result;
 | 
						|
    },
 | 
						|
    AVPPlayerSetAudioTrack__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSetAudioTrack: function (playerIndex, trackIndex) {
 | 
						|
    	if (!_hasVideos(playerIndex)) {
 | 
						|
    		return;
 | 
						|
    	}
 | 
						|
    	if (_videos[playerIndex].video.audioTracks) {
 | 
						|
    		var audioTracks = _videos[playerIndex].video.audioTracks;
 | 
						|
    		for (i = 0; i < audioTracks.length; i++) {
 | 
						|
    			audioTracks[i].enabled = (i == trackIndex);
 | 
						|
    		}
 | 
						|
    	}
 | 
						|
    },
 | 
						|
    AVPPlayerGetDecodedFrameCount__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetDecodedFrameCount: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        var vid = _videos[playerIndex].video;
 | 
						|
        if (vid.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        var frameCount = 0;
 | 
						|
 | 
						|
        if (vid.webkitDecodedFrameCount)
 | 
						|
        {
 | 
						|
        	frameCount = vid.webkitDecodedFrameCount;
 | 
						|
        }
 | 
						|
        else if (vid.mozDecodedFrames)
 | 
						|
        {
 | 
						|
        	frameCount = vid.mozDecodedFrames;
 | 
						|
        }
 | 
						|
 | 
						|
        return frameCount;
 | 
						|
    },
 | 
						|
    AVPPlayerSupportedDecodedFrameCount__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerSupportedDecodedFrameCount: function (playerIndex) {
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
 | 
						|
        var vid = _videos[playerIndex].video;
 | 
						|
 | 
						|
        if (vid.webkitDecodedFrameCount)
 | 
						|
        {
 | 
						|
        	return true;
 | 
						|
        }
 | 
						|
        else if (vid.mozDecodedFrames)
 | 
						|
        {
 | 
						|
        	return true;
 | 
						|
        }
 | 
						|
 | 
						|
        return false;
 | 
						|
    },    
 | 
						|
    AVPPlayerGetNumBufferedTimeRanges__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetNumBufferedTimeRanges: function(playerIndex){   
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.buffered.length;
 | 
						|
    },
 | 
						|
    AVPPlayerGetTimeRangeStart__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetTimeRangeStart: function(playerIndex, rangeIndex){
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        if(rangeIndex >= _videos[playerIndex].video.buffered.length){
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.buffered.start(rangeIndex);
 | 
						|
    },
 | 
						|
    AVPPlayerGetTimeRangeEnd__deps: ["videos", "hasVideos"],
 | 
						|
    AVPPlayerGetTimeRangeEnd: function(playerIndex, rangeIndex){
 | 
						|
        if (!_hasVideos(playerIndex)) {
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        if(rangeIndex >= _videos[playerIndex].video.buffered.length){
 | 
						|
            return 0.0;
 | 
						|
        }
 | 
						|
 | 
						|
        return _videos[playerIndex].video.buffered.end(rangeIndex);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
autoAddDeps(AVProVideoWebGL, 'count');
 | 
						|
autoAddDeps(AVProVideoWebGL, 'videos');
 | 
						|
autoAddDeps(AVProVideoWebGL, 'hasVideos');
 | 
						|
mergeInto(LibraryManager.library, AVProVideoWebGL); |