Changed buffer full/empty behaviour to trigger at 3 segments instead of 50% of buffer size.
This commit is contained in:
parent
b6f03a4591
commit
a6ef31d1ea
2 changed files with 26 additions and 17 deletions
|
@ -17,6 +17,11 @@
|
||||||
#define TIMEOUTMULTIPLIER 2
|
#define TIMEOUTMULTIPLIER 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*LTS-START*/
|
||||||
|
//We consider a stream playable when this many fragments are available.
|
||||||
|
#define FRAG_BOOT 3
|
||||||
|
/*LTS-END*/
|
||||||
|
|
||||||
namespace Mist {
|
namespace Mist {
|
||||||
inputBuffer::inputBuffer(Util::Config * cfg) : Input(cfg){
|
inputBuffer::inputBuffer(Util::Config * cfg) : Input(cfg){
|
||||||
capa["name"] = "Buffer";
|
capa["name"] = "Buffer";
|
||||||
|
@ -137,7 +142,7 @@ namespace Mist {
|
||||||
config->is_active = false;
|
config->is_active = false;
|
||||||
if (myMeta.tracks.size()){
|
if (myMeta.tracks.size()){
|
||||||
/*LTS-START*/
|
/*LTS-START*/
|
||||||
if (myMeta.bufferWindow >= bufferTime /2){
|
if (myMeta.bufferWindow){
|
||||||
if(Triggers::shouldTrigger("STREAM_BUFFER")){
|
if(Triggers::shouldTrigger("STREAM_BUFFER")){
|
||||||
std::string payload = config->getString("streamname")+"\nEMPTY";
|
std::string payload = config->getString("streamname")+"\nEMPTY";
|
||||||
Triggers::doTrigger("STREAM_BUFFER", payload, config->getString("streamname"));
|
Triggers::doTrigger("STREAM_BUFFER", payload, config->getString("streamname"));
|
||||||
|
@ -176,14 +181,16 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \triggers
|
/// \triggers
|
||||||
/// The `"STREAM_BUFFER"` trigger is stream-specific, and is ran whenever the buffer changes state between mostly full or mostly emptu. It cannot be cancelled. Its payload is:
|
/// The `"STREAM_BUFFER"` trigger is stream-specific, and is ran whenever the buffer changes state between playable (FULL) or not (EMPTY). It cannot be cancelled. It is possible to receive multiple EMPTY calls without FULL calls in between, as EMPTY is always generated when a stream is unloaded from memory, even if this stream never reached playable state in the first place (e.g. a broadcast was cancelled before filling enough buffer to be playable). Its payload is:
|
||||||
/// ~~~~~~~~~~~~~~~
|
/// ~~~~~~~~~~~~~~~
|
||||||
/// streamname
|
/// streamname
|
||||||
/// FULL or EMPTY (depending on current state)
|
/// FULL or EMPTY (depending on current state)
|
||||||
/// ~~~~~~~~~~~~~~~
|
/// ~~~~~~~~~~~~~~~
|
||||||
void inputBuffer::updateMeta(){
|
void inputBuffer::updateMeta(){
|
||||||
|
static long long unsigned int lastFragCount = 0xFFFFull;
|
||||||
long long unsigned int firstms = 0xFFFFFFFFFFFFFFFFull;
|
long long unsigned int firstms = 0xFFFFFFFFFFFFFFFFull;
|
||||||
long long unsigned int lastms = 0;
|
long long unsigned int lastms = 0;
|
||||||
|
long long unsigned int fragCount = 0xFFFFull;
|
||||||
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
|
||||||
if (it->second.type == "meta" || !it->second.type.size()){continue;}
|
if (it->second.type == "meta" || !it->second.type.size()){continue;}
|
||||||
if (it->second.init.size()){
|
if (it->second.init.size()){
|
||||||
|
@ -195,6 +202,9 @@ namespace Mist {
|
||||||
it->second.init = initData[it->first];
|
it->second.init = initData[it->first];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (it->second.fragments.size() < fragCount){
|
||||||
|
fragCount = it->second.fragments.size();
|
||||||
|
}
|
||||||
if (it->second.firstms < firstms){
|
if (it->second.firstms < firstms){
|
||||||
firstms = it->second.firstms;
|
firstms = it->second.firstms;
|
||||||
}
|
}
|
||||||
|
@ -203,18 +213,19 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*LTS-START*/
|
/*LTS-START*/
|
||||||
if (myMeta.bufferWindow < bufferTime /2 && (lastms - firstms) >= bufferTime/2){
|
if (fragCount >= FRAG_BOOT && fragCount != 0xFFFFull && (lastFragCount == 0xFFFFull || lastFragCount < FRAG_BOOT)){
|
||||||
if(Triggers::shouldTrigger("STREAM_BUFFER")){
|
if(Triggers::shouldTrigger("STREAM_BUFFER")){
|
||||||
std::string payload = config->getString("streamname")+"\nFULL";
|
std::string payload = config->getString("streamname")+"\nFULL";
|
||||||
Triggers::doTrigger("STREAM_BUFFER", payload, config->getString("streamname"));
|
Triggers::doTrigger("STREAM_BUFFER", payload, config->getString("streamname"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (myMeta.bufferWindow >= bufferTime /2 && (lastms - firstms) < bufferTime/2){
|
if ((fragCount < FRAG_BOOT || fragCount == 0xFFFFull) && (lastFragCount >= FRAG_BOOT && lastFragCount != 0xFFFFull)){
|
||||||
if(Triggers::shouldTrigger("STREAM_BUFFER")){
|
if(Triggers::shouldTrigger("STREAM_BUFFER")){
|
||||||
std::string payload = config->getString("streamname")+"\nEMPTY";
|
std::string payload = config->getString("streamname")+"\nEMPTY";
|
||||||
Triggers::doTrigger("STREAM_BUFFER", payload, config->getString("streamname"));
|
Triggers::doTrigger("STREAM_BUFFER", payload, config->getString("streamname"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastFragCount = fragCount;
|
||||||
/*LTS-END*/
|
/*LTS-END*/
|
||||||
myMeta.bufferWindow = lastms - firstms;
|
myMeta.bufferWindow = lastms - firstms;
|
||||||
myMeta.vod = false;
|
myMeta.vod = false;
|
||||||
|
|
|
@ -164,14 +164,13 @@ namespace Mist {
|
||||||
snprintf(lineBuf, 400, "#EXTINF:%lld, no desc\r\n%lld_%lld,ts\r\n", ((duration + 500) / 1000), starttime, starttime + duration);
|
snprintf(lineBuf, 400, "#EXTINF:%lld, no desc\r\n%lld_%lld,ts\r\n", ((duration + 500) / 1000), starttime, starttime + duration);
|
||||||
lines.push_back(lineBuf);
|
lines.push_back(lineBuf);
|
||||||
}
|
}
|
||||||
//skip the first fragment if live and there are more than 2 fragments.
|
|
||||||
unsigned int skippedLines = 0;
|
unsigned int skippedLines = 0;
|
||||||
if (myMeta.live) {
|
if (myMeta.live) {
|
||||||
//only print the last segment when VoD
|
//only print the last segment when VoD
|
||||||
lines.pop_back();
|
lines.pop_back();
|
||||||
/*LTS-START*/
|
/*LTS-START*/
|
||||||
unsigned int skip = (( myMeta.tracks[tid].fragments.size()-1) * config->getInteger("startpos")) / 1000u;
|
unsigned int skip = (( myMeta.tracks[tid].fragments.size()-1) * config->getInteger("startpos")) / 1000u;
|
||||||
while (skippedLines < skip && lines.size()) {
|
while (skippedLines < skip && lines.size() >= 3){
|
||||||
lines.pop_front();
|
lines.pop_front();
|
||||||
skippedLines++;
|
skippedLines++;
|
||||||
}
|
}
|
||||||
|
@ -297,17 +296,16 @@ namespace Mist {
|
||||||
if (!myMeta.tracks.size()) {
|
if (!myMeta.tracks.size()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
//loop trough all the tracks
|
//check main track
|
||||||
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
|
DTSC::Track & mainTrack = myMeta.tracks[*selectedTracks.begin()];
|
||||||
//return "too late" if one track is past this point
|
//return "too late" if one track is past this point
|
||||||
if (ms < it->second.firstms) {
|
if (ms < mainTrack.firstms){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
//return "too early" if one track is not yet at this point
|
//return "too early" if one track is not yet at this point
|
||||||
if (ms > it->second.lastms) {
|
if (ms > mainTrack.lastms){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue