Added ability for outputs to elect to only receive completed (i.e.: whole) keyframes, by Oswald de Bruin.
This commit is contained in:
parent
c254085579
commit
17f3a37454
2 changed files with 45 additions and 0 deletions
|
@ -39,10 +39,12 @@ namespace Mist {
|
||||||
sought = false;
|
sought = false;
|
||||||
isInitialized = false;
|
isInitialized = false;
|
||||||
isBlocking = false;
|
isBlocking = false;
|
||||||
|
completeKeysOnly = false;
|
||||||
lastStats = 0;
|
lastStats = 0;
|
||||||
maxSkipAhead = 7500;
|
maxSkipAhead = 7500;
|
||||||
minSkipAhead = 5000;
|
minSkipAhead = 5000;
|
||||||
realTime = 1000;
|
realTime = 1000;
|
||||||
|
completeKeyReadyTimeOut = false;
|
||||||
if (myConn){
|
if (myConn){
|
||||||
setBlocking(true);
|
setBlocking(true);
|
||||||
}else{
|
}else{
|
||||||
|
@ -584,6 +586,47 @@ namespace Mist {
|
||||||
Util::sleep(nxt.time - (((Util::getMS() - firstTime)*1000)+minSkipAhead)/realTime);
|
Util::sleep(nxt.time - (((Util::getMS() - firstTime)*1000)+minSkipAhead)/realTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//delay the stream until its current keyframe is complete
|
||||||
|
if (completeKeysOnly){
|
||||||
|
bool completeKeyReady = false;
|
||||||
|
int timeoutTries = 40;//attempts to updateMeta before timeOut and moving on; default is approximately 10 seconds
|
||||||
|
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
||||||
|
if (it->second.keys.size() >1){
|
||||||
|
int thisTimeoutTries = ((it->second.lastms - it->second.firstms) / (it->second.keys.size()-1)) / 125;
|
||||||
|
if (thisTimeoutTries > timeoutTries) timeoutTries = thisTimeoutTries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!completeKeyReady && timeoutTries>0){
|
||||||
|
completeKeyReady = true;
|
||||||
|
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
||||||
|
if (!it->second.keys.size() || it->second.keys.rbegin()->getTime() + it->second.keys.rbegin()->getLength() <= nxt.time ){
|
||||||
|
completeKeyReady = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!completeKeyReady){
|
||||||
|
if (completeKeyReadyTimeOut){
|
||||||
|
INSANE_MSG("Complete Key not ready and time-out is being skipped");
|
||||||
|
timeoutTries = 0;
|
||||||
|
}else{
|
||||||
|
INSANE_MSG("Timeout: %d",timeoutTries);
|
||||||
|
timeoutTries--;//we count down
|
||||||
|
stats();
|
||||||
|
Util::wait(250);
|
||||||
|
updateMeta();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (timeoutTries<=0){
|
||||||
|
if (!completeKeyReadyTimeOut){
|
||||||
|
INFO_MSG("Wait for keyframe Timeout triggered! Ended to avoid endless loops");
|
||||||
|
}
|
||||||
|
completeKeyReadyTimeOut = true;
|
||||||
|
}else{
|
||||||
|
//untimeout handling
|
||||||
|
completeKeyReadyTimeOut = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (curPage[nxt.tid]){
|
if (curPage[nxt.tid]){
|
||||||
if (nxt.offset < curPage[nxt.tid].len){
|
if (nxt.offset < curPage[nxt.tid].len){
|
||||||
unsigned long long nextTime = getDTSCTime(curPage[nxt.tid].mapped, nxt.offset);
|
unsigned long long nextTime = getDTSCTime(curPage[nxt.tid].mapped, nxt.offset);
|
||||||
|
|
|
@ -73,6 +73,7 @@ namespace Mist {
|
||||||
std::map<unsigned long, unsigned long> nxtKeyNum;///< Contains the number of the next key, for page seeking purposes.
|
std::map<unsigned long, unsigned long> nxtKeyNum;///< Contains the number of the next key, for page seeking purposes.
|
||||||
std::set<sortedPageInfo> buffer;///< A sorted list of next-to-be-loaded packets.
|
std::set<sortedPageInfo> buffer;///< A sorted list of next-to-be-loaded packets.
|
||||||
bool sought;///<If a seek has been done, this is set to true. Used for seeking on prepareNext().
|
bool sought;///<If a seek has been done, this is set to true. Used for seeking on prepareNext().
|
||||||
|
bool completeKeyReadyTimeOut;//a bool to see if there has been a keyframe TimeOut for complete keys in Live
|
||||||
protected://these are to be messed with by child classes
|
protected://these are to be messed with by child classes
|
||||||
IPC::sharedClient statsPage;///< Shared memory used for statistics reporting.
|
IPC::sharedClient statsPage;///< Shared memory used for statistics reporting.
|
||||||
bool isBlocking;///< If true, indicates that myConn is blocking.
|
bool isBlocking;///< If true, indicates that myConn is blocking.
|
||||||
|
@ -83,6 +84,7 @@ namespace Mist {
|
||||||
unsigned int maxSkipAhead;///< Maximum ms that we will go ahead of the intended timestamps.
|
unsigned int maxSkipAhead;///< Maximum ms that we will go ahead of the intended timestamps.
|
||||||
unsigned int minSkipAhead;///< Minimum ms that we will go ahead of the intended timestamps.
|
unsigned int minSkipAhead;///< Minimum ms that we will go ahead of the intended timestamps.
|
||||||
unsigned int realTime;///< Playback speed in ms of data per second. eg: 0 is infinite, 1000 real-time, 5000 is 0.2X speed, 500 = 2X speed.
|
unsigned int realTime;///< Playback speed in ms of data per second. eg: 0 is infinite, 1000 real-time, 5000 is 0.2X speed, 500 = 2X speed.
|
||||||
|
bool completeKeysOnly;///< Bool if we send whole keys only, so the metadata is complete and the output knows in advance what will be sent.
|
||||||
|
|
||||||
//Read/write status variables
|
//Read/write status variables
|
||||||
Socket::Connection & myConn;///< Connection to the client.
|
Socket::Connection & myConn;///< Connection to the client.
|
||||||
|
|
Loading…
Add table
Reference in a new issue