diff --git a/src/input/input_buffer.cpp b/src/input/input_buffer.cpp index 2a69914b..5d8807d6 100644 --- a/src/input/input_buffer.cpp +++ b/src/input/input_buffer.cpp @@ -305,9 +305,12 @@ namespace Mist { } bool inputBuffer::removeKey(unsigned int tid) { - if ((myMeta.tracks[tid].keys.size() < 2 || myMeta.tracks[tid].fragments.size() < 2) && config->is_active) { + //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) { return false; } + //If we're shutting down, and this track is empty, abort if (!myMeta.tracks[tid].keys.size()) { return false; } diff --git a/src/output/output.cpp b/src/output/output.cpp index cb62bfde..0fefc6a0 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -216,7 +216,7 @@ namespace Mist { selectDefaultTracks(); } unsigned int mainTrack = getMainSelectedTrack(); - if (mainTrack && myMeta.tracks.count(mainTrack) && myMeta.tracks[mainTrack].keys.size() >= 2){ + if (mainTrack && myMeta.tracks.count(mainTrack) && (myMeta.tracks[mainTrack].keys.size() >= 2 || myMeta.tracks[mainTrack].lastms - myMeta.tracks[mainTrack].firstms > 5000)){ return true; }else{ HIGH_MSG("NOT READY YET (%lu tracks, %lu = %lu keys)", myMeta.tracks.size(), getMainSelectedTrack(), myMeta.tracks[getMainSelectedTrack()].keys.size()); diff --git a/src/output/output_progressive_mp4.cpp b/src/output/output_progressive_mp4.cpp index 7ab0c04f..8b7fd070 100644 --- a/src/output/output_progressive_mp4.cpp +++ b/src/output/output_progressive_mp4.cpp @@ -32,6 +32,46 @@ namespace Mist { //capa["canRecord"].append("m3u"); } + /// Same as default implementation, except it will never play the very last keyframe + /// unless that is the only keyframe available. + void OutProgressiveMP4::initialSeek(){ + unsigned long long seekPos = 0; + if (myMeta.live){ + long unsigned int mainTrack = getMainSelectedTrack(); + //cancel if there are no keys in the main track + if (!myMeta.tracks.count(mainTrack) || !myMeta.tracks[mainTrack].keys.size()){return;} + //seek to the newest keyframe, unless that is <5s, then seek to the oldest keyframe + bool first = true; + for (std::deque::reverse_iterator it = myMeta.tracks[mainTrack].keys.rbegin(); it != myMeta.tracks[mainTrack].keys.rend(); ++it){ + seekPos = it->getTime(); + if (first){ + first = false; + continue; + } + if (seekPos < 5000){continue;}//if we're near the start, skip back + bool good = true; + //check if all tracks have data for this point in time + for (std::set::iterator ti = selectedTracks.begin(); ti != selectedTracks.end(); ++ti){ + if (mainTrack == *ti){continue;}//skip self + if (!myMeta.tracks.count(*ti)){ + HIGH_MSG("Skipping track %lu, not in tracks", *ti); + continue; + }//ignore missing tracks + if (myMeta.tracks[*ti].lastms == myMeta.tracks[*ti].firstms){ + HIGH_MSG("Skipping track %lu, last equals first", *ti); + continue; + }//ignore point-tracks + if (myMeta.tracks[*ti].lastms < seekPos){good = false; break;} + HIGH_MSG("Track %lu is good", *ti); + } + //if yes, seek here + if (good){break;} + } + } + MEDIUM_MSG("Initial seek to %llums", seekPos); + seek(seekPos); + } + long long unsigned OutProgressiveMP4::estimateFileSize() { long long unsigned retVal = 0; for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++) { diff --git a/src/output/output_progressive_mp4.h b/src/output/output_progressive_mp4.h index b26fc2fe..a7fd5161 100644 --- a/src/output/output_progressive_mp4.h +++ b/src/output/output_progressive_mp4.h @@ -49,6 +49,7 @@ namespace Mist { void onHTTP(); void sendNext(); void sendHeader(); + void initialSeek(); protected: long long fileSize; long long byteStart;