Improved output timing

This commit is contained in:
Thulinma 2018-11-05 13:48:01 +01:00
parent 672c0d55b9
commit 25bb8aac5f
2 changed files with 26 additions and 9 deletions

View file

@ -75,6 +75,7 @@ namespace Mist{
isInitialized = false; isInitialized = false;
isBlocking = false; isBlocking = false;
needsLookAhead = 0; needsLookAhead = 0;
extraKeepAway = 0;
lastStats = 0; lastStats = 0;
maxSkipAhead = 7500; maxSkipAhead = 7500;
uaDelay = 10; uaDelay = 10;
@ -758,7 +759,7 @@ namespace Mist{
nxtKeyNum[trackId] = 0; nxtKeyNum[trackId] = 0;
} }
stats(true); stats(true);
Util::wait(100); playbackSleep(100);
pageNum = pageNumForKey(trackId, keyNum); pageNum = pageNumForKey(trackId, keyNum);
} }
@ -988,7 +989,7 @@ namespace Mist{
continue; continue;
}//ignore missing tracks }//ignore missing tracks
DTSC::Track & thisTrack = myMeta.tracks[*ti]; DTSC::Track & thisTrack = myMeta.tracks[*ti];
if (thisTrack.lastms < seekPos+needsLookAhead+thisTrack.minKeepAway){good = false; break;} if (thisTrack.lastms < seekPos+needsLookAhead+extraKeepAway+thisTrack.minKeepAway){good = false; break;}
if (mainTrack == *ti){continue;}//skip self if (mainTrack == *ti){continue;}//skip self
if (thisTrack.lastms == thisTrack.firstms){ if (thisTrack.lastms == thisTrack.firstms){
HIGH_MSG("Skipping track %lu, last equals first", *ti); HIGH_MSG("Skipping track %lu, last equals first", *ti);
@ -1143,7 +1144,6 @@ namespace Mist{
if (!myMeta.tracks.count(mainTrack)){return false;} if (!myMeta.tracks.count(mainTrack)){return false;}
DTSC::Track & mainTrk = myMeta.tracks[mainTrack]; DTSC::Track & mainTrk = myMeta.tracks[mainTrack];
if (!mainTrk.keys.size()){return false;} if (!mainTrk.keys.size()){return false;}
uint32_t minKeepAway = mainTrk.minKeepAway;
for (std::deque<DTSC::Key>::reverse_iterator it = myMeta.tracks[mainTrack].keys.rbegin(); it != myMeta.tracks[mainTrack].keys.rend(); ++it){ for (std::deque<DTSC::Key>::reverse_iterator it = myMeta.tracks[mainTrack].keys.rbegin(); it != myMeta.tracks[mainTrack].keys.rend(); ++it){
seekPos = it->getTime(); seekPos = it->getTime();
@ -1157,7 +1157,7 @@ namespace Mist{
continue; continue;
}//ignore missing tracks }//ignore missing tracks
DTSC::Track & thisTrack = myMeta.tracks[*ti]; DTSC::Track & thisTrack = myMeta.tracks[*ti];
if (thisTrack.lastms < seekPos+needsLookAhead+thisTrack.minKeepAway){good = false; break;} if (thisTrack.lastms < seekPos+needsLookAhead+extraKeepAway+thisTrack.minKeepAway){good = false; break;}
if (mainTrack == *ti){continue;}//skip self if (mainTrack == *ti){continue;}//skip self
if (thisTrack.lastms == thisTrack.firstms){ if (thisTrack.lastms == thisTrack.firstms){
HIGH_MSG("Skipping track %lu, last equals first", *ti); HIGH_MSG("Skipping track %lu, last equals first", *ti);
@ -1167,7 +1167,7 @@ namespace Mist{
} }
//if yes, seek here //if yes, seek here
if (good){ if (good){
INFO_MSG("Skipping forward %llums (%u ms LA, %lu ms mKA, > %lums)", seekPos - thisPacket.getTime(), needsLookAhead, mainTrk.minKeepAway, seekCount*250); INFO_MSG("Skipping forward %llums (%u ms LA, %lu ms mKA, %lu eKA, > %lums)", seekPos - thisPacket.getTime(), needsLookAhead, mainTrk.minKeepAway, extraKeepAway, seekCount*250);
if (seekCount < 20){++seekCount;} if (seekCount < 20){++seekCount;}
seek(seekPos); seek(seekPos);
return true; return true;
@ -1195,6 +1195,16 @@ namespace Mist{
} }
} }
/// Waits for the given amount of millis, increasing the realtime playback
/// related times as needed to keep smooth playback intact.
void Output::playbackSleep(uint64_t millis){
if (realTime){
firstTime += millis;
extraKeepAway += millis;
}
Util::wait(millis);
}
/// \triggers /// \triggers
/// The `"CONN_OPEN"` trigger is stream-specific, and is ran when a connection is made or passed to a new handler. Its payload is: /// The `"CONN_OPEN"` trigger is stream-specific, and is ran when a connection is made or passed to a new handler. Its payload is:
/// ~~~~~~~~~~~~~~~ /// ~~~~~~~~~~~~~~~
@ -1288,6 +1298,7 @@ namespace Mist{
//wait at most double the look ahead time, plus ten seconds //wait at most double the look ahead time, plus ten seconds
uint32_t timeoutTries = (needsLookAhead / sleepTime) * 2 + (10000/sleepTime); uint32_t timeoutTries = (needsLookAhead / sleepTime) * 2 + (10000/sleepTime);
uint64_t needsTime = thisPacket.getTime() + needsLookAhead; uint64_t needsTime = thisPacket.getTime() + needsLookAhead;
bool firstTime = true;
while(--timeoutTries && keepGoing()){ while(--timeoutTries && keepGoing()){
bool lookReady = true; bool lookReady = true;
for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
@ -1300,7 +1311,11 @@ namespace Mist{
} }
} }
if (lookReady){break;} if (lookReady){break;}
Util::wait(sleepTime); if (firstTime){
firstTime = false;
}else{
playbackSleep(sleepTime);
}
stats(); stats();
updateMeta(); updateMeta();
} }
@ -1501,7 +1516,7 @@ namespace Mist{
//VoD might be slow, so we check VoD case also, just in case //VoD might be slow, so we check VoD case also, just in case
if (currKeyOpen.count(nxt.tid) && (currKeyOpen[nxt.tid] == (unsigned int)nextPage || nextPage == -1)){ if (currKeyOpen.count(nxt.tid) && (currKeyOpen[nxt.tid] == (unsigned int)nextPage || nextPage == -1)){
if (++emptyCount < 100){ if (++emptyCount < 100){
Util::wait(250); playbackSleep(250);
//we're waiting for new data to show up //we're waiting for new data to show up
if (emptyCount % 64 == 0){ if (emptyCount % 64 == 0){
reconnect();//reconnect every 16 seconds reconnect();//reconnect every 16 seconds
@ -1588,7 +1603,7 @@ namespace Mist{
while(myMeta.live && counter < 40 && myMeta.tracks[nxt.tid].getKey(nxtKeyNum[nxt.tid]).getTime() != thisPacket.getTime()){ while(myMeta.live && counter < 40 && myMeta.tracks[nxt.tid].getKey(nxtKeyNum[nxt.tid]).getTime() != thisPacket.getTime()){
if (counter++){ if (counter++){
//Only sleep 250ms if this is not the first updatemeta try //Only sleep 250ms if this is not the first updatemeta try
Util::wait(250); playbackSleep(250);
} }
updateMeta(); updateMeta();
nxtKeyNum[nxt.tid] = getKeyForTime(nxt.tid, thisPacket.getTime()); nxtKeyNum[nxt.tid] = getKeyForTime(nxt.tid, thisPacket.getTime());

View file

@ -81,6 +81,7 @@ namespace Mist {
virtual void onFail(); virtual void onFail();
virtual void requestHandler(); virtual void requestHandler();
static Util::Config * config; static Util::Config * config;
void playbackSleep(uint64_t millis);
private://these *should* not be messed with in child classes. private://these *should* not be messed with in child classes.
/*LTS-START*/ /*LTS-START*/
void Log(std::string type, std::string message); void Log(std::string type, std::string message);
@ -106,6 +107,7 @@ namespace Mist {
std::string UA; ///< User Agent string, if known. std::string UA; ///< User Agent string, if known.
uint16_t uaDelay;///<Seconds to wait before setting the UA. uint16_t uaDelay;///<Seconds to wait before setting the UA.
uint64_t lastRecv; uint64_t lastRecv;
uint64_t extraKeepAway;
long long unsigned int firstTime;///< Time of first packet after last seek. Used for real-time sending. long long unsigned int firstTime;///< Time of first packet after last seek. Used for real-time sending.
virtual std::string getConnectedHost(); virtual std::string getConnectedHost();
virtual std::string getConnectedBinHost(); virtual std::string getConnectedBinHost();