]> git.sesse.net Git - vlc/blob - modules/stream_filter/dash/dash.cpp
DASH: allocate hot-path parser on the stack and cosmetics
[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
42 #define SEEK 0
43
44 /*****************************************************************************
45  * Module descriptor
46  *****************************************************************************/
47 static int  Open    (vlc_object_t *);
48 static void Close   (vlc_object_t *);
49
50 vlc_module_begin ()
51         set_shortname( N_("DASH"))
52         set_description( N_("Dynamic Adaptive Streaming over HTTP") )
53         set_capability( "stream_filter", 19 )
54         set_category( CAT_INPUT )
55         set_subcategory( SUBCAT_INPUT_STREAM_FILTER )
56         set_callbacks( Open, Close )
57 vlc_module_end ()
58
59 /*****************************************************************************
60  * Local prototypes
61  *****************************************************************************/
62 struct stream_sys_t
63 {
64         dash::DASHManager                   *p_dashManager;
65         dash::http::HTTPConnectionManager   *p_conManager;
66         dash::xml::Node                     *p_node;
67         int                                 position;
68         bool                                isLive;
69 };
70
71 static int  Read            (stream_t *p_stream, void *p_buffer, unsigned int i_len);
72 static int  Peek            (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek);
73 static int  Control         (stream_t *p_stream, int i_query, va_list args);
74
75 /*****************************************************************************
76  * Open:
77  *****************************************************************************/
78 static int Open(vlc_object_t *p_this)
79 {
80     stream_t *p_stream = (stream_t*) p_this;
81
82     dash::xml::DOMParser parser(p_stream->p_source);
83     if(!parser.isDash())
84         return VLC_EGENERIC;
85     if(!parser.parse())
86     {
87         msg_Dbg(p_stream, "could not parse file");
88         return VLC_EGENERIC;
89     }
90
91     stream_sys_t *p_sys = (stream_sys_t *) malloc(sizeof(stream_sys_t));
92
93     if (unlikely(p_sys == NULL))
94         return VLC_ENOMEM;
95
96     dash::http::HTTPConnectionManager *p_conManager =
97         new dash::http::HTTPConnectionManager(p_stream);
98     dash::xml::Node *p_node = parser.getRootNode();
99     dash::DASHManager*p_dashManager =
100         new dash::DASHManager(p_conManager, p_node,
101                               dash::logic::IAdaptationLogic::RateBased,
102                               parser.getProfile(p_node));
103
104     p_sys->p_dashManager    = p_dashManager;
105     p_sys->p_node           = p_node;
106     p_sys->p_conManager     = p_conManager;
107     p_sys->position         = 0;
108     p_sys->isLive           = true;
109     p_stream->p_sys         = p_sys;
110     p_stream->pf_read       = Read;
111     p_stream->pf_peek       = Peek;
112     p_stream->pf_control    = Control;
113
114     msg_Dbg(p_this,"DASH filter: open (%s)", p_stream->psz_path);
115
116     return VLC_SUCCESS;
117 }
118 /*****************************************************************************
119  * Close:
120  *****************************************************************************/
121 static void Close(vlc_object_t *p_this)
122 {
123     stream_t                            *p_stream       = (stream_t*) p_this;
124     stream_sys_t                        *p_sys          = (stream_sys_t *) p_stream->p_sys;
125     dash::DASHManager                   *p_dashManager  = p_sys->p_dashManager;
126     dash::http::HTTPConnectionManager   *p_conManager   = p_sys->p_conManager;
127     dash::xml::Node                     *p_node         = p_sys->p_node;
128
129     delete(p_conManager);
130     delete(p_dashManager);
131     delete(p_node);
132     free(p_sys);
133 }
134 /*****************************************************************************
135  * Callbacks:
136  *****************************************************************************/
137 static int  Read            (stream_t *p_stream, void *p_buffer, unsigned int i_len)
138 {
139     stream_sys_t        *p_sys          = (stream_sys_t *) p_stream->p_sys;
140     dash::DASHManager   *p_dashManager  = p_sys->p_dashManager;
141     int                 i_ret           = 0;
142
143     i_ret = p_dashManager->read(p_buffer, i_len);
144
145     if (i_ret < 0)
146     {
147         switch (errno)
148         {
149             case EINTR:
150             case EAGAIN:
151                 break;
152             default:
153                 msg_Dbg(p_stream, "DASH Read: failed to read (%m)");
154                 return 0;
155         }
156         return 0;
157     }
158
159     p_sys->position += i_ret;
160
161     return i_ret;
162 }
163 static int  Peek            (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek)
164 {
165     stream_sys_t        *p_sys          = (stream_sys_t *) p_stream->p_sys;
166     dash::DASHManager   *p_dashManager  = p_sys->p_dashManager;
167
168     return p_dashManager->peek(pp_peek, i_peek);
169 }
170 static int  Control         (stream_t *p_stream, int i_query, va_list args)
171 {
172     stream_sys_t *p_sys = p_stream->p_sys;
173
174     switch (i_query)
175     {
176         case STREAM_CAN_SEEK:
177         case STREAM_CAN_FASTSEEK:
178             /*TODO Support Seek */
179             *(va_arg (args, bool *)) = SEEK;
180             break;
181         case STREAM_GET_POSITION:
182             *(va_arg (args, uint64_t *)) = p_sys->position;
183             break;
184         case STREAM_SET_POSITION:
185             return VLC_EGENERIC;
186         case STREAM_GET_SIZE:
187             if(p_sys->isLive)
188                 *(va_arg (args, uint64_t *)) = 0;
189             break;
190         default:
191             return VLC_EGENERIC;
192     }
193     return VLC_SUCCESS;
194 }