[vlc-commits] demux: adaptive: use demux relative positions for time and seek

Francois Cartegnie git at videolan.org
Wed Jun 26 22:13:07 CEST 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jun 21 10:32:28 2019 +0200| [fd6888e1c2d932ac054128fe24afe7d025e3b0b5] | committer: Francois Cartegnie

demux: adaptive: use demux relative positions for time and seek

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=fd6888e1c2d932ac054128fe24afe7d025e3b0b5
---

 modules/demux/adaptive/PlaylistManager.cpp | 141 ++++++++++++++++-------------
 modules/demux/adaptive/PlaylistManager.h   |   9 +-
 modules/demux/adaptive/Streams.cpp         |  37 +++-----
 modules/demux/adaptive/Streams.hpp         |   5 +-
 modules/demux/adaptive/tools/Debug.hpp     |   7 ++
 5 files changed, 102 insertions(+), 97 deletions(-)

diff --git a/modules/demux/adaptive/PlaylistManager.cpp b/modules/demux/adaptive/PlaylistManager.cpp
index 9a67b7c8cb..71498da06a 100644
--- a/modules/demux/adaptive/PlaylistManager.cpp
+++ b/modules/demux/adaptive/PlaylistManager.cpp
@@ -74,12 +74,11 @@ PlaylistManager::PlaylistManager( demux_t *p_demux_,
     vlc_cond_init(&waitcond);
     vlc_mutex_init(&cached.lock);
     cached.b_live = false;
-    cached.i_length = 0;
     cached.f_position = 0.0;
     cached.i_time = VLC_TICK_INVALID;
-    cached.rangeStart = 0;
-    cached.rangeEnd = 0;
-    cached.rangeLength = 0;
+    cached.playlistStart = 0;
+    cached.playlistEnd = 0;
+    cached.playlistLength = 0;
     cached.lastupdate = 0;
 }
 
@@ -397,7 +396,7 @@ vlc_tick_t PlaylistManager::getFirstPlaybackTime() const
     return 0;
 }
 
-vlc_tick_t PlaylistManager::getCurrentPlaybackTime() const
+vlc_tick_t PlaylistManager::getCurrentDemuxTime() const
 {
     vlc_mutex_locker locker(&demux.lock);
     return demux.i_nzpcr;
@@ -537,16 +536,16 @@ int PlaylistManager::doControl(int i_query, va_list args)
         case DEMUX_GET_LENGTH:
         {
             vlc_mutex_locker locker(&cached.lock);
-            if(cached.b_live && cached.i_length == 0)
+            if(cached.b_live && cached.playlistLength == 0)
                 return VLC_EGENERIC;
-            *(va_arg (args, vlc_tick_t *)) = cached.i_length;
+            *(va_arg (args, vlc_tick_t *)) = cached.playlistLength;
             break;
         }
 
         case DEMUX_GET_POSITION:
         {
             vlc_mutex_locker locker(&cached.lock);
-            if(cached.b_live && cached.i_length == 0)
+            if(cached.b_live && cached.playlistLength == 0)
                 return VLC_EGENERIC;
             *(va_arg (args, double *)) = cached.f_position;
             break;
@@ -557,35 +556,26 @@ int PlaylistManager::doControl(int i_query, va_list args)
             setBufferingRunState(false); /* stop downloader first */
             vlc_mutex_locker locker(&cached.lock);
 
-            vlc_tick_t i_start, i_duration;
-            if(cached.b_live)
-            {
-                i_duration = cached.i_length;
-                if(cached.rangeStart < 0)
-                    i_start = vlc_tick_from_sec(time(NULL)) - cached.i_length;
-                else
-                    i_start = cached.rangeStart;
-            }
-            else
-            {
-                i_duration = playlist->duration.Get();
-                i_start = getFirstPlaybackTime();
-            }
-
-            if(i_duration == 0)
+            if(cached.playlistLength == 0)
             {
                 setBufferingRunState(true);
                 return VLC_EGENERIC;
             }
 
-            vlc_tick_t seektime = i_start + i_duration * va_arg(args, double);
-            if(!setPosition(seektime))
+            double pos = va_arg(args, double);
+            vlc_tick_t seekTime = cached.playlistStart + cached.playlistLength * pos;
+
+            SeekDebug(msg_Dbg(p_demux, "Seek %f to %ld plstart %ld duration %ld",
+                   pos, seekTime, cached.playlistEnd, cached.playlistLength));
+
+            if(!setPosition(seekTime))
             {
                 setBufferingRunState(true);
                 return VLC_EGENERIC;
             }
 
             demux.i_nzpcr = VLC_TICK_INVALID;
+            cached.lastupdate = 0;
             setBufferingRunState(true);
             break;
         }
@@ -603,6 +593,7 @@ int PlaylistManager::doControl(int i_query, va_list args)
 
             vlc_mutex_locker locker(&cached.lock);
             demux.i_nzpcr = VLC_TICK_INVALID;
+            cached.lastupdate = 0;
             setBufferingRunState(true);
             break;
         }
