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 *****************************************************************************/
28 #include "SegmentList.h"
30 #include "SegmentInformation.hpp"
31 #include "SegmentTimeline.h"
35 using namespace adaptive::playlist
;
37 SegmentList::SegmentList( SegmentInformation
*parent
):
38 AbstractMultipleSegmentBaseType( parent
)
42 SegmentList::~SegmentList()
44 std::vector
<Segment
*>::iterator it
;
45 for(it
= segments
.begin(); it
!= segments
.end(); ++it
)
49 const std::vector
<Segment
*>& SegmentList::getSegments() const
54 Segment
* SegmentList::getMediaSegment(uint64_t number
) const
56 const SegmentTimeline
*timeline
= inheritSegmentTimeline();
59 uint64_t listindex
= timeline
->getElementIndexBySequence(number
);
60 if(listindex
>= segments
.size())
62 return segments
.at(listindex
);
65 std::vector
<Segment
*>::const_iterator it
= segments
.begin();
66 for(it
= segments
.begin(); it
!= segments
.end(); ++it
)
69 if(seg
->getSequenceNumber() == number
)
73 else if (seg
->getSequenceNumber() > number
)
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_
,
91 AbstractMultipleSegmentBaseType::updateWith(updated_
);
93 SegmentList
*updated
= dynamic_cast<SegmentList
*>(updated_
);
94 if(!updated
|| updated
->segments
.empty())
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
)
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
);
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())
143 if(seg
->getSequenceNumber() >= tobelownum
)
146 totalLength
-= (*it
)->duration
.Get();
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())
159 stime_t stime
, sduration
;
161 const SegmentTimeline
* timeline
= inheritSegmentTimeline();
164 timescale
= timeline
->inheritTimescale();
165 if(!timeline
->getScaledPlaybackTimeDurationBySegmentNumber(number
, &stime
, &sduration
))
170 *time
= *dur
= VLC_TICK_INVALID
;
171 timescale
= inheritTimescale();
176 const ISegment
*first
= segments
.front();
177 if(first
->getSequenceNumber() > number
)
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();
191 sduration
= duration
.Get();
193 /* Assuming there won't be any discontinuity in sequence */
194 if(seg
->getSequenceNumber() == number
)
207 *time
= VLC_TICK_0
+ timescale
.ToTime(stime
);
208 *dur
= VLC_TICK_0
+ timescale
.ToTime(sduration
);
212 stime_t
SegmentList::getTotalLength() const
214 const SegmentTimeline
*timeline
= inheritSegmentTimeline();
216 return timeline
->getTotalLength();
220 vlc_tick_t
SegmentList::getMinAheadTime(uint64_t curnum
) const
222 const SegmentTimeline
*timeline
= inheritSegmentTimeline();
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());
241 Segment
* SegmentList::getNextMediaSegment(uint64_t i_pos
,uint64_t *pi_newpos
,
247 const SegmentTimeline
*timeline
= inheritSegmentTimeline();
250 uint64_t listindex
= timeline
->getElementIndexBySequence(i_pos
);
251 if(listindex
>= segments
.size())
253 return segments
.at(listindex
);
256 std::vector
<Segment
*>::const_iterator it
;
257 for(it
= segments
.begin(); it
!= segments
.end(); ++it
)
260 if(seg
->getSequenceNumber() >= i_pos
)
262 *pi_newpos
= seg
->getSequenceNumber();
263 *pb_gap
= (*pi_newpos
!= i_pos
);
270 uint64_t SegmentList::getStartSegmentNumber() const
272 const SegmentTimeline
*timeline
= inheritSegmentTimeline();
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();
283 const Timescale timescale
= timeline
->getTimescale().isValid()
284 ? timeline
->getTimescale()
285 : inheritTimescale();
286 stime_t st
= timescale
.ToScaled(time
);
287 *ret
= timeline
->getElementNumberByScaledPlaybackTime(st
);
291 const Timescale timescale
= inheritTimescale();
292 if(!timescale
.isValid())
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
);
306 segmentTimeline
->debug(obj
, indent
+ 1);