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>
42 #include "xml/DOMParser.h"
43 #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_BUFFER_TEXT N_("Buffer Size (Seconds)")
60 #define DASH_BUFFER_LONGTEXT N_("Buffer size in seconds")
63 set_shortname( N_("DASH"))
64 set_description( N_("Dynamic Adaptive Streaming over HTTP") )
65 set_capability( "stream_filter", 19 )
66 set_category( CAT_INPUT )
67 set_subcategory( SUBCAT_INPUT_STREAM_FILTER )
68 add_integer( "dash-prefwidth", 480, DASH_WIDTH_TEXT, DASH_WIDTH_LONGTEXT, true )
69 add_integer( "dash-prefheight", 360, DASH_HEIGHT_TEXT, DASH_HEIGHT_LONGTEXT, true )
70 add_integer( "dash-buffersize", 30, DASH_BUFFER_TEXT, DASH_BUFFER_LONGTEXT, true )
71 set_callbacks( Open, Close )
74 /*****************************************************************************
76 *****************************************************************************/
78 static int Read (stream_t *p_stream, void *p_ptr, unsigned int i_len);
79 static int Peek (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek);
80 static int Control (stream_t *p_stream, int i_query, va_list args);
82 /*****************************************************************************
84 *****************************************************************************/
85 static int Open(vlc_object_t *p_obj)
87 stream_t *p_stream = (stream_t*) p_obj;
89 if(!dash::xml::DOMParser::isDash(p_stream->p_source))
93 dash::xml::DOMParser parser(p_stream->p_source);
96 msg_Dbg( p_stream, "Could not parse mpd file." );
100 //Begin the actual MPD parsing:
101 dash::mpd::MPD *mpd = dash::mpd::MPDFactory::create(parser.getRootNode(), p_stream->p_source, parser.getProfile());
106 stream_sys_t *p_sys = (stream_sys_t *) malloc(sizeof(stream_sys_t));
107 if (unlikely(p_sys == NULL))
110 p_sys->psz_useragent = var_InheritString(p_stream, "http-user-agent");
113 dash::DASHManager*p_dashManager = new dash::DASHManager(p_sys->p_mpd,
114 dash::logic::IAdaptationLogic::RateBased,
117 if(!p_dashManager->start())
119 delete p_dashManager;
121 free( p_sys->psz_useragent );
124 p_sys->p_dashManager = p_dashManager;
126 p_stream->p_sys = p_sys;
127 p_stream->pf_read = Read;
128 p_stream->pf_peek = Peek;
129 p_stream->pf_control = Control;
131 msg_Dbg(p_obj,"opening mpd file (%s)", p_stream->psz_path);
135 /*****************************************************************************
137 *****************************************************************************/
138 static void Close(vlc_object_t *p_obj)
140 stream_t *p_stream = (stream_t*) p_obj;
141 stream_sys_t *p_sys = (stream_sys_t *) p_stream->p_sys;
142 dash::DASHManager *p_dashManager = p_sys->p_dashManager;
144 delete(p_dashManager);
145 free(p_sys->psz_useragent);
148 /*****************************************************************************
150 *****************************************************************************/
151 static int Seek ( stream_t *p_stream, uint64_t pos )
153 stream_sys_t *p_sys = (stream_sys_t *) p_stream->p_sys;
154 dash::DASHManager *p_dashManager = p_sys->p_dashManager;
159 if( pos < p_sys->position )
161 if( p_sys->position - pos > UINT_MAX )
163 msg_Err( p_stream, "Cannot seek backward that far!" );
166 i_len = p_sys->position - pos;
167 i_ret = p_dashManager->seekBackwards( i_len );
168 if( i_ret == VLC_EGENERIC )
170 msg_Err( p_stream, "Cannot seek backward outside the current block :-/" );
178 if( pos - p_sys->position > UINT_MAX )
180 msg_Err( p_stream, "Cannot seek forward that far!" );
183 i_len = pos - p_sys->position;
184 i_read = Read( p_stream, (void *)NULL, i_len );
185 if( (unsigned)i_read == i_len )
191 static int Read (stream_t *p_stream, void *p_ptr, unsigned int i_len)
193 stream_sys_t *p_sys = (stream_sys_t *) p_stream->p_sys;
194 dash::DASHManager *p_dashManager = p_sys->p_dashManager;
195 uint8_t *p_buffer = (uint8_t*)p_ptr;
201 i_read = p_dashManager->read( p_buffer, i_len );
218 msg_Dbg(p_stream, "DASH Read: failed to read (%s)",
219 vlc_strerror_c(errno));
225 p_sys->position += i_ret;
230 static int Peek (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek)
232 stream_sys_t *p_sys = (stream_sys_t *) p_stream->p_sys;
233 dash::DASHManager *p_dashManager = p_sys->p_dashManager;
235 return p_dashManager->peek( pp_peek, i_peek );
238 static int Control (stream_t *p_stream, int i_query, va_list args)
240 stream_sys_t *p_sys = p_stream->p_sys;
244 case STREAM_CAN_SEEK:
245 case STREAM_CAN_FASTSEEK:
246 /*TODO Support Seek */
247 *(va_arg (args, bool *)) = SEEK;
249 case STREAM_CAN_CONTROL_PACE:
250 *(va_arg (args, bool *)) = true;
252 case STREAM_CAN_PAUSE:
253 *(va_arg (args, bool *)) = false; /* TODO */
256 case STREAM_GET_POSITION:
257 *(va_arg (args, uint64_t *)) = p_sys->position;
259 case STREAM_SET_POSITION:
261 uint64_t pos = (uint64_t)va_arg(args, uint64_t);
262 if(Seek(p_stream, pos) == VLC_SUCCESS)
264 p_sys->position = pos;
270 case STREAM_GET_SIZE:
272 uint64_t* res = (va_arg (args, uint64_t *));
273 *res = p_sys->p_dashManager->getDuration();
276 case STREAM_GET_PTS_DELAY:
277 *va_arg (args, int64_t *) = INT64_C(1000) *
278 var_InheritInteger(p_stream, "network-caching");