@@ -697,46 +688,62 @@ void PlaylistManager::updateControlsPosition()
         return;
     cached.lastupdate = now;
 
-    cached.i_time = getCurrentPlaybackTime();
-    cached.b_live = playlist->isLive();
-    if(cached.b_live)
+    vlc_tick_t rapPlaylistStart = 0;
+    vlc_tick_t rapDemuxStart = 0;
+    std::vector<AbstractStream *>::iterator it;
+    for(it=streams.begin(); it!=streams.end(); ++it)
     {
-        std::vector<AbstractStream *>::iterator it;
-        for(it=streams.begin(); it!=streams.end(); ++it)
+        AbstractStream *st = *it;
+        if(st->isValid() && !st->isDisabled() && st->isSelected())
         {
-            AbstractStream *st = *it;
-            if(st->isValid() && !st->isDisabled() && st->isSelected())
-            {
-                if(st->getMediaPlaybackRange(&cached.rangeStart, &cached.rangeEnd,
-                                             &cached.rangeLength))
-                    break;
-            }
+            if(st->getMediaPlaybackTimes(&cached.playlistStart, &cached.playlistEnd,
+                                         &cached.playlistLength,
+                                         &rapPlaylistStart, &rapDemuxStart))
+                break;
         }
+    }
 
-        if(cached.rangeStart != cached.rangeEnd)
-        {
-            if(cached.rangeStart < 0) /* Live template. Range start = now() - buffering depth */
-                cached.i_length = cached.rangeLength;
-            else
-                cached.i_length = cached.rangeEnd - cached.rangeStart;
-        }
+    /*
+     * Relative position:
+     * -> Elapsed demux time (current demux time - first demux time)
+     * Since PlaylistTime != DemuxTime (HLS crap, TS):
+     * -> Use Playlist<->Demux time offset provided by EsOut
+     *    to convert to elapsed playlist time.
+     *    But this diff is not available until we have demuxed data...
+     *    Fallback on relative seek from playlist start in that case
+     * But also playback might not have started at beginning of playlist
+     * -> Apply relative start from seek point (set on EsOut as ExpectedTime)
+     *
+     * All seeks need to be done in playlist time !
+     */
+
+    vlc_tick_t currentDemuxTime = getCurrentDemuxTime();
+    cached.b_live = playlist->isLive();
 
