Send boot-up progress percentages to status websocket for HLS input
This commit is contained in:
parent
52a10fc177
commit
d96524968d
5 changed files with 43 additions and 16 deletions
|
@ -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.
|
||||||
|
|
|
@ -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 = "");
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()));}
|
||||||
|
|
|
@ -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()){
|
||||||
|
|
Loading…
Add table
Reference in a new issue