From 01e15663e98c7835737988cadfd99568ee12086f Mon Sep 17 00:00:00 2001 From: Thulinma Date: Wed, 8 Aug 2018 12:24:50 +0200 Subject: [PATCH] Improved seek function for real-time protocols --- src/output/output.cpp | 22 +++++++++++++++++++++- src/output/output.h | 2 +- src/output/output_rtmp.cpp | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/output/output.cpp b/src/output/output.cpp index 6ae934a2..646a7a2c 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -592,7 +592,8 @@ namespace Mist{ } /// Prepares all tracks from selectedTracks for seeking to the specified ms position. - void Output::seek(unsigned long long pos){ + /// If toKey is true, clips the seek to the nearest keyframe if the main track is a video track. + void Output::seek(unsigned long long pos, bool toKey){ sought = true; if (!isInitialized){ initialize(); @@ -602,6 +603,25 @@ namespace Mist{ if (myMeta.live){ updateMeta(); } + if (toKey){ + long unsigned int mainTrack = getMainSelectedTrack(); + //abort toKey if there are no keys in the main track + if (!myMeta.tracks.count(mainTrack) || !myMeta.tracks[mainTrack].keys.size()){ + WARN_MSG("Sync-seeking impossible (main track invalid); performing regular seek instead"); + seek(pos); + return; + } + DTSC::Track & Trk = myMeta.tracks[mainTrack]; + if (Trk.type == "video"){ + unsigned long long seekPos = 0; + for (std::deque::iterator it = Trk.keys.begin(); it != Trk.keys.end(); ++it){ + unsigned long long currPos = it->getTime(); + if (currPos > pos){break;}//stop if we're past the point we wanted + seekPos = currPos; + } + pos = seekPos; + } + } MEDIUM_MSG("Seeking to %llums", pos); std::set seekTracks = selectedTracks; for (std::set::iterator it = seekTracks.begin(); it != seekTracks.end(); it++){ diff --git a/src/output/output.h b/src/output/output.h index 4db104be..b3e306ac 100644 --- a/src/output/output.h +++ b/src/output/output.h @@ -43,7 +43,7 @@ namespace Mist { //non-virtual generic functions virtual int run(); virtual void stats(bool force = false); - void seek(unsigned long long pos); + void seek(unsigned long long pos, bool toKey = false); bool seek(unsigned int tid, unsigned long long pos, bool getNextKey = false); void stop(); uint64_t currentTime(); diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp index 84f52275..9f9f6d2f 100644 --- a/src/output/output_rtmp.cpp +++ b/src/output/output_rtmp.cpp @@ -711,7 +711,7 @@ namespace Mist { amfReply.getContentP(3)->addContent(AMF::Object("details", "DDV")); amfReply.getContentP(3)->addContent(AMF::Object("clientid", (double)1337)); sendCommand(amfReply, playMessageType, playStreamId); - seek((long long int)amfData.getContentP(3)->NumValue()); + seek((long long int)amfData.getContentP(3)->NumValue(), true); //send a status reply AMF::Object amfreply("container", AMF::AMF0_DDV_CONTAINER);