1 /*****************************************************************************
2 * dash.cpp: DASH module
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 /*****************************************************************************
27 *****************************************************************************/
28 #define __STDC_CONSTANT_MACROS 1
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_demux.h>
44 #include "xml/DOMParser.h"
45 #include "mpd/MPDFactory.h"
47 /*****************************************************************************
49 *****************************************************************************/
50 static int Open (vlc_object_t *);
51 static void Close (vlc_object_t *);
53 #define DASH_WIDTH_TEXT N_("Preferred Width")
54 #define DASH_WIDTH_LONGTEXT N_("Preferred Width")
56 #define DASH_HEIGHT_TEXT N_("Preferred Height")
57 #define DASH_HEIGHT_LONGTEXT N_("Preferred Height")
59 #define DASH_BW_TEXT N_("Fixed Bandwidth in KiB/s")
60 #define DASH_BW_LONGTEXT N_("Preferred bandwidth for non adaptative streams")
62 #define DASH_LOGIC_TEXT N_("Adaptation Logic")
64 static const int pi_logics[] = {dash::logic::AbstractAdaptationLogic::RateBased,
65 dash::logic::AbstractAdaptationLogic::FixedRate,
66 dash::logic::AbstractAdaptationLogic::AlwaysLowest,
67 dash::logic::AbstractAdaptationLogic::AlwaysBest};
69 static const char *const ppsz_logics[] = { N_("Bandwidth Adaptive"),
70 N_("Fixed Bandwidth"),
71 N_("Lowest Bandwidth/Quality"),
72 N_("Highest Bandwith/Quality")};
75 set_shortname( N_("DASH"))
76 set_description( N_("Dynamic Adaptive Streaming over HTTP") )
77 set_capability( "demux", 10 )
78 set_category( CAT_INPUT )
79 set_subcategory( SUBCAT_INPUT_DEMUX )
80 add_integer( "dash-logic", dash::logic::AbstractAdaptationLogic::Default,
81 DASH_LOGIC_TEXT, NULL, false )
82 change_integer_list( pi_logics, ppsz_logics )
83 add_integer( "dash-prefwidth", 480, DASH_WIDTH_TEXT, DASH_WIDTH_LONGTEXT, true )
84 add_integer( "dash-prefheight", 360, DASH_HEIGHT_TEXT, DASH_HEIGHT_LONGTEXT, true )
85 add_integer( "dash-prefbw", 250, DASH_BW_TEXT, DASH_BW_LONGTEXT, false )
86 set_callbacks( Open, Close )
89 /*****************************************************************************
91 *****************************************************************************/
93 static int Demux( demux_t * );
94 static int Control (demux_t *p_demux, int i_query, va_list args);
96 /*****************************************************************************
98 *****************************************************************************/
99 static int Open(vlc_object_t *p_obj)
101 demux_t *p_demux = (demux_t*) p_obj;
103 bool b_mimematched = false;
104 char *psz_mime = stream_ContentType(p_demux->s);
107 b_mimematched = !strcmp(psz_mime, "application/dash+xml");
111 if(!b_mimematched && !dash::xml::DOMParser::isDash(p_demux->s))
115 dash::xml::DOMParser parser(p_demux->s);
116 if( !parser.parse() )
118 msg_Err( p_demux, "Could not parse MPD" );
122 //Begin the actual MPD parsing:
123 dash::mpd::MPD *mpd = dash::mpd::MPDFactory::create(parser.getRootNode(), p_demux->s, parser.getProfile());
126 msg_Err( p_demux, "Cannot create/unknown MPD for profile");
130 demux_sys_t *p_sys = (demux_sys_t *) malloc(sizeof(demux_sys_t));
131 if (unlikely(p_sys == NULL))
135 int logic = var_InheritInteger( p_obj, "dash-logic" );
136 dash::DASHManager*p_dashManager = new dash::DASHManager(p_sys->p_mpd,
137 static_cast<dash::logic::AbstractAdaptationLogic::LogicType>(logic),
140 dash::mpd::Period *period = mpd->getFirstPeriod();
141 if(period && !p_dashManager->start(p_demux))
143 delete p_dashManager;
147 p_sys->p_dashManager = p_dashManager;
148 p_demux->p_sys = p_sys;
149 p_demux->pf_demux = Demux;
150 p_demux->pf_control = Control;
152 msg_Dbg(p_obj,"opening mpd file (%s)", p_demux->s->psz_path);
156 /*****************************************************************************
158 *****************************************************************************/
159 static void Close(vlc_object_t *p_obj)
161 demux_t *p_demux = (demux_t*) p_obj;
162 demux_sys_t *p_sys = (demux_sys_t *) p_demux->p_sys;
163 dash::DASHManager *p_dashManager = p_sys->p_dashManager;
165 delete p_dashManager;
168 /*****************************************************************************
170 *****************************************************************************/
171 static int Demux(demux_t *p_demux)
173 demux_sys_t *p_sys = p_demux->p_sys;
174 if ( p_sys->p_dashManager->read() > 0 )
176 if ( p_sys->p_dashManager->esCount() )
178 mtime_t pcr = p_sys->p_dashManager->getPCR();
179 int group = p_sys->p_dashManager->getGroup();
181 es_out_Control(p_demux->out, ES_OUT_SET_GROUP_PCR, group, pcr);
183 es_out_Control(p_demux->out, ES_OUT_SET_PCR, pcr);
185 return VLC_DEMUXER_SUCCESS;
188 return VLC_DEMUXER_EOF;
191 static int Control (demux_t *p_demux, int i_query, va_list args)
193 demux_sys_t *p_sys = p_demux->p_sys;
198 *(va_arg (args, bool *)) = false;
201 case DEMUX_CAN_CONTROL_PACE:
202 *(va_arg (args, bool *)) = true;
205 case DEMUX_CAN_PAUSE:
206 *(va_arg (args, bool *)) = p_sys->p_mpd->isLive();
210 *(va_arg (args, int64_t *)) = p_sys->p_dashManager->getPCR();
213 case DEMUX_GET_LENGTH:
214 *(va_arg (args, int64_t *)) = p_sys->p_dashManager->getDuration();
217 case DEMUX_GET_POSITION:
218 if(!p_sys->p_dashManager->getDuration())
221 *(va_arg (args, double *)) = (double) p_sys->p_dashManager->getPCR()
222 / p_sys->p_dashManager->getDuration();
225 case DEMUX_GET_PTS_DELAY:
226 *va_arg (args, int64_t *) = INT64_C(1000) *
227 var_InheritInteger(p_demux, "network-caching");
232 if(!p_sys->p_mpd->getProgramInformation())
235 vlc_meta_t *p_meta = (vlc_meta_t *) va_arg (args, vlc_meta_t*);
236 vlc_meta_t *meta = vlc_meta_New();
240 if(!p_sys->p_mpd->getProgramInformation()->getTitle().empty())
241 vlc_meta_SetTitle(meta, p_sys->p_mpd->getProgramInformation()->getTitle().c_str());
243 if(!p_sys->p_mpd->getProgramInformation()->getSource().empty())
244 vlc_meta_SetPublisher(meta, p_sys->p_mpd->getProgramInformation()->getSource().c_str());
246 if(!p_sys->p_mpd->getProgramInformation()->getCopyright().empty())
247 vlc_meta_SetCopyright(meta, p_sys->p_mpd->getProgramInformation()->getCopyright().c_str());
249 if(!p_sys->p_mpd->getProgramInformation()->getMoreInformationUrl().empty())
250 vlc_meta_SetURL(meta, p_sys->p_mpd->getProgramInformation()->getMoreInformationUrl().c_str());
252 vlc_meta_Merge(p_meta, meta);
253 vlc_meta_Delete(meta);