]> git.sesse.net Git - vlc/blob - src/input/input_psi.c
cae2e381ba0bf23e14843692ddb0a0f7afeba486
[vlc] / src / input / input_psi.c
1 /*******************************************************************************
2  * psi.c: PSI management 
3  * (c)1999 VideoLAN
4  *******************************************************************************
5  * Manages structures containing PSI information, and affiliated decoders.
6  * TO DO: Fonctions d'init des structures
7  *******************************************************************************/
8
9 /*******************************************************************************
10  * Preamble
11  *******************************************************************************/
12 #include <errno.h>
13 #include <pthread.h>
14 #include <stdio.h>
15 #include <sys/uio.h>                                                 /* iovec */
16 #include <stdlib.h>                               /* atoi(), malloc(), free() */
17 #include <string.h>
18 #include <netinet/in.h>                                              /* ntohs */
19 #include <sys/soundcard.h>
20 #include <X11/Xlib.h>
21 #include <X11/extensions/XShm.h>
22
23 #include "common.h"
24 #include "config.h"
25 #include "mtime.h"
26 #include "intf_msg.h"
27 #include "debug.h"
28
29 #include "input.h"
30 #include "input_ctrl.h"
31 #include "input_psi.h"
32 #include "input_vlan.h"
33
34 #include "audio_output.h"
35 #include "video.h"
36 #include "video_output.h"
37 #include "xconsole.h"
38 #include "interface.h"
39
40 #include "pgm_data.h"
41
42 /*
43  * Precalculated 32-bits CRC table, shared by all instances of the PSI decoder
44  */
45 boolean_t b_crc_initialised = 0;
46 u32 i_crc_32_table[256];
47
48 /*
49  * Global configuration variable, need by AUTO_SPAWN to determine
50  * the option (audio and video) passed to the VideoLAN client.
51  */
52 #ifdef AUTO_SPAWN
53 extern program_data_t *p_program_data;
54 #endif
55
56 /*
57  * Locale type definitions
58  */
59 #define PSI_VIDEO_STREAM_DESCRIPTOR                 0x02
60 #define PSI_AUDIO_STREAM_DESCRIPTOR                 0x03
61 #define PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR       0x07
62 #define PSI_VIDEO_WINDOW_DESCRIPTOR                 0x08
63
64 #ifdef DVB_EXTENSIONS
65 #define PSI_SERVICE_DESCRIPTOR                      0x48
66 #endif
67
68 /* That info must be stored in the version field since it contains
69    unused bits */
70 #define PSI_UNINITIALISED                           0xFF
71
72 /*
73  * Local prototypes
74  */
75 static int input_AddPsiPID( input_thread_t *p_input, int i_pid );
76 static int input_DelPsiPID( input_thread_t *p_input, int i_pid );
77 static void DecodePgrmAssocSection( byte_t* p_pas, input_thread_t *p_input );
78 static void DecodePgrmMapSection( byte_t* p_pms, input_thread_t *p_input );
79 static void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input );
80 static void DecodePgrmDescriptor( byte_t* p_descriptor, pgrm_descriptor_t* p_pgrm );
81 static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es );
82
83 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input,
84                                            u16 i_stream_id);
85 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id);
86 static pgrm_descriptor_t* AddPgrmDescr(stream_descriptor_t* p_stream,
87                                        u16 i_pgrm_id);
88 static void DestroyPgrmDescr(input_thread_t* p_input, stream_descriptor_t* p_stream, u16 i_pgrm_id);
89 static es_descriptor_t* AddESDescr(input_thread_t* p_input,
90                                    pgrm_descriptor_t* p_pgrm, u16 i_es_pid);
91 static void DestroyESDescr(input_thread_t* p_input, pgrm_descriptor_t* p_pgrm,
92                            u16 i_es_pid);
93
94 static void BuildCrc32Table();
95 static int CheckCRC32( u8* p_pms, int i_size);
96 static boolean_t Is_known( byte_t* a_known_section, u8 i_section );
97 static void Set_known( byte_t* a_known_section, u8 i_section );
98 static void Unset_known( byte_t* a_known_section, u8 i_section );
99
100 /******************************************************************************
101  * input_PsiInit: Initialize PSI decoder
102  ******************************************************************************
103  * Init the structures in which the PSI decoder will put the informations it
104  * got from PSI tables and request for the reception of the PAT.
105  ******************************************************************************/
106 int input_PsiInit( input_thread_t *p_input )
107 {
108   ASSERT(p_input);
109   
110   /* Precalculate the 32-bit CRC table if not already done ???
111      TO DO -> Put a lock or do that at pgrm init */
112   if( !b_crc_initialised )
113   {
114     BuildCrc32Table();
115     b_crc_initialised = 1;
116   }
117   
118   /* Init the structure that describes the stream we are receiving */
119   AddStreamDescr( p_input, PSI_UNINITIALISED );
120
121   /* Request for reception of the program association table */
122   input_AddPsiPID( p_input, 0 );
123
124 #ifdef DVB_EXTENSIONS
125   /* Request for reception of the service description table */
126   input_AddPsiPID( p_input, 17 );
127 #endif
128
129   return( 0 );
130 }
131
132 /******************************************************************************
133  * input_PsiClean: Clean PSI structures before dying
134  ******************************************************************************/
135 int input_PsiClean( input_thread_t *p_input )
136 {
137   ASSERT(p_input);
138
139   /* Stop to receive all the PSI tables associated with that program */
140   /* TO DO ??? -> Not really usefull */
141
142   /* Clean also descriptors for programs associated with that stream */
143   /* TO DO ??? -> Not really usefull and maybe buggy */
144
145   /* Destroy the stream description */
146   DestroyStreamDescr( p_input, p_input->p_stream->i_stream_id );
147
148   return( 0 );
149 }
150
151 /******************************************************************************
152  * input_PsiRead: Read the table of programs
153  ******************************************************************************
154  * Ugly debugging function at that time ???????
155  ******************************************************************************/
156 void input_PsiRead( input_thread_t *p_input /* ??? */ )
157 {
158   int i_index;
159   int i_index2;
160   pgrm_descriptor_t* p_pgrm;
161   
162   ASSERT( p_input );
163  
164   /* Lock the tables, since this method can be called from any thread */
165   //pthread_mutex_lock()
166
167   /* Check if the table is complete or not */
168   if( !p_input->p_stream->b_is_PMT_complete )
169   {
170     intf_IntfMsg( "Warning: PMT not yet complete\n" );
171   }
172   
173   /* Read the table */
174   for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
175   {
176     p_pgrm = p_input->p_stream->ap_programs[i_index];
177     intf_Msg("Printing info for program %d\n", p_pgrm->i_number );
178     intf_IntfMsg("Printing info for program %d\n", p_pgrm->i_number );
179
180     for( i_index2 = 0; i_index2 < p_pgrm->i_es_number; i_index2++ )
181     {
182       intf_Msg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n", p_pgrm->ap_es[i_index2]->i_id,
183                     p_pgrm->ap_es[i_index2]->i_type, p_pgrm->ap_es[i_index2]->b_pcr,
184                     p_pgrm->ap_es[i_index2]->b_psi);
185
186       intf_IntfMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n", p_pgrm->ap_es[i_index2]->i_id,
187                     p_pgrm->ap_es[i_index2]->i_type, p_pgrm->ap_es[i_index2]->b_pcr,
188                     p_pgrm->ap_es[i_index2]->b_psi);
189     }
190   }
191
192   /* Unock the tables */
193   //pthread_mutex_unlock()
194 }
195
196 /******************************************************************************
197  * input_PsiDecode: Decode a PSI section
198  ******************************************************************************
199  * This funtion is essentially a wrapper that will  perform basic checks on
200  * the section and then call the right function according to its type.
201  ******************************************************************************/
202 void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section )
203 {
204   ASSERT(p_input);
205   ASSERT(p_psi_section);
206
207   /* Hexa dump of the beginning of the section (for real men) */
208   //intf_DbgMsg( "Section: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", (u8)p_psi_section->buffer[0], (u8)p_psi_section->buffer[1], (u8)p_psi_section->buffer[2], (u8)p_psi_section->buffer[3], (u8)p_psi_section->buffer[4], (u8)p_psi_section->buffer[5], (u8)p_psi_section->buffer[6], (u8)p_psi_section->buffer[7], (u8)p_psi_section->buffer[8], (u8)p_psi_section->buffer[9], (u8)p_psi_section->buffer[10], (u8)p_psi_section->buffer[11], (u8)p_psi_section->buffer[12], (u8)p_psi_section->buffer[13], (u8)p_psi_section->buffer[14], (u8)p_psi_section->buffer[15], (u8)p_psi_section->buffer[16], (u8)p_psi_section->buffer[17], (u8)p_psi_section->buffer[18], (u8)p_psi_section->buffer[19] );
209
210   /* Check the CRC validity if any CRC is carried */
211   if( p_psi_section->buffer[1] & 0x80 )
212   {
213     if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )
214     {
215       intf_DbgMsg("iSize: %d, CRC: %d\n", p_psi_section->i_length,
216                   U32_AT(&p_psi_section->buffer[p_psi_section->i_length-4]));
217       intf_DbgMsg( "Invalid CRC for PSI\n" );
218       return;
219     }
220   }
221   
222   /* If the section is not immediatly applicable, trash it (DVB drafts disallow
223      transmission of such sections, so we didn't implement it) */
224   if( !p_psi_section->buffer[5] & 0x01 )
225   {
226     intf_DbgMsg( "PSI not yet applicable: trash it\n" );
227     return;
228   }
229   
230   /* Handle the packet according to it's type given it the table_id  */
231   switch ( p_psi_section->buffer[0] )
232   {
233     case 0x00:
234       //intf_DbgMsg("Program association section received\n");
235       DecodePgrmAssocSection(p_psi_section->buffer, p_input);
236       break;
237     case 0x01:
238       //intf_DbgMsg("Conditional access section received\n");
239       break;
240     case 0x02:
241       //intf_DbgMsg("Program map section received\n");
242       DecodePgrmMapSection(p_psi_section->buffer, p_input);
243       break;
244     case 0x42:
245       //intf_DbgMsg("Service description section received\n");
246       DecodeSrvDescrSection(p_psi_section->buffer, p_input);
247       break;
248     default:
249       //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",
250       //            p_psi_section->buffer[0]);
251   }
252 }
253
254 /******************************************************************************
255  * DecodeAssocSection: Decode a PAS
256  ******************************************************************************
257  * No check is made to known if the table is currently applicable or not, so
258  * that unapplicable sections must be filtered before calling this function
259  * The Program Association Table can be segmented to occupy multiple sections
260  * so that we have to know which sections we have already received (IsKnown() /
261  * SetKnown() calls)
262  ******************************************************************************/
263 static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input )
264 {
265   u8 i_stream_id;               /* Id of the stream described in that section */
266     u8 i_version;              /* Version of the table carried in the section */
267
268     u16 i_pgrm_id;                       /* Id of the current described  pgrm */
269     u16 i_pgrm_map_pid;            /* PID of the associated program map table */
270     int i_pgrm_number;         /* Number of programs described in the section */
271
272     boolean_t b_is_invalid = 0;
273     
274     u8 i_current_section;
275     u8 i_last_section;
276
277     int i_pgrm_index;
278     int i_es_index;
279
280     ASSERT(p_pas);
281     ASSERT(p_input);
282
283 #define p_descr (p_input->p_stream)
284
285    /* Read stream id and version number immediately, to be sure they will be
286       initialised in all cases we will need it */
287    i_stream_id = U16_AT(&p_pas[3]);
288    i_version = (p_pas[5] >> 1) & 0x1F;
289    //intf_DbgMsg("TS Id: %d, version: %d\n", U16_AT(&p_pas[3]),(p_pas[5] >> 1) & 0x1F);
290
291     /* Test if the stream has not changed by looking at the stream_id */
292     if( p_descr->i_stream_id != i_stream_id )
293     {
294       /* This can either mean that the PSI decoder has just started or that
295          the stream has changed */
296       if( p_descr->i_PAT_version== PSI_UNINITIALISED )
297         intf_Msg("Building Program Association table\n");
298       else
299         intf_ErrMsg( "Stream Id has suddently changed ! Rebuilding PAT\n" );
300
301       /* Whatever it is, ask the PSI decoder to rebuild the table */
302       b_is_invalid = 1;
303     }
304     else
305     {
306       /* Stream has not changed, test if the PMT is up to date */
307       if( p_descr->i_PAT_version != i_version )
308       {
309         intf_Msg("PAT has been updated, rebuilding it\n");
310         /* Ask the PSI decoder to rebuild the table */
311         b_is_invalid = 1;
312       }
313     }
314     
315     /* Clear the table if needed */
316     if( b_is_invalid )
317     {
318         intf_DbgMsg("Updating PAT table\n");
319
320         /* Any program in the stream may have disapeared, or a new one
321            can have been added. The good way to handle such a case would be
322            to build a temporary table and to make a diff */
323
324         /* Stop the reception of all programs and PSI informations
325            associated with this stream, excepted the PAT on PID 0 and the SDT
326            on PID 17 */
327         for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES && 
328              p_input->pp_selected_es[i_es_index]; i_es_index++ )
329         {
330           if( p_input->pp_selected_es[i_es_index]->b_psi )
331           {
332             if( p_input->pp_selected_es[i_es_index]->i_id != 0
333 #ifdef DVB_EXTENSIONS
334                 && p_input->pp_selected_es[i_es_index]->i_id != 17
335 #endif
336             )
337               input_DelPsiPID( p_input, p_input->pp_selected_es[i_es_index]->i_id );
338           }
339           else
340             input_DelPgrmElem( p_input, p_input->pp_selected_es[i_es_index]->i_id );
341         }
342
343         /* Recreate a new stream description. Since it is virgin, the decoder
344            will on is own rebuild it entirely */
345         DestroyStreamDescr(p_input, p_descr->i_stream_id);
346         AddStreamDescr(p_input, i_stream_id);
347
348         /* Record the new version for that table */
349         p_descr->i_PAT_version = i_version;
350     }
351
352     /* Build the table if not already complete or if it was cleared */
353     if( p_descr->b_is_PAT_complete )
354     {
355       /* Nothing to do */
356       //intf_DbgMsg("Table already complete\n");
357     }
358     else
359     {
360         /* Check if we already heard about that section */
361         i_last_section = p_pas[7];
362         i_current_section = p_pas[6];
363
364 //        intf_DbgMsg( "Section %d (last section %d)\n",
365 //                     i_current_section, i_last_section );
366
367         if( Is_known(p_descr->a_known_PAT_sections, i_current_section) )
368         {
369           /* Nothing to do */
370 //          intf_DbgMsg("Section already received, skipping\n");
371         }
372         else
373         {
374           /* Compute the number of program_map PID carried in this section */
375           i_pgrm_number = ((U16_AT(&p_pas[1]) & 0xFFF) - 9) / 4;
376           intf_DbgMsg("Number of Pgrm in that section: %d\n", i_pgrm_number);
377
378           /* Start the reception of those program map PID */
379           for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ )
380           {
381             i_pgrm_id = U16_AT(&p_pas[8+4*i_pgrm_index]);
382             i_pgrm_map_pid = U16_AT(&p_pas[8+4*i_pgrm_index+2]) & 0x1FFF;
383             intf_DbgMsg("Pgrm %d described on pid %d\n", i_pgrm_id, i_pgrm_map_pid);
384
385             /* Check we are not already receiving that pid because it carries info
386                for another program */
387             for( i_es_index = 0; i_es_index < INPUT_MAX_ES; i_es_index++ )
388             {
389               if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid)
390               {
391                 intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid);
392                 i_es_index = INPUT_MAX_ES+1;
393                 break;
394               } 
395             }
396             /* Start to receive that PID if we're not already doing it */
397             if( i_es_index <= INPUT_MAX_ES )
398               input_AddPsiPID( p_input, i_pgrm_map_pid );
399
400             /* Append an entry to the pgrm_descriptor table to later store
401                the description of this program, unless program number is 0
402                (Network information table) */
403             if( i_pgrm_id != 0 )
404             {
405               intf_Msg("Adding program %d to the Program Map Table\n", i_pgrm_id);
406               AddPgrmDescr(p_descr, i_pgrm_id);
407             }
408           }
409           
410           /* We now know the info carried in this section */
411           Set_known(p_descr->a_known_PAT_sections, i_current_section);
412         
413           /* Check if the table is now complete */
414           p_descr->i_known_PAT_sections++;
415           if( p_descr->i_known_PAT_sections >= i_last_section)
416             p_descr->b_is_PAT_complete = 1;
417         }
418     }
419
420 #undef p_descr
421 }
422
423 /******************************************************************************
424  * DecodePgrmMapSection: Decode a PMS
425  ******************************************************************************
426  * No check is made to known if the table is currently applicable or not, so
427  * that unapplicable sections must be filtered before calling this function
428  * The Program Map Table can be segmented to occupy multiple sections so that
429  * we have to know which sections we have already received (IsKnown() /
430  * SetKnown() calls)
431  * Note that the processing of those sections is different from the one of the
432  * others since here a section refers to a single program, and a program cannot
433  * be segmented into multiple sections
434  ******************************************************************************/
435 static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
436 {
437   u16 i_pgrm_number;         /* Id of the program described in that section */
438   u8 i_version;              /* Version of the description for that program */
439   
440   u16 i_offset;
441   u16 i_section_length;
442   u16 i_descr_end;
443   
444   u8 i_last_section;
445   u8 i_current_section;
446
447   u16 i_es_pid;
448
449   int i_index = 0;
450 #ifdef AUTO_SPAWN
451   int i_es_loop;
452 #endif
453   pgrm_descriptor_t* p_pgrm;
454   es_descriptor_t* p_es;
455
456 #define p_descr (p_input->p_stream)
457
458   /* Read the id of the program described in that section */
459   i_pgrm_number = U16_AT(&p_pms[3]);
460 //  intf_DbgMsg( "PMT section received for program %d\n", i_pgrm_number );
461
462   /* Find where is stored the description of this program */
463   for( i_index = 0; i_index < p_descr->i_pgrm_number &&
464        i_pgrm_number != p_descr->ap_programs[i_index]->i_number; i_index++ );
465
466   if( i_index >= p_descr->i_pgrm_number )
467   {
468     /* If none entry exists, this simply means that the PAT is not complete,
469        so skip this section since it is the responsability of the PAT decoder
470        to add pgrm_descriptor slots to the table of known pgrms */
471     intf_DbgMsg( "Pgrm %d is unknown: skipping its description\n", i_pgrm_number );
472     return;
473   }
474
475   /* We now have the slot which is the program described: we can begin with
476      the decoding of its description */
477   p_pgrm = p_descr->ap_programs[i_index];
478
479   /* Which section of the description of that program did we receive ? */
480   i_last_section = p_pms[7];
481   i_current_section = p_pms[6];
482 //  intf_DbgMsg("Section %d (last section %d)\n", i_current_section, i_last_section);
483
484   /* Is this an update of the description for this program ? */
485   i_version = (p_pms[5] >> 1) && 0x1F;
486     if( p_pgrm->i_version != i_version )
487     {
488         intf_Msg("Updating PMT for program %d\n", i_pgrm_number);
489
490         for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
491         {
492           /* Stop the reception of the ES if needed by calling the function
493              normally used by the interface to manage this */
494           if( input_IsElemRecv(p_input, p_pgrm->ap_es[i_index]->i_id) )
495           {
496             intf_Msg( "PID %d is no more valid: stopping its reception\n",
497                       p_pgrm->ap_es[i_index]->i_id );
498             input_DelPgrmElem( p_input, p_pgrm->ap_es[i_index]->i_id );
499           }
500
501           /* Remove the descriptor associated to the es of this programs */
502           intf_DbgMsg( "Invalidating PID %d\n", p_pgrm->ap_es[i_index]->i_id );
503           DestroyESDescr(p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id);
504         }
505         
506        /* Update version number */
507         p_pgrm->i_version = i_version;
508
509         /* Ask the decoder to update the description of that program */
510         p_descr->i_known_PMT_sections--;
511         Unset_known( p_descr->a_known_PMT_sections, i_current_section );
512         p_pgrm->b_is_ok = 0;
513     }
514
515     /* Read the info for that pgrm is the one we have is not up to date or
516        if we don't have any */
517     if( p_pgrm->b_is_ok )
518     {
519       /* Nothing to do */
520 //      intf_DbgMsg("Program description OK, nothing to do\n");
521     }
522     else
523     {
524         /* Check if we already heard about that section */
525         if( Is_known(p_descr->a_known_PMT_sections, i_current_section) )
526         {
527           /* Nothing to do */
528 //          intf_DbgMsg("Section already received, skipping\n");
529         }
530         else
531         {
532           /* Read the corresponding PCR */
533           p_pgrm->i_pcr_pid = U16_AT(&p_pms[8]) & 0x1fff;
534           intf_DbgMsg("PCR at PID: %d\n", p_pgrm->i_pcr_pid);
535
536           /* Compute the length of the section minus the final CRC */
537           i_section_length = (U16_AT(&p_pms[1]) & 0xFFF) + 3 - 4;
538           intf_DbgMsg("Section length (CRC not included): %d\n", i_section_length);
539
540           /* Read additional info stored in the descriptors if any */
541           intf_DbgMsg("description length for program %d: %d\n", p_pgrm->i_number,
542                    (U16_AT(&p_pms[10]) & 0x0FFF));
543           i_descr_end = (U16_AT(&p_pms[10]) & 0x0FFF) + 12;
544           intf_DbgMsg("description ends at offset: %d\n",  i_descr_end);
545
546           i_offset = 12;
547           while( i_offset < i_descr_end )
548           {
549             DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm);
550             i_offset += p_pms[i_offset+1] + 2;
551           }
552
553           /* Read all the ES descriptions */
554           while( i_offset < i_section_length )
555           {
556             /* Read type of that ES */
557             intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]);
558
559             /* Read PID of that ES */
560             i_es_pid = U16_AT(&p_pms[i_offset+1]) & 0x1FF;
561             intf_DbgMsg("ES PID: %d\n", i_es_pid);
562
563             /* Add the ES to the program description and reserve a slot in the
564                table of ES to store its description */
565             p_es = AddESDescr(p_input, p_pgrm, i_es_pid);
566             if (!p_es)
567             {
568               intf_ErrMsg("Warning: definition of program %d will be uncomplete\n", 
569                           p_pgrm->i_number);
570               /* The best way to handle this is to stop decoding the info for that
571                  section but do as if everything is ok. Thus we will eventually have
572                  an uncomplete ES table marked as being complete and some error msgs */
573               break;
574             }
575             else
576             {
577               /* Store the description of that PID in the slot */
578               p_es->i_type = p_pms[i_offset];
579               p_es->b_psi = 0;
580               if( i_es_pid == p_pgrm->i_pcr_pid )
581                 p_es->b_pcr = 1;
582               else
583                 p_es->b_pcr = 0;
584               
585               /* Read additional info given by the descriptors */
586               i_offset += 5;
587               intf_DbgMsg("description length for PID %d: %d\n", p_es->i_id,
588                        (U16_AT(&p_pms[i_offset-2]) & 0x0FFF));
589               i_descr_end = (U16_AT(&p_pms[i_offset-2]) & 0x0FFF) + i_offset;
590               intf_DbgMsg("description ends at offset: %d\n",  i_descr_end);
591               while( i_offset < i_descr_end )
592               {
593                 DecodeESDescriptor(&p_pms[i_offset], p_es);
594                 i_offset += p_pms[i_offset+1] + 2;
595               }
596             }
597
598             /* Jump to next ES description */
599           }
600
601           /* We now know the info carried in this section */
602           intf_Msg("Description of program %d complete\n", p_pgrm->i_number);
603           p_pgrm->b_is_ok = 1;
604           Set_known(p_descr->a_known_PMT_sections, i_current_section);
605         
606           /* Check if the PMT is now complete */
607           p_descr->i_known_PMT_sections++;
608           if( p_descr->i_known_PMT_sections >= i_last_section)
609           {
610               p_descr->b_is_PMT_complete = 1;
611
612 #ifdef AUTO_SPAWN
613               /* Spawn an audio and a video thread, if possible. */
614               for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
615               {
616                   switch( p_input->p_es[i_es_loop].i_type )
617                   {
618                   case MPEG1_VIDEO_ES:
619                   case MPEG2_VIDEO_ES:
620                       if( p_program_data->cfg.b_video )
621                       {
622                            /* Spawn a video thread */
623                            input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id );
624                       }
625                       break;
626                   case MPEG1_AUDIO_ES:
627                   case MPEG2_AUDIO_ES:
628                       if( p_program_data->cfg.b_audio )
629                       {
630                           /* Spawn an audio thread */
631                           input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id );
632                       }
633                       break;
634                   default:
635                   }
636               }
637 #endif
638           }
639         }
640     }
641
642 #undef p_descr
643 }
644
645 /******************************************************************************
646  * DecodeSrvDescrSection
647  ******************************************************************************
648  * A finir et a refaire proprement ????
649  ******************************************************************************/
650 void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input )
651 {
652   u16 i_stream_id;
653   u8 i_version;
654   u16 i_length;
655   
656   int i_index;
657   int i_offset;
658   boolean_t b_must_update = 0;
659   
660   int i_descr_end;
661
662   ASSERT(p_sdt);
663   ASSERT(p_input);
664
665 #define p_stream (p_input->p_stream)
666   
667    /* Read stream id and version number immediately, to be sure they will be
668       initialised in all the cases in which we will need them */
669    i_stream_id = U16_AT(&p_sdt[3]);
670    i_version = (p_sdt[5] >> 1) & 0x1F;
671    intf_DbgMsg("TS Id: %d, version: %d\n", i_stream_id, i_version);
672
673    /* Take the descriptor into account only if it describes the streams we are
674       receiving */
675    if( p_stream->i_stream_id != i_stream_id )
676    {
677      intf_DbgMsg("SDT doen't apply to our TS but to %s: aborting\n",
678                   U16_AT(&p_sdt[3]));
679    }
680    else
681    {
682      /* Section applyies to our TS, test if the SDT is up to date */
683      if( p_stream->i_SDT_version != i_version )
684      {
685        intf_Msg("SDT has been updated, NOT YET IMPLEMENTED\n");
686
687        /* Ask the PSI decoder to rebuild the table */
688         b_must_update = 1;
689      }
690    }
691
692    /* Rebuild the table if needed */
693    if( b_must_update )
694    {
695      intf_DbgMsg("Updating SDT table\n");
696
697      i_length = p_sdt[1] & 0x0FFF;
698      i_offset = 11;
699
700      while(i_offset < i_length)
701      {
702        
703        /* Find the program to which the description applies */
704        for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
705        {
706          if( p_stream->ap_programs[i_index]->i_number == U16_AT(&p_sdt[i_offset]) )
707          {
708            /* Here we are */
709            intf_Msg("FOUND: %d\n", p_stream->ap_programs[i_index]->i_number);
710            break;
711          }
712        }
713
714        /* Copy the info to the description of that program */
715        i_offset += 5;
716        intf_DbgMsg("description length for SDT: %d\n",
717                    (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF));
718        i_descr_end = (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF) + i_offset;
719        intf_DbgMsg("description ends at offset: %d\n",  i_descr_end);
720        while( i_offset < i_descr_end )
721        {
722          DecodePgrmDescriptor(&p_sdt[i_offset], p_stream->ap_programs[i_index]);
723          i_offset += p_sdt[i_offset+1] + 2;
724        }
725      }
726    }
727 #undef p_stream
728 }
729
730 /******************************************************************************
731  * DecodePgrmDescr
732  ******************************************************************************
733  * Decode any descriptor applying to the definition of a program
734  ******************************************************************************/
735 static void DecodePgrmDescriptor( byte_t* p_descriptor, pgrm_descriptor_t* p_pgrm )
736 {
737     u8 i_type;                                     /* Type of the descriptor */
738     u8 i_length;                                 /* Length of the descriptor */
739 #ifdef DVB_EXTENSIONS
740     int i_offset;                      /* Current position in the descriptor */
741 #endif
742
743     ASSERT(p_descriptor);
744     ASSERT(p_pgrm);
745
746     /* Read type and length of the descriptor */
747     i_type = p_descriptor[0];
748     i_length = p_descriptor[1];
749
750     /* Handle specific descriptor info */
751     switch(i_type)
752     {
753 #ifdef DVB_EXTENSIONS        
754     case PSI_SERVICE_DESCRIPTOR:
755     {
756         /* Store service type */
757         p_pgrm->i_srv_type = p_descriptor[2];
758
759         /* Jump to the beginning of the service name */
760         i_offset = p_descriptor[3] + 5;
761
762         /* Check that the charset used is the normal one (latin) by testing the
763            first byte of the name */
764         if( p_descriptor[i_offset] >= 0x20 )
765         {
766             /* The charset is the one of our computer: just manually dup the string */
767             p_pgrm->psz_srv_name = malloc(i_length - i_offset +1);
768             memcpy(p_pgrm->psz_srv_name, &p_descriptor[i_offset], i_length - i_offset);
769             p_pgrm->psz_srv_name[i_length - i_offset + 1] = '\0';
770         }
771         else
772         {
773             /* Indicate that the name couldn't be printed */
774             p_pgrm->psz_srv_name = "Ununderstandable :)";
775         }
776         break;
777     }
778 #endif
779     default:
780 //        intf_DbgMsg("Unhandled program descriptor received (type: %d)\n", i_type);
781 //        intf_Msg("Unhandled ES descriptor received (type: %d)\n", i_type);
782     }
783 }
784
785 /******************************************************************************
786  * DecodeESDescriptor
787  ******************************************************************************
788  * Decode any descriptor applying to the definition of an ES
789  ******************************************************************************/
790 static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es )
791 {
792     u8 i_type;                                     /* Type of the descriptor */
793     u8 i_length;                                 /* Length of the descriptor */
794 //    int i_offset;                      /* Current position in the descriptor */
795
796     ASSERT(p_descriptor);
797     ASSERT(p_es);
798
799     /* Read type and length of the descriptor */
800     i_type = p_descriptor[0];
801     i_length = p_descriptor[1];
802
803     switch( i_type )
804     {
805     case PSI_VIDEO_STREAM_DESCRIPTOR:
806     {
807         intf_DbgMsg("Video stream descriptor received\n");
808         break;
809     }
810     case PSI_AUDIO_STREAM_DESCRIPTOR:
811     {
812         intf_DbgMsg("Audio stream descriptor received\n");
813         break;
814     }
815     case PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR:
816     {
817         intf_DbgMsg("Target background descriptor received\n");
818         break;
819     }   
820     case PSI_VIDEO_WINDOW_DESCRIPTOR:
821     {
822         intf_DbgMsg("Video window descriptor received\n");
823         break;
824     }
825     default:
826 //        intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
827 //        intf_Msg("Unhandled ES descriptor received (type: %d)\n", i_type);
828     }
829 }
830
831 /******************************************************************************
832  * input_AddPsiPID: Start to receive the PSI info contained in a PID
833  ******************************************************************************
834  * Add a descriptor to the table of es descriptor for that es and mark the es
835  * as being to be received by the input (since all PSI must be received to
836  * build the description of the program)
837  ******************************************************************************/
838 static int input_AddPsiPID( input_thread_t *p_input, int i_pid )
839 {
840   int i_index;
841   es_descriptor_t* p_psi_es;
842   int i_rc = 0;  
843
844   /* Store the description of this stream in the input thread */
845   p_psi_es = AddESDescr(p_input, NULL, i_pid);
846   
847   if(p_psi_es)
848   {
849     /* Precise this ES carries PSI */
850     p_psi_es->b_psi = 1;
851
852     /* Create the buffer needed by the PSI decoder */
853     p_psi_es->p_psi_section = malloc( sizeof( psi_section_t) );
854     if( !p_psi_es->p_psi_section )
855     {
856       intf_ErrMsg( "Malloc error\n" );
857       i_rc = -1;
858     }
859     else
860     {
861       /* Init the reception for that PID */
862       p_psi_es->p_psi_section->b_running_section = 0;
863 //      p_psi_es->p_psi_section->b_discard_payload = 0;
864
865       /* Ask the input thread to demultiplex it: since the interface
866          can also access the table of selected es, lock the elementary
867          stream structure */
868       pthread_mutex_lock( &p_input->es_lock );
869       for( i_index = 0; i_index < INPUT_MAX_SELECTED_ES; i_index++ )
870       {
871         if( !p_input->pp_selected_es[i_index] )
872         {
873           intf_DbgMsg( "Free Selected ES slot found at offset %d: Will use it for PID %d\n",
874                        i_index, i_pid );
875           p_input->pp_selected_es[i_index] = p_psi_es;
876           break;
877         }
878       }
879       pthread_mutex_unlock( &p_input->es_lock );
880
881       if( i_index >= INPUT_MAX_SELECTED_ES )
882       {
883         intf_ErrMsg( "Stream carries to many PID for our decoder\n" );
884         i_rc = -1;
885       }
886     }
887   }
888
889   return( i_rc );
890 }
891
892 /******************************************************************************
893  * input_DelPsiPID: Stop to receive the PSI info contained in a PID
894  ******************************************************************************
895  * Remove the PID from the list of ES descriptors and from the list of ES that
896  * the input must receive.
897  * Known PID for PSI should always be received, so that their description
898  * should be pointed out by a member of pp_selected_es. But as INPUT_MAX_ES
899  * can be different of INPUT_MAX_SELECTED_ES, this may happen, so that we must
900  * do 2 loops.
901  ******************************************************************************/
902 static int input_DelPsiPID( input_thread_t *p_input, int i_pid )
903 {
904   int i_es_index, i_last_sel;  
905
906   intf_DbgMsg( "Deleting PSI PID %d\n", i_pid );
907
908   /* Stop to receive the ES. Since the interface can also access the table
909      of selected es, lock the elementary stream structure */
910   pthread_mutex_lock( &p_input->es_lock );
911   
912   for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES; i_es_index++ )
913   {
914     if( p_input->pp_selected_es[i_es_index] &&
915         p_input->pp_selected_es[i_es_index]->i_id == i_pid )
916     {
917       /* Unmark the stream */
918       p_input->pp_selected_es[i_es_index] = NULL;
919
920       /* There must not be any gap in the pp_selected_es, so move the last
921          selected stream to this slot */
922       for( i_last_sel = i_es_index; p_input->pp_selected_es[i_last_sel] &&
923             i_last_sel < INPUT_MAX_SELECTED_ES; i_last_sel++ );
924       p_input->pp_selected_es[i_es_index] = p_input->pp_selected_es[i_last_sel];
925       p_input->pp_selected_es[i_last_sel] = NULL;
926       break;
927     }
928   }
929
930   pthread_mutex_unlock( &p_input->es_lock );
931
932 #ifdef DEBUG
933   /* Check if the pp_selected_es table may be corrupted */
934   if( i_es_index >= INPUT_MAX_PROGRAM_ES )
935   {
936     intf_ErrMsg( "DelPsiPID error: PID %d is not currently received\n", i_pid );
937   }
938 #endif
939
940   /* Remove the desription of that ES from the table of ES */
941   DestroyESDescr(p_input, NULL, i_pid);
942
943   return( 0 );
944 }
945
946 /******************************************************************************
947  * Precalculate the 32-bit CRC table
948  ******************************************************************************
949  * This table is a global variable shared by all decoders, so it has to be
950  * initialised only once
951  ******************************************************************************/
952 void BuildCrc32Table( )
953 {
954     u32 i, j, k;
955     for( i = 0 ; i < 256 ; i++ )
956     {
957         k = 0;
958         for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1)
959             k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
960         i_crc_32_table[i] = k;
961     }
962 }
963
964 /******************************************************************************
965  * Test the validity of a checksum
966  ******************************************************************************
967  * The checksum must be stored at the end of the data, and the given size must
968  * include the 32 bits of the CRC.
969  * Return 0 if the checksum is OK, any other value if the data are corrupted
970  ******************************************************************************/
971 int CheckCRC32(byte_t* p_data, int i_data_size)
972 {  
973   int i;
974   u32 i_crc = 0xffffffff;
975
976   ASSERT(p_data);
977
978   for (i = 0; i < i_data_size; i++)
979     i_crc = (i_crc << 8) ^ i_crc_32_table[(i_crc >> 24) ^ p_data[i]];
980
981   return i_crc;
982 }
983
984 /******************************************************************************
985  * Is_known: check if a given section has already been received
986  ******************************************************************************
987  * As a table cannot be segmented into more than 256 sections, we store a 256
988  * bits long table, each bit set to one indicating that the corresponding
989  * saction has been received
990  ******************************************************************************/
991 boolean_t Is_known( byte_t* a_known_section, u8 i_section )
992 {
993   byte_t mask;
994   boolean_t b_is_known;
995   
996   /* Where to get the information ? */
997   int i_bit_in_byte = i_section % 8;
998   int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
999
1000   /* Build mask to read the Is_known flag */
1001   mask = 0x01 << i_bit_in_byte;
1002   
1003   /* Read the flag */
1004   b_is_known = a_known_section[i_byte_in_table] & mask;
1005
1006   return b_is_known;
1007 }
1008
1009 /******************************************************************************
1010  * Set_known: mark a given section has having been received
1011  ******************************************************************************
1012  *
1013  ******************************************************************************/
1014 static void Set_known( byte_t* a_known_section, u8 i_section )
1015 {
1016   byte_t mask;
1017   
1018   /* Where to get the information ? */
1019   int i_bit_in_byte = i_section % 8;
1020   int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1021
1022   /* Build mask to read the Is_known flag */
1023   mask = 0x01 << i_bit_in_byte;
1024   
1025   /* Set the flag */
1026   a_known_section[i_byte_in_table] |= mask;
1027 }
1028
1029 /******************************************************************************
1030  * Unset_known: remove the 'received' mark for a given section
1031  ******************************************************************************
1032  * 
1033  ******************************************************************************/
1034 static void Unset_known( byte_t* a_known_section, u8 i_section )
1035 {
1036   byte_t mask;
1037   
1038   /* Where to get the information ? */
1039   int i_bit_in_byte = i_section % 8;
1040   int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1041
1042   /* Build mask to read the Is_known flag */
1043   mask = 0x01 << i_bit_in_byte;
1044   mask = ~mask;
1045   
1046   /* Unset the flag */
1047   a_known_section[i_byte_in_table] &= mask;
1048 }
1049
1050 /******************************************************************************
1051  * AddStreamDescr: add and init the stream descriptor of the given input
1052  ******************************************************************************
1053  * 
1054  ******************************************************************************/
1055 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1056 {
1057   ASSERT(p_input);
1058   
1059   intf_DbgMsg("Adding description for stream %d\n", i_stream_id);
1060
1061   p_input->p_stream = malloc( sizeof(stream_descriptor_t) );
1062
1063   p_input->p_stream->i_stream_id = i_stream_id;
1064
1065   p_input->p_stream->i_PAT_version = PSI_UNINITIALISED;
1066   p_input->p_stream->i_known_PAT_sections = 0;
1067   bzero( p_input->p_stream->a_known_PAT_sections,
1068          sizeof(*p_input->p_stream->a_known_PAT_sections) );
1069   p_input->p_stream->b_is_PAT_complete = 0;
1070
1071   p_input->p_stream->i_known_PMT_sections = 0;
1072   bzero( p_input->p_stream->a_known_PMT_sections,
1073          sizeof(*p_input->p_stream->a_known_PMT_sections) );
1074   p_input->p_stream->b_is_PMT_complete = 0;
1075
1076 #ifdef DVB_EXTENSIONS
1077   p_input->p_stream->i_SDT_version = PSI_UNINITIALISED;
1078   p_input->p_stream->i_known_SDT_sections = 0;
1079   bzero( p_input->p_stream->a_known_SDT_sections,
1080          sizeof(*p_input->p_stream->a_known_SDT_sections) );
1081   p_input->p_stream->b_is_SDT_complete = 0;
1082 #endif
1083
1084   p_input->p_stream->i_pgrm_number = 0;
1085   p_input->p_stream->ap_programs = NULL;
1086
1087   return p_input->p_stream;
1088 }
1089
1090 /******************************************************************************
1091  * DestroyStreamDescr: destroy the stream desciptor of the given input
1092  ******************************************************************************
1093  * 
1094  ******************************************************************************/
1095 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1096 {
1097   int i_index;
1098
1099   ASSERT(p_input);
1100
1101   /* Free the structures that describes the programs of that stream */
1102   for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
1103   {
1104     DestroyPgrmDescr( p_input, p_input->p_stream, p_input->p_stream->ap_programs[i_index]->i_number );
1105   }
1106
1107   /* Free the table of pgrm descriptors */
1108   free( p_input->p_stream->ap_programs );
1109
1110   /* Free the structure that describes the stream itself */
1111   free( p_input->p_stream );
1112
1113   /* Input thread has no more stream descriptor */
1114   p_input->p_stream = NULL;
1115 }
1116
1117 /******************************************************************************
1118  * AddPgrmDescr: add and init a program descriptor
1119  ******************************************************************************
1120  * This program descriptor will be referenced in the given stream descriptor
1121  ******************************************************************************/
1122 static pgrm_descriptor_t* AddPgrmDescr(stream_descriptor_t* p_stream, u16 i_pgrm_id)
1123 {
1124   ASSERT(p_stream);
1125
1126   intf_DbgMsg("Adding description for pgrm %d\n", i_pgrm_id);
1127
1128   /* Add an entry to the list of program associated with the stream */
1129   p_stream->i_pgrm_number++;
1130   p_stream->ap_programs = realloc( p_stream->ap_programs, 
1131                                    p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t*) );
1132
1133   /* Allocate the structure to store this description */
1134   p_stream->ap_programs[p_stream->i_pgrm_number-1] = malloc(sizeof(pgrm_descriptor_t));
1135
1136   /* Init this entry */
1137   p_stream->ap_programs[p_stream->i_pgrm_number-1]->i_number = i_pgrm_id;
1138   p_stream->ap_programs[p_stream->i_pgrm_number-1]->i_version = PSI_UNINITIALISED;
1139   p_stream->ap_programs[p_stream->i_pgrm_number-1]->b_is_ok = 0;
1140
1141   p_stream->ap_programs[p_stream->i_pgrm_number-1]->i_es_number = 0;
1142   p_stream->ap_programs[p_stream->i_pgrm_number-1]->ap_es = NULL;
1143
1144   /* descriptors ???? */
1145
1146   return p_stream->ap_programs[p_stream->i_pgrm_number-1];
1147 }
1148
1149 /******************************************************************************
1150  * AddPgrmDescr: destroy a program descriptor
1151  ******************************************************************************
1152  * All ES descriptions referenced in the descriptor will be deleted.
1153  ******************************************************************************/
1154 static void DestroyPgrmDescr( input_thread_t * p_input, stream_descriptor_t * p_stream, u16 i_pgrm_id )
1155 {
1156   int i_index, i_pgrm_index;
1157   pgrm_descriptor_t * p_pgrm;
1158
1159   ASSERT( p_stream );
1160
1161   /* Find where this program is described */
1162   for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
1163   {
1164     if( p_stream->ap_programs[i_index]->i_number == i_pgrm_id )
1165     {
1166       i_pgrm_index = i_index;
1167       p_pgrm = p_stream->ap_programs[ i_pgrm_index ];
1168       break;
1169     }
1170   }
1171
1172   /* Free the structures that describe the es that belongs to that program */
1173   for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
1174   {
1175     DestroyESDescr( p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id );
1176   }
1177
1178   /* Free the table of es descriptors */
1179   free( p_pgrm->ap_es );
1180
1181   /* Free the description of this stream */
1182   free( p_pgrm );
1183
1184   /* Remove this program from the stream's list of programs */
1185   p_stream->i_pgrm_number--;
1186   p_stream->ap_programs[ i_pgrm_index ] = p_stream->ap_programs[ p_stream->i_pgrm_number ];
1187   p_stream->ap_programs = realloc( p_stream->ap_programs, p_stream->i_pgrm_number * sizeof(pgrm_descriptor_t *) );
1188 }
1189
1190 /******************************************************************************
1191  * AddESDescr:
1192  ******************************************************************************
1193  * Reserve a slot in the table of ES descritors for the ES and add it to the
1194  * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
1195  * alone (PSI ?)
1196  ******************************************************************************/
1197 static es_descriptor_t* AddESDescr(input_thread_t* p_input,
1198                                    pgrm_descriptor_t* p_pgrm, u16 i_es_pid)
1199 {
1200   int i_index;
1201   es_descriptor_t* p_es = NULL;
1202   
1203   ASSERT(p_input);
1204   
1205   intf_DbgMsg("Adding description for ES %d\n", i_es_pid);
1206
1207   /* Find an empty slot to store the description of that es */
1208   for( i_index = 0; i_index < INPUT_MAX_ES &&
1209         p_input->p_es[i_index].i_id != EMPTY_PID; i_index++ );
1210
1211   if( i_index >= INPUT_MAX_ES )
1212   {
1213     /* No slot is empty */
1214     intf_ErrMsg("Stream carries to many PID for our decoder\n");
1215   }
1216   else
1217   {
1218     /* Reserve the slot for that ES */
1219     p_es = &p_input->p_es[i_index];
1220     p_es->i_id = i_es_pid;
1221     intf_DbgMsg("Slot %d in p_es table reserved for ES %d\n", i_index, i_es_pid);
1222     
1223     /* Init its values */
1224     p_es->i_type = 0;  /* ??? */
1225     p_es->b_psi = 0;
1226     p_es->b_pcr = 0;
1227     
1228     p_es->p_pes_packet = NULL;
1229 //    p_es->p_next_pes_packet = NULL;
1230     p_es->p_dec = NULL;
1231
1232     /* Add this ES to the program definition if one is given */
1233     if( p_pgrm )
1234     {
1235       p_pgrm->i_es_number++;
1236       p_pgrm->ap_es = realloc( p_pgrm->ap_es, p_pgrm->i_es_number*sizeof(es_descriptor_t *) );
1237       p_pgrm->ap_es[p_pgrm->i_es_number-1] = p_es;
1238       intf_DbgMsg("Added ES %d to definition of pgrm %d\n", i_es_pid, p_pgrm->i_number);
1239     }
1240     else
1241       intf_DbgMsg("Added ES %d not added to the definition of any pgrm\n", i_es_pid);
1242   }
1243   
1244   return p_es;
1245 }
1246
1247 /******************************************************************************
1248  * DestroyESDescr:
1249  ******************************************************************************
1250  * 
1251  ******************************************************************************/
1252 static void DestroyESDescr(input_thread_t* p_input, pgrm_descriptor_t* p_pgrm, u16 i_pid)
1253 {
1254   int i_index;
1255   
1256   ASSERT(p_pgrm);
1257
1258   /* Look for the description of the ES */
1259   for(i_index = 0; i_index < INPUT_MAX_ES; i_index++)
1260   {
1261     if( p_input->p_es[i_index].i_id == i_pid )
1262     {
1263       /* The table of stream descriptors is static, so don't free memory
1264          but just mark the slot as unused */
1265       p_input->p_es[i_index].i_id = EMPTY_PID;
1266       break;
1267     }
1268   }
1269
1270   /* Remove this ES from the description of the program if it is associated to
1271    one */
1272   if( p_pgrm )
1273   {
1274     for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
1275     {
1276       if( p_input->p_es[i_index].i_id == i_pid )
1277       {
1278         p_pgrm->i_es_number--;
1279         p_pgrm->ap_es[i_index] = p_pgrm->ap_es[p_pgrm->i_es_number];
1280         p_pgrm->ap_es = realloc(p_pgrm->ap_es, p_pgrm->i_es_number);
1281         break;
1282       }
1283     }
1284   }
1285 }