[vlc-commits] demux: adaptative: restart on seek

Francois Cartegnie git at videolan.org
Wed Jun 10 18:58:07 CEST 2015


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jun  5 15:44:23 2015 +0200| [ed2fe051dab89da249b97bfe5c68927c872a7595] | committer: Francois Cartegnie

demux: adaptative: restart on seek

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

 modules/demux/adaptative/SegmentTracker.cpp |    7 +-
 modules/demux/adaptative/SegmentTracker.hpp |    2 +-
 modules/demux/adaptative/Streams.cpp        |  113 ++++++++++++++++++++++-----
 modules/demux/adaptative/Streams.hpp        |    8 +-
 4 files changed, 106 insertions(+), 24 deletions(-)

diff --git a/modules/demux/adaptative/SegmentTracker.cpp b/modules/demux/adaptative/SegmentTracker.cpp
index a9fc992..7480d89 100644
--- a/modules/demux/adaptative/SegmentTracker.cpp
+++ b/modules/demux/adaptative/SegmentTracker.cpp
@@ -54,7 +54,7 @@ void SegmentTracker::resetCounter()
     prevRepresentation = NULL;
 }
 
-Chunk * SegmentTracker::getNextChunk(StreamType type)
+Chunk * SegmentTracker::getNextChunk(StreamType type, bool switch_allowed)
 {
     BaseRepresentation *rep;
     ISegment *segment;
@@ -62,7 +62,8 @@ Chunk * SegmentTracker::getNextChunk(StreamType type)
     if(!currentPeriod)
         return NULL;
 
-    if(prevRepresentation && prevRepresentation->getSwitchPolicy() == SegmentInformation::SWITCH_UNAVAILABLE)
+    if( !switch_allowed ||
+       (prevRepresentation && prevRepresentation->getSwitchPolicy() == SegmentInformation::SWITCH_UNAVAILABLE) )
         rep = prevRepresentation;
     else
         rep = logic->getCurrentRepresentation(type, currentPeriod);
@@ -97,7 +98,7 @@ Chunk * SegmentTracker::getNextChunk(StreamType type)
     {
         currentPeriod = playlist->getNextPeriod(currentPeriod);
         resetCounter();
-        return getNextChunk(type);
+        return getNextChunk(type, switch_allowed);
     }
 
     Chunk *chunk = segment->toChunk(count, rep);
diff --git a/modules/demux/adaptative/SegmentTracker.hpp b/modules/demux/adaptative/SegmentTracker.hpp
index e1d1510..e293c07 100644
--- a/modules/demux/adaptative/SegmentTracker.hpp
+++ b/modules/demux/adaptative/SegmentTracker.hpp
@@ -58,7 +58,7 @@ namespace adaptative
 
             void setAdaptationLogic(AbstractAdaptationLogic *);
             void resetCounter();
-            Chunk* getNextChunk(StreamType);
+            Chunk* getNextChunk(StreamType, bool);
             bool setPosition(mtime_t, bool, bool);
             mtime_t getSegmentStart() const;
             void pruneFromCurrent();
diff --git a/modules/demux/adaptative/Streams.cpp b/modules/demux/adaptative/Streams.cpp
index 0637357..2c5a0c2 100644
--- a/modules/demux/adaptative/Streams.cpp
+++ b/modules/demux/adaptative/Streams.cpp
@@ -127,7 +127,7 @@ Chunk * Stream::getChunk()
 {
     if (currentChunk == NULL)
     {
-        currentChunk = segmentTracker->getNextChunk(type);
+        currentChunk = segmentTracker->getNextChunk(type, output->switchAllowed());
         if (currentChunk == NULL)
             eof = true;
     }
@@ -280,6 +280,7 @@ BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) :
 {
     this->name = name;
     seekable = true;
+    restarting = false;
     demuxstream = NULL;
 
     fakeesout = new es_out_t;
@@ -295,7 +296,8 @@ BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) :
     fakeesout->pf_send = esOutSend;
     fakeesout->p_sys = (es_out_sys_t*) this;
 
-    if(!restart())
+    demuxstream = stream_DemuxNew(realdemux, name.c_str(), fakeesout);
+    if(!demuxstream)
         throw VLC_EGENERIC;
 }
 
