demux: adaptive: rework profile specific types for global timeline
[vlc.git] / modules / demux / adaptive / playlist / SegmentTemplate.cpp
blobf66fe7eb024f1e5aaf571d0e6171f0c2074f1997
1 /*****************************************************************************
2 * SegmentTemplate.cpp: Implement the UrlTemplate element.
3 *****************************************************************************
4 * Copyright (C) 1998-2007 VLC authors and VideoLAN
6 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include "SegmentTemplate.h"
27 #include "SegmentTimeline.h"
28 #include "SegmentInformation.hpp"
29 #include "AbstractPlaylist.hpp"
30 #include <limits>
32 using namespace adaptive::playlist;
34 SegmentTemplateSegment::SegmentTemplateSegment( SegmentTemplate *templ_,
35 ICanonicalUrl *parent ) :
36 Segment( parent )
38 debugName = "SegmentTemplateSegment";
39 classId = Segment::CLASSID_SEGMENT;
40 templated = true;
41 templ = templ_;
44 SegmentTemplateSegment::~SegmentTemplateSegment()
49 void SegmentTemplateSegment::setSourceUrl(const std::string &url)
51 sourceUrl = Url(Url::Component(url, templ));
54 SegmentTemplate::SegmentTemplate( SegmentInformation *parent ) :
55 AbstractMultipleSegmentBaseType( NULL ) /* we don't want auto inherit */
57 initialisationSegment.Set( NULL );
58 parentSegmentInformation = parent;
59 segments.push_back( new SegmentTemplateSegment( this, parent ) );
62 SegmentTemplate::~SegmentTemplate()
64 delete *segments.begin();
67 void SegmentTemplate::setSourceUrl( const std::string &url )
69 (*segments.begin())->setSourceUrl(url);
72 void SegmentTemplate::pruneByPlaybackTime(vlc_tick_t time)
74 if(segmentTimeline)
75 return segmentTimeline->pruneByPlaybackTime(time);
78 size_t SegmentTemplate::pruneBySequenceNumber(uint64_t number)
80 if(segmentTimeline)
81 return segmentTimeline->pruneBySequenceNumber(number);
82 return 0;
85 uint64_t SegmentTemplate::getLiveTemplateNumber(vlc_tick_t playbacktime, bool abs) const
87 uint64_t number = inheritStartNumber();
88 /* live streams / templated */
89 const stime_t dur = inheritDuration();
90 if(dur)
92 /* compute, based on current time */
93 /* N = (T - AST - PS - D)/D + sSN */
94 const Timescale timescale = inheritTimescale();
95 if(abs)
97 vlc_tick_t streamstart =
98 parentSegmentInformation->getPlaylist()->availabilityStartTime.Get();
99 streamstart += parentSegmentInformation->getPeriodStart();
100 playbacktime -= streamstart;
102 stime_t elapsed = timescale.ToScaled(playbacktime) - dur;
103 if(elapsed > 0)
104 number += elapsed / dur;
107 return number;
110 void SegmentTemplate::debug(vlc_object_t *obj, int indent) const
112 AbstractSegmentBaseType::debug(obj, indent);
113 (*segments.begin())->debug(obj, indent);
114 if(segmentTimeline)
115 segmentTimeline->debug(obj, indent + 1);
118 vlc_tick_t SegmentTemplate::getMinAheadTime(uint64_t number) const
120 if( segmentTimeline )
122 const Timescale timescale = segmentTimeline->inheritTimescale();
123 return timescale.ToTime(segmentTimeline->getMinAheadScaledTime(number));
125 else
127 const Timescale timescale = inheritTimescale();
128 uint64_t current = getLiveTemplateNumber(vlc_tick_from_sec(time(NULL)));
129 stime_t i_length = (current - number) * inheritDuration();
130 return timescale.ToTime(i_length);
134 Segment * SegmentTemplate::getMediaSegment(uint64_t number) const
136 const SegmentTimeline *tl = inheritSegmentTimeline();
137 if(tl == NULL || tl->maxElementNumber() > number)
138 return *segments.begin();
139 return NULL;
142 InitSegment * SegmentTemplate::getInitSegment() const
144 return initialisationSegment.Get();
147 Segment * SegmentTemplate::getNextMediaSegment(uint64_t i_pos,uint64_t *pi_newpos,
148 bool *pb_gap) const
150 *pb_gap = false;
151 *pi_newpos = i_pos;
152 /* Check if we don't exceed timeline */
153 const SegmentTimeline *timeline = inheritSegmentTimeline();
154 if(timeline)
156 *pi_newpos = std::max(timeline->minElementNumber(), i_pos);
157 if (timeline->maxElementNumber() < i_pos)
158 return NULL;
160 else
162 /* check template upper bound */
163 const AbstractPlaylist *playlist = parentSegmentInformation->getPlaylist();
164 if(!playlist->isLive())
166 const Timescale timescale = inheritTimescale();
167 const stime_t segmentduration = inheritDuration();
168 vlc_tick_t totalduration = parentSegmentInformation->getPeriodDuration();
169 if(totalduration == 0)
170 totalduration = playlist->duration.Get();
171 if(totalduration && segmentduration)
173 uint64_t endnum = inheritStartNumber() +
174 (timescale.ToScaled(totalduration) + segmentduration - 1) / segmentduration;
175 if(i_pos >= endnum)
177 *pi_newpos = i_pos;
178 return NULL;
182 *pi_newpos = i_pos;
183 /* start number */
184 *pi_newpos = std::max(inheritStartNumber(), i_pos);
186 return *segments.begin();
189 uint64_t SegmentTemplate::getStartSegmentNumber() const
191 const SegmentTimeline *timeline = inheritSegmentTimeline();
192 return timeline ? timeline->minElementNumber() : inheritStartNumber();
195 bool SegmentTemplate::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const
197 const SegmentTimeline *timeline = inheritSegmentTimeline();
198 if(timeline)
200 const Timescale timescale = timeline->getTimescale().isValid()
201 ? timeline->getTimescale()
202 : inheritTimescale();
203 stime_t st = timescale.ToScaled(time);
204 *ret = timeline->getElementNumberByScaledPlaybackTime(st);
205 return true;
208 const stime_t duration = inheritDuration();
209 if( duration && parent )
211 AbstractPlaylist *playlist = parent->getPlaylist();
212 if( playlist->isLive() )
214 vlc_tick_t now = vlc_tick_from_sec(::time(NULL));
215 if(playlist->availabilityStartTime.Get())
217 if(time >= playlist->availabilityStartTime.Get() && time < now)
218 *ret = getLiveTemplateNumber(time, true);
219 else if(now - playlist->availabilityStartTime.Get() > time)
220 *ret = getLiveTemplateNumber(time, false);
222 else return false;
224 else
226 const Timescale timescale = inheritTimescale();
227 *ret = inheritStartNumber();
228 *ret += timescale.ToScaled(time) / duration;
230 return true;
233 return false;
237 bool SegmentTemplate::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
238 vlc_tick_t *time,
239 vlc_tick_t *duration) const
241 if(number == std::numeric_limits<uint64_t>::max())
242 return false;
244 Timescale timescale;
245 stime_t stime, sduration;
247 const SegmentTimeline * timeline = inheritSegmentTimeline();
248 if(timeline)
250 timescale = timeline->inheritTimescale();
251 if(!timeline->getScaledPlaybackTimeDurationBySegmentNumber(number, &stime, &sduration))
252 return false;
254 else
256 timescale = inheritTimescale();
257 uint64_t startNumber = inheritStartNumber();
258 if(number < startNumber)
259 return false;
260 sduration = inheritDuration();
261 stime = (number - startNumber) * sduration;
264 *time = timescale.ToTime(stime);
265 *duration = timescale.ToTime(sduration);
266 return true;
270 SegmentTemplateInit::SegmentTemplateInit( SegmentTemplate *templ_,
271 ICanonicalUrl *parent ) :
272 InitSegment(parent)
274 debugName = "InitSegmentTemplate";
275 classId = InitSegment::CLASSID_INITSEGMENT;
276 templ = templ_;
279 SegmentTemplateInit::~SegmentTemplateInit()
284 void SegmentTemplateInit::setSourceUrl(const std::string &url)
286 sourceUrl = Url(Url::Component(url, templ));