diff --git a/lib/dtsc.h b/lib/dtsc.h index 94f524c1..0ddc6793 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -313,6 +313,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 8f48ec2b..cca7ed8e 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -1272,6 +1272,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 5d8807d6..48d18dbe 100644 --- a/src/input/input_buffer.cpp +++ b/src/input/input_buffer.cpp @@ -305,15 +305,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 fc53eecf..50a6a000 100644 --- a/src/output/output_hls.cpp +++ b/src/output/output_hls.cpp @@ -134,20 +134,7 @@ 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++) {