]> git.sesse.net Git - vlc/blob - src/input/input_programs.c
* Moved input_DecodePES() to input_dec.c ;
[vlc] / src / input / input_programs.c
1 /*****************************************************************************
2  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3  * FIXME : check the return value of realloc() and malloc() !
4  *****************************************************************************
5  * Copyright (C) 1999, 2000 VideoLAN
6  * $Id: input_programs.c,v 1.14 2000/12/22 10:58:27 massiot Exp $
7  *
8  * Authors:
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 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 General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include "defs.h"
29
30 #include <stdlib.h>
31
32 #include "config.h"
33 #include "common.h"
34 #include "threads.h"
35 #include "mtime.h"
36 #include "debug.h"
37
38 #include "intf_msg.h"
39
40 #include "stream_control.h"
41 #include "input_ext-intf.h"
42 #include "input_ext-dec.h"
43 #include "input.h"
44 #include "input_dec.h"
45
46 #include "main.h"                                     /* --noaudio --novideo */
47
48 /*
49  * NOTICE : all of these functions expect you to have taken the lock on
50  * p_input->stream.lock
51  */
52
53 /*****************************************************************************
54  * input_InitStream: init the stream descriptor of the given input
55  *****************************************************************************/
56 void input_InitStream( input_thread_t * p_input, size_t i_data_len )
57 {
58     p_input->stream.i_stream_id = 0;
59     p_input->stream.pp_es = NULL;
60     p_input->stream.pp_selected_es = NULL;
61     p_input->stream.pp_programs = NULL;
62
63     if( i_data_len )
64     {
65         p_input->stream.p_demux_data = malloc( i_data_len );
66         memset( p_input->stream.p_demux_data, 0, i_data_len );
67     }
68 }
69
70 /*****************************************************************************
71  * input_EndStream: free all stream descriptors
72  *****************************************************************************/
73 void input_EndStream( input_thread_t * p_input )
74 {
75     int i;
76
77     /* Free all programs and associated ES, and associated decoders. */
78     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
79     {
80         /* Don't put i instead of 0 !! */
81         input_DelProgram( p_input, p_input->stream.pp_programs[0] );
82     }
83     free( p_input->stream.pp_programs );
84
85     /* Free standalone ES */
86     for( i = 0; i < p_input->stream.i_es_number; i++ )
87     {
88         input_DelES( p_input, p_input->stream.pp_es[0] );
89     }
90     free( p_input->stream.pp_es );
91     free( p_input->stream.pp_selected_es );
92 }
93
94 /*****************************************************************************
95  * input_FindProgram: returns a pointer to a program described by its ID
96  *****************************************************************************/
97 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input, u16 i_pgrm_id )
98 {
99     int     i;
100
101     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
102     {
103         if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
104         {
105             return p_input->stream.pp_programs[i];
106         }
107     }
108
109     return( NULL );
110 }
111
112 /*****************************************************************************
113  * input_AddProgram: add and init a program descriptor
114  *****************************************************************************
115  * This program descriptor will be referenced in the given stream descriptor
116  *****************************************************************************/
117 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
118                                       u16 i_pgrm_id, size_t i_data_len )
119 {
120     /* Where to add the pgrm */
121     int i_pgrm_index = p_input->stream.i_pgrm_number;
122
123     intf_DbgMsg("Adding description for pgrm %d", i_pgrm_id);
124
125     /* Add an entry to the list of program associated with the stream */
126     p_input->stream.i_pgrm_number++;
127     p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
128                                            p_input->stream.i_pgrm_number
129                                             * sizeof(pgrm_descriptor_t *) );
130
131     /* Allocate the structure to store this description */
132     p_input->stream.pp_programs[i_pgrm_index] =
133                                         malloc( sizeof(pgrm_descriptor_t) );
134
135     /* Init this entry */
136     p_input->stream.pp_programs[i_pgrm_index]->i_number = i_pgrm_id;
137     p_input->stream.pp_programs[i_pgrm_index]->b_is_ok = 0;
138     p_input->stream.pp_programs[i_pgrm_index]->i_version = 0;
139
140     p_input->stream.pp_programs[i_pgrm_index]->i_es_number = 0;
141     p_input->stream.pp_programs[i_pgrm_index]->pp_es = NULL;
142
143     p_input->stream.pp_programs[i_pgrm_index]->delta_cr = 0;
144     p_input->stream.pp_programs[i_pgrm_index]->delta_absolute = 0;
145     p_input->stream.pp_programs[i_pgrm_index]->last_cr = 0;
146     p_input->stream.pp_programs[i_pgrm_index]->c_average_count = 0;
147     p_input->stream.pp_programs[i_pgrm_index]->i_synchro_state
148                                                 = SYNCHRO_NOT_STARTED;
149     p_input->stream.pp_programs[i_pgrm_index]->b_discontinuity = 0;
150
151     p_input->stream.pp_programs[i_pgrm_index]->p_vout
152                                             = p_input->p_default_vout;
153     p_input->stream.pp_programs[i_pgrm_index]->p_aout
154                                             = p_input->p_default_aout;
155
156     if( i_data_len )
157     {
158         p_input->stream.pp_programs[i_pgrm_index]->p_demux_data =
159             malloc( i_data_len );
160         memset( p_input->stream.pp_programs[i_pgrm_index]->p_demux_data, 0,
161                 i_data_len );
162     }
163
164     return p_input->stream.pp_programs[i_pgrm_index];
165 }
166
167 /*****************************************************************************
168  * input_DelProgram: destroy a program descriptor
169  *****************************************************************************
170  * All ES descriptions referenced in the descriptor will be deleted.
171  *****************************************************************************/
172 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
173 {
174     int i_index, i_pgrm_index;
175
176     ASSERT( p_pgrm );
177
178     intf_DbgMsg("Deleting description for pgrm %d", p_pgrm->i_stream_id);
179
180     /* Free the structures that describe the es that belongs to that program */
181     for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
182     {
183         input_DelES( p_input, p_pgrm->pp_es[i_index] );
184     }
185
186     /* Free the table of es descriptors */
187     free( p_pgrm->pp_es );
188
189     /* Free the demux data */
190     if( p_pgrm->p_demux_data != NULL )
191     {
192         free( p_pgrm->p_demux_data );
193     }
194
195     /* Find the program in the programs table */
196     for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
197          i_pgrm_index++ )
198     {
199         if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
200             break;
201     }
202
203     /* Remove this program from the stream's list of programs */
204     p_input->stream.i_pgrm_number--;
205     p_input->stream.pp_programs[i_pgrm_index] =
206         p_input->stream.pp_programs[p_input->stream.i_pgrm_number];
207     p_input->stream.pp_programs = realloc( p_input->stream.pp_programs,
208                                            p_input->stream.i_pgrm_number
209                                             * sizeof(pgrm_descriptor_t *) );
210
211     /* Free the description of this program */
212     free( p_pgrm );
213 }
214
215 /*****************************************************************************
216  * input_FindES: returns a pointer to an ES described by its ID
217  *****************************************************************************/
218 es_descriptor_t * input_FindES( input_thread_t * p_input, u16 i_es_id )
219 {
220     int     i;
221
222     for( i = 0; i < p_input->stream.i_es_number; i++ )
223     {
224         if( p_input->stream.pp_es[i]->i_id == i_es_id )
225         {
226             return p_input->stream.pp_es[i];
227         }
228     }
229
230     return( NULL );
231 }
232
233 /*****************************************************************************
234  * input_AddES:
235  *****************************************************************************
236  * Reserve a slot in the table of ES descriptors for the ES and add it to the
237  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
238  * alone (PSI ?)
239  *****************************************************************************/
240 es_descriptor_t * input_AddES( input_thread_t * p_input,
241                                pgrm_descriptor_t * p_pgrm, u16 i_es_id,
242                                size_t i_data_len )
243 {
244     es_descriptor_t * p_es;
245
246     intf_DbgMsg("Adding description for ES %d", i_es_id);
247
248     p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
249     p_input->stream.i_es_number++;
250     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
251                                      p_input->stream.i_es_number
252                                       * sizeof(es_descriptor_t *) );
253     p_input->stream.pp_es[p_input->stream.i_es_number - 1] = p_es;
254     p_es->i_id = i_es_id;
255
256     /* Init its values */
257     p_es->b_discontinuity = 0;
258     p_es->p_pes = NULL;
259     p_es->p_decoder_fifo = NULL;
260
261     if( i_data_len )
262     {
263         p_es->p_demux_data = malloc( i_data_len );
264         memset( p_es->p_demux_data, 0, i_data_len );
265     }
266     else
267     {
268         p_es->p_demux_data = NULL;
269     }
270
271     /* Add this ES to the program definition if one is given */
272     if( p_pgrm )
273     {
274         p_pgrm->i_es_number++;
275         p_pgrm->pp_es = realloc( p_pgrm->pp_es,
276                                  p_pgrm->i_es_number
277                                   * sizeof(es_descriptor_t *) );
278         p_pgrm->pp_es[p_pgrm->i_es_number - 1] = p_es;
279         p_es->p_pgrm = p_pgrm;
280     }
281     else
282     {
283         p_es->p_pgrm = NULL;
284     }
285
286     return p_es;
287 }
288
289 /*****************************************************************************
290  * input_DelES:
291  *****************************************************************************/
292 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
293 {
294     int                     i_index, i_es_index;
295     pgrm_descriptor_t *     p_pgrm;
296
297     ASSERT( p_es );
298     p_pgrm = p_es->p_pgrm;
299
300     /* Kill associated decoder, if any. */
301     if( p_es->p_decoder_fifo != NULL )
302     {
303         input_EndDecoder( p_es->p_decoder_fifo, p_es->thread_id );
304         free( p_es->p_decoder_fifo );
305     }
306
307     /* Remove this ES from the description of the program if it is associated to
308      * one */
309     if( p_pgrm )
310     {
311         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
312         {
313             if( p_pgrm->pp_es[i_index] == p_es )
314             {
315                 p_pgrm->i_es_number--;
316                 p_pgrm->pp_es[i_index] = p_pgrm->pp_es[p_pgrm->i_es_number];
317                 p_pgrm->pp_es = realloc( p_pgrm->pp_es,
318                                          p_pgrm->i_es_number
319                                           * sizeof(es_descriptor_t *));
320                 break;
321             }
322         }
323     }
324
325     /* Free the demux data */
326     if( p_es->p_demux_data != NULL )
327     {
328         free( p_es->p_demux_data );
329     }
330
331     /* Find the ES in the ES table */
332     for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
333          i_es_index++ )
334     {
335         if( p_input->stream.pp_es[i_es_index] == p_es )
336             break;
337     }
338
339     /* Free the ES */
340     free( p_es );
341     p_input->stream.i_es_number--;
342     p_input->stream.pp_es[i_es_index] =
343                     p_input->stream.pp_es[p_input->stream.i_es_number];
344     p_input->stream.pp_es = realloc( p_input->stream.pp_es,
345                                      p_input->stream.i_es_number
346                                       * sizeof(es_descriptor_t *));
347 }
348
349 #ifdef STATS
350 /*****************************************************************************
351  * input_DumpStream: dumps the contents of a stream descriptor
352  *****************************************************************************/
353 void input_DumpStream( input_thread_t * p_input )
354 {
355     int i, j;
356 #define S   p_input->stream
357     intf_Msg( "input info: Dumping stream ID 0x%x\n", S.i_stream_id );
358     if( S.b_seekable )
359         intf_Msg( "input info: seekable stream, position: %d/%d\n",
360                   S.i_tell, S.i_size );
361     else
362         intf_Msg( "input info: %s\n", S.b_pace_control ? "pace controlled" :
363                   "pace un-controlled" );
364 #undef S
365     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
366     {
367 #define P   p_input->stream.pp_programs[i]
368         intf_Msg( "input info: Dumping program 0x%x, version %d (%s)\n",
369                   P->i_number, P->i_version,
370                   P->b_is_ok ? "complete" : "partial" );
371         if( P->i_synchro_state == SYNCHRO_OK )
372             intf_Msg( "input info: synchro absolute delta : %lld (jitter : %lld)\n",
373                       P->delta_absolute, P->delta_cr );
374 #undef P
375         for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
376         {
377 #define ES  p_input->stream.pp_programs[i]->pp_es[j]
378             intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s\n",
379                       ES->i_id, ES->i_stream_id, ES->i_type,
380                       ES->p_decoder_fifo != NULL ? "selected" : "not selected");
381 #undef ES
382         }
383     }
384 }
385 #endif
386
387 /*****************************************************************************
388  * InitDecConfig: initializes a decoder_config_t
389  *****************************************************************************/
390 static int InitDecConfig( input_thread_t * p_input, es_descriptor_t * p_es,
391                           decoder_config_t * p_config )
392 {
393     p_config->i_stream_id = p_es->i_stream_id;
394     p_config->i_type = p_es->i_type;
395     p_config->p_stream_ctrl =
396         &p_input->stream.control;
397
398     /* Decoder FIFO */
399     if( (p_config->p_decoder_fifo =
400             (decoder_fifo_t *)malloc( sizeof(decoder_fifo_t) )) == NULL )
401     {
402         intf_ErrMsg( "Out of memory" );
403         return( -1 );
404     }
405
406     vlc_mutex_init(&p_config->p_decoder_fifo->data_lock);
407     vlc_cond_init(&p_config->p_decoder_fifo->data_wait);
408     p_config->p_decoder_fifo->i_start = p_config->p_decoder_fifo->i_end = 0;
409     p_config->p_decoder_fifo->b_die = p_config->p_decoder_fifo->b_error = 0;
410     p_config->p_decoder_fifo->p_packets_mgt = p_input->p_method_data;
411     p_config->p_decoder_fifo->pf_delete_pes =
412         p_input->p_plugin->pf_delete_pes;
413     p_es->p_decoder_fifo = p_config->p_decoder_fifo;
414
415     p_config->pf_init_bit_stream = InitBitstream;
416
417     return( 0 );
418 }
419
420 /*****************************************************************************
421  * GetVdecConfig: returns a valid vdec_config_t
422  *****************************************************************************/
423 static vdec_config_t * GetVdecConfig( input_thread_t * p_input,
424                                       es_descriptor_t * p_es )
425 {
426     vdec_config_t *     p_config;
427
428     p_config = (vdec_config_t *)malloc( sizeof(vdec_config_t) );
429     p_config->p_vout = p_input->p_default_vout;
430     if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
431     {
432         free( p_config );
433         return NULL;
434     }
435
436     return( p_config );
437 }
438
439 /*****************************************************************************
440  * GetAdecConfig: returns a valid adec_config_t
441  *****************************************************************************/
442 static adec_config_t * GetAdecConfig( input_thread_t * p_input,
443                                       es_descriptor_t * p_es )
444 {
445     adec_config_t *     p_config;
446
447     p_config = (adec_config_t *)malloc( sizeof(adec_config_t) );
448     p_config->p_aout = p_input->p_default_aout;
449     if( InitDecConfig( p_input, p_es, &p_config->decoder_config ) == -1 )
450     {
451         free( p_config );
452         return NULL;
453     }
454
455     return( p_config );
456 }
457
458 /*****************************************************************************
459  * input_SelectES: selects an ES and spawns the associated decoder
460  *****************************************************************************/
461 /* FIXME */
462 vlc_thread_t adec_CreateThread( void * );
463 vlc_thread_t ac3dec_CreateThread( void * );
464 vlc_thread_t vpar_CreateThread( void * );
465 vlc_thread_t spudec_CreateThread( void * );
466
467 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
468 {
469     /* FIXME ! */
470     decoder_capabilities_t  decoder;
471
472 #ifdef DEBUG_INPUT
473     intf_DbgMsg( "Selecting ES %d", p_es->i_id );
474 #endif
475
476     if( p_es->p_decoder_fifo != NULL )
477     {
478         intf_ErrMsg( "ES %d is already selected", p_es->i_id );
479         return( -1 );
480     }
481
482     switch( p_es->i_type )
483     {
484     case MPEG1_AUDIO_ES:
485     case MPEG2_AUDIO_ES:
486         if( p_main->b_audio )
487         {
488             decoder.pf_create_thread = adec_CreateThread;
489             p_es->thread_id = input_RunDecoder( &decoder,
490                                     (void *)GetAdecConfig( p_input, p_es ) );
491         }
492         break;
493
494     case MPEG1_VIDEO_ES:
495     case MPEG2_VIDEO_ES:
496         if( p_main->b_video )
497         {
498             decoder.pf_create_thread = vpar_CreateThread;
499             p_es->thread_id = input_RunDecoder( &decoder,
500                                     (void *)GetVdecConfig( p_input, p_es ) );
501         }
502         break;
503
504     case AC3_AUDIO_ES:
505         if( p_main->b_audio )
506         {
507             decoder.pf_create_thread = ac3dec_CreateThread;
508             p_es->thread_id = input_RunDecoder( &decoder,
509                                     (void *)GetAdecConfig( p_input, p_es ) );
510         }
511         break;
512
513     case DVD_SPU_ES:
514         if( p_main->b_video )
515         {
516             decoder.pf_create_thread = spudec_CreateThread;
517             p_es->thread_id = input_RunDecoder( &decoder,
518                                     (void *)GetVdecConfig( p_input, p_es ) );
519         }
520         break;
521
522     default:
523         intf_ErrMsg( "Unknown stream type %d", p_es->i_type );
524         return( -1 );
525         break;
526     }
527
528     if( p_es->p_decoder_fifo != NULL )
529     {
530         p_input->stream.i_selected_es_number++;
531         p_input->stream.pp_selected_es = realloc(
532                                            p_input->stream.pp_selected_es,
533                                            p_input->stream.i_selected_es_number
534                                             * sizeof(es_descriptor_t *) );
535         p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number - 1]
536                 = p_es;
537     }
538     return( 0 );
539 }