demux: dash: add timeline support
authorFrancois Cartegnie <fcvlcdev@free.fr>
Wed, 7 Jan 2015 20:07:01 +0000 (21:07 +0100)
committerFrancois Cartegnie <fcvlcdev@free.fr>
Mon, 12 Jan 2015 19:21:57 +0000 (20:21 +0100)
modules/demux/dash/mpd/SegmentInfoCommon.cpp
modules/demux/dash/mpd/SegmentInformation.cpp
modules/demux/dash/mpd/SegmentInformation.hpp
modules/demux/dash/mpd/SegmentTimeline.cpp
modules/demux/dash/mpd/SegmentTimeline.h
modules/demux/dash/mpd/Url.cpp
modules/demux/dash/mpd/Url.hpp

index c0d342d..eebacac 100644 (file)
@@ -45,7 +45,7 @@ Timelineable::~Timelineable()
 
 SegmentInfoCommon::SegmentInfoCommon( ICanonicalUrl *parent ) :
     ICanonicalUrl( parent ), Initializable(),
-    duration( -1 ),
+    duration( 0 ),
     startIndex( 0 )
 {
 }
index ac8680e..fc80959 100644 (file)
@@ -23,6 +23,7 @@
 #include "SegmentBase.h"
 #include "SegmentList.h"
 #include "SegmentTemplate.h"
+#include "SegmentTimeline.h"
 
 using namespace dash::mpd;
 using namespace std;
@@ -158,18 +159,19 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
 {
     SegmentList *segList;
     MediaSegmentTemplate *mediaTemplate;
-    uint64_t timescale;
+    uint64_t timescale = 0;
     mtime_t duration = 0;
-    if ( (segList = inheritSegmentList()) )
-    {
-        timescale = segList->timescale.Get();
-        duration = segList->getDuration();
-    }
-    else if( (mediaTemplate = inheritSegmentTemplate()) )
+
+    if( (mediaTemplate = inheritSegmentTemplate()) )
     {
         timescale = mediaTemplate->timescale.Get();
         duration = mediaTemplate->duration.Get();
     }
+    else if ( (segList = inheritSegmentList()) )
+    {
+        timescale = segList->timescale.Get();
+        duration = segList->getDuration();
+    }
 
     if(duration)
     {
@@ -182,6 +184,41 @@ bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) con
     return false;
 }
 
+mtime_t SegmentInformation::getPlaybackTimeBySegmentNumber(uint64_t number) const
+{
+    SegmentList *segList;
+    MediaSegmentTemplate *mediaTemplate;
+    uint64_t timescale = 0;
+    mtime_t time = 0;
+    if( (mediaTemplate = inheritSegmentTemplate()) )
+    {
+        timescale = mediaTemplate->timescale.Get();
+        if(mediaTemplate->segmentTimeline.Get())
+        {
+            time = mediaTemplate->segmentTimeline.Get()->
+                    getScaledPlaybackTimeByElementNumber(number);
+        }
+        else
+        {
+            time = number * mediaTemplate->duration.Get();
+        }
+    }
+    else if ( (segList = inheritSegmentList()) )
+    {
+        timescale = segList->timescale.Get();
+        time = number * segList->getDuration();
+    }
+
+    if(time)
+    {
+        if(!timescale)
+            timescale = getTimescale(); /* inherit */
+        time = CLOCK_FREQ * time / timescale;
+    }
+
+    return time;
+}
+
 bool SegmentInformation::canBitswitch() const
 {
     if(bitswitch_policy == BITSWITCH_INHERIT)
index b940241..f099645 100644 (file)
@@ -72,6 +72,7 @@ namespace dash
 
                 ISegment * getSegment(SegmentInfoType, uint64_t = 0) const;
                 bool getSegmentNumberByTime(mtime_t, uint64_t *) const;
+                mtime_t getPlaybackTimeBySegmentNumber(uint64_t) const;
 
             protected:
                 std::vector<ISegment *> getSegments() const;
index 2f1b240..07c4dbf 100644 (file)
@@ -47,6 +47,53 @@ void SegmentTimeline::addElement(mtime_t d, uint64_t r, mtime_t t)
         elements.push_back(element);
 }
 
