const { pipelines, components, utils, Buffer } = window.mediaStreamLibrary; Number.prototype.toUnsigned = function() { return ((this >>> 1) * 2 + (this & 1)); }; const ulawencodeTable = [ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]; window.vxgwsplayer = function(id, options_){ window.vxgwsplayer.version="1.1.2"; //version is updated by 'npm run build' window.vxgwsplayer.players = window.vxgwsplayer.players || {}; if(!document.getElementById(id)){ console.error(" Player with " + id + " did not found"); return undefined; } if(!window.vxgwsplayer.players[id]){ /* if(typeof chrome == "undefined"){ vxgwsplayer.showAvailableInChrome(id); return undefined; } if(navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i) ){ vxgwsplayer.showAvailableInChrome(id); return undefined; }; */ /* if(!vxgwsplayer.browserSupportsPluginPnacl()){ console.log("Not installed vxg_media_player"); vxgwsplayer.showNotInstalled(id); var fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (fs) { fs(window.TEMPORARY,100,function(){},function(){ vxgwsplayer.showNotInstalledInIncognitoMode(id); }); } return undefined; } */ // magic run app /* var fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (!fs) { //console.log("RequestFileSystem failed"); window.location.href = "https://www.videoexpertsgroup.com/player_start/"; } else { fs(window.TEMPORARY, 1, function(){ //console.log("not in incognito mode"); if(!vxgwsplayer.isFrame()){ //console.log("Start Chrome App"); window.location.href = "https://www.videoexpertsgroup.com/player_start/"; } }, function(){ console.log("Not installed vxg_media_player"); }); } */ // check web socket server /* if(window.location.protocol != "https:" && !vxgwsplayer.isFrame()){ vxgwsplayer.checkWebSocket().done(function(result){ //console.log('websocket: success'); }).fail(function(err){ // check incognito mode fs(window.TEMPORARY,1,function(){ vxgwsplayer.showWebSocketFailed(id); },function(){ vxgwsplayer.showNotStartedInIncognitoMode(id); }); }); } */ if(window.location.protocol != "https:" && vxgwsplayer.isFrame()){ vxgwsplayer.checkWebSocket().done(function(result){ //console.log('websocket: success'); }).fail(function(err){ vxgwsplayer.showNotStartedInIFrame(id); }); } //window.location.href = "https://videoexpertsgroup.com/player_start/"; window.vxgwsplayer.players[id] = new function(id, opts){ const self = this; self.id = id; self.player = document.getElementById(id); /* init options */ window.vxgwsplayer.initOptions(self, opts); self.playerWidth=self.options.width || 640; self.playerHeight=self.options.height || 480; self.playerWidth = parseInt(self.player.getAttribute('width'),10) || self.playerWidth; self.playerHeight = parseInt(self.player.getAttribute('height'),10) || self.playerHeight; self.player.style.width = self.playerWidth + 'px'; self.player.style.height = self.playerHeight + 'px'; self.wd = null; self.wdtries = 0; self.wdwork = null; var html = '' + '
' + '' + '' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + ' ' + ' ' +'
' +'
' +'
' + '
' + '' // + '' + '' + '' /* + window.vxgwsplayer.generateEmbededElement(self); */ self.player.innerHTML = html; var el_controls = self.player.getElementsByClassName('vxgwsplayer-controls')[0]; var el_controls_zoom = self.player.getElementsByClassName('vxgwsplayer-controls-zoom')[0]; var el_controls_zoom_position = self.player.getElementsByClassName('vxgwsplayer-controls-zoom-position')[0]; var el_play = self.player.getElementsByClassName('vxgwsplayer-play')[0]; var el_pause = self.player.getElementsByClassName('vxgwsplayer-pause')[0]; var el_stop = self.player.getElementsByClassName('vxgwsplayer-stop')[0]; var el_fullscreen = self.player.getElementsByClassName('vxgwsplayer-fullscreen')[0]; var el_takescreenshot = self.player.getElementsByClassName('vxgwsplayer-takescreenshot')[0]; var el_screenshot_loading = self.player.getElementsByClassName('vxgwsplayer-screenshot-loading')[0]; var el_scale = self.player.getElementsByClassName('vxgwsplayer-scale')[0]; var el_zoomUp = self.player.getElementsByClassName('vxgwsplayer-zoom-up')[0]; var el_zoomDown = self.player.getElementsByClassName('vxgwsplayer-zoom-down')[0]; var el_zoomProgress = self.player.getElementsByClassName('vxgwsplayer-zoom-progress')[0]; var el_zoomPositionCursor = self.player.getElementsByClassName('vxgwsplayer-zoom-position-cursor')[0]; var el_loader = self.player.getElementsByClassName('vxgwsplayer-loader')[0]; var el_error = self.player.getElementsByClassName('vxgwsplayer-error')[0]; var el_error_text = self.player.getElementsByClassName('vxgwsplayer-error-text')[0]; var el_video = self.player.getElementsByClassName('vxgwsplayer-native-video')[0]; var el_snap_stub = self.player.getElementsByClassName('vxgwsplayer-stub-snapshot')[0]; var el_record = self.player.getElementsByClassName('vxgwsplayer-stub-record')[0]; var el_btnstart = document.getElementById(id + '_btnstart'); self.video = el_video; self.video.onplay = function() { var b = self.video.buffered; if (b.length > 0) self.video.currentTime = b.end(b.length - 1) - self.m.latency/1000; console.log('onplay: start=' + self.video.currentTime + ', buffer=(' + b.start(b.length - 1) + ', ' + b.end(b.length - 1) + ')'); /* var b = self.video.buffered; if (b.length == 0) { console.log('no buffer'); } else { if ((b.end(0)*1000 - self.m.latency > 0) && (self.video.paused )) { self.video.paused = false; self.video.currentTime = b.end(0) - self.m.latency/1000; self.pipeline.play(); } console.log('buffer:' + b.start(0) + '~' + b.end(0)); } */ } self.video.onpause = function() { console.log('onpause'); } /* self.module = document.getElementById(id + '_nacl_module'); self.module.command = function(){ var cmd = []; for(var i = 0; i < arguments.length; i++){ cmd.push(arguments[i]); } if(id != self.id || self.id + '_nacl_module' != self.module.id){ console.error("Mixed player id"); } if(self.m.debug){ console.log('Player: ' + self.id + ' cmd=[' + cmd.join('] ')); } self.module.postMessage(cmd); // self.module.postMessage(arguments); } // Request the offsetTop property to force a relayout. As of Apr 10, 2014 // this is needed if the module is being loaded on a Chrome App's // background page (see crbug.com/350445). self.module.offsetTop; */ self.m.versionapp = "unknown"; self.m.debug = self.options.debug || self.player.hasAttribute('debug') || false; var watchdog_tr = self.player.getAttribute('watchdog'); // self.m.watchdog = ( (watchdog_tr !== undefined) && (watchdog_tr !==null) && (watchdog_tr !== "") ) ? parseInt(watchdog_tr,10) : 3; // if fps=1, 3sec is not enough to fill buffer to satisfy latency. self.m.watchdog = ( (watchdog_tr !== undefined) && (watchdog_tr !==null) && (watchdog_tr !== "") ) ? parseInt(watchdog_tr,10) : 5; self.m.autostart = self.player.hasAttribute('autostart'); self.m.is_opened = false; self.m.latency = 0; self.m.controls = true; self.m.avsync = self.options.avsync || false; self.m.vxgReadyState = 0; self.m.autohide = self.options.autohide || 2000; self.m.lastErrorCode = -1; self.m.lastErrorDecoder = 0; self.m.autoreconnect = self.options.autoreconnect || 0; self.m.connection_timeout = self.options.connection_timeout || 0; self.m.connection_udp = self.options.connection_udp || 0; self.m.isCustomDigitalZoom = self.options.custom_digital_zoom || false; self.currentZoom = 10; self.m.snapshotFile = ""; self.m.snapshotPTS = "-1"; self.m.PTSVideo = "-1"; self.m.PTSAudio = "-1"; self.m.playAfterBufferFill = false; self.m.lastRecvTime = Date.now(); vxgwsplayer.initVolumeControls(self, false); if(self.m.debug){ console.log("Player " + self.id + " - init new player"); } self.set_controls_opacity = function(val){ el_controls.style.opacity = val; el_controls_zoom.style.opacity = val; el_controls_zoom_position.style.opacity = val; } self.set_controls_display = function(val){ el_controls.style.display = val; if(self.m.isCustomDigitalZoom == true){ el_controls_zoom.style.display = "none"; el_controls_zoom_position.style.display = "none"; }else{ el_controls_zoom.style.display = val; el_controls_zoom_position.style.display = self.currentZoom == 10 ? "none" : ""; } } if(self.m.isCustomDigitalZoom == false){ el_controls_zoom_position.style.display = self.currentZoom == 10 ? "none" : ""; } if(self.player.hasAttribute('custom-digital-zoom')){ self.m.isCustomDigitalZoom = true; el_controls_zoom.style.display = "none"; el_controls_zoom_position.style.display = "none"; } if(!self.player.hasAttribute('controls')){ self.m.controls = false; self.set_controls_display("none"); } if(self.options.controls && self.options.controls == true){ self.m.controls = true; self.set_controls_display(""); } self.m.avsync = self.player.hasAttribute('avsync'); self.m.aspectRatio = (self.player.hasAttribute('aspect-ratio-mode'))?(parseInt(self.player.getAttribute('aspect-ratio-mode'),10)):0; if(self.player.hasAttribute('autohide')){ self.m.autohide = parseInt(self.player.getAttribute('autohide'),10)*1000; }else if(self.options.autohide){ self.m.autohide = self.options.autohide*1000; } self.timeout = undefined; self.loadSettings = function(){ if(self.m.debug){ console.log('Player ' + self.id + ' - loadSettings'); } /* if(self.player.hasAttribute('useragent-prefix')){ self.module.command('setuseragent', self.player.getAttribute('useragent-prefix') + ' ' + navigator.userAgent) }else if(self.options.useragent_prefix){ self.module.command('setuseragent', self.options.useragent_prefix + ' ' + navigator.userAgent) } */ /* self.module = document.getElementById(self.id + '_nacl_module'); self.module.command = function(){ var cmd = []; for(var i = 0; i < arguments.length; i++){ cmd.push(arguments[i]); } if(id != self.id || self.id + '_nacl_module' != self.module.id){ console.error("Mixed player id"); } if(self.m.debug){ console.log('Player: ' + self.id + ' cmd=[' + cmd.join('] ')); } self.module.postMessage(cmd); // self.module.postMessage(arguments); } self.module.offsetTop; self.module.command('setversion', window.vxgwsplayer.version); */ //self.m.autoreconnect = 0; if(self.player.hasAttribute('auto-reconnect') || self.options.autoreconnect){ self.m.autoreconnect = 1; /* self.module.command('setautoreconnect', '1'); */ } if(self.player.hasAttribute('connection-timeout')){ self.m.connection_timeout = parseInt(self.player.getAttribute('connection-timeout'), 10); } if(self.options.connection_timeout != 0){ /* self.module.command('setconnection_timeout', self.m.connection_timeout.toString()); */ } if(self.player.hasAttribute('connection-udp') || self.m.connection_udp){ self.m.connection_udp = 1; /* self.module.command('setconnection_udp', '1'); */ } self.m.avsync = self.player.hasAttribute('avsync'); self.m.aspectRatio = 0; if(self.player.hasAttribute('aspect-ratio-mode')){ self.m.aspectRatio = parseInt(self.player.getAttribute('aspect-ratio-mode'), 10); }else if(self.options.aspect_ratio_mode){ self.m.aspectRatio = self.options.aspect_ratio_mode; } self.aspectRatioMode(self.m.aspectRatio); /* self.module.command('setavsync', self.m.avsync ? '1' : '0'); */ if(self.player.hasAttribute('latency')){ self.m.latency = parseInt(self.player.getAttribute('latency'), 10); /* self.module.command('setlatency', self.m.latency.toString()); */ }else if(self.options.latency){ self.m.latency = self.options.latency; /* self.module.command('setlatency', self.m.latency.toString()); */ } if (self.m.latency < 0) { self.m.latency = 0; } window.vxgwsplayer.initVolumeControls(self, true); if(self.player.hasAttribute('autohide')){ self.m.autohide = parseInt(self.player.getAttribute('autohide'),10)*1000; }else if(self.options.autohide){ self.m.autohide = self.options.autohide*1000; } } self.moduleDidLoad = function(){ if(self.m.debug){ console.log('Player ' + self.id + ' - moduleDidLoad'); } self.loadSettings(); if(window.location.protocol == "https:"){ //use Native protocol self.connectToApp(); }else{ //use Websocket protocol /* self.module.command('startwebsclient', vxgwsplayer.webserverport) */ } } self.playerDidLoad = function(){ self.loadSettings(); if(self.m.debug){ console.log('Player ' + self.id + " - playerDidLoad"); } if(self.onReadyStateCallback){ self.m.is_opened = false; self.onReadyStateCallback(); }else{ self.setSource(); //binary, wsurl and rtspurl should be inited } } self.connectToApp = function(){ if(self.m.debug){ console.log('Player ' + self.id + ' connectToApp'); } //self.m.port = chrome.runtime.connect("hncknjnnbahamgpjoafdebabmoamcnni"); //self.m.port = chrome.runtime.connect("invalid"); if(self.m.debug){ console.log('Player ' + self.id + ' connected port='+self.m.port); } self.m.portName = ""+ new Date().getTime().toString(); /* self.m.port.onDisconnect.addListener(function(){ if(self.m.debug) console.log('disconnected portName='+self.m.portName); self.module.command( 'stopnativeclient', '@'+self.m.portName); self.m.port = undefined; }); */ if(self.m.debug) console.log('connected portName='+self.m.portName); /* self.m.port.onMessage.addListener(function(msg) { if( msg != undefined && msg.id == undefined && msg[0] != undefined && msg[0].charAt(0) == '@'){ if(self.module.postMessage == undefined){ self.m.port.disconnect(); }else{ self.module.postMessage(msg); } }else if( msg != undefined && msg.cmd == 'getversionapp'){ if(0 == msg.data.indexOf("VERSION_APP")){ self.m.versionapp = msg.data.split(' ')[1]; if(self.m.debug){ console.log('Player ' + self.id + ' =VERSION_APP '+self.m.versionapp); } self.module.command( 'setappversion', self.m.versionapp); self.module.command( 'startnativeclient', '@'+self.m.portName); self.playerDidLoad(); }else{ console.log('Player ' + self.id + ' Invalid VERSION_APP msg.data='+msg.data); } }else{ console.log('Player ' + self.id + 'getversionapp unknown msg=', msg); } }); self.m.port.postMessage({id: ""+self.m.portName, cmd: "getversionapp", data: ""} ); */ } self.showerror = function(text){ el_loader.style.display = "none"; el_error.style.display = "inline-block"; el_error_text.style.display = "inline-block"; el_error_text.innerHTML = text; } self.hideerror = function(text){ el_error.style.display = "none"; el_error_text.style.display = "none"; } self.readyState = function(){ return self.m.vxgReadyState; } self.onReadyStateChange = function(cb){ self.onReadyStateCallback = cb; } self.ready = self.onReadyStateChange; self.onStateChange = function(cb){ self.onStateChangeCallback = cb; } self.onBandwidthError = function(cb){ self.m.handlerBandwidthError = cb; } self.onError = function(cb){ self.m.handlerError = cb; } /* self.handleMessage = function(msgEvent){ if(self.m.debug){ console.log('Player ' + self.id + ' handleMessage: ' + msgEvent.data); } if(msgEvent == undefined || msgEvent.data == undefined){ return; } if(msgEvent.data[0] != undefined && msgEvent.data[0].charAt(0) == '@'){ //proto native send to app if(self.m.port != undefined){ self.m.port.postMessage(msgEvent.data); } }else if(0 == msgEvent.data.indexOf("PLAYER_INITED")){ self.moduleDidLoad(); }else if(0 == msgEvent.data.indexOf("PLAYER_INIT_ERR")){ str = "PLAYER_INIT_ERR "; err = parseInt(msgEvent.data.split(' ')[1], 10); err_type = (err >> 16)&0xffff; console.log('err_type='+err_type); switch(err_type){ case 4: str += "Init audio output error "; break; case 2: str += "Init video decoder error "; break; default: str += "Init D3D error "; break; } str += ""+err.toString(); vxgwsplayer.showInitFailed(id, str); }else // Player source error=60935 WSS status=6 // Player listener2: Skip picture: 170, frame_duration: 41, latencyms: 0<=frames_buf:0, b: 0, p: 0 if(0 == msgEvent.data.indexOf("VERSION_APP")){ self.m.versionapp = msgEvent.data.split(' ')[1]; if(self.m.debug) console.log('=VERSION_APP '+self.m.versionapp); self.playerDidLoad(); }else if(0 == msgEvent.data.indexOf("PTS_VIDEO")){ self.m.PTSVideo = msgEvent.data.split(' ')[1]; //console.log('=PTS_VIDEO '+self.m.PTSVideo); }else if(0 == msgEvent.data.indexOf("PTS_AUDIO")){ self.m.PTSAudio = msgEvent.data.split(' ')[1]; //console.log('=PTS_AUDIO '+self.m.PTSAudio); }else if(0 == msgEvent.data.indexOf("TAKE_SNAPSHOT")){ snap_status = msgEvent.data.split(' ')[1]; snap_pts = msgEvent.data.split(' ')[2]; console.log('TAKE_SNAPSHOT snap_status='+snap_status+' snap_pts='+snap_pts); if(0 != snap_status.indexOf("ERROR")){ self.m.snapshotFile = snap_status; if(snap_pts != undefined) self.m.snapshotPTS = snap_pts; window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem(window.TEMPORARY, 1, function(fs) { fs.root.getFile(self.m.snapshotFile, {create: false}, function(fileEntry) { // /test is filename var pom = document.createElement('a'); pom.setAttribute('href', fileEntry.toURL()); if(self.m.snapshotPTS == -1){ pom.setAttribute('download', "snapshot.jpg"); }else{ pom.setAttribute('download', "snapshot_"+self.m.snapshotPTS+".jpg"); } pom.style.display = 'none'; document.body.appendChild(pom); pom.click(); document.body.removeChild(pom); }, function(e) { console.error("[vxgwsplayer] TAKE_SNAPSHOT fs.root.getFile FAILED") }); }, function(e) { console.error("[vxgwsplayer] TAKE_SNAPSHOT requestFileSystem window.TEMPORARY FAILED") }); } }else if(msgEvent.data == "MEDIA_ERR_URL"){ self.showerror('Problem with URL'); self.m.lastErrorCode = 0; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_NETWORK")){ self.showerror('Problem with network'); self.m.lastErrorCode = 1; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_SOURCE")){ self.showerror('Problem with source'); self.m.lastErrorCode = 2; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_CARRIER")){ self.showerror('Problem with carrier'); self.m.lastErrorCode = 3; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_AUDIO")){ self.showerror('Problem with audio'); self.m.lastErrorCode = 4; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_VIDEO")){ self.showerror('Problem with video'); self.m.lastErrorCode = 5; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_AUTHENTICATION")){ self.showerror('Problem with authentification'); self.m.lastErrorCode = 6; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_BANDWIDTH")){ //self.stop(); self.m.lastErrorCode = 7; if(self.m.handlerError) self.m.handlerError(self); if(self.m.handlerBandwidthError){ self.m.handlerBandwidthError(self); }else{ //self.showerror('Problem with bandwidth'); } }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_EOF")){ self.showerror('End of File'); self.m.lastErrorCode = 8; if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("MEDIA_ERR_DECODER")){ var arr = msgEvent.data.split(' '); self.m.lastErrorDecoder = (arr.length > 1) ? parseInt(arr[1],10) : 0; if(self.m.debug) console.log('=MEDIA_ERR_DECODER '+self.m.lastErrorDecoder + ' ' + (self.m.lastErrorDecoder == 0)?'Decoder resumed':''); if(self.m.lastErrorDecoder == 0){ self.m.lastErrorCode = -1; //self.hideerror(); }else{ self.m.lastErrorCode = 9; //self.showerror('Decoder error '+self.m.lastErrorDecoder); } if(self.m.handlerError) self.m.handlerError(self); }else if(0 == msgEvent.data.indexOf("PLAYER_CONNECTING")){ self.m.vxgReadyState = 1; //el_play.style.display = "none"; // el_stop.style.display = "none"; // self.hideerror(); el_loader.style.display = "inline-block"; el_takescreenshot.style.display = "none"; if(self.onStateChangeCallback) self.onStateChangeCallback(self.m.vxgReadyState); }else if(0 == msgEvent.data.indexOf("PLAYER_PLAYING")){ //console.log('PLAYER_PLAYING'); self.m.vxgReadyState = 2; el_play.style.display = "none"; el_stop.style.display = "inline-block"; el_pause.style.display = "inline-block"; el_takescreenshot.style.display = "inline-block"; self.hideerror(); el_loader.style.display = "none"; if(self.onStateChangeCallback) self.onStateChangeCallback(self.m.vxgReadyState); }else if(0 == msgEvent.data.indexOf("PLAYER_STOPPING")){ self.m.vxgReadyState = 3; // el_error.style.display = "none"; // el_loader.style.display = "inline-block"; el_play.style.display = "none"; el_stop.style.display = "none"; el_pause.style.display = "none"; el_takescreenshot.style.display = "none"; }else if(0 == msgEvent.data.indexOf("PLAYER_STOPPED")){ self.m.vxgReadyState = 0; el_play.style.display = "inline-block"; el_stop.style.display = "none"; el_pause.style.display = "none"; el_takescreenshot.style.display = "none"; if(self.onStateChangeCallback) self.onStateChangeCallback(self.m.vxgReadyState); }else if(0 == msgEvent.data.indexOf("PLAYER_PAUSED")){ //console.log('PLAYER_PAUSED'); self.m.vxgReadyState = 4; el_play.style.display = "inline-block"; el_stop.style.display = "inline-block"; el_pause.style.display = "none"; // el_takescreenshot.style.display = "none"; if(self.onStateChangeCallback) self.onStateChangeCallback(self.m.vxgReadyState); } } */ self.handleError = function(){ el_loader.style.display = "none"; el_error.style.display = "block"; console.error("ERROR"); self.showerror('Unknown error'); } self.handleCrash = function(){ el_loader.style.display = "none"; el_error.style.display = "block"; self.showerror('Crashed'); } self.restartTimeout = function(){ if(self.m.autohide <= 0){ self.set_controls_opacity("0"); return; } self.set_controls_opacity("0.7"); clearTimeout(self.timeout); self.timeout = setTimeout(function(){ self.set_controls_opacity("0"); },self.m.autohide); }; self.player.addEventListener('mousemove', function(){ self.restartTimeout(); }, true); self.restartTimeout(); /* //self.module.addEventListener('load', self.moduleDidLoad, true); self.module.addEventListener('message', self.handleMessage, true); self.module.addEventListener('error', self.handleError, true); self.module.addEventListener('crash', self.handleCrash, true); */ if (typeof window.attachListeners !== 'undefined') { window.attachListeners(); } self.error = function(){ return self.m.lastErrorCode; } self.errorDecoder = function(){ return self.m.lastErrorDecoder; } self.controls = function(val){ if(val == undefined){ return self.m.controls; }else{ if(val == true){ self.set_controls_display(""); self.m.controls = true; }else if(val == false){ self.set_controls_display("none"); self.m.controls = false; } } } self.debug = function(val){ if(val == undefined){ return self.m.debug; }else{ self.m.debug = val; } } // Truen var stinit = 0; var svt = 0; var sdt = 0; self.play = function(){ self.hideerror(); self.m.vxgReadyState = 1; if (self.pipeline === undefined || self.pipeline == null) { var isCreated = self.createPipeline(); if (isCreated != true) { el_loader.style.display = "none"; return; } } self.pipeline.ready.then(function(){ firstPackage = null; self.pipeline.rtsp.play(); //self.pipeline.play(); //record-on-start 300s //self.startRecord(300*1000); el_stop.style.display = "inline-block"; el_pause.style.display = "inline-block"; el_takescreenshot.style.display = "inline-block"; el_loader.style.display = "none"; if(self.onStateChangeCallback){ self.onStateChangeCallback(self.m.vxgReadyState); } }); if(self.m.debug) console.log( 'self.play self.m.url='+self.m.url + ' self.m.is_opened='+self.m.is_opened); if(!self.m.is_opened){ self.m.is_opened = true; /* self.module.command('open', self.m.url); */ } el_play.style.display = "none"; if(self.m.vxgReadyState != 4) {//not paused=>play, show progress el_loader.style.display = "inline-block"; } /* self.module.command('play', '0'); */ self.applyVolume(); stinit = 0; svt = 0; sdt = 0; self.wdwork = setTimeout(function(){ self.updateStreamInfo(); }, 1000); }; self.restart = function (reason) { console.log(reason); self.wdtries = 0; self.wd = null; clearTimeout(self.wdwork); self.wdwork = null; self.stop(); self.play(); } self.updateStreamInfo = function() { if (self.pipeline) { var curtime = self.pipeline.currentTime; if(self.m.debug){ console.log("curtime:" + curtime + "; wd:" + self.wd); } if (stinit == 0) { svt = curtime; sdt = Date.now(); stinit = 1; } var stdiff = ((Date.now() - sdt) / 1000) - (curtime - svt); if (stdiff >= 0.5) { //console.warn('update currenttime! id : ' + self.id + ', dif : ' + stdiff); //el_video.currentTime = Date.now(); } if (self.m.watchdog <= 0 ) { console.log('Watchdog disabled by user'); return; } if (self.video.paused && !self.m.playAfterBufferFill) { console.log('Video paused. Skip watchdog'); var now = Date.now(); //console.log("Now: " + now + ", lastRecvTime: " + self.m.lastRecvTime); if ((now - self.m.lastRecvTime) > 5 * 1000) { self.m.lastRecvTime = now; self.restart('restart by recvTime'); return; } self.wdtries = 0; self.wd = curtime; self.wdwork = setTimeout(function(){ self.updateStreamInfo(); }, 1000); return; } if ((self.wd == null) || /*(self.video.paused) || */((curtime - self.wd >= 0.0) && (self.wdtries < self.m.watchdog) ) ){ if ((curtime - self.wd > 0.2)/* || (self.video.paused)*/ ){ self.wdtries = 0; } else { self.wdtries += 1; } self.wd = curtime; self.wdwork = setTimeout(function(){ self.updateStreamInfo(); }, 1000); } else { self.restart('restart by wd'); } } } self.stop = function(){ /* self.module.command('stop', '0'); */ pps = ''; sps = ''; if (self.wdwork) { clearTimeout(self.wdwork); self.wdwork = null; } self.wdtries = 0; self.wd = null; if (dataCatcherWdId) { clearTimeout(dataCatcherWdId); dataCatcherWdId = null; } dataCatcherWdCnt = 0; if (self.pipeline !== undefined && self.pipeline != null) { self.pipeline.pause(); self.pipeline.close(); self.pipeline = null; } if (self.audBuffer) { self.audBuffer.clear(); //self.audBuffer = null; } self.m.vxgReadyState = 0; el_play.style.display = "inline-block"; el_stop.style.display = "none"; el_pause.style.display = "none"; el_takescreenshot.style.display = "none"; if(self.onStateChangeCallback){ self.onStateChangeCallback(self.m.vxgReadyState); } el_loader.style.display = "none"; }; self.pause = function(){ //console.log("pause"); /* self.module.command('pause', '0'); */ self.pipeline.pause(); if (self.audBuffer) { self.audBuffer.clear(); } self.m.vxgReadyState = 4; el_play.style.display = "inline-block"; el_stop.style.display = "inline-block"; el_pause.style.display = "none"; // el_takescreenshot.style.display = "none"; if(self.onStateChangeCallback) { self.onStateChangeCallback(self.m.vxgReadyState); } el_loader.style.display = "none"; }; self.autohide = function(val){ if(val){ self.m.autohide = val*1000; }else{ return self.m.autohide/1000; } } self.autoreconnect = function(val){ if(val == undefined){ return self.m.autoreconnect; }else{ self.m.autoreconnect = parseInt(val,10); /* self.module.command('setautoreconnect', self.m.autoreconnect.toString()); */ } }; self.latency = function(val){ if(val && val >= 0){ self.m.latency = parseInt(val,10); /* self.module.command('setlatency', val.toString()); */ }else{ return self.m.latency; } }; self.connection_timeout = function(val){ if(val){ self.m.connection_timeout = parseInt(val,10); /* self.module.command('setconnection_timeout', val.toString()); */ }else{ return self.m.connection_timeout; } }; self.connection_udp = function(val){ if(val){ self.m.connection_udp = parseInt(val,10); /* self.module.command('setconnection_udp', val.toString()); */ }else{ return self.m.connection_udp; } }; /* self.aspectRatio = function(val){ if(val == undefined){ return self.m.aspectRatio?true:false; }else{ self.m.aspectRatio = (val)?self.m.aspectRatioMode:0; self.module.command('setaspectratio', self.m.aspectRatio.toString()); } } */ self.aspectRatioMode = function(val){ if(val == undefined){ return self.m.aspectRatioMode; }else{ self.m.aspectRatioMode = (val > 0)?val:self.m.aspectRatioMode; self.m.aspectRatio = val; if (val == 0) { self.video.classList.remove('fill'); self.video.classList.remove('cover'); self.video.classList.add('contain'); } else if (val == 1) { self.video.classList.remove('fill'); self.video.classList.add('cover'); self.video.classList.remove('contain'); } else if (val == 2) { self.video.classList.add('fill'); self.video.classList.remove('cover'); self.video.classList.remove('contain'); } } } self.aspectRatioMode(self.m.aspectRatio); self.avsync = function(val){ if(val == undefined){ return self.m.avsync; }else{ self.m.avsync = val; /* self.module.command('setavsync', self.m.avsync ? '1':'0'); */ } } self.isPlaying = function(){ return (self.m.vxgReadyState == 2); } self.versionPLG = function(){ return window.vxgwsplayer.version; } self.versionAPP = function(){ return self.m.versionapp; } self.size = function(width, height){ if(width && height){ if(Number.isInteger(width) && Number.isInteger(height)){ var w = parseInt(width,10); var h = parseInt(height,10); self.playerWidth = self.playerWidth != w ? w : self.playerWidth; self.playerHeight = self.playerHeight != h ? h : self.playerHeight; self.player.style.width = width + 'px'; self.player.style.height = height + 'px'; }else{ self.player.style.width = width; self.player.style.height = height; } }else{ return { width: self.playerWidth, height: self.playerHeight }; } }; self.changedFullscreen = function(){ console.log('changedFullscreen'); if (document.webkitIsFullScreen){ self.size('100%', '100%'); console.log('changedFullscreen -> fullscreen'); }else{ self.size(self.playerWidth + 'px', self.playerHeight + 'px'); console.log('changedFullscreen -> NOT fullscreen'); } }; if (document.addEventListener){ document.addEventListener('webkitfullscreenchange', self.changedFullscreen, false); document.addEventListener('mozfullscreenchange', self.changedFullscreen, false); document.addEventListener('fullscreenchange', self.changedFullscreen, false); document.addEventListener('MSFullscreenChange', self.changedFullscreen, false); } self.fullscreen = function(){ console.log("fullscreen: clicked"); if(document.webkitIsFullScreen == true){ document.webkitCancelFullScreen(); }else{ if(self.player.requestFullscreen) { self.player.requestFullscreen(); } else if(self.player.webkitRequestFullscreen) { self.player.webkitRequestFullscreen(); } else if(self.player.mozRequestFullscreen) { self.player.mozRequestFullScreen(); } } }; self.takescreenshot = function(){ var stub = el_snap_stub; var videotag = el_video; if (videotag != null ) { var width = videotag.videoWidth ; var height = videotag.videoHeight; if ((width > 0) && (height > 0)) { stub.setAttribute('width', width); stub.setAttribute('height', height); context = stub.getContext('2d'); if (context != null) { context.fillRect(0, 0, width, height); context.drawImage(videotag, 0, 0, width, height); var downloadLink = document.createElement('a'); // jpg downloadLink.setAttribute('download', 'snapshot.jpg'); stub.toBlob(function(blob) { var url = URL.createObjectURL(blob); downloadLink.setAttribute('href', url); downloadLink.click(); }, 'image/jpeg', 1.0); /* png downloadLink.setAttribute('download', 'snapshot.png'); stub.toBlob(function(blob) { var url = URL.createObjectURL(blob); downloadLink.setAttribute('href', url); downloadLink.click(); }); */ } } } el_screenshot_loading.style.display = "block"; setTimeout(function(){ el_screenshot_loading.style.display = ""; },3000); }; self.getScreenshotPTS = function(){ return self.m.snapshotPTS; }; self.getPTSVideo = function(){ return self.m.PTSVideo; }; self.getPTSAudio = function(){ return self.m.PTSAudio; }; var audioCtx = null; var audioGain = null; var audioFlt = null; var audIsRun = false; var audBuffer = null; self.initAudioCtx = function() { if (self.audioCtx != null || self.audioCtx !== undefined) { return; } try { window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext; self.audioCtx = new AudioContext(); self.audioCtx.onstatechange = function() { if (self.audioCtx !== null && self.audioCtx !== undefined) { if (self.audioCtx.state === "running") { console.log(" audio context running"); self.audIsRun = true; } else if (audioContext.state === "closed") { console.log(" audio context close"); self.audioCtx = null; self.audIsRun = false; } } } if (self.audioCtx !== undefined && self.audioCtx !== null) { self.audioGain = self.audioCtx.createGain(); self.audBuffer = new audioBufferPCM(self.audioCtx, self.audioGain, 8000, 8/*48*/); self.audioGain.connect(self.audioCtx.destination) } return true; } catch (err) { console.warn("Web Audio API is not supported in this web browser! : ", err); } } self.audioPlayBuffer = function( data ) { if (!self.audIsRun) { return; } //test sinus for noise camera //for (var i = 0; i < data.length; ++i) { // data[i] = (Math.sin( i ) + 1.0) * 256; //} var data_js = new Float32Array(data.length); for (var i = 0; i < data.length; i++) { data_js[i] = data[i] / Math.pow(2, 15) } if(self.isMute()) { self.audioGain.gain.value = 0; } else { self.audioGain.gain.value = self.m.volume; } if (self.audBuffer != null && self.audBuffer !== undefined) { self.audBuffer.addBuffer( data_js); } delete data_js; data_js = null; } self.recordedData264 = null; self.recordedData711 = null; var recData264Len = 0; var recData711Len = 0; var isRecording = false; var isRecStarted = false; var isRecStopping = false; var firstPackage = null; var record_wd = null; var record_try = 0; var prevRecLen = 0; self.rech264maxsize = self.options.clipH264maxsize || Number(self.player.getAttribute('clipH264maxsize')) || 768*1024*1024; //~10min for 10Mbit self.recg711maxsize = self.options.clipG711maxsize || Number(self.player.getAttribute('clipG711maxsize')) || 64*1024*1024; self.defaultClipName = self.options.clipname || self.player.getAttribute('clipname') || 'clip'; var pps = ''; var sps = ''; // Truen var dataCatcherWdId = undefined; var dataCatcherWdCnt = 0; self.m.debug = self.options.debug || self.player.hasAttribute('debug') || false; function arraysAreEqual(a, b) { var ret_val = Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]); return ret_val; } self.debug = function(){ //pps = '1'; //test possible pps-changing } self.createPipeline = function(){ el_loader.style.display = "inline-block"; firstPackage = null; if ((self.m.wsurl !== undefined && self.m.wsurl.length > 0) && (self.m.rtspurl !== undefined && self.m.rtspurl.length > 0)){ self.m.is_opened = true; let Pipeline = pipelines.Html5VideoPipeline; let mediaElement = el_video; pps = ''; sps = ''; var authopts = {} if (self.m.user && self.m.password) { authopts = { username: self.m.user, password: self.m.password } } self.pipeline = new Pipeline({ ws: { uri: self.m.wsurl, }, rtsp: { uri: self.m.rtspurl, }, auth: authopts, mediaElement, }); self.pipeline.onSourceOpen = function(mse, tracks) { //mse.duration = 10.0; //mse.sourceBuffers[0].timestampOffset = -3.0; } var dataCatcherRTP = new components.dataCatcherDepay(0);//ULAW dataCatcherRTP.onDataCallback = function( msg) { if(self.m.debug){ console.log('Playback' + ((isRecording)?('+Recording'):('')) +': data(ulaw) catcher: len ' + msg.data.length + ' type:' + msg.type + ' rawdata len ' + msg.rawdata.length ); } if (isRecStarted == true) { if (recData711Len + msg.data.length < self.recg711maxsize) { var data = msg.data; self.recordedData711.set( data, recData711Len); recData711Len += data.length; delete msg.data; delete data; data = null; } } msg = null; } self.pipeline.insertAfter(self.pipeline.firstComponent.next, dataCatcherRTP); var lastupdatetime = Date.now(); var forceupdatecheckcount = 0; var forceupdatecountthreshold = 10; var forceupdatetimethreshold = 100; //ms self.pipeline.onDataCallback = function(sourceBuffer, msg) { // mp4 with H264 or H264+AAC self.m.lastRecvTime = Date.now(); var b = sourceBuffer.buffered; if (b.length == 0) { //console.log('no buffer'); } else if (false) { if ((b.end(0)*1000 - self.m.latency > 0) && (self.video.paused ) && (self.m.vxgReadyState != 4)) { self.video.paused = false; self.pipeline.play(); } else { if ((Date.now() - lastupdatetime >= 100) || forceupdatecheckcount > 0) { if ((self.video.currentTime + (self.m.latency + forceupdatetimethreshold)/1000) < b.end(0)) { forceupdatecheckcount++; if (forceupdatecheckcount > forceupdatecountthreshold) { console.log('update time'); self.video.currentTime = b.end(0) - self.m.latency/1000; forceupdatecheckcount = 0; } } else { if (forceupdatecheckcount > 0) { forceupdatecheckcount = 0; } } lastupdatetime = Date.now(); } } //console.log('buffer:' + b.start(0) + '~' + b.end(0)); } else { if (self.m.playAfterBufferFill) { /* for (var i = 0; i < b.length; i++) { console.log('buffer[' + i + ']: ' + b.start(i) + ', ' + b.end(i)); } */ if (b.end(b.length - 1) * 1000 - self.m.latency >= 0) { self.m.playAfterBufferFill = false; console.log("Buffer filled. Start pipeline."); self.pipeline.play(); } } } if(self.m.debug){ console.log( 'Playback' + ((isRecording)?('+Recording'):('')) +': w.data length:' + msg.data.length ); } if (firstPackage == null) { firstPackage = msg.data; } if (isRecording == true) { if (msg.idrPicture == true) { isRecStarted = true; } if (isRecStarted) { if( recData264Len + msg.data.length < self.rech264maxsize) { var data = msg.data; self.recordedData264.set( data, recData264Len); recData264Len += data.length; delete msg.data; delete data; data = null; } else { // Truen console.warn('len(' + recData264Len + ') + new(' + msg.data.length + ') >= max(' + self.rech264maxsize + ')'); clearTimeout(record_wd); self.stopRecord(); record_try = 0; } } } msg = null; } // Truen function dataCatcherWd() { dataCatcherWdCnt++; if (dataCatcherWdCnt > 4) { setTimeout(function() { self.restart('restart by dataCatcherWd'); },10); } else { dataCatcherWdId = setTimeout(function() { dataCatcherWd(); }, 1000); } } /* raw pcm (after g711 decode) data callback*/ var dataCatcherPCM = new components.g711toPCM(); //96-h264, 97-aac, 98-metadata, 0-g711? dataCatcherPCM.onDataCallback = function( msg) { self.initAudioCtx(); self.audioPlayBuffer(msg.data); delete msg.data; msg = null; // Truen if (dataCatcherWdId != undefined) { clearTimeout(dataCatcherWdId); } dataCatcherWdCnt = 0; dataCatcherWdId = setTimeout(function() { dataCatcherWd(); },1000); } self.pipeline.insertAfter(self.pipeline.firstComponent.next.next, dataCatcherPCM); /* catch h264 sps/pps data callback*/ var dataCatcherH264 = new components.dataCatcherDepay(96); dataCatcherH264.onDataCallback = function( msg) { /* Truen if (msg.data[0] == 0x67) { //console.log('data[H264] : SPS'); if (sps == '') { sps = Array.from(msg.data); } else if ( !arraysAreEqual (sps, Array.from(msg.data)) ) { setTimeout(function(){ self.restart('restart by sps-changed'); },10); } } else */if (msg.data[0] == 0x68) { //console.log('data[H264] : PPS'); if (pps == '') { pps = Array.from(msg.data); } else if ( !arraysAreEqual ( pps, Array.from(msg.data)) ) { setTimeout(function(){ self.restart('restart by pps-changed'); },10); } } // Truen if (dataCatcherWdId != undefined) { clearTimeout(dataCatcherWdId); } dataCatcherWdCnt = 0; dataCatcherWdId = setTimeout(function() { dataCatcherWd(); },1000); } self.pipeline.insertAfter(self.pipeline.firstComponent.next, dataCatcherH264); /* // aac - data callback var dataCatcherAAC = new components.dataCatcherDepay(97); //96-h264, 97-aac, 98-metadata, 0-g711? dataCatcherAAC.onDataCallback = function( msg) { console.log('data(aac) catcher: ' + msg.data.length + ' type:' + msg.type ); } self.pipeline.insertAfter(self.pipeline.firstComponent.next, dataCatcherAAC); */ self.pipeline.onSdp = function(sdp) { console.log('onSdp'); var str = sdp.rawdata.toString(); console.log(str); console.log(sdp); } self.pipeline.onPlay = function(range) { console.log('onPlay: latency: ' + self.m.latency); self.m.playAfterBufferFill = true; //self.pipeline.play(); } return true; } return false; } self.setSource = function (cameraIP, user, pwd, wsport=80, rtspport=554 ) { if (cameraIP !== undefined) { self.m.wsurl = 'ws://'+cameraIP+':'+wsport+'/rtsp_over_websocket'; self.m.rtspurl = 'rtsp://'+cameraIP+':'+rtspport+'/video1_audio1'; self.m.user = user; self.m.password = pwd; } var isCreated = self.createPipeline(); if (isCreated) { self.wdtries = 0; self.play(); } else { self.m.is_opened = false; self.stop(); return undefined; } /* if(url != undefined){ self.m.url = url; console.log('Player ' + self.id+' src='+self.m.url+' autostart='+self.m.autostart+' is_opened='+self.m.is_opened); if(self.m.url.length > 0 && self.m.autostart){ self.m.is_opened = true; self.module.command('open', url); }else{ self.m.is_opened = false; //el_play.style.display = "inline-block"; //el_stop.style.display = "none"; //el_loader.style.display = 'none'; self.stop(); } } else { return self.m.url; } */ } self.dispose = function(){ self.player.innerHTML = ""; delete window.vxgwsplayer.players[self.id]; } self.custom_digital_zoom = function(newval){ if(newval != undefined){ if(self.m.isCustomDigitalZoom == false && newval == true){ self.m.isCustomDigitalZoom = true; self.setCustomDigitalZoom(100,0,0); // reset self.set_controls_display(""); }else if(self.m.isCustomDigitalZoom == true && newval == false){ self.m.isCustomDigitalZoom = false; self.set_controls_display(""); self.setNewZoom(10); } }else{ return self.m.isCustomDigitalZoom; } } self.setCustomDigitalZoom = function(ratio, x, y){ if (ratio !== parseInt(ratio, 10) || x !== parseInt(x, 10) || y !== parseInt(y, 10)){ throw "[vxgwsplayer] setDigitalZoom / Some values is not integer"; } if(ratio < 100 || ratio > 1000/*500*/){ // Truen throw "[vxgwsplayer] setDigitalZoom / Parameter Ratio must be 100..500"; } if(self.m.isCustomDigitalZoom != true){ throw "[vxgwsplayer] setDigitalZoom / Please enable custom digital zoom"; } self.video.style.transform = "scale(" + (ratio/100) + ")"; el_controls_zoom_position.style.display = "none"; var s = self.size(); var newx = x - s.width/2; var newy = y - s.height/2; var neww = s.width*(100/ratio); var newh = s.height*(100/ratio); var left = Math.floor(-100*(newx + neww/2)/neww); var top = Math.floor(-100*(newy + newh/2)/newh); self.video.style.left = left + '%'; self.video.style.top = top + '%'; } self.setNewZoom = function(v){ if(v >= 30){ v = 30; } if(v <= 10){ v = 10; } if(self.currentZoom != v){ self.currentZoom = v; self.video.style.transform = "scale(" + (ratio/100) + ")"; el_zoomPositionCursor.style.transform = "scale(" + (10/self.currentZoom) + ")"; el_zoomProgress.className = el_zoomProgress.className.replace(/zoom\d+x/g,'zoom' + Math.ceil(self.currentZoom) + 'x'); el_controls_zoom_position.style.display = self.currentZoom == 10 ? "none" : ""; self.video.style.left = left + '%'; self.video.style.top = top + '%'; el_zoomPositionCursor.style.left = ''; el_zoomPositionCursor.style.top = ''; } } self.zoomUp = function(){ self.setNewZoom(self.currentZoom + 5) } self.zoomDown = function(){ self.setNewZoom(self.currentZoom - 5); } self.zoomProgressDownBool = false; self.zoomProgressDown = function(e){ self.zoomProgressDownBool = true; } self.zoomProgressMove = function(e){ if(self.zoomProgressDownBool == true){ var y = e.pageY - vxgwsplayer.getAbsolutePosition(e.currentTarget).y; var height = el_zoomProgress.offsetHeight; var steps = height/5; y = 10*(Math.floor((height-y)/steps)/2 + 1); self.setNewZoom(y); } } self.zoomProgressLeave = function(e){ self.zoomProgressDownBool = false; } self.zoomProgressUp = function(e){ if(self.zoomProgressDownBool == true){ var y = e.pageY - vxgwsplayer.getAbsolutePosition(e.currentTarget).y; var height = el_zoomProgress.offsetHeight; var steps = height/5; y = 10*(Math.floor((height-y)/steps)/2 + 1); self.setNewZoom(y); } self.zoomProgressDownBool = false; } self.zoomCursorDownBool = false; self.zoomCursorX = 0; self.zoomCursorY = 0; self.zoomCursorWidth = 160; self.zoomCursorHeight = 120; self.zoomControlsWidth = 0; self.zoomControlsHeight = 0; self.zoomCursorDown = function(e){ self.zoomCursorX = e.pageX; self.zoomCursorY = e.pageY; self.zoomCursorWidth = el_zoomPositionCursor.offsetWidth; self.zoomCursorHeight = el_zoomPositionCursor.offsetHeight; self.zoomControlsWidth = el_controls_zoom_position.offsetWidth; self.zoomControlsHeight = el_controls_zoom_position.offsetHeight; self.zoomCursorDownBool = true; } self.zoomCursorUp = function(e){ console.log("zoomCursorUp"); self.zoomCursorDownBool = false; } self.zoomCursorMove = function(e){ if(self.zoomCursorDownBool == true){ var diffX = self.zoomCursorX - e.pageX; var diffY = self.zoomCursorY - e.pageY; self.zoomCursorX = e.pageX; self.zoomCursorY = e.pageY; var newx = el_zoomPositionCursor.offsetLeft - diffX; var newy = el_zoomPositionCursor.offsetTop - diffY; var d2x = (self.zoomControlsWidth - self.zoomCursorWidth*(10/self.currentZoom)); var d2y = (self.zoomControlsHeight - self.zoomCursorHeight*(10/self.currentZoom)); var minX = -1*d2x/2; var maxX = d2x/2; var minY = -1*d2y/2; var maxY = d2y/2; if(newx < minX) newx = minX; if(newy < minY) newy = minY; if(newx >= maxX) newx = maxX; if(newy >= maxY) newy = maxY; el_zoomPositionCursor.style.left = newx + "px"; el_zoomPositionCursor.style.top = newy + "px"; var zoom = self.currentZoom/10 - 1; var left = Math.floor(-100*((newx/d2x)*zoom)); var top = Math.floor(-100*((newy/d2y)*zoom)); self.video.style.left = left + '%'; self.video.style.top = top + '%'; } } self.setNewZoom = function(v){ if(v >= 30){ v = 30; } if(v <= 10){ v = 10; } if(self.currentZoom != v){ self.currentZoom = v; self.video.style.transform = "scale(" + (self.currentZoom/10) + ")"; el_zoomPositionCursor.style.transform = "scale(" + (10/self.currentZoom) + ")"; el_zoomProgress.className = el_zoomProgress.className.replace(/zoom\d+x/g,'zoom' + Math.ceil(self.currentZoom) + 'x'); el_controls_zoom_position.style.display = self.currentZoom == 10 ? "none" : ""; self.video.style.left = ''; self.video.style.top = ''; el_zoomPositionCursor.style.left = ''; el_zoomPositionCursor.style.top = ''; } } self.zoomUp = function(){ self.setNewZoom(self.currentZoom + 5) } self.zoomDown = function(){ self.setNewZoom(self.currentZoom - 5); } self.zoomProgressDownBool = false; self.zoomProgressDown = function(e){ self.zoomProgressDownBool = true; } self.zoomProgressMove = function(e){ if(self.zoomProgressDownBool == true){ var y = e.pageY - vxgwsplayer.getAbsolutePosition(e.currentTarget).y; var height = el_zoomProgress.offsetHeight; var steps = height/5; y = 10*(Math.floor((height-y)/steps)/2 + 1); self.setNewZoom(y); } } self.zoomProgressLeave = function(e){ self.zoomProgressDownBool = false; } self.zoomProgressUp = function(e){ if(self.zoomProgressDownBool == true){ var y = e.pageY - vxgwsplayer.getAbsolutePosition(e.currentTarget).y; var height = el_zoomProgress.offsetHeight; var steps = height/5; y = 10*(Math.floor((height-y)/steps)/2 + 1); self.setNewZoom(y); } self.zoomProgressDownBool = false; } self.zoomCursorDownBool = false; self.zoomCursorX = 0; self.zoomCursorY = 0; self.zoomCursorWidth = 160; self.zoomCursorHeight = 120; self.zoomControlsWidth = 0; self.zoomControlsHeight = 0; self.zoomCursorDown = function(e){ self.zoomCursorX = e.pageX; self.zoomCursorY = e.pageY; self.zoomCursorWidth = el_zoomPositionCursor.offsetWidth; self.zoomCursorHeight = el_zoomPositionCursor.offsetHeight; self.zoomControlsWidth = el_controls_zoom_position.offsetWidth; self.zoomControlsHeight = el_controls_zoom_position.offsetHeight; self.zoomCursorDownBool = true; } self.zoomCursorUp = function(e){ console.log("zoomCursorUp"); self.zoomCursorDownBool = false; } self.zoomCursorMove = function(e){ if(self.zoomCursorDownBool == true){ var diffX = self.zoomCursorX - e.pageX; var diffY = self.zoomCursorY - e.pageY; self.zoomCursorX = e.pageX; self.zoomCursorY = e.pageY; var newx = el_zoomPositionCursor.offsetLeft - diffX; var newy = el_zoomPositionCursor.offsetTop - diffY; var d2x = (self.zoomControlsWidth - self.zoomCursorWidth*(10/self.currentZoom)); var d2y = (self.zoomControlsHeight - self.zoomCursorHeight*(10/self.currentZoom)); var minX = -1*d2x/2; var maxX = d2x/2; var minY = -1*d2y/2; var maxY = d2y/2; if(newx < minX) newx = minX; if(newy < minY) newy = minY; if(newx >= maxX) newx = maxX; if(newy >= maxY) newy = maxY; el_zoomPositionCursor.style.left = newx + "px"; el_zoomPositionCursor.style.top = newy + "px"; var zoom = self.currentZoom/10 - 1; var left = Math.floor(-100*((newx/d2x)*zoom)); var top = Math.floor(-100*((newy/d2y)*zoom)); self.video.style.left = left + '%'; self.video.style.top = top + '%'; } } var isAudioCapture = false; var audioCapture = null; self.startBackwardAudio = function () { if (self.isAudioCapture) { return; } if (!self.pipeline.rtsp.audioback_chnl) { console.warn('backward channel not found in SDP'); return; } if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { console.log('getUserMedia supported.'); navigator.mediaDevices.getUserMedia ({ audio: true }) .then(function(stream) { var buflen = 2048; var numchannels = 1; var rtp_pkt; var rtsp_hdr; self.audioCapture = new AudioContext({ sampleRate: 8000 }); var input = self.audioCapture.createMediaStreamSource(stream); var node = (input.context.createScriptProcessor || input.context.createJavaScriptNode).call(input.context, buflen, numchannels, numchannels ); self.isAudioCapture = true; input.connect(node); node.connect(input.context.destination); node.onaudioprocess = function(e) { if (self.isAudioCapture) { var data = e.inputBuffer.getChannelData(0); /* console.log("got audio buffer: " + e.inputBuffer.length + " for " + e.inputBuffer.duration + " samplerate " + e.inputBuffer.sampleRate + " data: [" + data[0] + "][" + data[1] + "][" + data[2] + "][" + data[3] + "]" ); */ if (!rtsp_hdr) { //console.log(self.pipeline); //console.log(self.pipeline.rtsp); //console.log(self.pipeline.rtsp.audioback_chnl); // Stream data (such as RTP packets) is encapsulated by an ASCII dollar sign // (0x24 hexadecimal), followed by one byte of channel identifier, followed by two bytes of the length of // the encapsulated binary data.The stream data follows immediately afterwards.Each $ block contains // only one upper layer protocol data unit, such as an RTP packet. var len = e.inputBuffer.length + 12; rtsp_hdr = new Uint8Array(4); rtsp_hdr[0] = 0x24; rtsp_hdr[1] = self.pipeline.rtsp.audioback_chnl; rtsp_hdr[2] = (len >>> 8); rtsp_hdr[3] = (len & 0xFF); rtsp_hdr._isBuffer = true; rtsp_hdr.data = rtsp_hdr; /* RFC3550 http://www.ietf.org/rfc/rfc3550.txt V = 2, // version. always 2 (2 bits) P = 0, // padding. (1 bit) X = 0, // header extension (1 bit) CC = 0, // CSRC count (4 bits) M = 0, // marker (1 bit) PT = 0, // payload type. (7 bits) SN = // sequence number. SHOULD be random (16 bits) TS = 1, // timestamp (32 bits) SSRC = 1; // synchronization source (32 bits) //CSRC = 0, // contributing sources (32 bits) //DP = 0, // header extension, 'Defined By Profile' (16 bits) //EL = 0; // header extension length (16 bits) */ rtp_pkt = new Uint8Array(len); rtp_pkt[0] = 0x80; rtp_pkt[1] = 0;//ulaw var SN = Math.floor(1000 * Math.random()); rtp_pkt[2] = (SN >>> 8) rtp_pkt[3] = (SN & 0xFF); rtp_pkt[4] = 0; rtp_pkt[5] = 0; rtp_pkt[6] = 0; rtp_pkt[7] = 1; rtp_pkt[8] = 0; rtp_pkt[9] = 0; rtp_pkt[10] = 0; rtp_pkt[11] = 1; rtp_pkt._isBuffer = true; rtp_pkt.data = rtp_pkt; } var seq = (rtp_pkt[2] << 8 | rtp_pkt[3]) + 1; seq = seq.toUnsigned(); if (seq <= 65535) { rtp_pkt[2] = (seq >>> 8); rtp_pkt[3] = (seq & 0xFF); } var time = (rtp_pkt[4] << 24 | rtp_pkt[5] << 16 | rtp_pkt[6] << 8 | rtp_pkt[7]) + rtp_pkt.length; time = time.toUnsigned(); if (time <= 4294967295) { rtp_pkt[4] = (time >>> 24); rtp_pkt[5] = (time >>> 16 & 0xFF); rtp_pkt[6] = (time >>> 8 & 0xFF); rtp_pkt[7] = (time & 0xFF); } self.pipeline._src.outgoing.write(rtsp_hdr); self.pipeline._src.outgoing.write(rtp_pkt); const BIAS = 0x84; const CLIP = 32635; for (var i = 0; i < e.inputBuffer.length; ++i) { var pcm_16_sample = Math.min(1, data[i]) * 0x7FFF; var sign = (pcm_16_sample >> 8) & 0x80; if (sign != 0) pcm_16_sample = -pcm_16_sample; pcm_16_sample = pcm_16_sample + BIAS; if (pcm_16_sample > CLIP) pcm_16_sample = CLIP; var exponent = ulawencodeTable[(pcm_16_sample >> 7) & 0xFF]; var mantissa = (pcm_16_sample >> (exponent + 3)) & 0x0F; rtp_pkt[i+12] = ~(sign | (exponent << 4) | mantissa); } self.pipeline._src.outgoing.write(rtsp_hdr); self.pipeline._src.outgoing.write(rtp_pkt); } } }).catch(function(err) { console.log('The following getUserMedia error occured: ' + err); }); } else { console.log('getUserMedia not supported on your browser!'); } } self.stopBackwardAudio = function() { self.isAudioCapture = false; self.audioCapture = null; } function wait(delayInMS) { return new Promise(resolve => setTimeout(resolve, delayInMS)); } function mergeTypedArrays(a, b) { if(!a && !b) throw 'Please specify valid arguments for parameters a and b.'; if(!b || b.length === 0) return a; if(!a || a.length === 0) return b; if(Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) throw 'The types of the two arguments passed for parameters a and b do not match.'; var c = new a.constructor(a.length + b.length); c.set(a); c.set(b, a.length); return c; } self.onRecord = null; self.ffmpeg_worker = null; self.startRecord = function( ms_length = 5000){ isRecStarted = false; if (isRecording || isRecStopping) return; self.ffmpeg_worker = new Worker('/vxgwsplayer/ffmpeg/ffmpeg-worker-mp4.js'); clearTimeout(record_wd); prevRecLen = 0; self.recordedData264 = new Uint8Array(self.rech264maxsize); self.recordedData711 = new Uint8Array(self.recg711maxsize); recData264Len = 0; recData711Len = 0; if (firstPackage != null) { self.recordedData264.set(firstPackage, recData264Len); recData264Len += firstPackage.length; } isRecording = true; isRecStopping = false; if (self.onRecord !== null) { var args = {}; args.isRecording = isRecording; args.isRecStopping = isRecStopping; self.onRecord(args); } if (ms_length > 0) { setTimeout(function(){ self.stopRecord(); }, ms_length); } function recordWd () { clearTimeout(record_wd); if (!isRecording) return; if (!isRecStarted || recData264Len > prevRecLen) { prevRecLen = recData264Len; console.log('record watchdog: OK - record in process'); record_wd = setTimeout(function(){recordWd();}, 5000); } else { if (record_try > 3) { console.warn('Early record save before expected time due record stream error or allocated memmory is over'); self.stopRecord(); record_try = 0; } else { console.log('record watchdog: may be error (recdata:'+recData264Len+'<= prevrecorded:'+prevRecLen+'<= maxsize:'+self.rech264maxsize+'): - check in process '); record_try += 1; record_wd = setTimeout(function(){recordWd();}, 5000); } } } record_wd = setTimeout(function(){recordWd();}, 5000); } self.stopRecord = async function stopRecord() { if (isRecording == false || isRecStopping == true) { return; } isRecording = false; isRecStarted = false; isRecStopping = true; if (self.onRecord !== null) { var args = {}; args.isRecording = isRecording; args.isRecStopping = isRecStopping; self.onRecord(args); } //const OUT_FILE_NAME = self.defaultClipName + '.avi'; const OUT_FILE_NAME = self.defaultClipName + '.mkv'; //const OUT_FILE_NAME = self.defaultClipName + '.mov'; var data = self.recordedData264.subarray(0, recData264Len); var outfile; self.ffmpeg_worker.onmessage = function(arg) { var msg = arg.data; switch (msg.type) { case "stdout": console.log("ffmpeg: stdout: " + msg.data); break; case "stderr": console.log("ffmpeg: stderr: " + msg.data); break; case "exit": console.log("Process exited with code " + msg.data); break; case 'done': { //const blob = new Blob([msg.data.MEMFS[0].data], {type: "video/avi"}); const blob = new Blob([msg.data.MEMFS[0].data], {type: "video/mkv"}); //const blob = new Blob([msg.data.MEMFS[0].data], {type: "video/mov"}); let a = document.createElement("a"); //document.body.appendChild(a); a.style.display = 'none'; let url = URL.createObjectURL(blob); a.href = url; a.download = OUT_FILE_NAME; a.click(); window.URL.revokeObjectURL(url); delete self.recordedData264; self.recordedData264 = null; delete self.recordedData711; self.recordedData711 = null; recData264Len = 0; recData711Len = 0; isRecStopping = false; if (self.onRecord !== null) { var args = {}; args.isRecording = isRecording; args.isRecStopping = isRecStopping; self.onRecord(args); } setTimeout(function () { if (self.ffmpeg_worker != null) { self.ffmpeg_worker.terminate(); self.ffmpeg_worker = null; } }, 0); } break; } }; if(self.recordedData711.length>0){ var data711 = self.recordedData711.subarray(0, recData711Len); self.ffmpeg_worker.postMessage({ type: 'run', TOTAL_MEMORY: 581510912, // 268435456, // arguments: ['-formats'] //avi //arguments: ['-r','30', '-i', 'input.mp4', '-f', 'mulaw', '-ar', '8000', '-ac', '1', '-i', 'input.ulaw', '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME], //mkv arguments: ['-i', 'input.mp4', '-f', 'mulaw', '-ar', '8000', '-ac', '1', '-i', 'input.ulaw', '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME], //mov //arguments: ['-i', 'input.mp4', '-f', 'mulaw', '-ar', '8000', '-ac', '1', '-i', 'input.ulaw', '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME], MEMFS: [{name: 'input.mp4', data: data}, {name: 'input.ulaw', data: data711 }], }); }else{ self.ffmpeg_worker.postMessage({ type: 'run', TOTAL_MEMORY: 581510912, // 268435456, //avi //arguments: ['-r','30', '-i', 'input.mp4', '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME], //mkv arguments: ['-i', 'input.mp4', '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME], //mov //arguments: ['-i', 'input.mp4', '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME], MEMFS: [{name: 'input.mp4', data: data}], }); } /* if(self.recordedData711.length>0){ var data711 = self.recordedData711.subarray(0, recData711Len); var file2 = { name:IN_FILE_NAME_ULAW, data:data711} const args = ['-i', IN_FILE_NAME_264, '-f', 'mulaw', '-ar', '8000', '-ac', '1', '-i', IN_FILE_NAME_ULAW, '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME]; var ret = await runFFmpeg(IN_FILE_NAME_264, data, args, OUT_FILE_NAME, [ file2 ] ); data = null; data711 = null; ret.Core.PThread.ih(); delete ret.Core; outfile = ret.file; } else{ const args = ['-i', IN_FILE_NAME_264, '-vcodec', 'copy', '-acodec', 'copy', OUT_FILE_NAME]; const ret = await runFFmpeg(IN_FILE_NAME_264, data, args, OUT_FILE_NAME ); data = null; ret.Core.PThread.ih(); delete ret.Core; outfile = ret.file; } let a = document.createElement("a"); document.body.appendChild(a); a.style.display = 'none'; a.href = URL.createObjectURL(new Blob([outfile.buffer], { type: 'video/mp4' })); a.download = OUT_FILE_NAME; a.click(); delete self.recordedData264; self.recordedData264 = null; delete self.recordedData711; self.recordedData711 = null; recData264Len = 0; recData711Len = 0; isRecStopping = false; if (self.onRecord !== null) { var args = {}; args.isRecording = isRecording; args.isRecStopping = isRecStopping; self.onRecord(args); } */ } self.recordStatus = function() { if (isRecording == true) { var ret = {}; ret.recording = true; ret.recStopping = false; ret.recData264Len = recData264Len; ret.recData711Len = recData711Len; return ret; } else if (isRecording == false && isRecStopping) { var ret = {}; ret.recording = false; ret.recStopping = true; ret.recData264Len = recData264Len; ret.recData711Len = recData711Len; return ret; } else { var ret = {}; ret.recording = false; ret.recStopping = false; ret.recData264Len = recData264Len; ret.recData711Len = recData711Len; return ret; } } el_play.onclick = self.play; el_pause.onclick = self.pause; el_stop.onclick = self.stop; el_fullscreen.onclick = self.fullscreen; el_takescreenshot.onclick = self.takescreenshot; el_zoomUp.onclick = self.zoomUp; el_zoomDown.onclick = self.zoomDown; el_zoomPositionCursor.addEventListener('mousedown',self.zoomCursorDown,false); el_zoomPositionCursor.addEventListener('mousemove',self.zoomCursorMove,false); el_zoomPositionCursor.addEventListener('mouseleave',self.zoomCursorUp,false); el_zoomPositionCursor.addEventListener('mouseup',self.zoomCursorUp,false); el_zoomProgress.addEventListener('mousedown',self.zoomProgressDown,false); el_zoomProgress.addEventListener('mousemove',self.zoomProgressMove,false); el_zoomProgress.addEventListener('mouseleave',self.zoomProgressLeave,false); el_zoomProgress.addEventListener('mouseup',self.zoomProgressUp,false); }(id, options_); window.vxgwsplayer.players[id].playerDidLoad(); }else{ // console.warn(id + " - already exists player"); } return window.vxgwsplayer.players[id]; }; window.vxgwsplayer.webserverport = '8778'; window.vxgwsplayer.isFrame = function() { try { return window.self !== window.top; } catch (e) { return true; } } /* window.vxgwsplayer.browserSupportsPluginPnacl = function() { return navigator.mimeTypes['application/x-pnacl'] !== undefined && navigator.mimeTypes['application/vxg_media_player'] !== undefined; } */ window.vxgwsplayer.showGlobalErrorMessage = function(id, html){ var player = document.getElementById(id); var width=640; var height=480; width = parseInt(player.width,10) || width; height = parseInt(player.height,10) || height; player.style.width = width + 'px'; player.style.height = height + 'px'; player.innerHTML = html; return undefined; } window.vxgwsplayer.showNotInstalled = function(id){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
' + ' Click here for install plugin' + '

or visit in webstore VXG Media Player' + '
' + '
'); } window.vxgwsplayer.showAvailableInChrome = function(id){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
' + ' Available in Chrome for Desktop PC only' + '
' + '
'); } window.vxgwsplayer.showWebSocketFailed = function(id){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
' + ' Could not connect to plugin (WebSocket Error). Please try restart your browser.' + '
' + '
'); } window.vxgwsplayer.showNotInstalledInIncognitoMode = function(id){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
You have opened this page in incognito mode. Please open it in a regular tab, install the plugin and then come back.' + '

Also you can install VXG Media Player from webstore in regular tab.' + '
' + '
'); } window.vxgwsplayer.showNotStartedInIncognitoMode = function(id){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
You have opened this page in incognito mode. Please open it in a regular tab and then come back.' + '
' + '
'); } window.vxgwsplayer.startPlayerInNewTab = function(){ console.log('start player'); var params = "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes" var win = window.open('https://www.videoexpertsgroup.com/player_start/', "_blank", params) setTimeout(function(){ win.close(); location.reload(); /*for(var id in window.vxgwsplayer.players){ console.log("Restart player: " + id); }*/ },1000); } window.vxgwsplayer.showNotStartedInIFrame = function(id){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
You have opened this page in frame.
' + ' Please click on this link for start Chrome App (VXG Media Player).' + '
' + '
'); } window.vxgwsplayer.showInitFailed = function(id, str){ vxgwsplayer.showGlobalErrorMessage(id, '' + '
' + '
' + ' Chrome plugin init error. Try to update Video/Audio drivers. ' + str + '
' + '
'); } window.vxgwsplayer.Promise = function(){ var completed = false; this.done = function(callback){ this.done_callback = callback; if(this.completed){ this.done_callback(this.err); } return this; } this.fail = function(callback){ this.fail_callback = callback; if(this.completed){ this.fail_callback(this.err); } return this; } this.resolve = function(result) { if(!this.completed){ this.result = result; this.done_callback(result); } this.completed = true; } this.reject = function(err) { if(!this.completed){ this.err = err; this.fail_callback(err); } this.completed = true; } }; /* window.vxgwsplayer.checkWebSocket = function(){ var p = new vxgwsplayer.Promise(); setTimeout(function(){ var testWebSocket = new WebSocket('ws://127.0.0.1:' + vxgwsplayer.webserverport + '/'); testWebSocket.onerror=function(event){ p.reject(); } testWebSocket.onmessage = function(evt){ console.log(evt); } testWebSocket.onopen=function(){ testWebSocket.close(); p.resolve(); } },60000); return p; } */ // helper funxtion window.vxgwsplayer.getAbsolutePosition = function(element){ var r = { x: element.offsetLeft, y: element.offsetTop }; if (element.offsetParent) { var tmp = vxgwsplayer.getAbsolutePosition(element.offsetParent); r.x += tmp.x; r.y += tmp.y; } return r; }; // init options window.vxgwsplayer.initOptions = function(self, options){ self.options = options || {}; self.m = {}; self.m.wsurl = self.player.getAttribute('wsurl') || self.options.wsurl || ""; self.m.rtspurl = self.player.getAttribute('rtspurl') || self.options.rtspurl || ""; self.m.user = self.player.getAttribute('user') || self.options.user || ""; self.m.password = self.player.getAttribute('password') || self.options.password || ""; /* var nmf_path = "media_player.nmf"; var nmf_src = "pnacl/Release/media_player.nmf"; self.m.nmf_path = self.player.getAttribute('nmf-path') || self.options.nmf_path || nmf_path; self.m.nmf_src = self.player.getAttribute('nmf-src') || self.options.nmf_src || nmf_src; */ self.m.autostart_parameter = self.player.hasAttribute('autostart') ? '1' : '0'; self.m.audio_parameter = (self.player.hasAttribute('audio') && parseInt(self.player.getAttribute('audio', 10)) == 0) ? '0' : '1'; self.m.mute_parameter = (self.player.hasAttribute('mute') && parseInt(self.player.getAttribute('mute', 10)) == 1) ? '1' : '0'; } // generate embeded element for nacl player /* window.vxgwsplayer.generateEmbededElement = function(self){ return '' + ''; } */ class audioBufferPCM { constructor(audioCtx, audioGain, sampleRate, bufferSize = 10) { this.ctx = audioCtx; this.gain = audioGain; this.sampleRate = sampleRate; this.bufferSize = bufferSize; this.chunks = []; this.isPlaying = false; this.startTime = 0; this.lastChunkOffset = 0; } clear() { this.chunks.splice(0, this.chunks.length); } createChunk(chunk) { var audioBuffer = this.ctx.createBuffer(1, chunk.length, this.sampleRate); audioBuffer.getChannelData(0).set(chunk); var source = this.ctx.createBufferSource(); source.buffer = audioBuffer; source.connect(this.gain); source.onended = (e) => { this.chunks.splice(this.chunks.indexOf(source), 1); if (this.chunks.length == 0) { this.isPlaying = false; this.startTime = 0; this.lastChunkOffset = 0; } }; return source; } addBuffer(data) { if (this.isPlaying && (this.chunks.length > this.bufferSize)) { console.warn("audio chunk discarded"); return; } else if (this.isPlaying && (this.chunks.length <= this.bufferSize)) { // schedule & add right now var chunk = this.createChunk(data); chunk.start(this.startTime + this.lastChunkOffset); this.lastChunkOffset += chunk.buffer.duration; this.chunks.push(chunk); chunk = null; } else if ((this.chunks.length < (this.bufferSize / 2)) && !this.isPlaying) { // add & don't schedule var chunk = this.createChunk(data); this.chunks.push(chunk); chunk = null; } else { // add & schedule entire buffer this.isPlaying = true; var chunk = this.createChunk(data); this.chunks.push(chunk); chunk = null; this.startTime = this.ctx.currentTime; this.lastChunkOffset = 0; for (let i = 0; i < this.chunks.length; i++) { var chunk = this.chunks[i]; chunk.start(this.startTime + this.lastChunkOffset); this.lastChunkOffset += chunk.buffer.duration; } } } } // init volumes window.vxgwsplayer.initVolumeControls = function(self, onloadsettings){ self.m.volume = self.options.volume || 0.7; var el_volumeMute = self.player.getElementsByClassName('vxgwsplayer-volume-mute')[0]; var el_volumeDown = self.player.getElementsByClassName('vxgwsplayer-volume-down')[0]; var el_volumeProgress = self.player.getElementsByClassName('vxgwsplayer-volume-progress')[0]; var el_volumeUp = self.player.getElementsByClassName('vxgwsplayer-volume-up')[0]; if(self.player.hasAttribute('volume')){ self.m.volume = parseFloat(self.player.getAttribute('volume')); self.m.volume = Math.ceil(self.m.volume*10)/10; if(onloadsettings){ /* self.module.command('setvolume', self.m.volume.toFixed(1)); */ } }else if(self.options.volume){ console.warn("TODO volume"); } self.m.mute = self.video.hasAttribute('muted') || self.options.mute || self.m.volume == 0 || self.m.mute_parameter == '1'; if(self.m.mute){ el_volumeDown.style.display='none'; el_volumeProgress.style.display='none'; el_volumeUp.style.display='none'; } el_volumeProgress.className = el_volumeProgress.className.replace(/vol\d+/g,'vol' + Math.ceil(self.m.volume*10)); self.isMute = function(){ return self.m.mute; } self.applyVolume = function(){ if(self.isMute()){ el_volumeDown.style.display='none'; el_volumeProgress.style.display='none'; el_volumeUp.style.display='none'; el_volumeProgress.className = el_volumeProgress.className.replace(/vol\d+/g,'vol0') }else{ el_volumeDown.style.display='inline-block'; el_volumeProgress.style.display='inline-block'; el_volumeUp.style.display='inline-block'; el_volumeProgress.className = el_volumeProgress.className.replace(/vol\d+/g,'vol' + Math.floor(self.m.volume*10)); } /* self.module.command('setvolume', self.m.mute? '0': '' + self.m.volume.toFixed(1)); */ if (self.isMute()){ self.video.setAttribute('muted', true); self.video.muted = true; if (self.audioGain != null && self.audioGain !== undefined && self.audioCtx != null && self.audioCtx !== undefined) { self.audioGain.gain.setValueAtTime(0, self.audioCtx.currentTime); } } else { self.video.removeAttribute('muted'); self.video.muted = false; self.video.setAttribute('volume', self.m.volume.toFixed(1)); self.video.volume = self.m.volume.toFixed(1); if (self.audioGain != null && self.audioGain !== undefined && self.audioCtx != null && self.audioCtx !== undefined) { self.audioGain.gain.setValueAtTime( self.m.volume, self.audioCtx.currentTime); } } // self.video.volume = self.m.mute? '0': '' + self.m.volume.toFixed(1) if (self.audioCtx !== undefined || self.audioCtx != null) { self.audioCtx.resume(); } } self.mute = function(){ self.restartTimeout(); self.m.mute = !self.m.mute; self.applyVolume(); } self.volume = function(val){ if(val != undefined){ val = val > 1 ? 1 : val; val = val < 0 ? 0 : val; self.m.volume = Math.ceil(val*10)/10; self.applyVolume(); }else{ return self.m.volume; } } self.volup = function(){ self.restartTimeout(); if(Math.round(self.m.volume*10) < 10){ self.m.volume = self.m.volume + 0.1; self.applyVolume(); } }; self.voldown = function(){ self.restartTimeout(); if(Math.round(self.m.volume*10) > 0){ self.m.volume = self.m.volume - 0.1; self.applyVolume(); } }; el_volumeMute.onclick = self.mute; el_volumeDown.onclick = self.voldown; el_volumeUp.onclick = self.volup; } document.addEventListener('DOMContentLoaded', function() { console.log("vxgwsplayer isFrame: " + window.vxgwsplayer.isFrame()); // console.log("vxgwsplayer browserSupportsPluginPnacl: " + window.vxgwsplayer.browserSupportsPluginPnacl()); // search all vxgwsplayers var els = document.getElementsByClassName("vxgwsplayer"); for (var i = 0; i < els.length; i++) { if(els[i].id){ vxgwsplayer(els[i].id); }else{ console.error("Player has not id", els[i]); } } // TODO check ws // TODO start Chrome App });