diff --git a/lib/dtsc.h b/lib/dtsc.h index 5d70e893..8cfb40ed 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -289,6 +289,7 @@ namespace DTSC { void reset(); void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0); void finalize(); + uint32_t biggestFragment(); std::string getIdentifier(); std::string getWritableIdentifier(); diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 1913925e..28c1fb8d 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -1218,6 +1218,17 @@ namespace DTSC { void Track::finalize(){ keys.rbegin()->setLength(lastms - keys.rbegin()->getTime() + parts.rbegin()->getDuration()); } + + /// Returns the duration in ms of the longest-duration fragment. + uint32_t Track::biggestFragment(){ + uint32_t ret = 0; + for (unsigned int i = 0; i ret){ + ret = fragments[i].getDuration(); + } + } + return ret; + } ///\brief Returns a key given its number, or an empty key if the number is out of bounds Key & Track::getKey(unsigned int keyNum) { diff --git a/src/input/input_buffer.cpp b/src/input/input_buffer.cpp index d8313ce4..d146709f 100644 --- a/src/input/input_buffer.cpp +++ b/src/input/input_buffer.cpp @@ -208,15 +208,28 @@ namespace Mist { } bool inputBuffer::removeKey(unsigned int tid) { + DTSC::Track & Trk = myMeta.tracks[tid]; //Make sure we have at least 3 whole fragments at all times, //unless we're shutting down the whole buffer right now - if (myMeta.tracks[tid].fragments.size() < 5 && config->is_active) { + if (Trk.fragments.size() < 5 && config->is_active) { return false; } //If we're shutting down, and this track is empty, abort if (!myMeta.tracks[tid].keys.size()) { return false; } + if (config->is_active && Trk.fragments.size() > 1){ + ///Make sure we have at least 3X the target duration. + //The target duration is the biggest fragment, rounded up to whole seconds. + uint32_t targetDuration = (Trk.biggestFragment() / 1000 + 1) * 1000; + //The start is the second fragment's begin + uint32_t fragStart = Trk.getKey((++Trk.fragments.begin())->getNumber()).getTime(); + //The end is the last fragment's begin + uint32_t fragEnd = Trk.getKey(Trk.fragments.rbegin()->getNumber()).getTime(); + if ((fragEnd - fragStart) < targetDuration * 3){ + return false; + } + } DEBUG_MSG(DLVL_HIGH, "Erasing key %d:%lu", tid, myMeta.tracks[tid].keys[0].getNumber()); //remove all parts of this key for (int i = 0; i < myMeta.tracks[tid].keys[0].getParts(); i++) { diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp index 8f7ff376..0e295fd8 100644 --- a/src/output/output_hls.cpp +++ b/src/output/output_hls.cpp @@ -57,21 +57,8 @@ namespace Mist { updateMeta(); std::stringstream result; //parse single track - int longestFragment = 0; - if (!myMeta.tracks[tid].fragments.size()){ - INFO_MSG("liveIndex called with track %d, which has no fragments!", tid); - return ""; - } - for (std::deque::iterator it = myMeta.tracks[tid].fragments.begin(); (it + 1) != myMeta.tracks[tid].fragments.end(); it++){ - if (it->getDuration() > longestFragment){ - longestFragment = it->getDuration(); - } - } - if ((myMeta.tracks[tid].lastms - myMeta.tracks[tid].firstms) / myMeta.tracks[tid].fragments.size() > longestFragment){ - longestFragment = (myMeta.tracks[tid].lastms - myMeta.tracks[tid].firstms) / myMeta.tracks[tid].fragments.size(); - } - result << "#EXTM3U\r\n#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n"; - + result << "#EXTM3U\r\n#EXT-X-TARGETDURATION:" << (myMeta.tracks[tid].biggestFragment() / 1000) + 1 << "\r\n"; + std::deque lines; for (std::deque::iterator it = myMeta.tracks[tid].fragments.begin(); it != myMeta.tracks[tid].fragments.end(); it++){ long long int starttime = myMeta.tracks[tid].getKey(it->getNumber()).getTime();