-        vlc_tick_t start, end;
-        if(cached.rangeStart < 0) /* Live template. Range start = now() - buffering depth */
-        {
-            end = vlc_tick_from_sec(now);
-            start = end - cached.i_length;
-        }
-        else
+    SeekDebug(msg_Dbg(p_demux, "playlist Start/End %ld/%ld len %ld"
+                               "rap pl/demux (%ld/%ld)",
+                      cached.playlistStart, cached.playlistEnd, cached.playlistEnd,
+                      rapPlaylistStart, rapDemuxStart));
+
+    if(cached.b_live)
+    {
+        /* Special case for live until we can provide relative start to fully match
+           the above description */
+        cached.i_time = currentDemuxTime;
+
+        if(cached.playlistStart != cached.playlistEnd)
         {
-            end = cached.rangeEnd;
-            start = cached.rangeStart;
+            if(cached.playlistStart < 0) /* Live template. Range start = now() - buffering depth */
+            {
+                cached.playlistEnd = vlc_tick_from_sec(now);
+                cached.playlistStart = cached.playlistEnd - cached.playlistLength;
+            }
         }
-
-        const vlc_tick_t currentTime = getCurrentPlaybackTime();
-        if(currentTime > start && currentTime <= end && cached.i_length)
+        const vlc_tick_t currentTime = getCurrentDemuxTime();
+        if(currentTime > cached.playlistStart &&
+           currentTime <= cached.playlistEnd && cached.playlistLength)
         {
-            cached.f_position = ((double)(currentTime - start)) / cached.i_length;
+            cached.f_position = ((double)(currentTime - cached.playlistStart)) / cached.playlistLength;
         }
         else
         {
@@ -745,18 +752,26 @@ void PlaylistManager::updateControlsPosition()
     }
     else
     {
-        cached.i_length = playlist->duration.Get();
-        cached.i_time -= getFirstPlaybackTime();
-        if(cached.i_length)
+        if(playlist->duration.Get() > cached.playlistLength)
+            cached.playlistLength = playlist->duration.Get();
+
+        if(cached.playlistLength && currentDemuxTime)
         {
-            const vlc_tick_t i_length = getCurrentPlaybackTime() - getFirstPlaybackTime();
-            cached.f_position = (double) i_length / cached.i_length;
+            /* convert to playlist time */
+            vlc_tick_t rapRelOffset = currentDemuxTime - rapDemuxStart; /* offset from start/seek */
+            vlc_tick_t absPlaylistTime = rapPlaylistStart + rapRelOffset; /* converted as abs playlist time */
+            vlc_tick_t relMediaTime = absPlaylistTime - cached.playlistStart; /* elapsed, in playlist time */
+            cached.i_time = absPlaylistTime;
+            cached.f_position = (double) relMediaTime / cached.playlistLength;
         }
         else
         {
             cached.f_position = 0.0;
         }
     }
+
+    SeekDebug(msg_Dbg(p_demux, "cached.i_time (%ld) cur %ld rap start (pl %ld/dmx %ld)",
+               cached.i_time, currentDemuxTime, rapPlaylistStart, rapDemuxStart));
 }
 
 AbstractAdaptationLogic *PlaylistManager::createLogic(AbstractAdaptationLogic::LogicType type, AbstractConnectionManager *conn)
diff --git a/modules/demux/adaptive/PlaylistManager.h b/modules/demux/adaptive/PlaylistManager.h
index 03f799ac1d..b94f59d7de 100644
--- a/modules/demux/adaptive/PlaylistManager.h
+++ b/modules/demux/adaptive/PlaylistManager.h
@@ -79,7 +79,7 @@ namespace adaptive
             vlc_tick_t getFirstDTS() const;
 
             virtual vlc_tick_t getFirstPlaybackTime() const;
-            vlc_tick_t getCurrentPlaybackTime() const;
+            vlc_tick_t getCurrentDemuxTime() const;
 
             virtual bool reactivateStream(AbstractStream *);
             bool setupPeriod();
@@ -118,13 +118,12 @@ namespace adaptive
             struct
             {
                 bool        b_live;
-                vlc_tick_t  i_length;
                 vlc_tick_t  i_time;
                 double      f_position;
                 mutable vlc_mutex_t lock;
-                vlc_tick_t  rangeStart;
-                vlc_tick_t  rangeEnd;
-                vlc_tick_t  rangeLength;
+                vlc_tick_t  playlistStart;
+                vlc_tick_t  playlistEnd;
+                vlc_tick_t  playlistLength;
                 time_t      lastupdate;
             } cached;
 
diff --git a/modules/demux/adaptive/Streams.cpp b/modules/demux/adaptive/Streams.cpp
index faa64e068d..e183efa0c8 100644
--- a/modules/demux/adaptive/Streams.cpp
+++ b/modules/demux/adaptive/Streams.cpp
@@ -91,7 +91,7 @@ bool AbstractStream::init(const StreamFormat &format_, SegmentTracker *tracker,
                     segmentTracker->registerListener(this);
                     segmentTracker->notifyBufferingState(true);
                     connManager = conn;
-                    setTimeOffset(segmentTracker->getPlaybackTime());
+                    fakeesout->setExpectedTimestamp(segmentTracker->getPlaybackTime());
                     declaredCodecs();
                     return true;
                 }
