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