From 27b85e76d3c1db1b037235350f643d285261a3ec Mon Sep 17 00:00:00 2001 From: Thulinma Date: Thu, 16 Mar 2017 11:14:03 +0100 Subject: [PATCH 1/3] Removed deprecated MistMultiplex header --- src/output/output_progressive_mp4.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/output/output_progressive_mp4.cpp b/src/output/output_progressive_mp4.cpp index a230a223..0261c413 100644 --- a/src/output/output_progressive_mp4.cpp +++ b/src/output/output_progressive_mp4.cpp @@ -511,10 +511,6 @@ namespace Mist { std::stringstream rangeReply; rangeReply << "bytes " << byteStart << "-" << byteEnd << "/" << fileSize; H.SetHeader("Content-Length", byteEnd - byteStart + 1); - //do not multiplex requests that are > 1MiB - if (byteEnd - byteStart + 1 > 1024*1024){ - H.SetHeader("MistMultiplex", "No"); - } H.SetHeader("Content-Range", rangeReply.str()); /// \todo Switch to chunked? H.SendResponse("206", "Partial content", myConn); @@ -522,8 +518,6 @@ namespace Mist { } }else{ H.SetHeader("Content-Length", byteEnd - byteStart + 1); - //do not multiplex requests that aren't ranged - H.SetHeader("MistMultiplex", "No"); /// \todo Switch to chunked? H.SendResponse("200", "OK", myConn); //HTTP_S.StartResponse(HTTP_R, conn); From b6486878cad7f1cc04007c0562a1b85050285edc Mon Sep 17 00:00:00 2001 From: Cat Date: Mon, 13 Mar 2017 13:32:00 +0100 Subject: [PATCH 2/3] Embed: - fixed timer issue causing player to reload after an unload - added version numbering --- embed/core.js | 24 ++++++++++++++++-------- embed/wrappers/dashjs.js | 9 +++++++++ embed/wrappers/flash_strobe.js | 1 + embed/wrappers/html5.js | 1 + embed/wrappers/img.js | 1 + embed/wrappers/jwplayer.js | 1 + embed/wrappers/polytrope.js | 1 + embed/wrappers/silverlight.js | 1 + embed/wrappers/template.js | 1 + embed/wrappers/theoplayer.js | 1 + embed/wrappers/videojs.js | 1 + lsp/minified.js | 6 +++--- lsp/mist.js | 1 + 13 files changed, 38 insertions(+), 11 deletions(-) diff --git a/embed/core.js b/embed/core.js index 42536729..16a87052 100644 --- a/embed/core.js +++ b/embed/core.js @@ -42,7 +42,7 @@ MistPlayer.prototype.build = function () { } MistPlayer.prototype.timer = { timers: {}, - add: function(callback,delay){ + add: function(callback,delay,isInterval){ var me = this; var i = setTimeout(function(){ delete me.timers[i]; @@ -50,19 +50,24 @@ MistPlayer.prototype.timer = { },delay); this.timers[i] = { delay: delay, - callback: callback + callback: callback, + interval: isInterval || false }; return i; }, remove: function(i){ - clearTimeout(i); + if (this.timers[i].interval) { + clearInterval(i); + } + else { + clearTimeout(i); + } delete this.timers[i]; }, clear: function(){ for (var i in this.timers) { - clearTimeout(i); + this.remove(i); } - this.timers = {}; } }; @@ -688,6 +693,7 @@ MistPlayer.prototype.askNextCombo = function(msg){ button.appendChild(t); err.appendChild(button); button.onclick = function(){ + me.addlog('Reloading player because the reload button was triggered'); me.reload(); } @@ -697,6 +703,7 @@ MistPlayer.prototype.askNextCombo = function(msg){ type: 'playback', warn: 'Automatically reloaded the current player after playback error' }); + me.addlog('Triggering reload button because of timeout'); button.click(); },20e3); @@ -785,6 +792,7 @@ MistPlayer.prototype.unload = function(){ } this.timer.clear(); this.target.innerHTML = ''; + this.element.innerHTML = ''; }; function mistCheck(streaminfo,options,embedLog) { @@ -1244,7 +1252,7 @@ function mistPlay(streamName,options) { if ((!element.checkProgressTimeout) && (player.element) && ('currentTime' in player.element)) { //check if the progress made is equal to the time spent var lasttime = player.element.currentTime; - element.checkProgressTimeout = setInterval(function(){ + element.checkProgressTimeout = player.timer.add(function(){ var newtime = player.element.currentTime; var progress = newtime - lasttime; lasttime = newtime; @@ -1279,13 +1287,13 @@ function mistPlay(streamName,options) { }); return; } - },30e3); + },30e3,true); } },true); element.addEventListener('pause',function(){ player.paused = true; if (element.checkProgressTimeout) { - clearInterval(element.checkProgressTimeout); + player.timer.remove(element.checkProgressTimeout); element.checkProgressTimeout = false; } },true); diff --git a/embed/wrappers/dashjs.js b/embed/wrappers/dashjs.js index c5bc4493..95639b01 100644 --- a/embed/wrappers/dashjs.js +++ b/embed/wrappers/dashjs.js @@ -1,5 +1,6 @@ mistplayers.dashjs = { name: 'Dash.js Player', + version: '1.1', mimes: ['dash/video/mp4'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { @@ -131,3 +132,11 @@ p.prototype.resize = function(size){ this.element.width = size.width; this.element.height = size.height; }; +p.prototype.updateSrc = function(src){ + if (src == '') { + this.dash.reset(); + return; + } + this.dash.attachSource(src); + return true; +}; diff --git a/embed/wrappers/flash_strobe.js b/embed/wrappers/flash_strobe.js index 9c3610b5..7d4fd1e5 100644 --- a/embed/wrappers/flash_strobe.js +++ b/embed/wrappers/flash_strobe.js @@ -1,5 +1,6 @@ mistplayers.flash_strobe = { name: 'Strobe Flash Media Playback', + version: '1.0', mimes: ['flash/10','flash/11','flash/7'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/html5.js b/embed/wrappers/html5.js index 073bd26f..de09bcbd 100644 --- a/embed/wrappers/html5.js +++ b/embed/wrappers/html5.js @@ -1,5 +1,6 @@ mistplayers.html5 = { name: 'HTML5 video player', + version: '1.0', mimes: ['html5/application/vnd.apple.mpegurl','html5/video/mp4','html5/video/ogg','html5/video/webm','html5/audio/mp3','html5/audio/webm','html5/audio/ogg','html5/audio/wav'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/img.js b/embed/wrappers/img.js index 8b3aed32..788cf484 100644 --- a/embed/wrappers/img.js +++ b/embed/wrappers/img.js @@ -1,5 +1,6 @@ mistplayers.img = { name: 'HTML img tag', + version: '1.0', mimes: ['html5/image/jpeg'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/jwplayer.js b/embed/wrappers/jwplayer.js index 9f136214..01394b4b 100644 --- a/embed/wrappers/jwplayer.js +++ b/embed/wrappers/jwplayer.js @@ -1,5 +1,6 @@ mistplayers.jwplayer = { name: 'JWPlayer', + version: '0.1', mimes: ['html5/video/mp4','html5/video/webm','dash/video/mp4','flash/10','flash/7','html5/application/vnd.apple.mpegurl','html5/audio/mp3','html5/audio/aac'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/polytrope.js b/embed/wrappers/polytrope.js index c123cf10..07a89ea2 100644 --- a/embed/wrappers/polytrope.js +++ b/embed/wrappers/polytrope.js @@ -1,5 +1,6 @@ mistplayers.polytrope = { name: 'Polytrope Flash Player', + version: '0.1', mimes: ['flash/11','flash/10','flash/7'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/silverlight.js b/embed/wrappers/silverlight.js index 67f6c7dd..6c4f89be 100644 --- a/embed/wrappers/silverlight.js +++ b/embed/wrappers/silverlight.js @@ -1,5 +1,6 @@ mistplayers.silverlight = { name: 'Silverlight', + version: '1.0', mimes: ['silverlight'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/template.js b/embed/wrappers/template.js index 6c159f7b..e8fe4736 100644 --- a/embed/wrappers/template.js +++ b/embed/wrappers/template.js @@ -1,5 +1,6 @@ mistplayers.myplayer = { name: 'My video player', + version: '0.1', mimes: ['my/mime/types'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/theoplayer.js b/embed/wrappers/theoplayer.js index 1b6f1bcc..f52960df 100644 --- a/embed/wrappers/theoplayer.js +++ b/embed/wrappers/theoplayer.js @@ -1,5 +1,6 @@ mistplayers.theoplayer = { name: 'TheoPlayer', + version: '0.1', mimes: ['html5/application/vnd.apple.mpegurl','dash/video/mp4'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/embed/wrappers/videojs.js b/embed/wrappers/videojs.js index fde60e77..fabbefe1 100644 --- a/embed/wrappers/videojs.js +++ b/embed/wrappers/videojs.js @@ -1,5 +1,6 @@ mistplayers.videojs = { name: 'VideoJS player', + version: '1.0', mimes: ['html5/video/mp4','html5/application/vnd.apple.mpegurl','html5/video/ogg','html5/video/webm'], priority: Object.keys(mistplayers).length + 1, isMimeSupported: function (mimetype) { diff --git a/lsp/minified.js b/lsp/minified.js index 9b229307..a1e2af48 100644 --- a/lsp/minified.js +++ b/lsp/minified.js @@ -67,9 +67,9 @@ top:a,left:d,right:"auto",bottom:"auto"})});a.parent().on("dragleave",function() "days, ")).append(UI.format.addUnit(d.hr,"hrs"));break;default:b.append([("0"+d.hr).slice(-2),("0"+d.min).slice(-2),("0"+d.sec).slice(-2)+(d.ms?"."+d.ms:"")].join(":"))}return b[0].innerHTML},number:function(a){if(isNaN(Number(a))||0==a)return a;var b=Math.pow(10,3-Math.floor(Math.log(a)/Math.LN10)-1),a=Math.round(a*b)/b;if(1E4"); if("undefined"==typeof a.online)return b.text("Unknown, checking.."),"undefined"!=typeof a.error&&b.text(a.error),b;switch(a.online){case -1:b.text("Enabling");break;case 0:b.text("Unavailable").addClass("red");break;case 1:b.text("Active").addClass("green");break;case 2:b.text("Standby").addClass("orange");break;default:b.text(a.online)}"error"in a&&b.text(a.error);return b},capital:function(a){return a.charAt(0).toUpperCase()+a.substring(1)},addUnit:function(a,b){var c=$("").html(a);c.append($("").addClass("unit").html(b)); return c[0].innerHTML},bytes:function(a,b){var c="bytes KiB MiB GiB TiB PiB".split(" ");if(0==a)unit=c[0];else{var d=Math.floor(Math.log(Math.abs(a))/Math.log(1024));0>d?unit=c[0]:(a/=Math.pow(1024,d),unit=c[d])}return UI.format.addUnit(UI.format.number(a),unit+(b?"/s":""))}},navto:function(a,b){var c=location.hash,d=c.split("@");d[0]=[mist.user.name,mist.user.host].join("&");d[1]=[a,b].join("&");"undefined"!=typeof screenlog&&screenlog.navto(d[1]);location.hash=d.join("@");location.hash==c&&$(window).trigger("hashchange")}, -showTab:function(a,b){var c=UI.elements.main;if(mist.user.loggedin&&!("ui_settings"in mist.data))c.html("Loading.."),mist.send(function(){UI.showTab(a,b)},{ui_settings:!0});else{var d=UI.elements.menu.removeClass("hide").find('.plain:contains("'+a+'")').closest(".button");0").text(a));switch(a){case "Login":if(mist.user.loggedin){UI.navto("Overview");return}UI.elements.menu.addClass("hide");UI.elements.connection.status.text("Disconnected").removeClass("green").addClass("red");c.append(UI.buildUI([{type:"help",help:"Please provide your account details.
You were asked to set these when MistController was started for the first time. If you did not yet set any account details, log in with your desired credentials to create a new account."},{label:"Host", -help:"Url location of the MistServer API. Generally located at http://MistServerIP:4242/api","default":"http://localhost:4242/api",pointer:{main:mist.user,index:"host"}},{label:"Username",help:"Please enter your username here.",validate:["required"],pointer:{main:mist.user,index:"name"}},{label:"Password",type:"password",help:"Please enter your password here.",validate:["required"],pointer:{main:mist.user,index:"rawpassword"}},{type:"buttons",buttons:[{label:"Login",type:"save","function":function(){mist.user.password= +showTab:function(a,b){var c=UI.elements.main;if(mist.user.loggedin&&!("ui_settings"in mist.data))c.html("Loading.."),mist.send(function(){UI.showTab(a,b)},{ui_settings:!0});else{var d=UI.elements.menu.removeClass("hide").find('.plain:contains("'+a+'")').closest(".button");0").text(a));switch(a){case "Login":if(mist.user.loggedin){UI.navto("Overview");return}UI.elements.menu.addClass("hide");UI.elements.connection.status.text("Disconnected").removeClass("green").addClass("red");c.append(UI.buildUI([{type:"help",help:"Please provide your account details.
You were asked to set these when MistController was started for the first time. If you did not yet set any account details, log in with your desired credentials to create a new account."}, +{label:"Host",help:"Url location of the MistServer API. Generally located at http://MistServerIP:4242/api","default":"http://localhost:4242/api",pointer:{main:mist.user,index:"host"}},{label:"Username",help:"Please enter your username here.",validate:["required"],pointer:{main:mist.user,index:"name"}},{label:"Password",type:"password",help:"Please enter your password here.",validate:["required"],pointer:{main:mist.user,index:"rawpassword"}},{type:"buttons",buttons:[{label:"Login",type:"save","function":function(){mist.user.password= MD5(mist.user.rawpassword);delete mist.user.rawpassword;mist.send(function(){UI.navto("Overview")})}}]}]));break;case "Create a new account":UI.elements.menu.addClass("hide");c.append($("

").text("No account has been created yet in the MistServer at ").append($("").text(mist.user.host)).append("."));c.append(UI.buildUI([{type:"buttons",buttons:[{label:"Select other host",type:"cancel",css:{"float":"left"},"function":function(){UI.navto("Login")}}]},{type:"custom",custom:$("
")},{label:"Desired username", type:"str",validate:["required"],help:"Enter your desired username. In the future, you will need this to access the Management Interface.",pointer:{main:mist.user,index:"name"}},{label:"Desired password",type:"password",validate:["required",function(a,b){$(".match_password").not($(b)).trigger("change");return false}],help:"Enter your desired password. In the future, you will need this to access the Management Interface.",pointer:{main:mist.user,index:"rawpassword"},classes:["match_password"]},{label:"Repeat password", type:"password",validate:["required",function(a,b){return a!=$(".match_password").not($(b)).val()?{msg:'The fields "Desired password" and "Repeat password" do not match.',classes:["red"]}:false}],help:"Repeat your desired password.",classes:["match_password"]},{type:"buttons",buttons:[{type:"save",label:"Create new account","function":function(){mist.send(function(){UI.navto("Account created")},{authorize:{new_username:mist.user.name,new_password:mist.user.rawpassword}});mist.user.password=MD5(mist.user.rawpassword); diff --git a/lsp/mist.js b/lsp/mist.js index d0a019bb..574f286a 100644 --- a/lsp/mist.js +++ b/lsp/mist.js @@ -1839,6 +1839,7 @@ var UI = { for (var i in mistvideo[s].embedded) { try { mistvideo[s].embedded[i].player.unload(); + delete mistvideo[s].embedded[i]; } catch (e) {} } From 43e82f8c875f3544327c265a8b59e8a4ab5f074d Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 14 Mar 2017 10:11:56 +0100 Subject: [PATCH 3/3] Fix for Windows semaphore problem in live streams --- src/input/input_buffer.cpp | 31 ++++++++++++++++--------------- src/input/input_buffer.h | 1 + 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/input/input_buffer.cpp b/src/input/input_buffer.cpp index c70e83f2..1d71d224 100644 --- a/src/input/input_buffer.cpp +++ b/src/input/input_buffer.cpp @@ -18,6 +18,7 @@ namespace Mist { inputBuffer::inputBuffer(Util::Config * cfg) : Input(cfg) { + liveMeta = 0; capa["name"] = "Buffer"; JSON::Value option; option["arg"] = "integer"; @@ -95,10 +96,11 @@ namespace Mist { } } } - char pageName[NAME_BUFFER_SIZE]; - snprintf(pageName, NAME_BUFFER_SIZE, SEM_LIVE, streamName.c_str()); - IPC::semaphore liveMeta(pageName, O_CREAT | O_RDWR, ACCESSPERMS, 1); - liveMeta.unlink(); + if (liveMeta){ + liveMeta->unlink(); + delete liveMeta; + liveMeta = 0; + } } @@ -120,13 +122,9 @@ namespace Mist { memset(tmp.mapped, 0xFF, size); } } - + //Delete the live stream semaphore, if any. + if (liveMeta){liveMeta->unlink();} { - //Delete the live stream semaphore, if any. - snprintf(pageName, NAME_BUFFER_SIZE, SEM_LIVE, streamName.c_str()); - IPC::semaphore liveMeta(pageName, O_CREAT | O_RDWR, ACCESSPERMS, 1); - liveMeta.unlink(); - }{ //Delete the stream index metapage. snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_INDEX, streamName.c_str()); IPC::sharedPage erasePage(pageName, DEFAULT_STRM_PAGE_SIZE, false, false); @@ -192,10 +190,13 @@ namespace Mist { myMeta.bufferWindow = lastms - firstms; myMeta.vod = false; myMeta.live = true; - static char liveSemName[NAME_BUFFER_SIZE]; - snprintf(liveSemName, NAME_BUFFER_SIZE, SEM_LIVE, streamName.c_str()); - IPC::semaphore liveMeta(liveSemName, O_CREAT | O_RDWR, ACCESSPERMS, 1); - liveMeta.wait(); + if (!liveMeta){ + static char liveSemName[NAME_BUFFER_SIZE]; + snprintf(liveSemName, NAME_BUFFER_SIZE, SEM_LIVE, streamName.c_str()); + liveMeta = new IPC::semaphore(liveSemName, O_CREAT | O_RDWR, ACCESSPERMS, 1); + } + liveMeta->wait(); + if (!nProxy.metaPages.count(0) || !nProxy.metaPages[0].mapped) { char pageName[NAME_BUFFER_SIZE]; snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_INDEX, streamName.c_str()); @@ -204,7 +205,7 @@ namespace Mist { } myMeta.writeTo(nProxy.metaPages[0].mapped); memset(nProxy.metaPages[0].mapped + myMeta.getSendLen(), 0, (nProxy.metaPages[0].len > myMeta.getSendLen() ? std::min(nProxy.metaPages[0].len - myMeta.getSendLen(), 4ll) : 0)); - liveMeta.post(); + liveMeta->post(); } ///Checks if removing a key from this track is allowed/safe, and if so, removes it. diff --git a/src/input/input_buffer.h b/src/input/input_buffer.h index 914cc14c..21ff4446 100644 --- a/src/input/input_buffer.h +++ b/src/input/input_buffer.h @@ -13,6 +13,7 @@ namespace Mist { unsigned int cutTime; bool hasPush; bool resumeMode; + IPC::semaphore * liveMeta; protected: //Private Functions bool setup();