demux: adaptive: rework profile specific types for global timeline
[vlc.git] / modules / demux / adaptive / playlist / SegmentList.cpp
blob211b9ef80ce4ae254f1fded6726cd4d3b966105f
1 /*
2 * SegmentList.cpp
3 *****************************************************************************
4 * Copyright (C) 2010 - 2012 Klagenfurt University
6 * Created on: Jan 27, 2012
7 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
8 * Christian Timmerer <christian.timmerer@itec.uni-klu.ac.at>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include "SegmentList.h"
29 #include "Segment.h"
30 #include "SegmentInformation.hpp"
31 #include "SegmentTimeline.h"
33 #include <limits>
35 using namespace adaptive::playlist;
37 SegmentList::SegmentList( SegmentInformation *parent ):
38 AbstractMultipleSegmentBaseType( parent )
40 totalLength = 0;
42 SegmentList::~SegmentList()
44 std::vector<Segment *>::iterator it;
45 for(it = segments.begin(); it != segments.end(); ++it)
46 delete(*it);
49 const std::vector<Segment*>& SegmentList::getSegments() const
51 return segments;
54 Segment * SegmentList::getMediaSegment(uint64_t number) const
56 const SegmentTimeline *timeline = inheritSegmentTimeline();
57 if(timeline)
59 uint64_t listindex = timeline->getElementIndexBySequence(number);
60 if(listindex >= segments.size())
61 return NULL;
62 return segments.at(listindex);
65 std::vector<Segment *>::const_iterator it = segments.begin();
66 for(it = segments.begin(); it != segments.end(); ++it)
68 Segment *seg = *it;
69 if(seg->getSequenceNumber() == number)
71 return seg;
73 else if (seg->getSequenceNumber() > number)
75 break;
78 return NULL;
81 void SegmentList::addSegment(Segment *seg)
83 seg->setParent(parent);
84 segments.push_back(seg);
85 totalLength += seg->duration.Get();
88 void SegmentList::updateWith(AbstractMultipleSegmentBaseType *updated_,
89 bool b_restamp)
91 AbstractMultipleSegmentBaseType::updateWith(updated_);
93 SegmentList *updated = dynamic_cast<SegmentList *>(updated_);
94 if(!updated || updated->segments.empty())
95 return;
97 const Segment * lastSegment = (segments.empty()) ? NULL : segments.back();
98 const Segment * prevSegment = lastSegment;
100 uint64_t firstnumber = updated->segments.front()->getSequenceNumber();
102 std::vector<Segment *>::iterator it;
103 for(it = updated->segments.begin(); it != updated->segments.end(); ++it)
105 Segment *cur = *it;
106 if(!lastSegment || lastSegment->compare(cur) < 0)
108 if(b_restamp && prevSegment)
110 stime_t starttime = prevSegment->startTime.Get() + prevSegment->duration.Get();
111 if(starttime != cur->startTime.Get() && !cur->discontinuity)
113 cur->startTime.Set(starttime);
116 prevSegment = cur;
118 addSegment(cur);
120 else
121 delete cur;
123 updated->segments.clear();
125 pruneBySegmentNumber(firstnumber);
128 void SegmentList::pruneByPlaybackTime(vlc_tick_t time)
130 const Timescale timescale = inheritTimescale();
131 uint64_t num = findSegmentNumberByScaledTime(segments, timescale.ToScaled(time));
132 if(num != std::numeric_limits<uint64_t>::max())
133 pruneBySegmentNumber(num);
136 void SegmentList::pruneBySegmentNumber(uint64_t tobelownum)
138 std::vector<Segment *>::iterator it = segments.begin();
139 while(it != segments.end())
141 Segment *seg = *it;
143 if(seg->getSequenceNumber() >= tobelownum)
144 break;
146 totalLength -= (*it)->duration.Get();
147 delete *it;
148 it = segments.erase(it);
152 bool SegmentList::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
153 vlc_tick_t *time, vlc_tick_t *dur) const
155 if(number == std::numeric_limits<uint64_t>::max())
156 return false;
158 Timescale timescale;
159 stime_t stime, sduration;
161 const SegmentTimeline * timeline = inheritSegmentTimeline();
162 if(timeline)
164 timescale = timeline->inheritTimescale();
165 if(!timeline->getScaledPlaybackTimeDurationBySegmentNumber(number, &stime, &sduration))
166 return false;
168 else
170 *time = *dur = VLC_TICK_INVALID;
171 timescale = inheritTimescale();
173 if(segments.empty())
174 return false;
176 const ISegment *first = segments.front();
177 if(first->getSequenceNumber() > number)
178 return false;
180 bool found = false;
181 stime_t stime = first->startTime.Get();
182 stime_t sduration = 0;
183 std::vector<Segment *>::const_iterator it = segments.begin();
184 for(it = segments.begin(); it != segments.end(); ++it)
186 const Segment *seg = *it;
188 if(seg->duration.Get())
189 sduration = seg->duration.Get();
190 else
191 sduration = duration.Get();
193 /* Assuming there won't be any discontinuity in sequence */
194 if(seg->getSequenceNumber() == number)
196 found = true;
197 break;
200 stime += sduration;
203 if(!found)
204 return false;
207 *time = VLC_TICK_0 + timescale.ToTime(stime);
208 *dur = VLC_TICK_0 + timescale.ToTime(sduration);
209 return true;
212 stime_t SegmentList::getTotalLength() const
214 const SegmentTimeline *timeline = inheritSegmentTimeline();
215 if(timeline)
216 return timeline->getTotalLength();
217 return totalLength;
220 vlc_tick_t SegmentList::getMinAheadTime(uint64_t curnum) const
222 const SegmentTimeline *timeline = inheritSegmentTimeline();
223 if( timeline )
225 const Timescale timescale = timeline->inheritTimescale();
226 return timescale.ToTime(timeline->getMinAheadScaledTime(curnum));
229 vlc_tick_t minTime = 0;
230 const Timescale timescale = inheritTimescale();
231 std::vector<Segment *>::const_iterator it;
232 for(it = segments.begin(); it != segments.end(); ++it)
234 const Segment *seg = *it;
235 if(seg->getSequenceNumber() > curnum)
236 minTime += timescale.ToTime(seg->duration.Get());
238 return minTime;
241 Segment * SegmentList::getNextMediaSegment(uint64_t i_pos,uint64_t *pi_newpos,
242 bool *pb_gap) const
244 *pb_gap = false;
245 *pi_newpos = i_pos;
247 const SegmentTimeline *timeline = inheritSegmentTimeline();
248 if(timeline)
250 uint64_t listindex = timeline->getElementIndexBySequence(i_pos);
251 if(listindex >= segments.size())
252 return NULL;
253 return segments.at(listindex);
256 std::vector<Segment *>::const_iterator it;
257 for(it = segments.begin(); it != segments.end(); ++it)
259 Segment *seg = *it;
260 if(seg->getSequenceNumber() >= i_pos)
262 *pi_newpos = seg->getSequenceNumber();
263 *pb_gap = (*pi_newpos != i_pos);
264 return seg;
267 return NULL;
270 uint64_t SegmentList::getStartSegmentNumber() const
272 const SegmentTimeline *timeline = inheritSegmentTimeline();
273 if( timeline )
274 return timeline->minElementNumber();
275 return !segments.empty() ? segments.front()->getSequenceNumber() : inheritStartNumber();
278 bool SegmentList::getSegmentNumberByTime(vlc_tick_t time, uint64_t *ret) const
280 const SegmentTimeline *timeline = inheritSegmentTimeline();
281 if(timeline)
283 const Timescale timescale = timeline->getTimescale().isValid()
284 ? timeline->getTimescale()
285 : inheritTimescale();
286 stime_t st = timescale.ToScaled(time);
287 *ret = timeline->getElementNumberByScaledPlaybackTime(st);
288 return true;
291 const Timescale timescale = inheritTimescale();
292 if(!timescale.isValid())
293 return false;
294 stime_t st = timescale.ToScaled(time);
295 *ret = AbstractSegmentBaseType::findSegmentNumberByScaledTime(segments, st);
296 return *ret != std::numeric_limits<uint64_t>::max();
299 void SegmentList::debug(vlc_object_t *obj, int indent) const
301 AbstractSegmentBaseType::debug(obj, indent);
302 std::vector<Segment *>::const_iterator it;
303 for(it = segments.begin(); it != segments.end(); ++it)
304 (*it)->debug(obj, indent);
305 if(segmentTimeline)
306 segmentTimeline->debug(obj, indent + 1);