Added options to DTSC pull for controlling the buffer config. Made 8X target duration the default buffer size. Inputs now wait for INPUT_TIMEOUT *and* two biggestFragment durations, added a few helper functions to DTSC::Meta. Buffer now automatically sets segment size to min(configed_size, biggest_fragment/2) to prevent sudden reductions of fragment sizes by more than 50%

This commit is contained in:
Thulinma 2016-10-11 15:02:29 +02:00
parent 65a225ed95
commit 22cd84fcd5
5 changed files with 43 additions and 5 deletions

View file

@ -326,6 +326,8 @@ namespace DTSC {
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0); void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
//members: //members:
std::map<unsigned int, Track> tracks; std::map<unsigned int, Track> tracks;
Track & mainTrack();
uint32_t biggestFragment();
bool vod; bool vod;
bool live; bool live;
bool merged; bool merged;

View file

@ -1347,6 +1347,28 @@ namespace DTSC {
} }
} }
/// Returns a reference to the first video track, or the first track.
/// Beware: returns a reference to invalid memory if there are no tracks!
/// Will print a WARN-level message if this is the case.
Track & Meta::mainTrack(){
if (!tracks.size()){
WARN_MSG("Returning nonsense reference - crashing is likely");
return tracks.begin()->second;
}
for (std::map<unsigned int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
if (it->second.type == "video"){
return it->second;
}
}
return tracks.begin()->second;
}
/// Returns 0 if there are no tracks, otherwise calls mainTrack().biggestFragment().
uint32_t Meta::biggestFragment(){
if (!tracks.size()){return 0;}
return mainTrack().biggestFragment();
}
///\brief Converts a track to a human readable string ///\brief Converts a track to a human readable string
///\param str The stringstream to append to ///\param str The stringstream to append to
///\param indent the amount of indentation needed ///\param indent the amount of indentation needed

View file

@ -170,7 +170,7 @@ namespace Mist {
DEBUG_MSG(DLVL_DEVEL,"Input for stream %s started", streamName.c_str()); DEBUG_MSG(DLVL_DEVEL,"Input for stream %s started", streamName.c_str());
long long int activityCounter = Util::bootSecs(); long long int activityCounter = Util::bootSecs();
while ((Util::bootSecs() - activityCounter) < INPUT_TIMEOUT && config->is_active) { //15 second timeout while (((Util::bootSecs() - activityCounter) < INPUT_TIMEOUT || (myMeta.live && (Util::bootSecs() - activityCounter) < myMeta.biggestFragment()/500)) && config->is_active) { //15 second timeout
userPage.parseEach(callbackWrapper); userPage.parseEach(callbackWrapper);
removeUnused(); removeUnused();
if (userPage.connectedUsers) { if (userPage.connectedUsers) {

View file

@ -27,7 +27,7 @@ namespace Mist {
option["value"].append(50000LL); option["value"].append(50000LL);
config->addOption("bufferTime", option); config->addOption("bufferTime", option);
capa["optional"]["DVR"]["name"] = "Buffer time (ms)"; capa["optional"]["DVR"]["name"] = "Buffer time (ms)";
capa["optional"]["DVR"]["help"] = "The target available buffer time for this live stream, in milliseconds. This is the time available to seek around in, and will automatically be extended to fit whole keyframes."; capa["optional"]["DVR"]["help"] = "The target available buffer time for this live stream, in milliseconds. This is the time available to seek around in, and will automatically be extended to fit whole keyframes as well as the minimum duration needed for stable playback.";
capa["optional"]["DVR"]["option"] = "--buffer"; capa["optional"]["DVR"]["option"] = "--buffer";
capa["optional"]["DVR"]["type"] = "uint"; capa["optional"]["DVR"]["type"] = "uint";
capa["optional"]["DVR"]["default"] = 50000LL; capa["optional"]["DVR"]["default"] = 50000LL;
@ -219,14 +219,14 @@ namespace Mist {
return false; return false;
} }
if (config->is_active && Trk.fragments.size() > 2){ if (config->is_active && Trk.fragments.size() > 2){
///Make sure we have at least 3X the target duration. ///Make sure we have at least 8X the target duration.
//The target duration is the biggest fragment, rounded up to whole seconds. //The target duration is the biggest fragment, rounded up to whole seconds.
uint32_t targetDuration = (Trk.biggestFragment() / 1000 + 1) * 1000; uint32_t targetDuration = (Trk.biggestFragment() / 1000 + 1) * 1000;
//The start is the third fragment's begin //The start is the third fragment's begin
uint32_t fragStart = Trk.getKey((++(++Trk.fragments.begin()))->getNumber()).getTime(); uint32_t fragStart = Trk.getKey((++(++Trk.fragments.begin()))->getNumber()).getTime();
//The end is the last fragment's begin //The end is the last fragment's begin
uint32_t fragEnd = Trk.getKey(Trk.fragments.rbegin()->getNumber()).getTime(); uint32_t fragEnd = Trk.getKey(Trk.fragments.rbegin()->getNumber()).getTime();
if ((fragEnd - fragStart) < targetDuration * 3){ if ((fragEnd - fragStart) < targetDuration * 8){
return false; return false;
} }
} }
@ -754,7 +754,7 @@ namespace Mist {
} }
//if the new value is different, print a message and apply it //if the new value is different, print a message and apply it
if (resumeMode != (bool)tmpNum) { if (resumeMode != (bool)tmpNum) {
DEBUG_MSG(DLVL_DEVEL, "Setting resume mode from %s to new value of %s", resumeMode ? "enabled" : "disabled", tmpNum ? "enabled" : "disabled"); INFO_MSG("Setting resume mode from %s to new value of %s", resumeMode ? "enabled" : "disabled", tmpNum ? "enabled" : "disabled");
resumeMode = tmpNum; resumeMode = tmpNum;
} }

View file

@ -26,6 +26,20 @@ namespace Mist {
capa["codecs"][0u][1u].append("AAC"); capa["codecs"][0u][1u].append("AAC");
capa["codecs"][0u][1u].append("MP3"); capa["codecs"][0u][1u].append("MP3");
capa["codecs"][0u][1u].append("vorbis"); capa["codecs"][0u][1u].append("vorbis");
JSON::Value option;
option["arg"] = "integer";
option["long"] = "buffer";
option["short"] = "b";
option["help"] = "Live stream DVR buffer time in ms";
option["value"].append(50000LL);
config->addOption("bufferTime", option);
capa["optional"]["DVR"]["name"] = "Buffer time (ms)";
capa["optional"]["DVR"]["help"] = "The target available buffer time for this live stream, in milliseconds. This is the time available to seek around in, and will automatically be extended to fit whole keyframes as well as the minimum duration needed for stable playback.";
capa["optional"]["DVR"]["option"] = "--buffer";
capa["optional"]["DVR"]["type"] = "uint";
capa["optional"]["DVR"]["default"] = 50000LL;
} }
bool inputDTSC::needsLock(){ bool inputDTSC::needsLock(){