+uint64_t SegmentTimeline::getElementNumberByScaledPlaybackTime(time_t scaled) const
+{
+    uint64_t count = 0;
+    std::list<Element *>::const_iterator it;
+    for(it = elements.begin(); it != elements.end(); it++)
+    {
+        const Element *el = *it;
+        for(uint64_t repeat = 1 + el->r; repeat; repeat--)
+        {
+            if(el->d >= scaled)
+                return count;
+
+            scaled -= el->d;
+            count++;
+        }
+    }
+    return count;
+}
+
+mtime_t SegmentTimeline::getScaledPlaybackTimeByElementNumber(uint64_t number) const
+{
+    mtime_t totalscaledtime = 0;
+
+    std::list<Element *>::const_iterator it;
+    for(it = elements.begin(); it != elements.end(); it++)
+    {
+        const Element *el = *it;
+
+        if(number == 0)
+        {
+            totalscaledtime = el->t;
+            break;
+        }
+        else if(number <= el->r)
+        {
+            totalscaledtime = el->t + (number * el->d);
+            break;
+        }
+        else
+        {
+            number -= el->r + 1;
+        }
+    }
+
+    return totalscaledtime;
+}
+
 SegmentTimeline::Element::Element(mtime_t d_, uint64_t r_, mtime_t t_)
 {
     d = d_;
index 9764730..f387372 100644 (file)
@@ -39,6 +39,8 @@ namespace dash
                 SegmentTimeline();
                 virtual ~SegmentTimeline();
                 void addElement(mtime_t d, uint64_t r = 0, mtime_t t = 0);
+                uint64_t getElementNumberByScaledPlaybackTime(time_t) const;
+                mtime_t getScaledPlaybackTimeByElementNumber(uint64_t) const;
 
             private:
                 std::list<Element *> elements;
index 5015185..446690b 100644 (file)
@@ -20,6 +20,7 @@
 #include "Url.hpp"
 #include "Representation.h"
 #include "SegmentTemplate.h"
+#include "SegmentTimeline.h"
 #include "MPD.h"
 
 #include <sstream>
@@ -85,21 +86,42 @@ Url::Component::Component(const std::string & str, const MediaSegmentTemplate *t
     templ = templ_;
 }
 
+mtime_t Url::Component::getScaledTimeBySegmentNumber(size_t index, const Representation *) const
+{
+    mtime_t time = 0;
+    if(templ->segmentTimeline.Get())
+    {
+        time = templ->segmentTimeline.Get()->getScaledPlaybackTimeByElementNumber(index);
+    }
+    else if(templ->duration.Get())
+    {
+        time = templ->duration.Get() * index;
+    }
+    return time;
+}
+
 size_t Url::Component::getSegmentNumber(size_t index, const Representation *rep) const
 {
     index += templ->startNumber.Get();
     /* live streams / templated */
-    if(rep->getMPD()->isLive() && templ->duration.Get())
+    if(rep->getMPD()->isLive())
     {
-        mtime_t playbackstart = rep->getMPD()->playbackStart.Get();
-        mtime_t streamstart = rep->getMPD()->getAvailabilityStartTime();
-        streamstart += rep->getPeriodStart();
-        mtime_t duration = templ->duration.Get();
-        uint64_t timescale = templ->timescale.Get() ?
-                             templ->timescale.Get() :
-                             rep->getTimescale();
-        if(duration && timescale)
-            index += (playbackstart - streamstart) * timescale / duration;
+        if(templ->segmentTimeline.Get())
+        {
+            // do nothing ?
+        }
+        else if(templ->duration.Get())
+        {
+            mtime_t playbackstart = rep->getMPD()->playbackStart.Get();
+            mtime_t streamstart = rep->getMPD()->getAvailabilityStartTime();
+            streamstart += rep->getPeriodStart();
+            mtime_t duration = templ->duration.Get();
+            uint64_t timescale = templ->timescale.Get() ?
+                                 templ->timescale.Get() :
+                                 rep->getTimescale();
+            if(duration && timescale)
+                index += (playbackstart - streamstart) * timescale / duration;
+        }
     }
     return index;
 }
@@ -118,7 +140,7 @@ std::string Url::Component::contextualize(size_t index, const Representation *re
         if(pos != std::string::npos)
         {
             std::stringstream ss;
-            ss << (templ->duration.Get() * index);
+            ss << getScaledTimeBySegmentNumber(index, rep);
             ret.replace(pos, std::string("$Time$").length(), ss.str());
         }
 
index 55d80c2..3fe09ad 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <string>
 #include <vector>
+#include <vlc_common.h>
 
 namespace dash
 {
@@ -41,6 +42,7 @@ namespace dash
 
                     protected:
                         std::string contextualize(size_t, const Representation *) const;
+                        mtime_t getScaledTimeBySegmentNumber(size_t, const Representation *) const;
                         size_t getSegmentNumber(size_t, const Representation *) const;
                         std::string component;
                         const MediaSegmentTemplate *templ;