]> git.sesse.net Git - vlc/blob - src/input/demux.c
* src/input/demux.c, src/misc/objects.c: demux2 has the VLC_OBJECT_DEMUX type.
[vlc] / src / input / demux.c
1 /*****************************************************************************
2  * demux.c
3  *****************************************************************************
4  * Copyright (C) 1999-2004 VideoLAN
5  * $Id$
6  *
7  * Author: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25 #include <vlc/vlc.h>
26 #include <vlc/input.h>
27
28 #include "ninput.h"
29
30 int demux_vaControl( input_thread_t *p_input, int i_query, va_list args )
31 {
32     if( p_input->pf_demux_control )
33     {
34         return p_input->pf_demux_control( p_input, i_query, args );
35     }
36     return VLC_EGENERIC;
37 }
38
39 int demux_Control( input_thread_t *p_input, int i_query, ...  )
40 {
41     va_list args;
42     int     i_result;
43
44     va_start( args, i_query );
45     i_result = demux_vaControl( p_input, i_query, args );
46     va_end( args );
47
48     return i_result;
49 }
50
51 static void SeekOffset( input_thread_t *p_input, int64_t i_pos );
52
53 int demux_vaControlDefault( input_thread_t *p_input, int i_query,
54                             va_list args )
55 {
56     int     i_ret;
57     double  f, *pf;
58     int64_t i64, *pi64;
59
60     vlc_mutex_lock( &p_input->stream.stream_lock );
61     switch( i_query )
62     {
63         case DEMUX_GET_POSITION:
64             pf = (double*)va_arg( args, double * );
65             if( p_input->stream.p_selected_area->i_size <= 0 )
66             {
67                 *pf = 0.0;
68             }
69             else
70             {
71                 *pf = (double)p_input->stream.p_selected_area->i_tell /
72                       (double)p_input->stream.p_selected_area->i_size;
73             }
74             i_ret = VLC_SUCCESS;
75             break;
76
77         case DEMUX_SET_POSITION:
78             f = (double)va_arg( args, double );
79             if( p_input->stream.b_seekable && p_input->pf_seek != NULL &&
80                 f >= 0.0 && f <= 1.0 )
81             {
82                 SeekOffset( p_input, (int64_t)(f *
83                             (double)p_input->stream.p_selected_area->i_size) );
84                 i_ret = VLC_SUCCESS;
85             }
86             else
87             {
88                 i_ret = VLC_EGENERIC;
89             }
90             break;
91
92         case DEMUX_GET_TIME:
93             pi64 = (int64_t*)va_arg( args, int64_t * );
94             if( p_input->stream.i_mux_rate > 0 )
95             {
96                 *pi64 = (int64_t)1000000 *
97                         ( p_input->stream.p_selected_area->i_tell / 50 ) /
98                         p_input->stream.i_mux_rate;
99                 i_ret = VLC_SUCCESS;
100             }
101             else
102             {
103                 *pi64 = 0;
104                 i_ret = VLC_EGENERIC;
105             }
106             break;
107
108         case DEMUX_SET_TIME:
109             i64 = (int64_t)va_arg( args, int64_t );
110             if( p_input->stream.i_mux_rate > 0 &&
111                 p_input->stream.b_seekable &&
112                 p_input->pf_seek != NULL && i64 >= 0 )
113             {
114                 SeekOffset( p_input, i64 * 50 *
115                                      (int64_t)p_input->stream.i_mux_rate /
116                                      (int64_t)1000000 );
117                 i_ret = VLC_SUCCESS;
118             }
119             else
120             {
121                 i_ret = VLC_EGENERIC;
122             }
123             break;
124
125         case DEMUX_GET_LENGTH:
126             pi64 = (int64_t*)va_arg( args, int64_t * );
127             if( p_input->stream.i_mux_rate > 0 )
128             {
129                 *pi64 = (int64_t)1000000 *
130                         ( p_input->stream.p_selected_area->i_size / 50 ) /
131                         p_input->stream.i_mux_rate;
132                 i_ret = VLC_SUCCESS;
133             }
134             else
135             {
136                 *pi64 = 0;
137                 i_ret = VLC_EGENERIC;
138             }
139             break;
140         case DEMUX_GET_FPS:
141             i_ret = VLC_EGENERIC;
142             break;
143         case DEMUX_GET_META:
144             i_ret = VLC_EGENERIC;
145             break;
146
147         default:
148             msg_Err( p_input, "unknown query in demux_vaControlDefault" );
149             i_ret = VLC_EGENERIC;
150             break;
151     }
152     vlc_mutex_unlock( &p_input->stream.stream_lock );
153
154     return i_ret;
155 }
156
157 static void SeekOffset( input_thread_t *p_input, int64_t i_pos )
158 {
159     /* Reinitialize buffer manager. */
160     input_AccessReinit( p_input );
161
162     vlc_mutex_unlock( &p_input->stream.stream_lock );
163     p_input->pf_seek( p_input, i_pos );
164     vlc_mutex_lock( &p_input->stream.stream_lock );
165 }
166
167
168 /*****************************************************************************
169  * demux2_New:
170  *****************************************************************************/
171 demux_t *__demux2_New( vlc_object_t *p_obj,
172                        char *psz_mrl, stream_t *s, es_out_t *out )
173 {
174     demux_t *p_demux = vlc_object_create( p_obj, VLC_OBJECT_DEMUX );
175
176     char    *psz_dup = strdup( psz_mrl ? psz_mrl : "" );
177     char    *psz = strchr( psz_dup, ':' );
178     char    *psz_module;
179
180     if( p_demux == NULL )
181     {
182         free( psz_dup );
183         return NULL;
184     }
185
186     /* Parse URL */
187     p_demux->psz_access = NULL;
188     p_demux->psz_demux  = NULL;
189     p_demux->psz_path   = NULL;
190
191     if( psz )
192     {
193         *psz++ = '\0';
194
195         if( psz[0] == '/' && psz[1] == '/' )
196         {
197             psz += 2;
198         }
199         p_demux->psz_path = strdup( psz );
200
201         psz = strchr( psz_dup, '/' );
202         if( psz )
203         {
204             *psz++ = '\0';
205             p_demux->psz_access = strdup( psz_dup );
206             p_demux->psz_demux  = strdup( psz );
207         }
208     }
209     else
210     {
211         p_demux->psz_path = strdup( psz_mrl );
212     }
213     free( psz_dup );
214
215
216     if( p_demux->psz_access == NULL )
217     {
218         p_demux->psz_access = strdup( "" );
219     }
220     if( p_demux->psz_demux == NULL )
221     {
222         p_demux->psz_demux = strdup( "" );
223     }
224     if( p_demux->psz_path == NULL )
225     {
226         p_demux->psz_path = strdup( "" );
227     }
228     msg_Dbg( p_obj, "demux2_New: '%s' -> access='%s' demux='%s' path='%s'",
229              psz_mrl,
230              p_demux->psz_access, p_demux->psz_demux, p_demux->psz_path );
231
232     p_demux->s          = s;
233     p_demux->out        = out;
234
235     p_demux->pf_demux   = NULL;
236     p_demux->pf_control = NULL;
237     p_demux->p_sys      = NULL;
238
239     psz_module = p_demux->psz_demux;
240     if( *psz_module == '\0' && strrchr( p_demux->psz_path, '.' ) )
241     {
242         /* XXX: add only file without any problem here and with strong detection.
243          *  - no .mp3, .a52, ... (aac is added as it works only by file ext anyway
244          *  - wav can't be added 'cause of a52 and dts in them as raw audio
245          */
246         static struct { char *ext; char *demux; } exttodemux[] =
247         {
248             { "aac",  "aac" },
249             { "aiff", "aiff" },
250             { "asf",  "asf" }, { "wmv",  "asf" }, { "wma",  "asf" },
251             { "avi",  "avi" },
252             { "au",   "au" },
253             { "flac", "flac" },
254             { "dv",   "dv" },
255             { "m3u",  "m3u" },
256             { "mkv",  "mkv" }, { "mka",  "mkv" }, { "mks",  "mkv" },
257             { "mp4",  "mp4" }, { "m4a",  "mp4" }, { "mov",  "mp4" }, { "moov", "mp4" },
258             { "mod",  "mod" }, { "xm",   "mod" },
259             { "nsv",  "nsv" },
260             { "ogg",  "ogg" }, { "ogm",  "ogg" },
261             { "pva",  "pva" },
262             { "rm",   "rm" },
263             { "",  "" },
264         };
265
266         char *psz_ext = strrchr( p_demux->psz_path, '.' ) + 1;
267         int  i;
268
269         for( i = 0; exttodemux[i].ext != NULL; i++ )
270         {
271             if( !strcasecmp( psz_ext, exttodemux[i].ext ) )
272             {
273                 psz_module = exttodemux[i].demux;
274                 break;
275             }
276         }
277     }
278
279     /* Before module_Need (for var_Create...) */
280     vlc_object_attach( p_demux, p_obj );
281
282     p_demux->p_module =
283         module_Need( p_demux, "demux2", psz_module,
284                      !strcmp( psz_module, p_demux->psz_demux ) ? VLC_TRUE : VLC_FALSE );
285
286     if( p_demux->p_module == NULL )
287     {
288         vlc_object_detach( p_demux );
289         free( p_demux->psz_path );
290         free( p_demux->psz_demux );
291         free( p_demux->psz_access );
292         vlc_object_destroy( p_demux );
293         return NULL;
294     }
295
296     return p_demux;
297 }
298
299 /*****************************************************************************
300  * demux2_Delete:
301  *****************************************************************************/
302 void demux2_Delete( demux_t *p_demux )
303 {
304     module_Unneed( p_demux, p_demux->p_module );
305     vlc_object_detach( p_demux );
306
307     free( p_demux->psz_path );
308     free( p_demux->psz_demux );
309     free( p_demux->psz_access );
310
311     vlc_object_destroy( p_demux );
312 }
313
314 /*****************************************************************************
315  * demux2_vaControlHelper:
316  *****************************************************************************/
317 int demux2_vaControlHelper( stream_t *s,
318                             int64_t i_start, int64_t i_end,
319                             int i_bitrate, int i_align,
320                             int i_query, va_list args )
321 {
322     int64_t i_tell;
323     double  f, *pf;
324     int64_t i64, *pi64;
325
326     if( i_end < 0 )    i_end   = stream_Size( s );
327     if( i_start < 0 )  i_start = 0;
328     if( i_align <= 0 ) i_align = 1;
329     i_tell = stream_Tell( s );
330
331     switch( i_query )
332     {
333         case DEMUX_GET_LENGTH:
334             pi64 = (int64_t*)va_arg( args, int64_t * );
335             if( i_bitrate > 0 && i_end > i_start )
336             {
337                 *pi64 = I64C(8000000) * (i_end - i_start) / i_bitrate;
338                 return VLC_SUCCESS;
339             }
340             return VLC_EGENERIC;
341
342         case DEMUX_GET_TIME:
343             pi64 = (int64_t*)va_arg( args, int64_t * );
344             if( i_bitrate > 0 && i_end > i_start )
345             {
346                 *pi64 = I64C(8000000) * (i_tell - i_start) / i_bitrate;
347                 return VLC_SUCCESS;
348             }
349             return VLC_EGENERIC;
350
351         case DEMUX_GET_POSITION:
352             pf = (double*)va_arg( args, double * );
353             if( i_start < i_end )
354             {
355                 *pf = (double)( i_tell - i_start ) /
356                       (double)( i_end  - i_start );
357                 return VLC_SUCCESS;
358             }
359             return VLC_EGENERIC;
360
361
362         case DEMUX_SET_POSITION:
363             f = (double)va_arg( args, double );
364             if( i_start < i_end && f >= 0.0 && f <= 1.0 )
365             {
366                 int64_t i_block = (f * ( i_end - i_start )) / i_align;
367
368                 if( stream_Seek( s, i_start + i_block * i_align ) )
369                 {
370                     return VLC_EGENERIC;
371                 }
372                 return VLC_SUCCESS;
373             }
374             return VLC_EGENERIC;
375
376         case DEMUX_SET_TIME:
377             i64 = (int64_t)va_arg( args, int64_t );
378             if( i_bitrate > 0 && i64 >= 0 )
379             {
380                 int64_t i_block = i64 * i_bitrate / I64C(8000000) / i_align;
381                 if( stream_Seek( s, i_start + i_block * i_align ) )
382                 {
383                     return VLC_EGENERIC;
384                 }
385                 return VLC_SUCCESS;
386             }
387             return VLC_EGENERIC;
388
389         case DEMUX_GET_FPS:
390         case DEMUX_GET_META:
391             return VLC_EGENERIC;
392
393         default:
394             msg_Err( s, "unknown query in demux_vaControlDefault" );
395             return VLC_EGENERIC;
396     }
397 }
398