]> git.sesse.net Git - vlc/blob - modules/stream_filter/dash/dash.cpp
Added DASH stream filter
[vlc] / modules / stream_filter / dash / dash.cpp
1 /*****************************************************************************
2  * dash.cpp: DASH module
3  *****************************************************************************
4  * Copyright (C) 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 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 <limits.h>
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_demux.h>
37 #include <vlc_stream.h>
38 #include <vlc_modules.h>
39 #include <vlc_input.h>
40
41 #include <errno.h>
42 #include <string>
43 #include <map>
44 #include <fcntl.h>
45 #include <iostream>
46 #include <stdio.h>
47
48 #include "DASHManager.h"
49 #include "xml/DOMParser.h"
50 #include "http/HTTPConnectionManager.h"
51 #include "adaptationlogic/IAdaptationLogic.h"
52
53 #define SEEK 0
54
55 /*****************************************************************************
56  * Module descriptor
57  *****************************************************************************/
58 static int  Open    (vlc_object_t *);
59 static void Close   (vlc_object_t *);
60
61 vlc_module_begin ()
62         set_shortname( N_("DASH"))
63         set_description( N_("Dynamic Adaptive Streaming over HTTP") )
64         set_capability( "stream_filter", 19 )
65         set_category( CAT_INPUT )
66         set_subcategory( SUBCAT_INPUT_STREAM_FILTER )
67         set_callbacks( Open, Close )
68 vlc_module_end ()
69 /*****************************************************************************
70  * Local prototypes
71  *****************************************************************************/
72 struct stream_sys_t
73 {
74         dash::DASHManager                   *p_dashManager;
75         dash::http::HTTPConnectionManager   *p_conManager;
76         dash::xml::Node                     *p_node;
77         int                                 position;
78         bool                                isLive;
79 };
80
81 static int  Read            (stream_t *p_stream, void *p_buffer, unsigned int i_len);
82 static int  Peek            (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek);
83 static int  Control         (stream_t *p_stream, int i_query, va_list args);
84 static bool IsDash          (stream_t *p_stream, dash::xml::DOMParser *p_parser);
85 /*****************************************************************************
86  * Open:
87  *****************************************************************************/
88 static int Open(vlc_object_t *p_this)
89 {
90     stream_t *p_stream = (stream_t*) p_this;
91
92     dash::xml::DOMParser *p_parser = new dash::xml::DOMParser(p_stream->p_source);
93
94     if(!IsDash(p_stream, p_parser))
95     {
96         delete(p_parser);
97         return VLC_EGENERIC;
98     }
99
100     stream_sys_t *p_sys = (stream_sys_t *) malloc(sizeof(stream_sys_t));
101
102     if (unlikely(p_sys == NULL))
103         return VLC_ENOMEM;
104
105     dash::http::HTTPConnectionManager   *p_conManager   = new dash::http::HTTPConnectionManager(p_stream);
106     dash::xml::Node                     *p_node         = p_parser->getRootNode();
107     dash::DASHManager                   *p_dashManager  = new dash::DASHManager(p_conManager,
108                                                                                 p_node,
109                                                                                 dash::logic::IAdaptationLogic::RateBased,
110                                                                                 p_parser->getProfile(p_node));
111     delete(p_parser);
112
113     p_sys->p_dashManager    = p_dashManager;
114     p_sys->p_node           = p_node;
115     p_sys->p_conManager     = p_conManager;
116     p_sys->position         = 0;
117     p_sys->isLive           = true;
118     p_stream->p_sys         = p_sys;
119     p_stream->pf_read       = Read;
120     p_stream->pf_peek       = Peek;
121     p_stream->pf_control    = Control;
122
123     msg_Dbg(p_this,"DASH filter: open (%s)", p_stream->psz_path);
124
125     return VLC_SUCCESS;
126 }
127 /*****************************************************************************
128  * Close:
129  *****************************************************************************/
130 static void Close(vlc_object_t *p_this)
131 {
132     stream_t                            *p_stream       = (stream_t*) p_this;
133     stream_sys_t                        *p_sys          = (stream_sys_t *) p_stream->p_sys;
134     dash::DASHManager                   *p_dashManager  = p_sys->p_dashManager;
135     dash::http::HTTPConnectionManager   *p_conManager   = p_sys->p_conManager;
136     dash::xml::Node                     *p_node         = p_sys->p_node;
137
138     delete(p_conManager);
139     delete(p_dashManager);
140     delete(p_node);
141     free(p_sys);
142 }
143 /*****************************************************************************
144  * Callbacks:
145  *****************************************************************************/
146 static int  Read            (stream_t *p_stream, void *p_buffer, unsigned int i_len)
147 {
148     stream_sys_t        *p_sys          = (stream_sys_t *) p_stream->p_sys;
149     dash::DASHManager   *p_dashManager  = p_sys->p_dashManager;
150     int                 i_ret           = 0;
151
152     i_ret = p_dashManager->read(p_buffer, i_len);
153
154     if (i_ret < 0)
155     {
156         switch (errno)
157         {
158             case EINTR:
159             case EAGAIN:
160                 break;
161             default:
162                 msg_Dbg(p_stream, "DASH Read: failed to read (%m)");
163                 return 0;
164         }
165         return 0;
166     }
167
168     p_sys->position += i_ret;
169
170     return i_ret;
171 }
172 static int  Peek            (stream_t *p_stream, const uint8_t **pp_peek, unsigned int i_peek)
173 {
174     stream_sys_t        *p_sys          = (stream_sys_t *) p_stream->p_sys;
175     dash::DASHManager   *p_dashManager  = p_sys->p_dashManager;
176
177     return p_dashManager->peek(pp_peek, i_peek);
178 }
179 static int  Control         (stream_t *p_stream, int i_query, va_list args)
180 {
181     stream_sys_t *p_sys = p_stream->p_sys;
182
183     switch (i_query)
184     {
185         case STREAM_CAN_SEEK:
186         case STREAM_CAN_FASTSEEK:
187             /*TODO Support Seek */
188             *(va_arg (args, bool *)) = SEEK;
189             break;
190         case STREAM_GET_POSITION:
191             *(va_arg (args, uint64_t *)) = p_sys->position;
192             break;
193         case STREAM_SET_POSITION:
194             return VLC_EGENERIC;
195         case STREAM_GET_SIZE:
196             if(p_sys->isLive)
197                 *(va_arg (args, uint64_t *)) = 0;
198             break;
199         default:
200             return VLC_EGENERIC;
201     }
202     return VLC_SUCCESS;
203 }
204 /*****************************************************************************
205  * Helpers:
206  *****************************************************************************/
207 static bool IsDash          (stream_t *p_stream, dash::xml::DOMParser *p_parser)
208 {
209     if(!p_parser->isDash())
210     {
211         msg_Dbg(p_stream,"DASH filter: file is no mpd");
212         return false;
213     }
214
215     if(!p_parser->parse())
216     {
217         msg_Dbg(p_stream,"DASH filter: could not parse file");
218         return false;
219     }
220
221     return true;
222 }