Send boot-up progress percentages to status websocket for HLS input

This commit is contained in:
Thulinma 2023-03-09 16:00:38 +01:00
parent 52a10fc177
commit d96524968d
5 changed files with 43 additions and 16 deletions

View file

@ -850,11 +850,19 @@ pid_t Util::startPush(const std::string &streamname, std::string &target, int de
uint8_t Util::getStreamStatus(const std::string &streamname){ uint8_t Util::getStreamStatus(const std::string &streamname){
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamname.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamname.c_str());
IPC::sharedPage streamStatus(pageName, 1, false, false); IPC::sharedPage streamStatus(pageName, 2, false, false);
if (!streamStatus){return STRMSTAT_OFF;} if (!streamStatus){return STRMSTAT_OFF;}
return streamStatus.mapped[0]; return streamStatus.mapped[0];
} }
uint8_t Util::getStreamStatusPercentage(const std::string &streamname){
char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamname.c_str());
IPC::sharedPage streamStatus(pageName, 2, false, false);
if (!streamStatus || streamStatus.len < 2){return 0;}
return streamStatus.mapped[1];
}
/// Checks if a given user agent is allowed according to the given exception. /// Checks if a given user agent is allowed according to the given exception.
bool Util::checkException(const JSON::Value &ex, const std::string &useragent){ bool Util::checkException(const JSON::Value &ex, const std::string &useragent){
// No user agent? Always allow everything. // No user agent? Always allow everything.

View file

@ -27,6 +27,7 @@ namespace Util{
JSON::Value getGlobalConfig(const std::string &optionName); JSON::Value getGlobalConfig(const std::string &optionName);
JSON::Value getInputBySource(const std::string &filename, bool isProvider = false); JSON::Value getInputBySource(const std::string &filename, bool isProvider = false);
uint8_t getStreamStatus(const std::string &streamname); uint8_t getStreamStatus(const std::string &streamname);
uint8_t getStreamStatusPercentage(const std::string &streamname);
bool checkException(const JSON::Value &ex, const std::string &useragent); bool checkException(const JSON::Value &ex, const std::string &useragent);
std::string codecString(const std::string &codec, const std::string &initData = ""); std::string codecString(const std::string &codec, const std::string &initData = "");

View file

@ -56,7 +56,6 @@ namespace Mist{
} }
uint32_t pageNumber = tPages.getInt("firstkey", pageIdx); uint32_t pageNumber = tPages.getInt("firstkey", pageIdx);
if (i == key){ if (i == key){
INFO_MSG("Track %zu key %zu is on page %" PRIu32, track, key, pageNumber);
keyLoadPriority[trackKey(track, pageNumber)] += 10000; keyLoadPriority[trackKey(track, pageNumber)] += 10000;
}else{ }else{
keyLoadPriority[trackKey(track, pageNumber)] += 1000 - (key - i); keyLoadPriority[trackKey(track, pageNumber)] += 1000 - (key - i);
@ -69,7 +68,6 @@ namespace Mist{
} }
void Input::userOnDisconnect(size_t id){} void Input::userOnDisconnect(size_t id){}
void Input::userLeadOut(){ void Input::userLeadOut(){
INFO_MSG("Wanna load %zu keys", keyLoadPriority.size());
if (!keyLoadPriority.size()){return;} if (!keyLoadPriority.size()){return;}
//Make reverse mapping //Make reverse mapping
std::multimap<uint64_t, trackKey> reverse; std::multimap<uint64_t, trackKey> reverse;
@ -412,7 +410,7 @@ namespace Mist{
//Set stream status to STRMSTAT_INIT, then close the page in non-master mode to keep it around //Set stream status to STRMSTAT_INIT, then close the page in non-master mode to keep it around
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false); streamStatus.init(pageName, 2, true, false);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
streamStatus.master = false; streamStatus.master = false;
streamStatus.close(); streamStatus.close();
@ -459,7 +457,7 @@ namespace Mist{
// Re-init streamStatus, previously closed // Re-init streamStatus, previously closed
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false); streamStatus.init(pageName, 2, true, false);
streamStatus.master = false; streamStatus.master = false;
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
} }
@ -469,7 +467,7 @@ namespace Mist{
playerLock.unlink(); playerLock.unlink();
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false); streamStatus.init(pageName, 2, true, false);
streamStatus.close(); streamStatus.close();
} }
playerLock.unlink(); playerLock.unlink();
@ -490,7 +488,7 @@ namespace Mist{
// Re-init streamStatus, previously closed // Re-init streamStatus, previously closed
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false); streamStatus.init(pageName, 2, true, false);
streamStatus.master = false; streamStatus.master = false;
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;}
} }
@ -528,7 +526,7 @@ namespace Mist{
if (playerLock){ if (playerLock){
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false); streamStatus.init(pageName, 2, true, false);
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INVALID;} if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INVALID;}
} }
#if DEBUG >= DLVL_DEVEL #if DEBUG >= DLVL_DEVEL
@ -559,7 +557,7 @@ namespace Mist{
pidPage.close(); pidPage.close();
//Clear stream state //Clear stream state
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
streamStatus.init(pageName, 1, true, false); streamStatus.init(pageName, 2, true, false);
streamStatus.close(); streamStatus.close();
//Delete lock //Delete lock
playerLock.unlink(); playerLock.unlink();

View file

@ -825,13 +825,21 @@ namespace Mist{
meta.reInit(isSingular() ? streamName : ""); meta.reInit(isSingular() ? streamName : "");
tthread::lock_guard<tthread::mutex> guard(entryMutex); tthread::lock_guard<tthread::mutex> guard(entryMutex);
size_t totalSegments = 0, currentSegment = 0;
for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin(); for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin();
pListIt != listEntries.end(); pListIt++){ pListIt != listEntries.end(); pListIt++){
totalSegments += pListIt->second.size();
}
for (std::map<uint32_t, std::deque<playListEntries> >::iterator pListIt = listEntries.begin();
pListIt != listEntries.end() && config->is_active; pListIt++){
tsStream.clear(); tsStream.clear();
uint32_t entId = 0; uint32_t entId = 0;
for (std::deque<playListEntries>::iterator entryIt = pListIt->second.begin(); for (std::deque<playListEntries>::iterator entryIt = pListIt->second.begin();
entryIt != pListIt->second.end(); entryIt++){ entryIt != pListIt->second.end() && config->is_active; entryIt++){
++currentSegment;
tsStream.partialClear(); tsStream.partialClear();
if (!segDowner.loadSegment(*entryIt)){ if (!segDowner.loadSegment(*entryIt)){
@ -840,7 +848,7 @@ namespace Mist{
} }
entId++; entId++;
allowRemap = true; allowRemap = true;
while (!segDowner.atEnd()){ while (!segDowner.atEnd() && config->is_active){
// Wait for packets on each track to make sure the offset is set based on the earliest packet // Wait for packets on each track to make sure the offset is set based on the earliest packet
hasPacket = tsStream.hasPacketOnEachTrack() || (segDowner.atEnd() && tsStream.hasPacket()); hasPacket = tsStream.hasPacketOnEachTrack() || (segDowner.atEnd() && tsStream.hasPacket());
if (hasPacket){ if (hasPacket){
@ -902,8 +910,14 @@ namespace Mist{
std::deque<playListEntries> &curList = listEntries[pListIt->first]; std::deque<playListEntries> &curList = listEntries[pListIt->first];
curList.at(entId-1).timeOffset = 0; curList.at(entId-1).timeOffset = 0;
} }
//Set progress counter
if (streamStatus && streamStatus.len > 1){
streamStatus.mapped[1] = (255 * currentSegment) / totalSegments;
} }
} }
}
if (!config->is_active){return false;}
// set bootMsOffset in order to display the program time correctly in the player // set bootMsOffset in order to display the program time correctly in the player
if (meta.getLive()){meta.setUTCOffset(streamOffset + (Util::unixMS() - Util::bootMS()));} if (meta.getLive()){meta.setUTCOffset(streamOffset + (Util::unixMS() - Util::bootMS()));}

View file

@ -437,6 +437,7 @@ namespace Mist{
json_resp["redirected"].append(streamName); json_resp["redirected"].append(streamName);
} }
uint8_t streamStatus = Util::getStreamStatus(streamName); uint8_t streamStatus = Util::getStreamStatus(streamName);
uint8_t streamStatusPerc = Util::getStreamStatusPercentage(streamName);
if (streamStatus != STRMSTAT_READY){ if (streamStatus != STRMSTAT_READY){
// If we haven't rewritten the stream name yet to a fallback, attempt to do so // If we haven't rewritten the stream name yet to a fallback, attempt to do so
if (origStreamName == streamName){ if (origStreamName == streamName){
@ -488,6 +489,7 @@ namespace Mist{
case STRMSTAT_INVALID: json_resp["error"] = "Stream status is invalid?!"; break; case STRMSTAT_INVALID: json_resp["error"] = "Stream status is invalid?!"; break;
default: json_resp["error"] = "Stream status is unknown?!"; break; default: json_resp["error"] = "Stream status is unknown?!"; break;
} }
if (streamStatusPerc){json_resp["perc"] = ((double)streamStatusPerc)/2.55;}
return json_resp; return json_resp;
} }
initialize(); initialize();
@ -806,7 +808,6 @@ namespace Mist{
if (!useragent.size()){useragent = req.GetHeader("User-Agent");} if (!useragent.size()){useragent = req.GetHeader("User-Agent");}
std::string response; std::string response;
std::string rURL = req.url; std::string rURL = req.url;
if (headersOnly){initialize();}
if (rURL.substr(0, 6) != "/json_"){ if (rURL.substr(0, 6) != "/json_"){
H.SetHeader("Content-Type", "application/javascript"); H.SetHeader("Content-Type", "application/javascript");
}else{ }else{
@ -1125,26 +1126,30 @@ namespace Mist{
if (!ws){return false;} if (!ws){return false;}
setBlocking(false); setBlocking(false);
// start the stream, if needed // start the stream, if needed
Util::startInput(streamName, "", true, false); Util::sanitizeName(streamName);
if (!Util::streamAlive(streamName)){Util::startInput(streamName, "", true, false);}
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
std::string currStreamName; std::string currStreamName;
currStreamName = streamName; currStreamName = streamName;
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str());
IPC::sharedPage streamStatus(pageName, 1, false, false); IPC::sharedPage streamStatus(pageName, 2, false, false);
uint8_t prevState, newState, pingCounter = 0; uint8_t prevState, newState, pingCounter = 0;
uint8_t prevStatePerc = 0, newStatePerc = 0;
std::set<size_t> prevTracks; std::set<size_t> prevTracks;
prevState = newState = STRMSTAT_INVALID; prevState = newState = STRMSTAT_INVALID;
while (keepGoing()){ while (keepGoing()){
if (!streamStatus || !streamStatus.exists()){streamStatus.init(pageName, 1, false, false);} if (!streamStatus || !streamStatus.exists()){streamStatus.init(pageName, 2, false, false);}
if (!streamStatus){ if (!streamStatus){
newState = STRMSTAT_OFF; newState = STRMSTAT_OFF;
newStatePerc = 0;
}else{ }else{
newState = streamStatus.mapped[0]; newState = streamStatus.mapped[0];
if (streamStatus.len > 1){newStatePerc = streamStatus.mapped[1];}
} }
if (meta){meta.reloadReplacedPagesIfNeeded();} if (meta){meta.reloadReplacedPagesIfNeeded();}
if (newState != prevState || (newState == STRMSTAT_READY && M.getValidTracks() != prevTracks)){ if (newState != prevState || (newState == STRMSTAT_READY && M.getValidTracks() != prevTracks) || (newState != STRMSTAT_READY && newStatePerc != prevStatePerc)){
if (newState == STRMSTAT_READY){ if (newState == STRMSTAT_READY){
thisError = ""; thisError = "";
reconnect(); reconnect();
@ -1170,6 +1175,7 @@ namespace Mist{
} }
ws.sendFrame(resp.toString()); ws.sendFrame(resp.toString());
prevState = newState; prevState = newState;
prevStatePerc = newStatePerc;
}else{ }else{
if (newState == STRMSTAT_READY){stats();} if (newState == STRMSTAT_READY){stats();}
if (myConn.spool() && ws.readFrame()){ if (myConn.spool() && ws.readFrame()){