]> git.sesse.net Git - vlc/blob - src/input/demux.c
* codec/theora.c: Removed the "multiple of 16" size restriction for the encoding.
[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 "input_internal.h"
29
30 /*****************************************************************************
31  * demux2_New:
32  *  if s is NULL then load a access_demux
33  *****************************************************************************/
34 demux_t *__demux2_New( vlc_object_t *p_obj,
35                        char *psz_access, char *psz_demux, char *psz_path,
36                        stream_t *s, es_out_t *out )
37 {
38     demux_t *p_demux = vlc_object_create( p_obj, VLC_OBJECT_DEMUX );
39     char *psz_module;
40
41     if( p_demux == NULL )
42     {
43         return NULL;
44     }
45
46     /* Parse URL */
47     p_demux->psz_access = strdup( psz_access );
48     p_demux->psz_demux  = strdup( psz_demux );
49     p_demux->psz_path   = strdup( psz_path );
50
51     /* Take into account "demux" to be able to do :demux=demuxdump */
52     if( *p_demux->psz_demux == '\0' )
53     {
54         free( p_demux->psz_demux );
55         p_demux->psz_demux = var_GetString( p_obj, "demux" );
56     }
57
58     msg_Dbg( p_obj, "demux2_New: access='%s' demux='%s' path='%s'",
59              p_demux->psz_access, p_demux->psz_demux, p_demux->psz_path );
60
61     p_demux->s          = s;
62     p_demux->out        = out;
63
64     p_demux->pf_demux   = NULL;
65     p_demux->pf_control = NULL;
66     p_demux->p_sys      = NULL;
67     p_demux->info.i_update = 0;
68     p_demux->info.i_title  = 0;
69     p_demux->info.i_seekpoint = 0;
70
71     if( s )
72         psz_module = p_demux->psz_demux;
73     else
74         psz_module = p_demux->psz_access;
75
76     if( s && *psz_module == '\0' && strrchr( p_demux->psz_path, '.' ) )
77     {
78         /* XXX: add only file without any problem here and with strong detection.
79          *  - no .mp3, .a52, ... (aac is added as it works only by file ext anyway
80          *  - wav can't be added 'cause of a52 and dts in them as raw audio
81          */
82         static struct { char *ext; char *demux; } exttodemux[] =
83         {
84             { "aac",  "aac" },
85             { "aiff", "aiff" },
86             { "asf",  "asf" }, { "wmv",  "asf" }, { "wma",  "asf" },
87             { "avi",  "avi" },
88             { "au",   "au" },
89             { "flac", "flac" },
90             { "dv",   "dv" },
91             { "m3u",  "m3u" },
92             { "mkv",  "mkv" }, { "mka",  "mkv" }, { "mks",  "mkv" },
93             { "mp4",  "mp4" }, { "m4a",  "mp4" }, { "mov",  "mp4" }, { "moov", "mp4" },
94             { "mod",  "mod" }, { "xm",   "mod" },
95             { "nsv",  "nsv" },
96             { "ogg",  "ogg" }, { "ogm",  "ogg" },
97             { "pva",  "pva" },
98             { "rm",   "rm" },
99             { "",  "" },
100         };
101
102         char *psz_ext = strrchr( p_demux->psz_path, '.' ) + 1;
103         int  i;
104
105         for( i = 0; exttodemux[i].ext != NULL; i++ )
106         {
107             if( !strcasecmp( psz_ext, exttodemux[i].ext ) )
108             {
109                 psz_module = exttodemux[i].demux;
110                 break;
111             }
112         }
113     }
114
115     /* Before module_Need (for var_Create...) */
116     vlc_object_attach( p_demux, p_obj );
117
118     if( s )
119     {
120         p_demux->p_module =
121             module_Need( p_demux, "demux2", psz_module,
122                          !strcmp( psz_module, p_demux->psz_demux ) ? VLC_TRUE : VLC_FALSE );
123     }
124     else
125     {
126         p_demux->p_module =
127             module_Need( p_demux, "access_demux", psz_module,
128                          !strcmp( psz_module, p_demux->psz_access ) ? VLC_TRUE : VLC_FALSE );
129     }
130
131     if( p_demux->p_module == NULL )
132     {
133         vlc_object_detach( p_demux );
134         free( p_demux->psz_path );
135         free( p_demux->psz_demux );
136         free( p_demux->psz_access );
137         vlc_object_destroy( p_demux );
138         return NULL;
139     }
140
141     return p_demux;
142 }
143
144 /*****************************************************************************
145  * demux2_Delete:
146  *****************************************************************************/
147 void demux2_Delete( demux_t *p_demux )
148 {
149     module_Unneed( p_demux, p_demux->p_module );
150     vlc_object_detach( p_demux );
151
152     free( p_demux->psz_path );
153     free( p_demux->psz_demux );
154     free( p_demux->psz_access );
155
156     vlc_object_destroy( p_demux );
157 }
158
159 /*****************************************************************************
160  * demux2_vaControlHelper:
161  *****************************************************************************/
162 int demux2_vaControlHelper( stream_t *s,
163                             int64_t i_start, int64_t i_end,
164                             int i_bitrate, int i_align,
165                             int i_query, va_list args )
166 {
167     int64_t i_tell;
168     double  f, *pf;
169     int64_t i64, *pi64;
170
171     if( i_end < 0 )    i_end   = stream_Size( s );
172     if( i_start < 0 )  i_start = 0;
173     if( i_align <= 0 ) i_align = 1;
174     i_tell = stream_Tell( s );
175
176     switch( i_query )
177     {
178         case DEMUX_GET_LENGTH:
179             pi64 = (int64_t*)va_arg( args, int64_t * );
180             if( i_bitrate > 0 && i_end > i_start )
181             {
182                 *pi64 = I64C(8000000) * (i_end - i_start) / i_bitrate;
183                 return VLC_SUCCESS;
184             }
185             return VLC_EGENERIC;
186
187         case DEMUX_GET_TIME:
188             pi64 = (int64_t*)va_arg( args, int64_t * );
189             if( i_bitrate > 0 && i_end > i_start )
190             {
191                 *pi64 = I64C(8000000) * (i_tell - i_start) / i_bitrate;
192                 return VLC_SUCCESS;
193             }
194             return VLC_EGENERIC;
195
196         case DEMUX_GET_POSITION:
197             pf = (double*)va_arg( args, double * );
198             if( i_start < i_end )
199             {
200                 *pf = (double)( i_tell - i_start ) /
201                       (double)( i_end  - i_start );
202                 return VLC_SUCCESS;
203             }
204             return VLC_EGENERIC;
205
206
207         case DEMUX_SET_POSITION:
208             f = (double)va_arg( args, double );
209             if( i_start < i_end && f >= 0.0 && f <= 1.0 )
210             {
211                 int64_t i_block = (f * ( i_end - i_start )) / i_align;
212
213                 if( stream_Seek( s, i_start + i_block * i_align ) )
214                 {
215                     return VLC_EGENERIC;
216                 }
217                 return VLC_SUCCESS;
218             }
219             return VLC_EGENERIC;
220
221         case DEMUX_SET_TIME:
222             i64 = (int64_t)va_arg( args, int64_t );
223             if( i_bitrate > 0 && i64 >= 0 )
224             {
225                 int64_t i_block = i64 * i_bitrate / I64C(8000000) / i_align;
226                 if( stream_Seek( s, i_start + i_block * i_align ) )
227                 {
228                     return VLC_EGENERIC;
229                 }
230                 return VLC_SUCCESS;
231             }
232             return VLC_EGENERIC;
233
234         case DEMUX_GET_FPS:
235         case DEMUX_GET_META:
236         case DEMUX_SET_NEXT_DEMUX_TIME:
237         case DEMUX_GET_TITLE_INFO:
238         case DEMUX_SET_GROUP:
239             return VLC_EGENERIC;
240
241         default:
242             msg_Err( s, "unknown query in demux_vaControlDefault" );
243             return VLC_EGENERIC;
244     }
245 }
246
247 /****************************************************************************
248  * stream_Demux*: create a demuxer for an outpout stream (allow demuxer chain)
249  ****************************************************************************/
250 typedef struct
251 {
252     /* Data buffer */
253     vlc_mutex_t lock;
254     int         i_buffer;
255     int         i_buffer_size;
256     uint8_t     *p_buffer;
257
258     int64_t     i_pos;
259
260     /* Demuxer */
261     char        *psz_name;
262     es_out_t    *out;
263     demux_t     *p_demux;
264 } d_stream_sys_t;
265
266 static int DStreamRead   ( stream_t *, void *p_read, int i_read );
267 static int DStreamPeek   ( stream_t *, uint8_t **pp_peek, int i_peek );
268 static int DStreamControl( stream_t *, int i_query, va_list );
269 static int DStreamThread ( stream_t * );
270
271
272 stream_t *__stream_DemuxNew( vlc_object_t *p_obj, char *psz_demux, es_out_t *out )
273 {
274     /* We create a stream reader, and launch a thread */
275     stream_t       *s;
276     d_stream_sys_t *p_sys;
277
278     if( psz_demux == NULL || *psz_demux == '\0' )
279     {
280         return NULL;
281     }
282
283     s = vlc_object_create( p_obj, VLC_OBJECT_STREAM );
284     s->pf_block  = NULL;
285     s->pf_read   = DStreamRead;
286     s->pf_peek   = DStreamPeek;
287     s->pf_control= DStreamControl;
288
289     s->p_sys = malloc( sizeof( d_stream_sys_t) );
290     p_sys = (d_stream_sys_t*)s->p_sys;
291
292     vlc_mutex_init( s, &p_sys->lock );
293     p_sys->i_buffer = 0;
294     p_sys->i_buffer_size = 1000000;
295     p_sys->p_buffer = malloc( p_sys->i_buffer_size );
296     p_sys->i_pos = 0;
297     p_sys->psz_name = strdup( psz_demux );
298     p_sys->out = out;
299     p_sys->p_demux = NULL;
300
301     if( vlc_thread_create( s, "stream out", DStreamThread, VLC_THREAD_PRIORITY_INPUT, VLC_FALSE ) )
302     {
303         vlc_mutex_destroy( &p_sys->lock );
304         vlc_object_destroy( s );
305         free( p_sys );
306         return NULL;
307     }
308
309     return s;
310 }
311
312 void     stream_DemuxSend( stream_t *s, block_t *p_block )
313 {
314     d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
315
316     if( p_block->i_buffer > 0 )
317     {
318         vlc_mutex_lock( &p_sys->lock );
319         /* Realloc if needed */
320         if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size )
321         {
322             if( p_sys->i_buffer_size > 5000000 )
323             {
324                 vlc_mutex_unlock( &p_sys->lock );
325                 msg_Err( s, "stream_DemuxSend: buffer size > 5000000" );
326                 block_Release( p_block );
327                 return;
328             }
329             /* I know, it's more than needed but that's perfect */
330             p_sys->i_buffer_size += p_block->i_buffer;
331             /* FIXME won't work with PEEK -> segfault */
332             p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
333             msg_Dbg( s, "stream_DemuxSend: realloc to %d", p_sys->i_buffer_size );
334         }
335
336         /* copy data */
337         memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer );
338         p_sys->i_buffer += p_block->i_buffer;
339
340         vlc_mutex_unlock( &p_sys->lock );
341     }
342
343     block_Release( p_block );
344 }
345
346 void     stream_DemuxDelete( stream_t *s )
347 {
348     d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
349
350     s->b_die = VLC_TRUE;
351
352     vlc_mutex_lock( &p_sys->lock );
353     if( p_sys->p_demux )
354     {
355         p_sys->p_demux->b_die = VLC_TRUE;
356     }
357     vlc_mutex_unlock( &p_sys->lock );
358
359     vlc_thread_join( s );
360
361     if( p_sys->p_demux )
362     {
363         demux2_Delete( p_sys->p_demux );
364     }
365     vlc_mutex_destroy( &p_sys->lock );
366     free( p_sys->psz_name );
367     free( p_sys->p_buffer );
368     free( p_sys );
369     vlc_object_destroy( s );
370 }
371
372
373 static int      DStreamRead   ( stream_t *s, void *p_read, int i_read )
374 {
375     d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
376     int           i_copy;
377
378     //msg_Dbg( s, "DStreamRead: wanted %d bytes", i_read );
379     for( ;; )
380     {
381         vlc_mutex_lock( &p_sys->lock );
382         //msg_Dbg( s, "DStreamRead: buffer %d", p_sys->i_buffer );
383         if( p_sys->i_buffer >= i_read || s->b_die )
384         {
385             break;
386         }
387         vlc_mutex_unlock( &p_sys->lock );
388         msleep( 10000 );
389     }
390
391     //msg_Dbg( s, "DStreamRead: read %d buffer %d", i_read, p_sys->i_buffer );
392
393     i_copy = __MIN( i_read, p_sys->i_buffer );
394     if( i_copy > 0 )
395     {
396         if( p_read )
397         {
398             memcpy( p_read, p_sys->p_buffer, i_copy );
399         }
400         p_sys->i_buffer -= i_copy;
401         p_sys->i_pos += i_copy;
402
403         if( p_sys->i_buffer > 0 )
404         {
405             memmove( p_sys->p_buffer, &p_sys->p_buffer[i_copy], p_sys->i_buffer );
406         }
407
408     }
409     vlc_mutex_unlock( &p_sys->lock );
410
411     return i_copy;
412 }
413 static int      DStreamPeek   ( stream_t *s, uint8_t **pp_peek, int i_peek )
414 {
415     d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
416     int           i_copy;
417
418     //msg_Dbg( s, "DStreamPeek: wanted %d bytes", i_peek );
419     for( ;; )
420     {
421         vlc_mutex_lock( &p_sys->lock );
422         //msg_Dbg( s, "DStreamPeek: buffer %d", p_sys->i_buffer );
423         if( p_sys->i_buffer >= i_peek || s->b_die )
424         {
425             break;
426         }
427         vlc_mutex_unlock( &p_sys->lock );
428         msleep( 10000 );
429     }
430     *pp_peek = p_sys->p_buffer;
431     i_copy = __MIN( i_peek, p_sys->i_buffer );
432
433     vlc_mutex_unlock( &p_sys->lock );
434
435     return i_copy;
436 }
437
438 static int      DStreamControl( stream_t *s, int i_query, va_list args )
439 {
440     d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
441     int64_t    *p_i64;
442     vlc_bool_t *p_b;
443     int        *p_int;
444     switch( i_query )
445     {
446         case STREAM_GET_SIZE:
447             p_i64 = (int64_t*) va_arg( args, int64_t * );
448             *p_i64 = 0;
449             return VLC_SUCCESS;
450
451         case STREAM_CAN_SEEK:
452             p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
453             *p_b = VLC_FALSE;
454             return VLC_SUCCESS;
455
456         case STREAM_CAN_FASTSEEK:
457             p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
458             *p_b = VLC_FALSE;
459             return VLC_SUCCESS;
460
461         case STREAM_GET_POSITION:
462             p_i64 = (int64_t*) va_arg( args, int64_t * );
463             *p_i64 = p_sys->i_pos;
464             return VLC_SUCCESS;
465
466         case STREAM_SET_POSITION:
467         {
468             int64_t i64 = (int64_t)va_arg( args, int64_t );
469             int i_skip;
470             if( i64 < p_sys->i_pos )
471                 return VLC_EGENERIC;
472             i_skip = i64 - p_sys->i_pos;
473
474             while( i_skip > 0 )
475             {
476                 int i_read = DStreamRead( s, NULL, i_skip );
477
478                 if( i_read <= 0 )
479                     return VLC_EGENERIC;
480
481                 i_skip -= i_read;
482             }
483             return VLC_SUCCESS;
484         }
485
486         case STREAM_GET_MTU:
487             p_int = (int*) va_arg( args, int * );
488             *p_int = 0;
489             return VLC_SUCCESS;
490
491         default:
492             msg_Err( s, "invalid DStreamControl query=0x%x", i_query );
493             return VLC_EGENERIC;
494     }
495 }
496
497 static int      DStreamThread ( stream_t *s )
498 {
499     d_stream_sys_t *p_sys = (d_stream_sys_t*)s->p_sys;
500     demux_t      *p_demux;
501
502     /* Create the demuxer */
503
504     if( ( p_demux = demux2_New( s, "", p_sys->psz_name, "", s, p_sys->out ) ) == NULL )
505     {
506         return VLC_EGENERIC;
507     }
508
509     vlc_mutex_lock( &p_sys->lock );
510     p_sys->p_demux = p_demux;
511     vlc_mutex_unlock( &p_sys->lock );
512
513     /* Main loop */
514     while( !s->b_die && !p_demux->b_die )
515     {
516         if( p_demux->pf_demux( p_demux ) <= 0 )
517         {
518             break;
519         }
520     }
521     p_demux->b_die = VLC_TRUE;
522     return VLC_SUCCESS;
523 }