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