@@ -303,14 +305,14 @@ BaseStreamOutput::~BaseStreamOutput()
 {
     if (demuxstream)
         stream_Delete(demuxstream);
-    delete fakeesout;
-
-    vlc_mutex_destroy(&lock);
 
     /* shouldn't be any */
     std::list<Demuxed *>::const_iterator it;
     for(it=queues.begin(); it!=queues.end();++it)
         delete *it;
+
+    delete fakeesout;
+    vlc_mutex_destroy(&lock);
 }
 
 int BaseStreamOutput::esCount() const
@@ -325,7 +327,8 @@ void BaseStreamOutput::pushBlock(block_t *block)
 
 bool BaseStreamOutput::seekAble() const
 {
-    return (demuxstream && seekable);
+    bool b_canswitch = switchAllowed();
+    return (demuxstream && seekable && b_canswitch);
 }
 
 void BaseStreamOutput::setPosition(mtime_t nztime)
@@ -353,6 +356,7 @@ bool BaseStreamOutput::restart()
         return false;
 
     vlc_mutex_lock(&lock);
+    restarting = true;
     stream_t *olddemuxstream = demuxstream;
     demuxstream = newdemuxstream;
     vlc_mutex_unlock(&lock);
@@ -365,7 +369,16 @@ bool BaseStreamOutput::restart()
 
 bool BaseStreamOutput::reinitsOnSeek() const
 {
-    return false;
+    return true;
+}
+
+bool BaseStreamOutput::switchAllowed() const
+{
+    bool b_allowed;
+    vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
+    b_allowed = !restarting;
+    vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
+    return b_allowed;
 }
 
 void BaseStreamOutput::sendToDecoder(mtime_t nzdeadline)
@@ -395,15 +408,18 @@ void BaseStreamOutput::sendToDecoderUnlocked(mtime_t nzdeadline)
     }
 }
 
-BaseStreamOutput::Demuxed::Demuxed()
+BaseStreamOutput::Demuxed::Demuxed(es_out_id_t *id, const es_format_t *fmt)
 {
     p_queue = NULL;
     pp_queue_last = &p_queue;
-    es_id = NULL;
+    es_id = id;
+    es_format_Init(&fmtcpy, UNKNOWN_ES, 0);
+    es_format_Copy(&fmtcpy, fmt);
 }
 
 BaseStreamOutput::Demuxed::~Demuxed()
 {
+    es_format_Clean(&fmtcpy);
     drop();
 }
 
@@ -418,18 +434,52 @@ void BaseStreamOutput::Demuxed::drop()
 es_out_id_t * BaseStreamOutput::esOutAdd(es_out_t *fakees, const es_format_t *p_fmt)
 {
     BaseStreamOutput *me = (BaseStreamOutput *) fakees->p_sys;
-    es_out_id_t *p_es = me->realdemux->out->pf_add(me->realdemux->out, p_fmt);
-    if(p_es)
+
+    es_out_id_t *p_es = NULL;
+
+    vlc_mutex_lock(&me->lock);
+
+    std::list<Demuxed *>::iterator it;
+    bool b_hasestorecyle = false;
+    for(it=me->queues.begin(); it!=me->queues.end();++it)
+    {
+        Demuxed *pair = *it;
+        b_hasestorecyle |= pair->recycle;
+
+        if( p_es )
+            continue;
+
+        if( me->restarting )
+        {
+            /* If we're recycling from same format */
+            if( es_format_IsSimilar(p_fmt, &pair->fmtcpy) &&
+                    p_fmt->i_extra == pair->fmtcpy.i_extra &&
+                    !memcmp(p_fmt->p_extra, pair->fmtcpy.p_extra, p_fmt->i_extra) )
+            {
+                msg_Err(me->realdemux, "using recycled");
+                pair->recycle = false;
+                p_es = pair->es_id;
+            }
+        }
+    }
+
+    if(!b_hasestorecyle)
+    {
+        me->restarting = false;
+    }
+
+    if(!p_es)
     {
-        vlc_mutex_lock(&me->lock);
-        Demuxed *pair = new (std::nothrow) Demuxed();
-        if(pair)
+        p_es = me->realdemux->out->pf_add(me->realdemux->out, p_fmt);
+        if(p_es)
         {
-            pair->es_id = p_es;
-            me->queues.push_back(pair);
+            Demuxed *pair = new (std::nothrow) Demuxed(p_es, p_fmt);
+            if(pair)
+                me->queues.push_back(pair);
         }
-        vlc_mutex_unlock(&me->lock);
     }
+    vlc_mutex_unlock(&me->lock);
+
     return p_es;
 }
 
