]> git.sesse.net Git - vlc/blob - modules/stream_filter/dash/dash.cpp
dash: bandwidth is in bits per second
[vlc] / modules / stream_filter / dash / dash.cpp
1 /*****************************************************************************
2  * dash.cpp: DASH module
3  *****************************************************************************
4  * Copyright © 2010 - 2011 Klagenfurt University
5  *
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>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it 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.
14  *
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.
19  *
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
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34
35 #include <errno.h>
36
37 #include "DASHManager.h"
38 #include "xml/DOMParser.h"
39 #include "http/HTTPConnectionManager.h"
40 #include "adaptationlogic/IAdaptationLogic.h"
41 #include "mpd/MPDFactory.h"
42
43 #define SEEK 0
44
45 /*****************************************************************************
46  * Module descriptor
47  *****************************************************************************/
48 static int  Open    (vlc_object_t *);
49 static void Close   (vlc_object_t *);
50
51 vlc_module_begin ()
52         set_shortname( N_("DASH"))
53         set_description( N_("Dynamic Adaptive Streaming over HTTP") )
54         set_capability( "stream_filter", 19 )
55         set_category( CAT_INPUT )
56         set_subcategory( SUBCAT_INPUT_STREAM_FILTER )
57         set_callbacks( Open, Close )
58 vlc_module_end ()
59
60 /*****************************************************************************
61  * Local prototypes
62  *****************************************************************************/
63 struct stream_sys_t
64 {
65         dash::DASHManager                   *p_dashManager;
66         dash::http::HTTPConnectionManager   *p_conManager;
67         dash::mpd::MPD                      *p_mpd;
68         int                                 position;
69         bool                                isLive;
70 };
71
72 static int  Read            (stream_t *p_stream, void *p_buffer, unsigned int i_len);
73 static int  Peek            (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek);
74 static int  Control         (stream_t *p_stream, int i_query, va_list args);
75
76 /*****************************************************************************
77  * Open:
78  *****************************************************************************/
79 static int Open(vlc_object_t *p_obj)
80 {
81     stream_t *p_stream = (stream_t*) p_obj;
82
83     if(!dash::xml::DOMParser::isDash(p_stream->p_source))
84         return VLC_EGENERIC;
85
86     //Build a XML tree
87     dash::xml::DOMParser        parser(p_stream->p_source);
88     if( !parser.parse() )
89     {
90         msg_Dbg( p_stream, "Could not parse mpd file." );
91         return VLC_EGENERIC;
92     }
93
94     //Begin the actual MPD parsing:
95     dash::mpd::MPD *mpd = dash::mpd::MPDFactory::create(parser.getRootNode(), p_stream->p_source, parser.getProfile());
96
97     if(mpd == NULL)
98         return VLC_EGENERIC;
99
100     stream_sys_t        *p_sys = (stream_sys_t *) malloc(sizeof(stream_sys_t));
101     if (unlikely(p_sys == NULL))
102         return VLC_ENOMEM;
103
104     p_sys->p_mpd = mpd;
105     dash::http::HTTPConnectionManager *p_conManager =
106                               new dash::http::HTTPConnectionManager( p_stream );
107     dash::DASHManager*p_dashManager =
108             new dash::DASHManager( p_conManager, p_sys->p_mpd,
109                                    dash::logic::IAdaptationLogic::RateBased );
110
111     if ( p_dashManager->getMpdManager() == NULL ||
112          p_dashManager->getMpdManager()->getMPD() == NULL ||
113          p_dashManager->getAdaptionLogic() == NULL )
114     {
115         delete p_conManager;
116         delete p_dashManager;
117         free( p_sys );
118         return VLC_EGENERIC;
119     }
120     p_sys->p_dashManager    = p_dashManager;
121     p_sys->p_conManager     = p_conManager;
122     p_sys->position         = 0;
123     p_sys->isLive           = p_dashManager->getMpdManager()->getMPD()->isLive();
124     p_stream->p_sys         = p_sys;
125     p_stream->pf_read       = Read;
126     p_stream->pf_peek       = Peek;
127     p_stream->pf_control    = Control;
128
129     msg_Dbg(p_obj,"opening mpd file (%s)", p_stream->psz_path);
130
131     return VLC_SUCCESS;
132 }
133 /*****************************************************************************
134  * Close:
135  *****************************************************************************/
136 static void Close(vlc_object_t *p_obj)
137 {
138     stream_t                            *p_stream       = (stream_t*) p_obj;
139     stream_sys_t                        *p_sys          = (stream_sys_t *) p_stream->p_sys;
140     dash::DASHManager                   *p_dashManager  = p_sys->p_dashManager;
141     dash::http::HTTPConnectionManager   *p_conManager   = p_sys->p_conManager;
142
143     delete(p_conManager);
144     delete(p_dashManager);
145     free(p_sys);
146 }
147 /*****************************************************************************
148  * Callbacks:
149  *****************************************************************************/
150 static int  Read            (stream_t *p_stream, void *p_buffer, unsigned int i_len)
151 {
152     stream_sys_t        *p_sys          = (stream_sys_t *) p_stream->p_sys;
153     dash::DASHManager   *p_dashManager  = p_sys->p_dashManager;
154     int                 i_ret           = 0;
155
156     i_ret = p_dashManager->read(p_buffer, i_len );
157
158     if (i_ret < 0)
159     {
160         switch (errno)
161         {
162             case EINTR:
163             case EAGAIN:
164                 break;
165             default:
166                 msg_Dbg(p_stream, "DASH Read: failed to read (%m)");
167                 return 0;
168         }
169         return 0;
170     }
171
172     p_sys->position += i_ret;
173
174     return i_ret;
175 }
176
177 static int  Peek            (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek)
178 {
179     stream_sys_t        *p_sys          = (stream_sys_t *) p_stream->p_sys;
180     dash::DASHManager   *p_dashManager  = p_sys->p_dashManager;
181
182     return p_dashManager->peek( pp_peek, i_peek );
183 }
184
185 static int  Control         (stream_t *p_stream, int i_query, va_list args)
186 {
187     stream_sys_t *p_sys = p_stream->p_sys;
188
189     switch (i_query)
190     {
191         case STREAM_CAN_SEEK:
192         case STREAM_CAN_FASTSEEK:
193             /*TODO Support Seek */
194             *(va_arg (args, bool *)) = SEEK;
195             break;
196         case STREAM_GET_POSITION:
197             *(va_arg (args, uint64_t *)) = p_sys->position;
198             break;
199         case STREAM_SET_POSITION:
200             return VLC_EGENERIC;
201         case STREAM_GET_SIZE:
202         {
203             uint64_t*   res = (va_arg (args, uint64_t *));
204             if(p_sys->isLive)
205                 *res = 0;
206             else
207             {
208                 const dash::mpd::Representation *rep = p_sys->p_dashManager->getAdaptionLogic()->getCurrentRepresentation();
209                 if ( rep == NULL )
210                     *res = 0;
211                 else
212                     *res = p_sys->p_mpd->getDuration() * rep->getBandwidth() / 8;
213             }
214             break;
215         }
216         default:
217             return VLC_EGENERIC;
218     }
219     return VLC_SUCCESS;
220 }