1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright © 2010 - 2011 Klagenfurt University
6 * Created on: Aug 10, 2010
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 *****************************************************************************/
25 /* config.h may include inttypes.h, so make sure we define that option
27 #define __STDC_FORMAT_MACROS 1
28 #define __STDC_CONSTANT_MACROS 1
29 #define __STDC_LIMIT_MACROS 1
37 #include "DASHManager.h"
38 #include "mpd/MPDFactory.h"
39 #include "mpd/SegmentTimeline.h"
40 #include "xml/DOMParser.h"
41 #include "adaptationlogic/AdaptationLogicFactory.h"
42 #include "SegmentTracker.hpp"
43 #include <vlc_stream.h>
46 using namespace dash::http;
47 using namespace dash::logic;
48 using namespace dash::mpd;
50 DASHManager::DASHManager ( MPD *mpd,
51 AbstractAdaptationLogic::LogicType type, stream_t *stream) :
58 for(int i=0; i<Streams::count; i++)
62 DASHManager::~DASHManager ()
65 for(int i=0; i<Streams::count; i++)
69 bool DASHManager::start(demux_t *demux)
71 const Period *period = mpd->getFirstPeriod();
75 for(int i=0; i<Streams::count; i++)
77 Streams::Type type = static_cast<Streams::Type>(i);
78 const AdaptationSet *set = period->getAdaptationSet(type);
81 streams[type] = new (std::nothrow) Streams::Stream(set->getMimeType());
84 AbstractAdaptationLogic *logic = AdaptationLogicFactory::create(logicType, mpd);
92 SegmentTracker *tracker = new (std::nothrow) SegmentTracker(logic, mpd);
97 streams[type]->create(demux, logic, tracker);
102 streams[type] = NULL;
107 conManager = new (std::nothrow) HTTPConnectionManager(stream);
111 mpd->playbackStart.Set(time(NULL));
112 nextMPDupdate = mpd->playbackStart.Get();
117 size_t DASHManager::read()
120 for(int type=0; type<Streams::count; type++)
124 i_ret += streams[type]->read(conManager);
129 mtime_t DASHManager::getPCR() const
131 mtime_t pcr = VLC_TS_INVALID;
132 for(int type=0; type<Streams::count; type++)
136 if(pcr == VLC_TS_INVALID || pcr > streams[type]->getPCR())
137 pcr = streams[type]->getPCR();
142 int DASHManager::getGroup() const
144 for(int type=0; type<Streams::count; type++)
148 return streams[type]->getGroup();
153 int DASHManager::esCount() const
156 for(int type=0; type<Streams::count; type++)
160 es += streams[type]->esCount();
165 mtime_t DASHManager::getDuration() const
170 return CLOCK_FREQ * mpd->duration.Get();
173 bool DASHManager::setPosition(mtime_t time)
176 for(int real = 0; real < 2; real++)
178 /* Always probe if we can seek first */
179 for(int type=0; type<Streams::count; type++)
183 ret &= streams[type]->setPosition(time, !real);
191 bool DASHManager::seekAble() const
196 for(int type=0; type<Streams::count; type++)
200 if(!streams[type]->seekAble())
206 bool DASHManager::updateMPD()
208 if(!mpd->isLive() || !mpd->minUpdatePeriod.Get())
211 mtime_t now = time(NULL);
212 if(nextMPDupdate && now < nextMPDupdate)
218 std::string url(stream->psz_access);
220 url.append(stream->psz_path);
222 stream_t *mpdstream = stream_UrlNew(stream, url.c_str());
226 xml::DOMParser parser(mpdstream);
229 stream_Delete(mpdstream);
233 mtime_t minsegmentTime = 0;
234 for(int type=0; type<Streams::count; type++)
238 mtime_t segmentTime = streams[type]->getPosition();
239 if(!minsegmentTime || segmentTime < minsegmentTime)
240 minsegmentTime = segmentTime;
243 MPD *newmpd = MPDFactory::create(parser.getRootNode(), mpdstream, parser.getProfile());
246 mpd->mergeWith(newmpd, minsegmentTime);
249 stream_Delete(mpdstream);
252 /* Compute new MPD update time */
253 mtime_t mininterval = 0;
254 mtime_t maxinterval = 0;
255 mpd->getTimeLinesBoundaries(&mininterval, &maxinterval);
256 if(maxinterval > mininterval)
257 maxinterval = (maxinterval - mininterval) / CLOCK_FREQ;
260 maxinterval = std::max(maxinterval, (mtime_t)60);
262 mininterval = std::max(mpd->minUpdatePeriod.Get(),
263 mpd->maxSegmentDuration.Get());
265 nextMPDupdate = now + (maxinterval - mininterval) / 2;
267 msg_Dbg(stream, "Updated MPD, next update in %"PRId64"s (%"PRId64"..%"PRId64")",
268 nextMPDupdate - now, mininterval, maxinterval );