@@ -461,13 +511,27 @@ void BaseStreamOutput::esOutDel(es_out_t *fakees, es_out_id_t *p_es)
         if((*it)->es_id == p_es)
         {
             me->sendToDecoderUnlocked(INT64_MAX - VLC_TS_0);
+            break;
+        }
+    }
+
+    if(it != me->queues.end())
+    {
+        if(me->restarting)
+        {
+            (*it)->recycle = true;
+        }
+        else
+        {
             delete *it;
             me->queues.erase(it);
-            break;
         }
     }
+
+    if(!me->restarting)
+        me->realdemux->out->pf_del(me->realdemux->out, p_es);
+
     vlc_mutex_unlock(&me->lock);
-    me->realdemux->out->pf_del(me->realdemux->out, p_es);
 }
 
 int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args)
@@ -484,6 +548,17 @@ int BaseStreamOutput::esOutControl(es_out_t *fakees, int i_query, va_list args)
         me->pcr = (int64_t)va_arg( args, int64_t );
         return VLC_SUCCESS;
     }
+    else if( i_query == ES_OUT_GET_ES_STATE )
+    {
+        va_arg( args, es_out_id_t * );
+        bool *pb = va_arg( args, bool * );
+        *pb = true;
+        return VLC_SUCCESS;
+    }
+    else if( me->restarting )
+    {
+        return VLC_EGENERIC;
+    }
 
     return me->realdemux->out->pf_control(me->realdemux->out, i_query, args);
 }
diff --git a/modules/demux/adaptative/Streams.hpp b/modules/demux/adaptative/Streams.hpp
index 6cfd66b..132da24 100644
--- a/modules/demux/adaptative/Streams.hpp
+++ b/modules/demux/adaptative/Streams.hpp
@@ -27,6 +27,7 @@
 #include <string>
 #include <list>
 #include <vlc_common.h>
+#include <vlc_es.h>
 #include "StreamsType.hpp"
 
 namespace adaptative
@@ -100,6 +101,7 @@ namespace adaptative
         virtual void setPosition(mtime_t) = 0;
         virtual void sendToDecoder(mtime_t) = 0;
         virtual bool reinitsOnSeek() const = 0;
+        virtual bool switchAllowed() const = 0;
 
     protected:
         demux_t  *realdemux;
@@ -130,12 +132,14 @@ namespace adaptative
         virtual void setPosition(mtime_t); /* reimpl */
         virtual void sendToDecoder(mtime_t); /* reimpl */
         virtual bool reinitsOnSeek() const; /* reimpl */
+        virtual bool switchAllowed() const; /* reimpl */
 
     protected:
         es_out_t *fakeesout; /* to intercept/proxy what is sent from demuxstream */
         stream_t *demuxstream;
         bool      seekable;
         std::string name;
+        bool      restarting;
 
     private:
         static es_out_id_t *esOutAdd(es_out_t *, const es_format_t *);
@@ -147,12 +151,14 @@ namespace adaptative
         class Demuxed
         {
             friend class BaseStreamOutput;
-            Demuxed();
+            Demuxed(es_out_id_t *, const es_format_t *);
             ~Demuxed();
             void drop();
             es_out_id_t *es_id;
             block_t  *p_queue;
             block_t **pp_queue_last;
+            bool recycle;
+            es_format_t fmtcpy;
         };
         std::list<Demuxed *> queues;
         vlc_mutex_t lock;



More information about the vlc-commits mailing list