demux: dash: Update MPD
authorFrancois Cartegnie <fcvlcdev@free.fr>
Sun, 11 Jan 2015 22:22:39 +0000 (23:22 +0100)
committerFrancois Cartegnie <fcvlcdev@free.fr>
Mon, 12 Jan 2015 19:21:57 +0000 (20:21 +0100)
modules/demux/dash/DASHManager.cpp
modules/demux/dash/DASHManager.h
modules/demux/dash/dash.cpp

index 5b891f9..5652c8a 100644 (file)
 #endif
 
 #include "DASHManager.h"
+#include "mpd/MPDFactory.h"
+#include "mpd/SegmentTimeline.h"
+#include "xml/DOMParser.h"
 #include "adaptationlogic/AdaptationLogicFactory.h"
 #include "SegmentTracker.hpp"
+#include <vlc_stream.h>
 
 using namespace dash;
 using namespace dash::http;
@@ -41,7 +45,8 @@ DASHManager::DASHManager    ( MPD *mpd,
              conManager     ( NULL ),
              logicType      ( type ),
              mpd            ( mpd ),
-             stream         ( stream )
+             stream         ( stream ),
+             nextMPDupdate  ( 0 )
 {
     for(int i=0; i<Streams::count; i++)
         streams[i] = NULL;
@@ -97,6 +102,7 @@ bool DASHManager::start(demux_t *demux)
         return false;
 
     mpd->playbackStart.Set(time(NULL));
+    nextMPDupdate = mpd->playbackStart.Get();
 
     return true;
 }
@@ -189,3 +195,60 @@ bool DASHManager::seekAble() const
     }
     return true;
 }
+
+bool DASHManager::updateMPD()
+{
+    if(!mpd->isLive() || !mpd->minUpdatePeriod.Get())
+        return true;
+
+    mtime_t now = time(NULL);
+    if(nextMPDupdate && now < nextMPDupdate)
+        return true;
+
+    /* do update */
+    if(nextMPDupdate)
+    {
+        std::string url(stream->psz_access);
+        url.append("://");
+        url.append(stream->psz_path);
+
+        stream_t *mpdstream = stream_UrlNew(stream, url.c_str());
+        if(!mpdstream)
+            return false;
+
+        xml::DOMParser parser(mpdstream);
+        if(!parser.parse())
+        {
+            stream_Delete(mpdstream);
+            return false;
+        }
+
+        MPD *newmpd = MPDFactory::create(parser.getRootNode(), mpdstream, parser.getProfile());
+        if(newmpd)
+        {
+            mpd->mergeWith(newmpd);
+            delete newmpd;
+        }
+        stream_Delete(mpdstream);
+    }
+
+    /* Compute new MPD update time */
+    mtime_t mininterval = 0;
+    mtime_t maxinterval = 0;
+    mpd->getTimeLinesBoundaries(&mininterval, &maxinterval);
+    if(maxinterval > mininterval)
+        maxinterval = (maxinterval - mininterval) / CLOCK_FREQ;
+    else
+        maxinterval = 60;
+    maxinterval = std::max(maxinterval, (mtime_t)60);
+
+    mininterval = std::max(mpd->minUpdatePeriod.Get(),
+                           mpd->maxSegmentDuration.Get());
+
+    nextMPDupdate = now + (maxinterval - mininterval) / 2;
+
+    msg_Dbg(stream, "Updated MPD, next update in %"PRId64"s (%"PRId64"..%"PRId64")",
+            nextMPDupdate - now, mininterval, maxinterval );
+
+    return true;
+}
index b2fc7e3..11398c4 100644 (file)
@@ -46,6 +46,7 @@ namespace dash
             int     esCount() const;
             bool    setPosition(mtime_t);
             bool    seekAble() const;
+            bool    updateMPD();
 
         private:
             http::HTTPConnectionManager         *conManager;
@@ -53,6 +54,7 @@ namespace dash
             mpd::MPD                            *mpd;
             stream_t                            *stream;
             Streams::Stream                     *streams[Streams::count];
+            mtime_t                              nextMPDupdate;
     };
 
 }
index e81d945..ee9bada 100644 (file)
@@ -182,6 +182,10 @@ static int Demux(demux_t *p_demux)
             else
                 es_out_Control(p_demux->out, ES_OUT_SET_PCR, pcr);
         }
+
+        if( !p_sys->p_dashManager->updateMPD() )
+            return VLC_DEMUXER_EOF;
+
         return VLC_DEMUXER_SUCCESS;
     }
     else