@@ -129,7 +129,7 @@ void AbstractStream::prepareRestart(bool b_discontinuity)
     {
         /* Enqueue Del Commands for all current ES */
         demuxer->drain();
-        setTimeOffset(-1);
+        fakeEsOut()->resetTimestamps();
         /* Enqueue Del Commands for all current ES */
         fakeEsOut()->scheduleAllForDeletion();
         if(b_discontinuity)
@@ -545,9 +545,10 @@ bool AbstractStream::setPosition(vlc_tick_t time, bool tryonly)
             currentChunk = NULL;
             needrestart = false;
 
-            setTimeOffset(-1);
-            setTimeOffset(segmentTracker->getPlaybackTime());
+            fakeEsOut()->resetTimestamps();
 
+            vlc_tick_t seekMediaTime = segmentTracker->getPlaybackTime();
+            fakeEsOut()->setExpectedTimestamp(seekMediaTime);
             if( !restartDemux() )
             {
                 msg_Info(p_realdemux, "Restart demux failed");
@@ -568,15 +569,13 @@ bool AbstractStream::setPosition(vlc_tick_t time, bool tryonly)
     return ret;
 }
 
-vlc_tick_t AbstractStream::getPlaybackTime() const
+bool AbstractStream::getMediaPlaybackTimes(vlc_tick_t *start, vlc_tick_t *end,
+                                           vlc_tick_t *length,
+                                           vlc_tick_t *mediaStart,
+                                           vlc_tick_t *demuxStart) const
 {
-    return segmentTracker->getPlaybackTime();
-}
-
-bool AbstractStream::getMediaPlaybackRange(vlc_tick_t *start, vlc_tick_t *end,
-                                           vlc_tick_t *length) const
-{
-    return segmentTracker->getMediaPlaybackRange(start, end, length);
+    return (segmentTracker->getMediaPlaybackRange(start, end, length) &&
+            fakeEsOut()->getStartTimestamps(mediaStart, demuxStart));
 }
 
 void AbstractStream::runUpdates()
@@ -593,20 +592,6 @@ void AbstractStream::fillExtraFMTInfo( es_format_t *p_fmt ) const
         p_fmt->psz_description = strdup(description.c_str());
 }
 
-void AbstractStream::setTimeOffset(vlc_tick_t i_offset)
-{
-    /* Check if we need to set an offset as the demuxer
-     * will start from zero from seek point */
-    if(i_offset < 0) /* reset */
-    {
-        fakeEsOut()->setExpectedTimestamp(-1);
-    }
-    else
-    {
-        fakeEsOut()->setExpectedTimestamp(i_offset);
-    }
-}
-
 AbstractDemuxer * AbstractStream::createDemux(const StreamFormat &format)
 {
     AbstractDemuxer *ret = newDemux( p_realdemux, format,
diff --git a/modules/demux/adaptive/Streams.hpp b/modules/demux/adaptive/Streams.hpp
index 5e7d2877f0..8bba367942 100644
--- a/modules/demux/adaptive/Streams.hpp
+++ b/modules/demux/adaptive/Streams.hpp
@@ -88,8 +88,8 @@ namespace adaptive
         status dequeue(vlc_tick_t, vlc_tick_t *);
         bool decodersDrained();
         virtual bool setPosition(vlc_tick_t, bool);
-        vlc_tick_t getPlaybackTime() const;
-        bool getMediaPlaybackRange(vlc_tick_t *, vlc_tick_t *, vlc_tick_t *) const;
+        bool getMediaPlaybackTimes(vlc_tick_t *, vlc_tick_t *, vlc_tick_t *,
+                                   vlc_tick_t *, vlc_tick_t *) const;
         void runUpdates();
 
         /* Used by demuxers fake streams */
@@ -103,7 +103,6 @@ namespace adaptive
     protected:
         bool seekAble() const;
         void setDisabled(bool);
-        virtual void setTimeOffset(vlc_tick_t);
         virtual block_t *checkBlock(block_t *, bool) = 0;
         AbstractDemuxer * createDemux(const StreamFormat &);
         virtual AbstractDemuxer * newDemux(demux_t *, const StreamFormat &,
diff --git a/modules/demux/adaptive/tools/Debug.hpp b/modules/demux/adaptive/tools/Debug.hpp
index a326d43ac2..7b6548b1c2 100644
--- a/modules/demux/adaptive/tools/Debug.hpp
+++ b/modules/demux/adaptive/tools/Debug.hpp
@@ -22,6 +22,7 @@
 
 //#define ADAPTATIVE_ADVANCED_DEBUG 0
 //#define ADAPTATIVE_BW_DEBUG 0
+//#define ADAPTATIVE_SEEK_DEBUG 0
 
 #ifdef ADAPTATIVE_ADVANCED_DEBUG
   #define AdvDebug(code) code
@@ -35,5 +36,11 @@
   #define BwDebug(code)
 #endif
 
+#ifdef ADAPTATIVE_SEEK_DEBUG
+  #define SeekDebug(code) code
+#else
+  #define SeekDebug(code)
+#endif
+
 #endif // DEBUG_HPP
 



More information about the vlc-commits mailing list