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