1 /*****************************************************************************
2  * SegmentTemplate.cpp: Implement the UrlTemplate element.
3  *****************************************************************************
4  * Copyright (C) 1998-2007 VLC authors and VideoLAN
5  * $Id: b13f85a494e379247b4055818200f059097d05e8 $
6  *
7  * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 
27 #include "SegmentTemplate.h"
28 #include "SegmentTimeline.h"
29 #include "SegmentInformation.hpp"
30 #include "AbstractPlaylist.hpp"
31 #include <limits>
32 
33 using namespace adaptive::playlist;
34 
BaseSegmentTemplate(ICanonicalUrl * parent)35 BaseSegmentTemplate::BaseSegmentTemplate( ICanonicalUrl *parent ) :
36     Segment( parent )
37 {
38 }
39 
~BaseSegmentTemplate()40 BaseSegmentTemplate::~BaseSegmentTemplate()
41 {
42 
43 }
44 
setSourceUrl(const std::string & url)45 void BaseSegmentTemplate::setSourceUrl(const std::string &url)
46 {
47     sourceUrl = Url(Url::Component(url, this));
48 }
49 
MediaSegmentTemplate(SegmentInformation * parent)50 MediaSegmentTemplate::MediaSegmentTemplate( SegmentInformation *parent ) :
51     BaseSegmentTemplate( parent ),
52     TimescaleAble( NULL ) /* we don't want auto inherit */
53 {
54     debugName = "SegmentTemplate";
55     classId = Segment::CLASSID_SEGMENT;
56     startNumber = std::numeric_limits<uint64_t>::max();
57     segmentTimeline = NULL;
58     initialisationSegment.Set( NULL );
59     templated = true;
60     parentSegmentInformation = parent;
61 }
62 
~MediaSegmentTemplate()63 MediaSegmentTemplate::~MediaSegmentTemplate()
64 {
65     delete segmentTimeline;
66 }
67 
updateWith(MediaSegmentTemplate * updated)68 void MediaSegmentTemplate::updateWith(MediaSegmentTemplate *updated)
69 {
70     SegmentTimeline *timeline = segmentTimeline;
71     if(timeline && updated->segmentTimeline)
72     {
73         timeline->updateWith(*updated->segmentTimeline);
74         /*if(prunebarrier)
75         {
76             const Timescale timescale = timeline->inheritTimescale();
77             const uint64_t number =
78                     timeline->getElementNumberByScaledPlaybackTime(timescale.ToScaled(prunebarrier));
79             timeline->pruneBySequenceNumber(number);
80         }*/
81     }
82 }
83 
pruneByPlaybackTime(mtime_t time)84 void MediaSegmentTemplate::pruneByPlaybackTime(mtime_t time)
85 {
86     if(segmentTimeline)
87         return segmentTimeline->pruneByPlaybackTime(time);
88 }
89 
pruneBySequenceNumber(uint64_t number)90 size_t MediaSegmentTemplate::pruneBySequenceNumber(uint64_t number)
91 {
92     if(segmentTimeline)
93         return segmentTimeline->pruneBySequenceNumber(number);
94     return 0;
95 }
96 
inheritStartNumber() const97 uint64_t MediaSegmentTemplate::inheritStartNumber() const
98 {
99     if( startNumber != std::numeric_limits<uint64_t>::max() )
100         return startNumber;
101 
102     const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
103                                                                 : NULL;
104     for( ; ulevel ; ulevel = ulevel->parent )
105     {
106         if( ulevel->mediaSegmentTemplate &&
107             ulevel->mediaSegmentTemplate->startNumber !=
108                 std::numeric_limits<uint64_t>::max() )
109             return ulevel->mediaSegmentTemplate->startNumber;
110     }
111     return 1;
112 }
113 
inheritTimescale() const114 Timescale MediaSegmentTemplate::inheritTimescale() const
115 {
116     const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
117                                                                 : NULL;
118     for( ; ulevel ; ulevel = ulevel->parent )
119     {
120         if( ulevel->mediaSegmentTemplate &&
121             ulevel->mediaSegmentTemplate->getTimescale().isValid() )
122             return ulevel->mediaSegmentTemplate->getTimescale();
123         if( ulevel->getTimescale().isValid() )
124             return ulevel->getTimescale();
125     }
126     return Timescale(1);
127 }
128 
inheritDuration() const129 stime_t MediaSegmentTemplate::inheritDuration() const
130 {
131     const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
132                                                                 : NULL;
133     for( ; ulevel ; ulevel = ulevel->parent )
134     {
135         if( ulevel->mediaSegmentTemplate &&
136             ulevel->mediaSegmentTemplate->duration.Get() > 0 )
137             return ulevel->mediaSegmentTemplate->duration.Get();
138     }
139     return 0;
140 }
141 
inheritSegmentTimeline() const142 SegmentTimeline * MediaSegmentTemplate::inheritSegmentTimeline() const
143 {
144     const SegmentInformation *ulevel = parentSegmentInformation ? parentSegmentInformation
145                                                           : NULL;
146     for( ; ulevel ; ulevel = ulevel->parent )
147     {
148         if( ulevel->mediaSegmentTemplate &&
149             ulevel->mediaSegmentTemplate->segmentTimeline )
150             return ulevel->mediaSegmentTemplate->segmentTimeline;
151     }
152     return NULL;
153 }
154 
getLiveTemplateNumber(mtime_t playbacktime,bool abs) const155 uint64_t MediaSegmentTemplate::getLiveTemplateNumber(mtime_t playbacktime, bool abs) const
156 {
157     uint64_t number = inheritStartNumber();
158     /* live streams / templated */
159     const stime_t dur = inheritDuration();
160     if(dur)
161     {
162         /* compute, based on current time */
163         /* N = (T - AST - PS - D)/D + sSN */
164         const Timescale timescale = inheritTimescale();
165         if(abs)
166         {
167             mtime_t streamstart =
168                     parentSegmentInformation->getPlaylist()->availabilityStartTime.Get();
169             streamstart += parentSegmentInformation->getPeriodStart();
170             playbacktime -= streamstart;
171         }
172         stime_t elapsed = timescale.ToScaled(playbacktime) - dur;
173         if(elapsed > 0)
174             number += elapsed / dur;
175     }
176 
177     return number;
178 }
179 
getMinAheadScaledTime(uint64_t number) const180 stime_t MediaSegmentTemplate::getMinAheadScaledTime(uint64_t number) const
181 {
182     if( segmentTimeline )
183         return segmentTimeline->getMinAheadScaledTime(number);
184 
185     uint64_t current = getLiveTemplateNumber(CLOCK_FREQ * time(NULL));
186     return (current - number) * inheritDuration();
187 }
188 
getSequenceNumber() const189 uint64_t MediaSegmentTemplate::getSequenceNumber() const
190 {
191     return inheritStartNumber();
192 }
193 
setStartNumber(uint64_t v)194 void MediaSegmentTemplate::setStartNumber( uint64_t v )
195 {
196     startNumber = v;
197 }
198 
setSegmentTimeline(SegmentTimeline * v)199 void MediaSegmentTemplate::setSegmentTimeline( SegmentTimeline *v )
200 {
201     delete segmentTimeline;
202     segmentTimeline = v;
203 }
204 
debug(vlc_object_t * obj,int indent) const205 void MediaSegmentTemplate::debug(vlc_object_t *obj, int indent) const
206 {
207     Segment::debug(obj, indent);
208     if(segmentTimeline)
209         segmentTimeline->debug(obj, indent + 1);
210 }
211 
InitSegmentTemplate(ICanonicalUrl * parent)212 InitSegmentTemplate::InitSegmentTemplate( ICanonicalUrl *parent ) :
213     BaseSegmentTemplate(parent)
214 {
215     debugName = "InitSegmentTemplate";
216     classId = InitSegment::CLASSID_INITSEGMENT;
217 }
218