1 /*******************************************************************************
2 * psi.c: PSI management
4 *******************************************************************************
5 * Manages structures containing PSI information, and affiliated decoders.
6 * TO DO: Fonctions d'init des structures
7 ******************************************************************************/
9 /*******************************************************************************
11 *******************************************************************************/
22 #include <netinet/in.h>
23 #include <sys/soundcard.h>
25 #include <X11/extensions/XShm.h>
30 #include "vlc_thread.h"
35 #include "input_ctrl.h"
36 #include "input_psi.h"
37 #include "input_vlan.h"
39 #include "audio_output.h"
41 #include "video_output.h"
43 #include "interface.h"
45 #include "pgm_data.h"*/
48 * Precalculated 32-bits CRC table, shared by all instances of the PSI decoder
50 boolean_t b_crc_initialised = 0;
51 u32 i_crc_32_table[256];
54 * Global configuration variable, need by AUTO_SPAWN to determine
55 * the option (audio and video) passed to the VideoLAN client.
58 //??extern program_data_t *p_main;
62 * Locale type definitions
64 #define PSI_VIDEO_STREAM_DESCRIPTOR 0x02
65 #define PSI_AUDIO_STREAM_DESCRIPTOR 0x03
66 #define PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR 0x07
67 #define PSI_VIDEO_WINDOW_DESCRIPTOR 0x08
70 #define PSI_SERVICE_DESCRIPTOR 0x48
73 /* That info must be stored in the version field since it contains
75 #define PSI_UNINITIALISED 0xFF
80 static int input_AddPsiPID( input_thread_t *p_input, int i_pid );
81 static int input_DelPsiPID( input_thread_t *p_input, int i_pid );
82 static void DecodePgrmAssocSection( byte_t* p_pas, input_thread_t *p_input );
83 static void DecodePgrmMapSection( byte_t* p_pms, input_thread_t *p_input );
84 static void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input );
85 static void DecodePgrmDescriptor( byte_t* p_descr, pgrm_descriptor_t* p_pgrm );
86 static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es );
88 static stream_descriptor_t* AddStreamDescr( input_thread_t* p_input,
90 static void DestroyStreamDescr( input_thread_t* p_input, u16 i_stream_id );
91 static pgrm_descriptor_t* AddPgrmDescr( stream_descriptor_t* p_stream,
93 static void DestroyPgrmDescr( input_thread_t* p_input,
94 stream_descriptor_t* p_stream, u16 i_pgrm_id );
95 static es_descriptor_t* AddESDescr( input_thread_t* p_input,
96 pgrm_descriptor_t* p_pgrm, u16 i_es_pid );
97 static void DestroyESDescr( input_thread_t* p_input, pgrm_descriptor_t* p_pgrm,
100 static void BuildCrc32Table();
101 static int CheckCRC32( u8* p_pms, int i_size);
102 static boolean_t Is_known( byte_t* a_known_section, u8 i_section );
103 static void Set_known( byte_t* a_known_section, u8 i_section );
104 static void Unset_known( byte_t* a_known_section, u8 i_section );
106 /******************************************************************************
107 * input_PsiInit: Initialize PSI decoder
108 ******************************************************************************
109 * Init the structures in which the PSI decoder will put the informations it
110 * got from PSI tables and request for the reception of the PAT.
111 ******************************************************************************/
112 int input_PsiInit( input_thread_t *p_input )
116 /* Precalculate the 32-bit CRC table if not already done ???
117 TO DO -> Put a lock or do that at pgrm init */
118 if( !b_crc_initialised )
121 b_crc_initialised = 1;
124 /* Init the structure that describes the stream we are receiving */
125 AddStreamDescr( p_input, PSI_UNINITIALISED );
127 /* Request for reception of the program association table */
128 input_AddPsiPID( p_input, 0 );
130 #ifdef DVB_EXTENSIONS
131 /* Request for reception of the service description table */
132 input_AddPsiPID( p_input, 17 );
138 /******************************************************************************
139 * input_PsiClean: Clean PSI structures before dying
140 ******************************************************************************/
141 int input_PsiClean( input_thread_t *p_input )
145 /* Stop to receive all the PSI tables associated with that program */
146 /* TO DO ??? -> Not really usefull */
148 /* Clean also descriptors for programs associated with that stream */
149 /* TO DO ??? -> Not really usefull and maybe buggy */
151 /* Destroy the stream description */
152 DestroyStreamDescr( p_input, p_input->p_stream->i_stream_id );
157 /******************************************************************************
158 * input_PsiRead: Read the table of programs
159 ******************************************************************************
160 * Ugly debugging function at that time ???????
161 ******************************************************************************/
162 void input_PsiRead( input_thread_t *p_input /* ??? */ )
166 pgrm_descriptor_t* p_pgrm;
170 /* Lock the tables, since this method can be called from any thread */
173 /* Check if the table is complete or not */
174 if( !p_input->p_stream->b_is_PMT_complete )
176 intf_IntfMsg( "Warning: PMT not yet complete\n" );
180 for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
182 p_pgrm = p_input->p_stream->ap_programs[i_index];
183 intf_DbgMsg("Printing info for program %d\n", p_pgrm->i_number );
184 intf_IntfMsg("Printing info for program %d\n", p_pgrm->i_number );
186 for( i_index2 = 0; i_index2 < p_pgrm->i_es_number; i_index2++ )
188 intf_DbgMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n",
189 p_pgrm->ap_es[i_index2]->i_id,
190 p_pgrm->ap_es[i_index2]->i_type,
191 p_pgrm->ap_es[i_index2]->b_pcr,
192 p_pgrm->ap_es[i_index2]->b_psi);
194 intf_IntfMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n",
195 p_pgrm->ap_es[i_index2]->i_id,
196 p_pgrm->ap_es[i_index2]->i_type,
197 p_pgrm->ap_es[i_index2]->b_pcr,
198 p_pgrm->ap_es[i_index2]->b_psi);
202 /* Unock the tables */
206 /******************************************************************************
207 * input_PsiDecode: Decode a PSI section
208 ******************************************************************************
209 * This funtion is essentially a wrapper that will perform basic checks on
210 * the section and then call the right function according to its type.
211 ******************************************************************************/
212 void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section )
215 ASSERT(p_psi_section);
217 /* Hexa dump of the beginning of the section (for real men) */
218 //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] );
220 /* Check the CRC validity if any CRC is carried */
221 if( p_psi_section->buffer[1] & 0x80 )
223 if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )
225 intf_DbgMsg("iSize: %d, CRC: %d\n", p_psi_section->i_length,
226 U32_AT(&p_psi_section->buffer[p_psi_section->i_length-4]));
227 intf_DbgMsg( "Invalid CRC for PSI\n" );
232 /* If the section is not immediatly applicable, trash it (DVB drafts disallow
233 transmission of such sections, so we didn't implement it) */
234 if( !p_psi_section->buffer[5] & 0x01 )
236 intf_DbgMsg( "PSI not yet applicable: trash it\n" );
240 /* Handle the packet according to it's type given it the table_id */
241 switch ( p_psi_section->buffer[0] )
244 //intf_DbgMsg("Program association section received\n");
245 DecodePgrmAssocSection(p_psi_section->buffer, p_input);
248 //intf_DbgMsg("Conditional access section received\n");
251 //intf_DbgMsg("Program map section received\n");
252 DecodePgrmMapSection(p_psi_section->buffer, p_input);
255 //intf_DbgMsg("Service description section received\n");
256 DecodeSrvDescrSection(p_psi_section->buffer, p_input);
259 //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",
260 // p_psi_section->buffer[0]);
264 /******************************************************************************
265 * DecodeAssocSection: Decode a PAS
266 ******************************************************************************
267 * No check is made to known if the table is currently applicable or not, so
268 * that unapplicable sections must be filtered before calling this function
269 * The Program Association Table can be segmented to occupy multiple sections
270 * so that we have to know which sections we have already received (IsKnown() /
272 ******************************************************************************/
273 static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input )
275 u8 i_stream_id; /* Id of the stream described in that section */
276 u8 i_version; /* Version of the table carried in the section */
278 u16 i_pgrm_id; /* Id of the current described pgrm */
279 u16 i_pgrm_map_pid; /* PID of the associated program map table */
280 int i_pgrm_number; /* Number of programs described in the section */
282 boolean_t b_is_invalid = 0;
284 u8 i_current_section;
293 #define p_descr (p_input->p_stream)
295 /* Read stream id and version number immediately, to be sure they will be
296 initialised in all cases we will need it */
297 i_stream_id = U16_AT(&p_pas[3]);
298 i_version = (p_pas[5] >> 1) & 0x1F;
299 //intf_DbgMsg("TS Id: %d, version: %d\n", U16_AT(&p_pas[3]),(p_pas[5] >> 1) & 0x1F);
301 /* Test if the stream has not changed by looking at the stream_id */
302 if( p_descr->i_stream_id != i_stream_id )
304 /* This can either mean that the PSI decoder has just started or that
305 the stream has changed */
306 if( p_descr->i_PAT_version== PSI_UNINITIALISED )
307 intf_DbgMsg("Building Program Association table\n");
309 intf_ErrMsg( "Stream Id has suddently changed ! Rebuilding PAT\n" );
311 /* Whatever it is, ask the PSI decoder to rebuild the table */
316 /* Stream has not changed, test if the PMT is up to date */
317 if( p_descr->i_PAT_version != i_version )
319 intf_DbgMsg("PAT has been updated, rebuilding it\n");
320 /* Ask the PSI decoder to rebuild the table */
325 /* Clear the table if needed */
328 intf_DbgMsg("Updating PAT table\n");
330 /* Any program in the stream may have disapeared, or a new one
331 can have been added. The good way to handle such a case would be
332 to build a temporary table and to make a diff */
334 /* Stop the reception of all programs and PSI informations
335 associated with this stream, excepted the PAT on PID 0 and the SDT
337 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES &&
338 p_input->pp_selected_es[i_es_index]; i_es_index++ )
340 if( p_input->pp_selected_es[i_es_index]->b_psi )
342 if( p_input->pp_selected_es[i_es_index]->i_id != 0
343 #ifdef DVB_EXTENSIONS
344 && p_input->pp_selected_es[i_es_index]->i_id != 17
347 input_DelPsiPID( p_input,
348 p_input->pp_selected_es[i_es_index]->i_id );
351 input_DelPgrmElem( p_input,
352 p_input->pp_selected_es[i_es_index]->i_id );
355 /* Recreate a new stream description. Since it is virgin, the decoder
356 will rebuild it entirely on is own */
357 DestroyStreamDescr(p_input, p_descr->i_stream_id);
358 AddStreamDescr(p_input, i_stream_id);
360 /* Record the new version for that table */
361 p_descr->i_PAT_version = i_version;
364 /* Build the table if not already complete or if it was cleared */
365 if( p_descr->b_is_PAT_complete )
369 intf_DbgMsg("Bug: table invalid but PAT said to be complete\n");
373 /* Check if we already heard about that section */
374 i_last_section = p_pas[7];
375 i_current_section = p_pas[6];
377 // intf_DbgMsg( "Section %d (last section %d)\n",
378 // i_current_section, i_last_section );
380 if( Is_known(p_descr->a_known_PAT_sections, i_current_section) )
383 // intf_DbgMsg("Section already received, skipping\n");
387 /* Compute the number of program_map PID carried in this section */
388 i_pgrm_number = ((U16_AT(&p_pas[1]) & 0xFFF) - 9) / 4;
389 intf_DbgMsg("Number of Pgrm in that section: %d\n", i_pgrm_number);
391 /* Start the reception of those program map PID */
392 for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ )
394 i_pgrm_id = U16_AT(&p_pas[8+4*i_pgrm_index]);
395 i_pgrm_map_pid = U16_AT(&p_pas[8+4*i_pgrm_index+2]) & 0x1FFF;
396 intf_DbgMsg("Pgrm %d described on pid %d\n", i_pgrm_id,
399 /* Check we are not already receiving that pid because it carries
400 info for another program */
401 for( i_es_index = 0; i_es_index < INPUT_MAX_ES; i_es_index++ )
403 if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid)
405 intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid);
406 i_es_index = INPUT_MAX_ES+1;
410 /* Start to receive that PID if we're not already doing it */
411 if( i_es_index <= INPUT_MAX_ES )
412 input_AddPsiPID( p_input, i_pgrm_map_pid );
414 /* Append an entry to the pgrm_descriptor table to later store
415 the description of this program, unless program number is 0
416 (Network information table) */
419 intf_DbgMsg("Adding program %d to the PMT\n", i_pgrm_id);
420 AddPgrmDescr(p_descr, i_pgrm_id);
424 /* We now know the info carried in this section */
425 Set_known(p_descr->a_known_PAT_sections, i_current_section);
427 /* Check if the table is now complete */
428 p_descr->i_known_PAT_sections++;
429 if( p_descr->i_known_PAT_sections >= i_last_section)
430 p_descr->b_is_PAT_complete = 1;
437 /******************************************************************************
438 * DecodePgrmMapSection: Decode a PMS
439 ******************************************************************************
440 * No check is made to known if the table is currently applicable or not, so
441 * that unapplicable sections must be filtered before calling this function
442 * The Program Map Table can be segmented to occupy multiple sections so that
443 * we have to know which sections we have already received (IsKnown() /
445 * Note that the processing of those sections is different from the one of the
446 * others since here a section refers to a single program, and a program cannot
447 * be segmented into multiple sections
448 ******************************************************************************/
449 static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
451 u16 i_pgrm_number; /* Id of the program described in that section */
452 u8 i_version; /* Version of the description for that program */
455 u16 i_section_length;
459 u8 i_current_section;
467 pgrm_descriptor_t* p_pgrm;
468 es_descriptor_t* p_es;
470 #define p_descr (p_input->p_stream)
472 /* Read the id of the program described in that section */
473 i_pgrm_number = U16_AT(&p_pms[3]);
474 // intf_DbgMsg( "PMT section received for program %d\n", i_pgrm_number );
476 /* Find where is stored the description of this program */
477 for( i_index = 0; i_index < p_descr->i_pgrm_number &&
478 i_pgrm_number != p_descr->ap_programs[i_index]->i_number; i_index++ );
480 if( i_index >= p_descr->i_pgrm_number )
482 /* If none entry exists, this simply means that the PAT is not complete,
483 so skip this section since it is the responsability of the PAT decoder
484 to add pgrm_descriptor slots to the table of known pgrms */
485 intf_DbgMsg( "Unknown pgrm %d: skipping its description\n", i_pgrm_number );
489 /* We now have the slot which is the program described: we can begin with
490 the decoding of its description */
491 p_pgrm = p_descr->ap_programs[i_index];
493 /* Which section of the description of that program did we receive ? */
494 i_last_section = p_pms[7];
495 i_current_section = p_pms[6];
496 // intf_DbgMsg("Section %d (last section %d)\n", i_current_section, i_last_section);
498 /* Is this an update of the description for this program ? */
499 i_version = (p_pms[5] >> 1) & 0x1F;
500 if( p_pgrm->i_version != i_version )
502 intf_DbgMsg("Updating PMT for program %d\n", i_pgrm_number);
504 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
506 /* Stop the reception of the ES if needed by calling the function
507 normally used by the interface to manage this */
508 if( input_IsElemRecv(p_input, p_pgrm->ap_es[i_index]->i_id) )
510 intf_DbgMsg( "PID %d is no more valid: stopping its reception\n",
511 p_pgrm->ap_es[i_index]->i_id );
512 input_DelPgrmElem( p_input, p_pgrm->ap_es[i_index]->i_id );
515 /* Remove the descriptor associated to the es of this programs */
516 intf_DbgMsg( "Invalidating PID %d\n", p_pgrm->ap_es[i_index]->i_id );
517 DestroyESDescr(p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id);
520 /* Update version number */
521 p_pgrm->i_version = i_version;
523 /* Ask the decoder to update the description of that program */
524 p_descr->i_known_PMT_sections--;
525 Unset_known( p_descr->a_known_PMT_sections, i_current_section );
529 /* Read the info for that pgrm is the one we have is not up to date or
530 if we don't have any */
531 if( p_pgrm->b_is_ok )
534 // intf_DbgMsg("Program description OK, nothing to do\n");
538 /* Check if we already heard about that section */
539 if( Is_known(p_descr->a_known_PMT_sections, i_current_section) )
542 // intf_DbgMsg("Section already received, skipping\n");
546 /* Read the corresponding PCR */
547 p_pgrm->i_pcr_pid = U16_AT(&p_pms[8]) & 0x1fff;
548 intf_DbgMsg("PCR at PID: %d\n", p_pgrm->i_pcr_pid);
550 /* Compute the length of the section minus the final CRC */
551 i_section_length = (U16_AT(&p_pms[1]) & 0xFFF) + 3 - 4;
552 intf_DbgMsg("Section length (without CRC): %d\n", i_section_length);
554 /* Read additional info stored in the descriptors if any */
555 intf_DbgMsg("Description length for program %d: %d\n",
556 p_pgrm->i_number, (U16_AT(&p_pms[10]) & 0x0FFF));
557 i_descr_end = (U16_AT(&p_pms[10]) & 0x0FFF) + 12;
558 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
561 while( i_offset < i_descr_end )
563 DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm);
564 i_offset += p_pms[i_offset+1] + 2;
567 /* Read all the ES descriptions */
568 while( i_offset < i_section_length )
570 /* Read type of that ES */
571 intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]);
573 /* Read PID of that ES */
574 i_es_pid = U16_AT(&p_pms[i_offset+1]) & 0x1FF;
575 intf_DbgMsg("ES PID: %d\n", i_es_pid);
577 /* Add the ES to the program description and reserve a slot in the
578 table of ES to store its description */
579 p_es = AddESDescr(p_input, p_pgrm, i_es_pid);
582 intf_ErrMsg("Warning: definition for pgrm %d won't be complete\n",
584 /* The best way to handle this is to stop decoding the info for
585 that section but do as if everything is ok. Thus we will
586 eventually have an uncomplete ES table marked as being
587 complete and some error msgs */
592 /* Store the description of that PID in the slot */
593 p_es->i_type = p_pms[i_offset];
595 if( i_es_pid == p_pgrm->i_pcr_pid )
600 /* Read additional info given by the descriptors */
602 intf_DbgMsg("description length for PID %d: %d\n", p_es->i_id,
603 (U16_AT(&p_pms[i_offset-2]) & 0x0FFF));
604 i_descr_end = (U16_AT(&p_pms[i_offset-2]) & 0x0FFF) + i_offset;
605 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
606 while( i_offset < i_descr_end )
608 DecodeESDescriptor(&p_pms[i_offset], p_es);
609 i_offset += p_pms[i_offset+1] + 2;
613 /* Jump to next ES description */
616 /* We now know the info carried in this section */
617 intf_DbgMsg("Description of program %d complete\n", p_pgrm->i_number);
619 Set_known(p_descr->a_known_PMT_sections, i_current_section);
621 /* Check if the PMT is now complete */
622 p_descr->i_known_PMT_sections++;
623 if( p_descr->i_known_PMT_sections >= i_last_section)
625 p_descr->b_is_PMT_complete = 1;
628 /* Spawn an audio and a video thread, if possible. */
629 for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
631 switch( p_input->p_es[i_es_loop].i_type )
635 if( p_main->b_video )
637 /* Spawn a video thread */
638 input_AddPgrmElem( p_input,
639 p_input->p_es[i_es_loop].i_id );
644 if( p_main->b_audio )
646 /* Spawn an audio thread */
647 input_AddPgrmElem( p_input,
648 p_input->p_es[i_es_loop].i_id );
662 /******************************************************************************
663 * DecodeSrvDescrSection
664 ******************************************************************************
665 * A finir et a refaire proprement ????
666 ******************************************************************************/
667 void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input )
675 boolean_t b_must_update = 0;
682 #define p_stream (p_input->p_stream)
684 /* Read stream id and version number immediately, to be sure they will be
685 initialised in all the cases in which we will need them */
686 i_stream_id = U16_AT(&p_sdt[3]);
687 i_version = (p_sdt[5] >> 1) & 0x1F;
688 intf_DbgMsg("TS Id: %d, version: %d\n", i_stream_id, i_version);
690 /* Take the descriptor into account only if it describes the streams we are
692 if( p_stream->i_stream_id != i_stream_id )
694 intf_DbgMsg("SDT doen't apply to our TS but to %s: aborting\n",
699 /* Section applyies to our TS, test if the SDT is up to date */
700 if( p_stream->i_SDT_version != i_version )
702 intf_DbgMsg("SDT has been updated, NOT YET IMPLEMENTED\n");
704 /* Ask the PSI decoder to rebuild the table */
709 /* Rebuild the table if needed */
712 intf_DbgMsg("Updating SDT table\n");
714 i_length = p_sdt[1] & 0x0FFF;
717 while(i_offset < i_length)
720 /* Find the program to which the description applies */
721 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
723 if( p_stream->ap_programs[i_index]->i_number ==
724 U16_AT(&p_sdt[i_offset]) )
727 intf_DbgMsg("FOUND: %d\n", p_stream->ap_programs[i_index]->i_number);
732 /* Copy the info to the description of that program */
734 intf_DbgMsg("description length for SDT: %d\n",
735 (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF));
736 i_descr_end = (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF) + i_offset;
737 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
738 while( i_offset < i_descr_end )
740 DecodePgrmDescriptor(&p_sdt[i_offset], p_stream->ap_programs[i_index]);
741 i_offset += p_sdt[i_offset+1] + 2;
748 /******************************************************************************
750 ******************************************************************************
751 * Decode any descriptor applying to the definition of a program
752 ******************************************************************************/
753 static void DecodePgrmDescriptor( byte_t* p_descriptor,
754 pgrm_descriptor_t* p_pgrm )
756 u8 i_type; /* Type of the descriptor */
757 u8 i_length; /* Length of the descriptor */
758 #ifdef DVB_EXTENSIONS
759 int i_offset; /* Current position in the descriptor */
762 ASSERT(p_descriptor);
765 /* Read type and length of the descriptor */
766 i_type = p_descriptor[0];
767 i_length = p_descriptor[1];
769 /* Handle specific descriptor info */
772 #ifdef DVB_EXTENSIONS
773 case PSI_SERVICE_DESCRIPTOR:
775 /* Store service type */
776 p_pgrm->i_srv_type = p_descriptor[2];
778 /* Jump to the beginning of the service name */
779 i_offset = p_descriptor[3] + 5;
781 /* Check that the charset used is the normal one (latin) by testing the
782 first byte of the name */
783 if( p_descriptor[i_offset] >= 0x20 )
785 /* The charset is the one of our computer: just dup the string */
786 p_pgrm->psz_srv_name = malloc(i_length - i_offset +1);
787 memcpy(p_pgrm->psz_srv_name, &p_descriptor[i_offset],
788 i_length - i_offset);
789 p_pgrm->psz_srv_name[i_length - i_offset + 1] = '\0';
793 /* Indicate that the name couldn't be printed */
794 p_pgrm->psz_srv_name = "Ununderstandable :)";
800 // intf_DbgMsg("Unhandled program descriptor received (type: %d)\n", i_type);
801 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
805 /******************************************************************************
807 ******************************************************************************
808 * Decode any descriptor applying to the definition of an ES
809 ******************************************************************************/
810 static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es )
812 u8 i_type; /* Type of the descriptor */
813 u8 i_length; /* Length of the descriptor */
814 // int i_offset; /* Current position in the descriptor */
816 ASSERT(p_descriptor);
819 /* Read type and length of the descriptor */
820 i_type = p_descriptor[0];
821 i_length = p_descriptor[1];
825 case PSI_VIDEO_STREAM_DESCRIPTOR:
827 intf_DbgMsg("Video stream descriptor received\n");
830 case PSI_AUDIO_STREAM_DESCRIPTOR:
832 intf_DbgMsg("Audio stream descriptor received\n");
835 case PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR:
837 intf_DbgMsg("Target background descriptor received\n");
840 case PSI_VIDEO_WINDOW_DESCRIPTOR:
842 intf_DbgMsg("Video window descriptor received\n");
846 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
847 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
851 /******************************************************************************
852 * input_AddPsiPID: Start to receive the PSI info contained in a PID
853 ******************************************************************************
854 * Add a descriptor to the table of es descriptor for that es and mark the es
855 * as being to be received by the input (since all PSI must be received to
856 * build the description of the program)
857 ******************************************************************************/
858 static int input_AddPsiPID( input_thread_t *p_input, int i_pid )
861 es_descriptor_t* p_psi_es;
864 /* Store the description of this stream in the input thread */
865 p_psi_es = AddESDescr(p_input, NULL, i_pid);
869 /* Precise this ES carries PSI */
872 /* Create the buffer needed by the PSI decoder */
873 p_psi_es->p_psi_section = malloc( sizeof( psi_section_t) );
874 if( !p_psi_es->p_psi_section )
876 intf_ErrMsg( "Malloc error\n" );
881 /* Init the reception for that PID */
882 p_psi_es->p_psi_section->b_running_section = 0;
883 // p_psi_es->p_psi_section->b_discard_payload = 0;
885 /* Ask the input thread to demultiplex it: since the interface
886 can also access the table of selected es, lock the elementary
888 vlc_mutex_lock( &p_input->es_lock );
889 for( i_index = 0; i_index < INPUT_MAX_SELECTED_ES; i_index++ )
891 if( !p_input->pp_selected_es[i_index] )
893 intf_DbgMsg( "Free Selected ES slot found at offset %d for PID %d\n",
895 p_input->pp_selected_es[i_index] = p_psi_es;
899 vlc_mutex_unlock( &p_input->es_lock );
901 if( i_index >= INPUT_MAX_SELECTED_ES )
903 intf_ErrMsg( "Stream carries to many PID for our decoder\n" );
912 /******************************************************************************
913 * input_DelPsiPID: Stop to receive the PSI info contained in a PID
914 ******************************************************************************
915 * Remove the PID from the list of ES descriptors and from the list of ES that
916 * the input must receive.
917 * Known PID for PSI should always be received, so that their description
918 * should be pointed out by a member of pp_selected_es. But as INPUT_MAX_ES
919 * can be different of INPUT_MAX_SELECTED_ES, this may happen, so that we must
921 ******************************************************************************/
922 static int input_DelPsiPID( input_thread_t *p_input, int i_pid )
924 int i_es_index, i_last_sel;
926 intf_DbgMsg( "Deleting PSI PID %d\n", i_pid );
928 /* Stop to receive the ES. Since the interface can also access the table
929 of selected es, lock the elementary stream structure */
930 vlc_mutex_lock( &p_input->es_lock );
932 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES; i_es_index++ )
934 if( p_input->pp_selected_es[i_es_index] &&
935 p_input->pp_selected_es[i_es_index]->i_id == i_pid )
937 /* Unmark the stream */
938 p_input->pp_selected_es[i_es_index] = NULL;
940 /* There must not be any gap in the pp_selected_es, so move the last
941 selected stream to this slot */
942 for( i_last_sel = i_es_index; p_input->pp_selected_es[i_last_sel] &&
943 i_last_sel < INPUT_MAX_SELECTED_ES; i_last_sel++ );
944 p_input->pp_selected_es[i_es_index] = p_input->pp_selected_es[i_last_sel];
945 p_input->pp_selected_es[i_last_sel] = NULL;
950 vlc_mutex_unlock( &p_input->es_lock );
953 /* Check if the pp_selected_es table may be corrupted */
954 if( i_es_index >= INPUT_MAX_PROGRAM_ES )
956 intf_ErrMsg( "DelPsiPID error: PID %d is not currently received\n", i_pid );
960 /* Remove the desription of that ES from the table of ES */
961 DestroyESDescr(p_input, NULL, i_pid);
966 /******************************************************************************
967 * Precalculate the 32-bit CRC table
968 ******************************************************************************
969 * This table is a global variable shared by all decoders, so it has to be
970 * initialised only once
971 ******************************************************************************/
972 void BuildCrc32Table( )
975 for( i = 0 ; i < 256 ; i++ )
978 for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1)
979 k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
980 i_crc_32_table[i] = k;
984 /******************************************************************************
985 * Test the validity of a checksum
986 ******************************************************************************
987 * The checksum must be stored at the end of the data, and the given size must
988 * include the 32 bits of the CRC.
989 * Return 0 if the checksum is OK, any other value if the data are corrupted
990 ******************************************************************************/
991 int CheckCRC32(byte_t* p_data, int i_data_size)
994 u32 i_crc = 0xffffffff;
998 for (i = 0; i < i_data_size; i++)
999 i_crc = (i_crc << 8) ^ i_crc_32_table[(i_crc >> 24) ^ p_data[i]];
1004 /******************************************************************************
1005 * Is_known: check if a given section has already been received
1006 ******************************************************************************
1007 * As a table cannot be segmented into more than 256 sections, we store a 256
1008 * bits long table, each bit set to one indicating that the corresponding
1009 * saction has been received
1010 ******************************************************************************/
1011 boolean_t Is_known( byte_t* a_known_section, u8 i_section )
1014 boolean_t b_is_known;
1016 /* Where to get the information ? */
1017 int i_bit_in_byte = i_section % 8;
1018 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1020 /* Build mask to read the Is_known flag */
1021 mask = 0x01 << i_bit_in_byte;
1024 b_is_known = a_known_section[i_byte_in_table] & mask;
1029 /******************************************************************************
1030 * Set_known: mark a given section has having been received
1031 ******************************************************************************
1033 ******************************************************************************/
1034 static void Set_known( byte_t* a_known_section, u8 i_section )
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;
1042 /* Build mask to read the Is_known flag */
1043 mask = 0x01 << i_bit_in_byte;
1046 a_known_section[i_byte_in_table] |= mask;
1049 /******************************************************************************
1050 * Unset_known: remove the 'received' mark for a given section
1051 ******************************************************************************
1053 ******************************************************************************/
1054 static void Unset_known( byte_t* a_known_section, u8 i_section )
1058 /* Where to get the information ? */
1059 int i_bit_in_byte = i_section % 8;
1060 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1062 /* Build mask to read the Is_known flag */
1063 mask = 0x01 << i_bit_in_byte;
1066 /* Unset the flag */
1067 a_known_section[i_byte_in_table] &= mask;
1070 /******************************************************************************
1071 * AddStreamDescr: add and init the stream descriptor of the given input
1072 ******************************************************************************
1074 ******************************************************************************/
1075 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input,
1080 intf_DbgMsg("Adding description for stream %d\n", i_stream_id);
1082 p_input->p_stream = malloc( sizeof(stream_descriptor_t) );
1084 p_input->p_stream->i_stream_id = i_stream_id;
1086 p_input->p_stream->i_PAT_version = PSI_UNINITIALISED;
1087 p_input->p_stream->i_known_PAT_sections = 0;
1088 bzero( p_input->p_stream->a_known_PAT_sections,
1089 sizeof(*p_input->p_stream->a_known_PAT_sections) );
1090 p_input->p_stream->b_is_PAT_complete = 0;
1092 p_input->p_stream->i_known_PMT_sections = 0;
1093 bzero( p_input->p_stream->a_known_PMT_sections,
1094 sizeof(*p_input->p_stream->a_known_PMT_sections) );
1095 p_input->p_stream->b_is_PMT_complete = 0;
1097 #ifdef DVB_EXTENSIONS
1098 p_input->p_stream->i_SDT_version = PSI_UNINITIALISED;
1099 p_input->p_stream->i_known_SDT_sections = 0;
1100 bzero( p_input->p_stream->a_known_SDT_sections,
1101 sizeof(*p_input->p_stream->a_known_SDT_sections) );
1102 p_input->p_stream->b_is_SDT_complete = 0;
1105 p_input->p_stream->i_pgrm_number = 0;
1106 p_input->p_stream->ap_programs = NULL;
1108 return p_input->p_stream;
1111 /******************************************************************************
1112 * DestroyStreamDescr: destroy the stream desciptor of the given input
1113 ******************************************************************************
1115 ******************************************************************************/
1116 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1122 /* Free the structures that describes the programs of that stream */
1123 for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
1125 DestroyPgrmDescr( p_input, p_input->p_stream,
1126 p_input->p_stream->ap_programs[i_index]->i_number );
1129 /* Free the table of pgrm descriptors */
1130 free( p_input->p_stream->ap_programs );
1132 /* Free the structure that describes the stream itself */
1133 free( p_input->p_stream );
1135 /* Input thread has no more stream descriptor */
1136 p_input->p_stream = NULL;
1139 /******************************************************************************
1140 * AddPgrmDescr: add and init a program descriptor
1141 ******************************************************************************
1142 * This program descriptor will be referenced in the given stream descriptor
1143 ******************************************************************************/
1144 static pgrm_descriptor_t* AddPgrmDescr( stream_descriptor_t* p_stream,
1147 int i_pgrm_index = p_stream->i_pgrm_number; /* Where to add the pgrm */
1151 intf_DbgMsg("Adding description for pgrm %d\n", i_pgrm_id);
1153 /* Add an entry to the list of program associated with the stream */
1154 p_stream->i_pgrm_number++;
1155 p_stream->ap_programs = realloc( p_stream->ap_programs,
1156 p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t*) );
1158 /* Allocate the structure to store this description */
1159 p_stream->ap_programs[i_pgrm_index] = malloc(sizeof(pgrm_descriptor_t));
1161 /* Init this entry */
1162 p_stream->ap_programs[i_pgrm_index]->i_number = i_pgrm_id;
1163 p_stream->ap_programs[i_pgrm_index]->i_version = PSI_UNINITIALISED;
1164 p_stream->ap_programs[i_pgrm_index]->b_is_ok = 0;
1166 p_stream->ap_programs[i_pgrm_index]->i_es_number = 0;
1167 p_stream->ap_programs[i_pgrm_index]->ap_es = NULL;
1169 /* descriptors ???? */
1171 return p_stream->ap_programs[i_pgrm_index];
1174 /******************************************************************************
1175 * AddPgrmDescr: destroy a program descriptor
1176 ******************************************************************************
1177 * All ES descriptions referenced in the descriptor will be deleted.
1178 ******************************************************************************/
1179 static void DestroyPgrmDescr( input_thread_t * p_input,
1180 stream_descriptor_t * p_stream, u16 i_pgrm_id )
1182 int i_index, i_pgrm_index = -1;
1183 pgrm_descriptor_t* p_pgrm = NULL;
1187 intf_DbgMsg("Deleting description for pgrm %d\n", i_pgrm_id);
1189 /* Find where this program is described */
1190 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
1192 if( p_stream->ap_programs[i_index]->i_number == i_pgrm_id )
1194 i_pgrm_index = i_index;
1195 p_pgrm = p_stream->ap_programs[ i_pgrm_index ];
1200 /* Make sure that the pgrm exists */
1201 ASSERT(i_pgrm_index >= 0);
1204 /* Free the structures that describe the es that belongs to that program */
1205 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
1207 DestroyESDescr( p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id );
1210 /* Free the table of es descriptors */
1211 free( p_pgrm->ap_es );
1213 /* Free the description of this stream */
1216 /* Remove this program from the stream's list of programs */
1217 p_stream->i_pgrm_number--;
1218 p_stream->ap_programs[i_pgrm_index] =
1219 p_stream->ap_programs[p_stream->i_pgrm_number];
1220 p_stream->ap_programs = realloc( p_stream->ap_programs,
1221 p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t *) );
1224 /******************************************************************************
1226 ******************************************************************************
1227 * Reserve a slot in the table of ES descritors for the ES and add it to the
1228 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
1230 ******************************************************************************/
1231 static es_descriptor_t* AddESDescr(input_thread_t* p_input,
1232 pgrm_descriptor_t* p_pgrm, u16 i_es_pid)
1235 es_descriptor_t* p_es = NULL;
1239 intf_DbgMsg("Adding description for ES %d\n", i_es_pid);
1241 /* Find an empty slot to store the description of that es */
1242 for( i_index = 0; i_index < INPUT_MAX_ES &&
1243 p_input->p_es[i_index].i_id != EMPTY_PID; i_index++ );
1245 if( i_index >= INPUT_MAX_ES )
1247 /* No slot is empty */
1248 intf_ErrMsg("Stream carries to many PID for our decoder\n");
1252 /* Reserve the slot for that ES */
1253 p_es = &p_input->p_es[i_index];
1254 p_es->i_id = i_es_pid;
1255 intf_DbgMsg("Slot %d in p_es table assigned to ES %d\n", i_index, i_es_pid);
1257 /* Init its values */
1258 p_es->i_type = 0; /* ??? */
1261 p_es->i_continuity_counter = 0xFF;
1263 p_es->p_pes_packet = NULL;
1264 // p_es->p_next_pes_packet = NULL;
1267 /* Add this ES to the program definition if one is given */
1270 p_pgrm->i_es_number++;
1271 p_pgrm->ap_es = realloc( p_pgrm->ap_es,
1272 p_pgrm->i_es_number*sizeof(es_descriptor_t *) );
1273 p_pgrm->ap_es[p_pgrm->i_es_number-1] = p_es;
1274 intf_DbgMsg( "Added ES %d to definition of pgrm %d\n",
1275 i_es_pid, p_pgrm->i_number );
1278 intf_DbgMsg( "Added ES %d not added to the definition of any pgrm\n",
1285 /******************************************************************************
1287 ******************************************************************************
1289 ******************************************************************************/
1290 static void DestroyESDescr(input_thread_t* p_input,
1291 pgrm_descriptor_t* p_pgrm, u16 i_pid)
1295 /* Look for the description of the ES */
1296 for(i_index = 0; i_index < INPUT_MAX_ES; i_index++)
1298 if( p_input->p_es[i_index].i_id == i_pid )
1300 /* The table of stream descriptors is static, so don't free memory
1301 but just mark the slot as unused */
1302 p_input->p_es[i_index].i_id = EMPTY_PID;
1307 /* Remove this ES from the description of the program if it is associated to
1311 for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
1313 if( p_input->p_es[i_index].i_id == i_pid )
1315 p_pgrm->i_es_number--;
1316 p_pgrm->ap_es[i_index] = p_pgrm->ap_es[p_pgrm->i_es_number];
1317 p_pgrm->ap_es = realloc(p_pgrm->ap_es, p_pgrm->i_es_number);