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 *****************************************************************************/
26 #include "SegmentTemplate.h"
27 #include "SegmentTimeline.h"
28 #include "SegmentInformation.hpp"
29 #include "AbstractPlaylist.hpp"
32 using namespace adaptive::playlist
;
34 SegmentTemplateSegment::SegmentTemplateSegment( SegmentTemplate
*templ_
,
35 ICanonicalUrl
*parent
) :
38 debugName
= "SegmentTemplateSegment";
39 classId
= Segment::CLASSID_SEGMENT
;
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
)
75 return segmentTimeline
->pruneByPlaybackTime(time
);
78 size_t SegmentTemplate::pruneBySequenceNumber(uint64_t number
)
81 return segmentTimeline
->pruneBySequenceNumber(number
);
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();
92 /* compute, based on current time */
93 /* N = (T - AST - PS - D)/D + sSN */
94 const Timescale timescale
= inheritTimescale();
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
;
104 number
+= elapsed
/ dur
;
110 void SegmentTemplate::debug(vlc_object_t
*obj
, int indent
) const
112 AbstractSegmentBaseType::debug(obj
, indent
);
113 (*segments
.begin())->debug(obj
, indent
);
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
));
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();
142 InitSegment
* SegmentTemplate::getInitSegment() const
144 return initialisationSegment
.Get();
147 Segment
* SegmentTemplate::getNextMediaSegment(uint64_t i_pos
,uint64_t *pi_newpos
,
152 /* Check if we don't exceed timeline */
153 const SegmentTimeline
*timeline
= inheritSegmentTimeline();
156 *pi_newpos
= std::max(timeline
->minElementNumber(), i_pos
);
157 if (timeline
->maxElementNumber() < i_pos
)
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
;
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();
200 const Timescale timescale
= timeline
->getTimescale().isValid()
201 ? timeline
->getTimescale()
202 : inheritTimescale();
203 stime_t st
= timescale
.ToScaled(time
);
204 *ret
= timeline
->getElementNumberByScaledPlaybackTime(st
);
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);
226 const Timescale timescale
= inheritTimescale();
227 *ret
= inheritStartNumber();
228 *ret
+= timescale
.ToScaled(time
) / duration
;
237 bool SegmentTemplate::getPlaybackTimeDurationBySegmentNumber(uint64_t number
,
239 vlc_tick_t
*duration
) const
241 if(number
== std::numeric_limits
<uint64_t>::max())
245 stime_t stime
, sduration
;
247 const SegmentTimeline
* timeline
= inheritSegmentTimeline();
250 timescale
= timeline
->inheritTimescale();
251 if(!timeline
->getScaledPlaybackTimeDurationBySegmentNumber(number
, &stime
, &sduration
))
256 timescale
= inheritTimescale();
257 uint64_t startNumber
= inheritStartNumber();
258 if(number
< startNumber
)
260 sduration
= inheritDuration();
261 stime
= (number
- startNumber
) * sduration
;
264 *time
= timescale
.ToTime(stime
);
265 *duration
= timescale
.ToTime(sduration
);
270 SegmentTemplateInit::SegmentTemplateInit( SegmentTemplate
*templ_
,
271 ICanonicalUrl
*parent
) :
274 debugName
= "InitSegmentTemplate";
275 classId
= InitSegment::CLASSID_INITSEGMENT
;
279 SegmentTemplateInit::~SegmentTemplateInit()
284 void SegmentTemplateInit::setSourceUrl(const std::string
&url
)
286 sourceUrl
= Url(Url::Component(url
, templ
));