From 26f74accdfb6fe209320cbbb78068f468c1bac93 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 9 Jun 2017 20:31:20 +0200 Subject: [PATCH] MistInBuffer no longer boots if the process starting it has no data to fill it with. Optimized and simplified HTTP internal output. --- lib/stream.cpp | 23 +++++++-- lib/stream.h | 2 +- src/input/input.cpp | 5 +- src/input/input_buffer.cpp | 1 + src/output/output.cpp | 6 +-- src/output/output_http.cpp | 46 ++++++++--------- src/output/output_http_internal.cpp | 77 ++++++++++------------------- src/output/output_http_internal.h | 1 - 8 files changed, 75 insertions(+), 86 deletions(-) diff --git a/lib/stream.cpp b/lib/stream.cpp index af60fc7a..c67f22da 100644 --- a/lib/stream.cpp +++ b/lib/stream.cpp @@ -115,11 +115,11 @@ bool Util::streamAlive(std::string & streamname){ } /// Assures the input for the given stream name is active. -/// Does stream name sanitizion first, followed by a stream name length check (<= 100 chars). -/// Then, checks if an input is already active by running streamAlive(). If yes, aborts. -/// If no, loads up the server configuration and attempts to start the given stream according to current config. +/// Does stream name sanitation first, followed by a stream name length check (<= 100 chars). +/// Then, checks if an input is already active by running streamAlive(). If yes, return true. +/// If no, loads up the server configuration and attempts to start the given stream according to current configuration. /// At this point, fails and aborts if MistController isn't running. -bool Util::startInput(std::string streamname, std::string filename, bool forkFirst) { +bool Util::startInput(std::string streamname, std::string filename, bool forkFirst, bool isProvider) { sanitizeName(streamname); if (streamname.size() > 100){ FAIL_MSG("Stream opening denied: %s is longer than 100 characters (%lu).", streamname.c_str(), streamname.size()); @@ -172,6 +172,7 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir DTSC::Scan inputs = config.getMember("capabilities").getMember("inputs"); DTSC::Scan input; unsigned int input_size = inputs.getSize(); + bool noProviderNoPick = false; for (unsigned int i = 0; i < input_size; ++i){ DTSC::Scan tmp_input = inputs.getIndice(i); @@ -185,6 +186,10 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir MEDIUM_MSG("Checking input %s: %s (%s)", inputs.getIndiceName(i).c_str(), tmp_input.getMember("name").asString().c_str(), source.c_str()); if (filename.substr(0,front.size()) == front && filename.substr(filename.size()-back.size()) == back){ + if (tmp_input.getMember("non-provider") && !isProvider){ + noProviderNoPick = true; + continue; + } player_bin = Util::getMyPath() + "MistIn" + tmp_input.getMember("name").asString(); curPrio = tmp_input.getMember("priority").asInt(); selected = true; @@ -198,6 +203,10 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir MEDIUM_MSG("Checking input %s: %s (%s)", inputs.getIndiceName(i).c_str(), tmp_input.getMember("name").asString().c_str(), source.c_str()); if (filename.substr(0,front.size()) == front && filename.substr(filename.size()-back.size()) == back){ + if (tmp_input.getMember("non-provider") && !isProvider){ + noProviderNoPick = true; + continue; + } player_bin = Util::getMyPath() + "MistIn" + tmp_input.getMember("name").asString(); curPrio = tmp_input.getMember("priority").asInt(); selected = true; @@ -210,7 +219,11 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir if (!selected){ configLock.post();//unlock the config semaphore - FAIL_MSG("No compatible input found for stream %s: %s", streamname.c_str(), filename.c_str()); + if (noProviderNoPick){ + INFO_MSG("Not a media provider for stream %s: %s", streamname.c_str(), filename.c_str()); + }else{ + FAIL_MSG("No compatible input found for stream %s: %s", streamname.c_str(), filename.c_str()); + } return false; } diff --git a/lib/stream.h b/lib/stream.h index 6b2e7759..837bf7ef 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -10,7 +10,7 @@ namespace Util { std::string getTmpFolder(); void sanitizeName(std::string & streamname); bool streamAlive(std::string & streamname); - bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true); + bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true, bool isProvider = false); JSON::Value getStreamConfig(std::string streamname); } diff --git a/src/input/input.cpp b/src/input/input.cpp index 6c323cd9..6557d2b5 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -261,7 +261,8 @@ namespace Mist { } } finish(); - DEBUG_MSG(DLVL_DEVEL,"Input for stream %s closing clean", streamName.c_str()); + DEBUG_MSG(DLVL_DEVEL, "Input for stream %s closing clean", streamName.c_str()); + userPage.finishEach(); //end player functionality } @@ -301,7 +302,7 @@ namespace Mist { WARN_MSG("Stream already online, cancelling"); return; } - if (!Util::startInput(streamName, "push://INTERNAL_ONLY:"+config->getString("input"))) {//manually override stream url to start the buffer + if (!Util::startInput(streamName, "push://INTERNAL_ONLY:"+config->getString("input"), true, true)) {//manually override stream url to start the buffer pullLock.post(); pullLock.close(); pullLock.unlink(); diff --git a/src/input/input_buffer.cpp b/src/input/input_buffer.cpp index 1d71d224..561ec99b 100644 --- a/src/input/input_buffer.cpp +++ b/src/input/input_buffer.cpp @@ -51,6 +51,7 @@ namespace Mist { option.null(); capa["source_match"] = "push://*"; + capa["non-provider"] = true;//Indicates we don't provide data, only collect it capa["priority"] = 9ll; capa["desc"] = "Provides buffered live input"; capa["codecs"][0u][0u].append("*"); diff --git a/src/output/output.cpp b/src/output/output.cpp index a923468a..6d47bd51 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -186,7 +186,7 @@ namespace Mist{ return; } }else{ - if (!Util::startInput(streamName)){ + if (!Util::startInput(streamName, "", true, isPushing())){ FAIL_MSG("Opening stream %s failed - aborting initialization", streamName.c_str()); onFail(); return; @@ -224,8 +224,8 @@ namespace Mist{ updateMeta(); selectDefaultTracks(); if (!myMeta.vod && !isReadyForPlay()){ - unsigned long long waitUntil = Util::epoch() + 15; - while (!myMeta.vod && !isReadyForPlay()){ + unsigned long long waitUntil = Util::epoch() + 30; + while (!myMeta.vod && !isReadyForPlay() && nProxy.userClient.isAlive()){ if (Util::epoch() > waitUntil + 45 || (!selectedTracks.size() && Util::epoch() > waitUntil)){ INFO_MSG("Giving up waiting for playable tracks. Stream: %s, IP: %s", streamName.c_str(), getConnectedHost().c_str()); break; diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index d4423ad6..e08cbec9 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -224,32 +224,34 @@ namespace Mist { } INFO_MSG("Received request %s", H.getUrl().c_str()); - selectedTracks.clear(); - if (H.GetVar("audio") != ""){ - selectedTracks.insert(JSON::Value(H.GetVar("audio")).asInt()); - } - if (H.GetVar("video") != ""){ - selectedTracks.insert(JSON::Value(H.GetVar("video")).asInt()); - } - selectDefaultTracks(); - std::set toRemove; - if (H.GetVar("video") == "0"){ - for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ - if (myMeta.tracks.at(*it).type=="video"){ - toRemove.insert(*it); + if (H.GetVar("audio") != "" || H.GetVar("video") != ""){ + selectedTracks.clear(); + if (H.GetVar("audio") != ""){ + selectedTracks.insert(JSON::Value(H.GetVar("audio")).asInt()); + } + if (H.GetVar("video") != ""){ + selectedTracks.insert(JSON::Value(H.GetVar("video")).asInt()); + } + selectDefaultTracks(); + std::set toRemove; + if (H.GetVar("video") == "0"){ + for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ + if (myMeta.tracks.at(*it).type=="video"){ + toRemove.insert(*it); + } } } - } - if (H.GetVar("audio") == "0"){ - for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ - if (myMeta.tracks.at(*it).type=="audio"){ - toRemove.insert(*it); + if (H.GetVar("audio") == "0"){ + for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ + if (myMeta.tracks.at(*it).type=="audio"){ + toRemove.insert(*it); + } } } - } - //remove those from selectedtracks - for (std::set::iterator it = toRemove.begin(); it != toRemove.end(); it++){ - selectedTracks.erase(*it); + //remove those from selectedtracks + for (std::set::iterator it = toRemove.begin(); it != toRemove.end(); it++){ + selectedTracks.erase(*it); + } } onHTTP(); diff --git a/src/output/output_http_internal.cpp b/src/output/output_http_internal.cpp index 752eb0f1..41d8f7ab 100644 --- a/src/output/output_http_internal.cpp +++ b/src/output/output_http_internal.cpp @@ -53,11 +53,6 @@ namespace Mist { Output::onFail(); } - /// The HTTP output is always ready to play - bool OutHTTP::isReadyForPlay() { - return true; - } - void OutHTTP::init(Util::Config * cfg){ HTTPOutput::init(cfg); capa.removeMember("deps"); @@ -65,6 +60,7 @@ namespace Mist { capa["desc"] = "Generic HTTP handler, required for all other HTTP-based outputs."; capa["provides"] = "HTTP"; capa["protocol"] = "http://"; + capa["codecs"][0u][0u].append("*"); capa["url_match"].append("/crossdomain.xml"); capa["url_match"].append("/clientaccesspolicy.xml"); capa["url_match"].append("/$.html"); @@ -321,12 +317,11 @@ namespace Mist { } std::string trackSources;//this string contains all track sources for MBR smil - DTSC::Scan tracks = DTSC::Scan(serverCfg.mapped, serverCfg.len).getMember("streams").getMember(streamName).getMember("meta").getMember("tracks"); - unsigned int track_ctr = tracks.getSize(); - for (unsigned int i = 0; i < track_ctr; ++i){//for all video tracks - DTSC::Scan trk = tracks.getIndice(i); - if (trk.getMember("type").asString() == "video"){ - trackSources += "