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 */
222 if( p_psi_section->buffer[1] & 0x80 )
224 if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )
226 intf_DbgMsg("iSize: %d, CRC: %d\n", p_psi_section->i_length,
227 U32_AT(&p_psi_section->buffer[p_psi_section->i_length-4]));
228 intf_DbgMsg( "Invalid CRC for PSI\n" );
234 /* If the section is not immediatly applicable, trash it (DVB drafts disallow
235 transmission of such sections, so we didn't implement it) */
236 if( !p_psi_section->buffer[5] & 0x01 )
238 intf_DbgMsg( "PSI not yet applicable: trash it\n" );
242 /* Handle the packet according to it's type given it the table_id */
243 switch ( p_psi_section->buffer[0] )
246 //intf_DbgMsg("Program association section received\n");
247 DecodePgrmAssocSection(p_psi_section->buffer, p_input);
250 //intf_DbgMsg("Conditional access section received\n");
253 //intf_DbgMsg("Program map section received\n");
254 DecodePgrmMapSection(p_psi_section->buffer, p_input);
257 //intf_DbgMsg("Service description section received\n");
258 DecodeSrvDescrSection(p_psi_section->buffer, p_input);
261 //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",
262 // p_psi_section->buffer[0]);
266 /******************************************************************************
267 * DecodeAssocSection: Decode a PAS
268 ******************************************************************************
269 * No check is made to known if the table is currently applicable or not, so
270 * that unapplicable sections must be filtered before calling this function
271 * The Program Association Table can be segmented to occupy multiple sections
272 * so that we have to know which sections we have already received (IsKnown() /
274 ******************************************************************************/
275 static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input )
277 u8 i_stream_id; /* Id of the stream described in that section */
278 u8 i_version; /* Version of the table carried in the section */
280 u16 i_pgrm_id; /* Id of the current described pgrm */
281 u16 i_pgrm_map_pid; /* PID of the associated program map table */
282 int i_pgrm_number; /* Number of programs described in the section */
284 boolean_t b_is_invalid = 0;
286 u8 i_current_section;
295 #define p_descr (p_input->p_stream)
297 /* Read stream id and version number immediately, to be sure they will be
298 initialised in all cases we will need it */
299 i_stream_id = U16_AT(&p_pas[3]);
300 i_version = (p_pas[5] >> 1) & 0x1F;
301 //intf_DbgMsg("TS Id: %d, version: %d\n", U16_AT(&p_pas[3]),(p_pas[5] >> 1) & 0x1F);
303 /* Test if the stream has not changed by looking at the stream_id */
304 if( p_descr->i_stream_id != i_stream_id )
306 /* This can either mean that the PSI decoder has just started or that
307 the stream has changed */
308 if( p_descr->i_PAT_version== PSI_UNINITIALISED )
309 intf_DbgMsg("Building Program Association table\n");
311 intf_ErrMsg( "Stream Id has suddently changed ! Rebuilding PAT\n" );
313 /* Whatever it is, ask the PSI decoder to rebuild the table */
318 /* Stream has not changed, test if the PMT is up to date */
319 if( p_descr->i_PAT_version != i_version )
321 intf_DbgMsg("PAT has been updated, rebuilding it\n");
322 /* Ask the PSI decoder to rebuild the table */
327 /* Clear the table if needed */
330 intf_DbgMsg("Updating PAT table\n");
332 /* Any program in the stream may have disapeared, or a new one
333 can have been added. The good way to handle such a case would be
334 to build a temporary table and to make a diff */
336 /* Stop the reception of all programs and PSI informations
337 associated with this stream, excepted the PAT on PID 0 and the SDT
339 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES &&
340 p_input->pp_selected_es[i_es_index]; i_es_index++ )
342 if( p_input->pp_selected_es[i_es_index]->b_psi )
344 if( p_input->pp_selected_es[i_es_index]->i_id != 0
345 #ifdef DVB_EXTENSIONS
346 && p_input->pp_selected_es[i_es_index]->i_id != 17
349 input_DelPsiPID( p_input,
350 p_input->pp_selected_es[i_es_index]->i_id );
353 input_DelPgrmElem( p_input,
354 p_input->pp_selected_es[i_es_index]->i_id );
357 /* Recreate a new stream description. Since it is virgin, the decoder
358 will rebuild it entirely on is own */
359 DestroyStreamDescr(p_input, p_descr->i_stream_id);
360 AddStreamDescr(p_input, i_stream_id);
362 /* Record the new version for that table */
363 p_descr->i_PAT_version = i_version;
366 /* Build the table if not already complete or if it was cleared */
367 if( p_descr->b_is_PAT_complete )
371 intf_DbgMsg("Bug: table invalid but PAT said to be complete\n");
375 /* Check if we already heard about that section */
376 i_last_section = p_pas[7];
377 i_current_section = p_pas[6];
379 // intf_DbgMsg( "Section %d (last section %d)\n",
380 // i_current_section, i_last_section );
382 if( Is_known(p_descr->a_known_PAT_sections, i_current_section) )
385 // intf_DbgMsg("Section already received, skipping\n");
389 /* Compute the number of program_map PID carried in this section */
390 i_pgrm_number = ((U16_AT(&p_pas[1]) & 0xFFF) - 9) / 4;
391 intf_DbgMsg("Number of Pgrm in that section: %d\n", i_pgrm_number);
393 /* Start the reception of those program map PID */
394 for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ )
396 i_pgrm_id = U16_AT(&p_pas[8+4*i_pgrm_index]);
397 i_pgrm_map_pid = U16_AT(&p_pas[8+4*i_pgrm_index+2]) & 0x1FFF;
398 intf_DbgMsg("Pgrm %d described on pid %d\n", i_pgrm_id,
401 /* Check we are not already receiving that pid because it carries
402 info for another program */
403 for( i_es_index = 0; i_es_index < INPUT_MAX_ES; i_es_index++ )
405 if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid)
407 intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid);
408 i_es_index = INPUT_MAX_ES+1;
412 /* Start to receive that PID if we're not already doing it */
413 if( i_es_index <= INPUT_MAX_ES )
414 input_AddPsiPID( p_input, i_pgrm_map_pid );
416 /* Append an entry to the pgrm_descriptor table to later store
417 the description of this program, unless program number is 0
418 (Network information table) */
421 intf_DbgMsg("Adding program %d to the PMT\n", i_pgrm_id);
422 AddPgrmDescr(p_descr, i_pgrm_id);
426 /* We now know the info carried in this section */
427 Set_known(p_descr->a_known_PAT_sections, i_current_section);
429 /* Check if the table is now complete */
430 p_descr->i_known_PAT_sections++;
431 if( p_descr->i_known_PAT_sections >= i_last_section)
432 p_descr->b_is_PAT_complete = 1;
439 /******************************************************************************
440 * DecodePgrmMapSection: Decode a PMS
441 ******************************************************************************
442 * No check is made to known if the table is currently applicable or not, so
443 * that unapplicable sections must be filtered before calling this function
444 * The Program Map Table can be segmented to occupy multiple sections so that
445 * we have to know which sections we have already received (IsKnown() /
447 * Note that the processing of those sections is different from the one of the
448 * others since here a section refers to a single program, and a program cannot
449 * be segmented into multiple sections
450 ******************************************************************************/
451 static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
453 u16 i_pgrm_number; /* Id of the program described in that section */
454 u8 i_version; /* Version of the description for that program */
457 u16 i_section_length;
461 u8 i_current_section;
469 pgrm_descriptor_t* p_pgrm;
470 es_descriptor_t* p_es;
472 #define p_descr (p_input->p_stream)
474 /* Read the id of the program described in that section */
475 i_pgrm_number = U16_AT(&p_pms[3]);
476 // intf_DbgMsg( "PMT section received for program %d\n", i_pgrm_number );
478 /* Find where is stored the description of this program */
479 for( i_index = 0; i_index < p_descr->i_pgrm_number &&
480 i_pgrm_number != p_descr->ap_programs[i_index]->i_number; i_index++ );
482 if( i_index >= p_descr->i_pgrm_number )
484 /* If none entry exists, this simply means that the PAT is not complete,
485 so skip this section since it is the responsability of the PAT decoder
486 to add pgrm_descriptor slots to the table of known pgrms */
487 intf_DbgMsg( "Unknown pgrm %d: skipping its description\n", i_pgrm_number );
491 /* We now have the slot which is the program described: we can begin with
492 the decoding of its description */
493 p_pgrm = p_descr->ap_programs[i_index];
495 /* Which section of the description of that program did we receive ? */
496 i_last_section = p_pms[7];
497 i_current_section = p_pms[6];
498 // intf_DbgMsg("Section %d (last section %d)\n", i_current_section, i_last_section);
500 /* Is this an update of the description for this program ? */
501 i_version = (p_pms[5] >> 1) & 0x1F;
502 if( p_pgrm->i_version != i_version )
504 intf_DbgMsg("Updating PMT for program %d\n", i_pgrm_number);
506 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
508 /* Stop the reception of the ES if needed by calling the function
509 normally used by the interface to manage this */
510 if( input_IsElemRecv(p_input, p_pgrm->ap_es[i_index]->i_id) )
512 intf_DbgMsg( "PID %d is no more valid: stopping its reception\n",
513 p_pgrm->ap_es[i_index]->i_id );
514 input_DelPgrmElem( p_input, p_pgrm->ap_es[i_index]->i_id );
517 /* Remove the descriptor associated to the es of this programs */
518 intf_DbgMsg( "Invalidating PID %d\n", p_pgrm->ap_es[i_index]->i_id );
519 DestroyESDescr(p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id);
522 /* Update version number */
523 p_pgrm->i_version = i_version;
525 /* Ask the decoder to update the description of that program */
526 p_descr->i_known_PMT_sections--;
527 Unset_known( p_descr->a_known_PMT_sections, i_current_section );
531 /* Read the info for that pgrm is the one we have is not up to date or
532 if we don't have any */
533 if( p_pgrm->b_is_ok )
536 // intf_DbgMsg("Program description OK, nothing to do\n");
540 /* Check if we already heard about that section */
541 if( Is_known(p_descr->a_known_PMT_sections, i_current_section) )
544 // intf_DbgMsg("Section already received, skipping\n");
548 /* Read the corresponding PCR */
549 p_pgrm->i_pcr_pid = U16_AT(&p_pms[8]) & 0x1fff;
550 intf_DbgMsg("PCR at PID: %d\n", p_pgrm->i_pcr_pid);
552 /* Compute the length of the section minus the final CRC */
553 i_section_length = (U16_AT(&p_pms[1]) & 0xFFF) + 3 - 4;
554 intf_DbgMsg("Section length (without CRC): %d\n", i_section_length);
556 /* Read additional info stored in the descriptors if any */
557 intf_DbgMsg("Description length for program %d: %d\n",
558 p_pgrm->i_number, (U16_AT(&p_pms[10]) & 0x0FFF));
559 i_descr_end = (U16_AT(&p_pms[10]) & 0x0FFF) + 12;
560 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
563 while( i_offset < i_descr_end )
565 DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm);
566 i_offset += p_pms[i_offset+1] + 2;
569 /* Read all the ES descriptions */
570 while( i_offset < i_section_length )
572 /* Read type of that ES */
573 intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]);
575 /* Read PID of that ES */
576 i_es_pid = U16_AT(&p_pms[i_offset+1]) & 0x1FF;
577 intf_DbgMsg("ES PID: %d\n", i_es_pid);
579 /* Add the ES to the program description and reserve a slot in the
580 table of ES to store its description */
581 p_es = AddESDescr(p_input, p_pgrm, i_es_pid);
584 intf_ErrMsg("Warning: definition for pgrm %d won't be complete\n",
586 /* The best way to handle this is to stop decoding the info for
587 that section but do as if everything is ok. Thus we will
588 eventually have an uncomplete ES table marked as being
589 complete and some error msgs */
594 /* Store the description of that PID in the slot */
595 p_es->i_type = p_pms[i_offset];
597 if( i_es_pid == p_pgrm->i_pcr_pid )
602 /* Read additional info given by the descriptors */
604 intf_DbgMsg("description length for PID %d: %d\n", p_es->i_id,
605 (U16_AT(&p_pms[i_offset-2]) & 0x0FFF));
606 i_descr_end = (U16_AT(&p_pms[i_offset-2]) & 0x0FFF) + i_offset;
607 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
608 while( i_offset < i_descr_end )
610 DecodeESDescriptor(&p_pms[i_offset], p_es);
611 i_offset += p_pms[i_offset+1] + 2;
615 /* Jump to next ES description */
618 /* We now know the info carried in this section */
619 intf_DbgMsg("Description of program %d complete\n", p_pgrm->i_number);
621 Set_known(p_descr->a_known_PMT_sections, i_current_section);
623 /* Check if the PMT is now complete */
624 p_descr->i_known_PMT_sections++;
625 if( p_descr->i_known_PMT_sections >= i_last_section)
627 p_descr->b_is_PMT_complete = 1;
630 /* Spawn an audio and a video thread, if possible. */
631 for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
633 switch( p_input->p_es[i_es_loop].i_type )
637 if( p_main->b_video )
639 /* Spawn a video thread */
640 input_AddPgrmElem( p_input,
641 p_input->p_es[i_es_loop].i_id );
646 if ( p_main->b_audio )
648 /* Spawn an ac3 thread */
649 input_AddPgrmElem( p_input,
650 p_input->p_es[i_es_loop].i_id );
656 if( p_main->b_audio )
658 /* Spawn an audio thread */
659 input_AddPgrmElem( p_input,
660 p_input->p_es[i_es_loop].i_id );
676 /******************************************************************************
677 * DecodeSrvDescrSection
678 ******************************************************************************
679 * A finir et a refaire proprement ????
680 ******************************************************************************/
681 void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input )
689 boolean_t b_must_update = 0;
696 #define p_stream (p_input->p_stream)
698 /* Read stream id and version number immediately, to be sure they will be
699 initialised in all the cases in which we will need them */
700 i_stream_id = U16_AT(&p_sdt[3]);
701 i_version = (p_sdt[5] >> 1) & 0x1F;
702 intf_DbgMsg("TS Id: %d, version: %d\n", i_stream_id, i_version);
704 /* Take the descriptor into account only if it describes the streams we are
706 if( p_stream->i_stream_id != i_stream_id )
708 intf_DbgMsg("SDT doen't apply to our TS but to %s: aborting\n",
713 /* Section applyies to our TS, test if the SDT is up to date */
714 if( p_stream->i_SDT_version != i_version )
716 intf_DbgMsg("SDT has been updated, NOT YET IMPLEMENTED\n");
718 /* Ask the PSI decoder to rebuild the table */
723 /* Rebuild the table if needed */
726 intf_DbgMsg("Updating SDT table\n");
728 i_length = p_sdt[1] & 0x0FFF;
731 while(i_offset < i_length)
734 /* Find the program to which the description applies */
735 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
737 if( p_stream->ap_programs[i_index]->i_number ==
738 U16_AT(&p_sdt[i_offset]) )
741 intf_DbgMsg("FOUND: %d\n", p_stream->ap_programs[i_index]->i_number);
746 /* Copy the info to the description of that program */
748 intf_DbgMsg("description length for SDT: %d\n",
749 (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF));
750 i_descr_end = (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF) + i_offset;
751 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
752 while( i_offset < i_descr_end )
754 DecodePgrmDescriptor(&p_sdt[i_offset], p_stream->ap_programs[i_index]);
755 i_offset += p_sdt[i_offset+1] + 2;
762 /******************************************************************************
764 ******************************************************************************
765 * Decode any descriptor applying to the definition of a program
766 ******************************************************************************/
767 static void DecodePgrmDescriptor( byte_t* p_descriptor,
768 pgrm_descriptor_t* p_pgrm )
770 u8 i_type; /* Type of the descriptor */
771 u8 i_length; /* Length of the descriptor */
772 #ifdef DVB_EXTENSIONS
773 int i_offset; /* Current position in the descriptor */
776 ASSERT(p_descriptor);
779 /* Read type and length of the descriptor */
780 i_type = p_descriptor[0];
781 i_length = p_descriptor[1];
783 /* Handle specific descriptor info */
786 #ifdef DVB_EXTENSIONS
787 case PSI_SERVICE_DESCRIPTOR:
789 /* Store service type */
790 p_pgrm->i_srv_type = p_descriptor[2];
792 /* Jump to the beginning of the service name */
793 i_offset = p_descriptor[3] + 5;
795 /* Check that the charset used is the normal one (latin) by testing the
796 first byte of the name */
797 if( p_descriptor[i_offset] >= 0x20 )
799 /* The charset is the one of our computer: just dup the string */
800 p_pgrm->psz_srv_name = malloc(i_length - i_offset +1);
801 memcpy(p_pgrm->psz_srv_name, &p_descriptor[i_offset],
802 i_length - i_offset);
803 p_pgrm->psz_srv_name[i_length - i_offset + 1] = '\0';
807 /* Indicate that the name couldn't be printed */
808 p_pgrm->psz_srv_name = "Ununderstandable :)";
814 // intf_DbgMsg("Unhandled program descriptor received (type: %d)\n", i_type);
815 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
819 /******************************************************************************
821 ******************************************************************************
822 * Decode any descriptor applying to the definition of an ES
823 ******************************************************************************/
824 static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es )
826 u8 i_type; /* Type of the descriptor */
827 u8 i_length; /* Length of the descriptor */
828 // int i_offset; /* Current position in the descriptor */
830 ASSERT(p_descriptor);
833 /* Read type and length of the descriptor */
834 i_type = p_descriptor[0];
835 i_length = p_descriptor[1];
839 case PSI_VIDEO_STREAM_DESCRIPTOR:
841 intf_DbgMsg("Video stream descriptor received\n");
844 case PSI_AUDIO_STREAM_DESCRIPTOR:
846 intf_DbgMsg("Audio stream descriptor received\n");
849 case PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR:
851 intf_DbgMsg("Target background descriptor received\n");
854 case PSI_VIDEO_WINDOW_DESCRIPTOR:
856 intf_DbgMsg("Video window descriptor received\n");
860 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
861 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
865 /******************************************************************************
866 * input_AddPsiPID: Start to receive the PSI info contained in a PID
867 ******************************************************************************
868 * Add a descriptor to the table of es descriptor for that es and mark the es
869 * as being to be received by the input (since all PSI must be received to
870 * build the description of the program)
871 ******************************************************************************/
872 static int input_AddPsiPID( input_thread_t *p_input, int i_pid )
875 es_descriptor_t* p_psi_es;
878 /* Store the description of this stream in the input thread */
879 p_psi_es = AddESDescr(p_input, NULL, i_pid);
883 /* Precise this ES carries PSI */
886 /* Create the buffer needed by the PSI decoder */
887 p_psi_es->p_psi_section = malloc( sizeof( psi_section_t) );
888 if( !p_psi_es->p_psi_section )
890 intf_ErrMsg( "Malloc error\n" );
895 /* Init the reception for that PID */
896 p_psi_es->p_psi_section->b_running_section = 0;
897 // p_psi_es->p_psi_section->b_discard_payload = 0;
899 /* Ask the input thread to demultiplex it: since the interface
900 can also access the table of selected es, lock the elementary
902 vlc_mutex_lock( &p_input->es_lock );
903 for( i_index = 0; i_index < INPUT_MAX_SELECTED_ES; i_index++ )
905 if( !p_input->pp_selected_es[i_index] )
907 intf_DbgMsg( "Free Selected ES slot found at offset %d for PID %d\n",
909 p_input->pp_selected_es[i_index] = p_psi_es;
913 vlc_mutex_unlock( &p_input->es_lock );
915 if( i_index >= INPUT_MAX_SELECTED_ES )
917 intf_ErrMsg( "Stream carries to many PID for our decoder\n" );
926 /******************************************************************************
927 * input_DelPsiPID: Stop to receive the PSI info contained in a PID
928 ******************************************************************************
929 * Remove the PID from the list of ES descriptors and from the list of ES that
930 * the input must receive.
931 * Known PID for PSI should always be received, so that their description
932 * should be pointed out by a member of pp_selected_es. But as INPUT_MAX_ES
933 * can be different of INPUT_MAX_SELECTED_ES, this may happen, so that we must
935 ******************************************************************************/
936 static int input_DelPsiPID( input_thread_t *p_input, int i_pid )
938 int i_es_index, i_last_sel;
940 intf_DbgMsg( "Deleting PSI PID %d\n", i_pid );
942 /* Stop to receive the ES. Since the interface can also access the table
943 of selected es, lock the elementary stream structure */
944 vlc_mutex_lock( &p_input->es_lock );
946 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES; i_es_index++ )
948 if( p_input->pp_selected_es[i_es_index] &&
949 p_input->pp_selected_es[i_es_index]->i_id == i_pid )
951 /* Unmark the stream */
952 p_input->pp_selected_es[i_es_index] = NULL;
954 /* There must not be any gap in the pp_selected_es, so move the last
955 selected stream to this slot */
956 for( i_last_sel = i_es_index; p_input->pp_selected_es[i_last_sel] &&
957 i_last_sel < INPUT_MAX_SELECTED_ES; i_last_sel++ );
958 p_input->pp_selected_es[i_es_index] = p_input->pp_selected_es[i_last_sel];
959 p_input->pp_selected_es[i_last_sel] = NULL;
964 vlc_mutex_unlock( &p_input->es_lock );
967 /* Check if the pp_selected_es table may be corrupted */
968 if( i_es_index >= INPUT_MAX_PROGRAM_ES )
970 intf_ErrMsg( "DelPsiPID error: PID %d is not currently received\n", i_pid );
974 /* Remove the desription of that ES from the table of ES */
975 DestroyESDescr(p_input, NULL, i_pid);
980 /******************************************************************************
981 * Precalculate the 32-bit CRC table
982 ******************************************************************************
983 * This table is a global variable shared by all decoders, so it has to be
984 * initialised only once
985 ******************************************************************************/
986 void BuildCrc32Table( )
989 for( i = 0 ; i < 256 ; i++ )
992 for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1)
993 k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
994 i_crc_32_table[i] = k;
998 /******************************************************************************
999 * Test the validity of a checksum
1000 ******************************************************************************
1001 * The checksum must be stored at the end of the data, and the given size must
1002 * include the 32 bits of the CRC.
1003 * Return 0 if the checksum is OK, any other value if the data are corrupted
1004 ******************************************************************************/
1005 int CheckCRC32(byte_t* p_data, int i_data_size)
1008 u32 i_crc = 0xffffffff;
1012 for (i = 0; i < i_data_size; i++)
1013 i_crc = (i_crc << 8) ^ i_crc_32_table[(i_crc >> 24) ^ p_data[i]];
1018 /******************************************************************************
1019 * Is_known: check if a given section has already been received
1020 ******************************************************************************
1021 * As a table cannot be segmented into more than 256 sections, we store a 256
1022 * bits long table, each bit set to one indicating that the corresponding
1023 * saction has been received
1024 ******************************************************************************/
1025 boolean_t Is_known( byte_t* a_known_section, u8 i_section )
1028 boolean_t b_is_known;
1030 /* Where to get the information ? */
1031 int i_bit_in_byte = i_section % 8;
1032 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1034 /* Build mask to read the Is_known flag */
1035 mask = 0x01 << i_bit_in_byte;
1038 b_is_known = a_known_section[i_byte_in_table] & mask;
1043 /******************************************************************************
1044 * Set_known: mark a given section has having been received
1045 ******************************************************************************
1047 ******************************************************************************/
1048 static void Set_known( byte_t* a_known_section, u8 i_section )
1052 /* Where to get the information ? */
1053 int i_bit_in_byte = i_section % 8;
1054 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1056 /* Build mask to read the Is_known flag */
1057 mask = 0x01 << i_bit_in_byte;
1060 a_known_section[i_byte_in_table] |= mask;
1063 /******************************************************************************
1064 * Unset_known: remove the 'received' mark for a given section
1065 ******************************************************************************
1067 ******************************************************************************/
1068 static void Unset_known( byte_t* a_known_section, u8 i_section )
1072 /* Where to get the information ? */
1073 int i_bit_in_byte = i_section % 8;
1074 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1076 /* Build mask to read the Is_known flag */
1077 mask = 0x01 << i_bit_in_byte;
1080 /* Unset the flag */
1081 a_known_section[i_byte_in_table] &= mask;
1084 /******************************************************************************
1085 * AddStreamDescr: add and init the stream descriptor of the given input
1086 ******************************************************************************
1088 ******************************************************************************/
1089 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input,
1094 intf_DbgMsg("Adding description for stream %d\n", i_stream_id);
1096 p_input->p_stream = malloc( sizeof(stream_descriptor_t) );
1098 p_input->p_stream->i_stream_id = i_stream_id;
1100 p_input->p_stream->i_PAT_version = PSI_UNINITIALISED;
1101 p_input->p_stream->i_known_PAT_sections = 0;
1102 bzero( p_input->p_stream->a_known_PAT_sections,
1103 sizeof(*p_input->p_stream->a_known_PAT_sections) );
1104 p_input->p_stream->b_is_PAT_complete = 0;
1106 p_input->p_stream->i_known_PMT_sections = 0;
1107 bzero( p_input->p_stream->a_known_PMT_sections,
1108 sizeof(*p_input->p_stream->a_known_PMT_sections) );
1109 p_input->p_stream->b_is_PMT_complete = 0;
1111 #ifdef DVB_EXTENSIONS
1112 p_input->p_stream->i_SDT_version = PSI_UNINITIALISED;
1113 p_input->p_stream->i_known_SDT_sections = 0;
1114 bzero( p_input->p_stream->a_known_SDT_sections,
1115 sizeof(*p_input->p_stream->a_known_SDT_sections) );
1116 p_input->p_stream->b_is_SDT_complete = 0;
1119 p_input->p_stream->i_pgrm_number = 0;
1120 p_input->p_stream->ap_programs = NULL;
1122 return p_input->p_stream;
1125 /******************************************************************************
1126 * DestroyStreamDescr: destroy the stream desciptor of the given input
1127 ******************************************************************************
1129 ******************************************************************************/
1130 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1136 /* Free the structures that describes the programs of that stream */
1137 for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
1139 DestroyPgrmDescr( p_input, p_input->p_stream,
1140 p_input->p_stream->ap_programs[i_index]->i_number );
1143 /* Free the table of pgrm descriptors */
1144 free( p_input->p_stream->ap_programs );
1146 /* Free the structure that describes the stream itself */
1147 free( p_input->p_stream );
1149 /* Input thread has no more stream descriptor */
1150 p_input->p_stream = NULL;
1153 /******************************************************************************
1154 * AddPgrmDescr: add and init a program descriptor
1155 ******************************************************************************
1156 * This program descriptor will be referenced in the given stream descriptor
1157 ******************************************************************************/
1158 static pgrm_descriptor_t* AddPgrmDescr( stream_descriptor_t* p_stream,
1161 int i_pgrm_index = p_stream->i_pgrm_number; /* Where to add the pgrm */
1165 intf_DbgMsg("Adding description for pgrm %d\n", i_pgrm_id);
1167 /* Add an entry to the list of program associated with the stream */
1168 p_stream->i_pgrm_number++;
1169 p_stream->ap_programs = realloc( p_stream->ap_programs,
1170 p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t*) );
1172 /* Allocate the structure to store this description */
1173 p_stream->ap_programs[i_pgrm_index] = malloc(sizeof(pgrm_descriptor_t));
1175 /* Init this entry */
1176 p_stream->ap_programs[i_pgrm_index]->i_number = i_pgrm_id;
1177 p_stream->ap_programs[i_pgrm_index]->i_version = PSI_UNINITIALISED;
1178 p_stream->ap_programs[i_pgrm_index]->b_is_ok = 0;
1180 p_stream->ap_programs[i_pgrm_index]->i_es_number = 0;
1181 p_stream->ap_programs[i_pgrm_index]->ap_es = NULL;
1183 /* descriptors ???? */
1185 return p_stream->ap_programs[i_pgrm_index];
1188 /******************************************************************************
1189 * AddPgrmDescr: destroy a program descriptor
1190 ******************************************************************************
1191 * All ES descriptions referenced in the descriptor will be deleted.
1192 ******************************************************************************/
1193 static void DestroyPgrmDescr( input_thread_t * p_input,
1194 stream_descriptor_t * p_stream, u16 i_pgrm_id )
1196 int i_index, i_pgrm_index = -1;
1197 pgrm_descriptor_t* p_pgrm = NULL;
1201 intf_DbgMsg("Deleting description for pgrm %d\n", i_pgrm_id);
1203 /* Find where this program is described */
1204 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
1206 if( p_stream->ap_programs[i_index]->i_number == i_pgrm_id )
1208 i_pgrm_index = i_index;
1209 p_pgrm = p_stream->ap_programs[ i_pgrm_index ];
1214 /* Make sure that the pgrm exists */
1215 ASSERT(i_pgrm_index >= 0);
1218 /* Free the structures that describe the es that belongs to that program */
1219 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
1221 DestroyESDescr( p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id );
1224 /* Free the table of es descriptors */
1225 free( p_pgrm->ap_es );
1227 /* Free the description of this stream */
1230 /* Remove this program from the stream's list of programs */
1231 p_stream->i_pgrm_number--;
1232 p_stream->ap_programs[i_pgrm_index] =
1233 p_stream->ap_programs[p_stream->i_pgrm_number];
1234 p_stream->ap_programs = realloc( p_stream->ap_programs,
1235 p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t *) );
1238 /******************************************************************************
1240 ******************************************************************************
1241 * Reserve a slot in the table of ES descritors for the ES and add it to the
1242 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
1244 ******************************************************************************/
1245 static es_descriptor_t* AddESDescr(input_thread_t* p_input,
1246 pgrm_descriptor_t* p_pgrm, u16 i_es_pid)
1249 es_descriptor_t* p_es = NULL;
1253 intf_DbgMsg("Adding description for ES %d\n", i_es_pid);
1255 /* Find an empty slot to store the description of that es */
1256 for( i_index = 0; i_index < INPUT_MAX_ES &&
1257 p_input->p_es[i_index].i_id != EMPTY_PID; i_index++ );
1259 if( i_index >= INPUT_MAX_ES )
1261 /* No slot is empty */
1262 intf_ErrMsg("Stream carries to many PID for our decoder\n");
1266 /* Reserve the slot for that ES */
1267 p_es = &p_input->p_es[i_index];
1268 p_es->i_id = i_es_pid;
1269 intf_DbgMsg("Slot %d in p_es table assigned to ES %d\n", i_index, i_es_pid);
1271 /* Init its values */
1272 p_es->i_type = 0; /* ??? */
1275 p_es->i_continuity_counter = 0xFF;
1277 p_es->p_pes_packet = NULL;
1278 // p_es->p_next_pes_packet = NULL;
1281 /* Add this ES to the program definition if one is given */
1284 p_pgrm->i_es_number++;
1285 p_pgrm->ap_es = realloc( p_pgrm->ap_es,
1286 p_pgrm->i_es_number*sizeof(es_descriptor_t *) );
1287 p_pgrm->ap_es[p_pgrm->i_es_number-1] = p_es;
1288 intf_DbgMsg( "Added ES %d to definition of pgrm %d\n",
1289 i_es_pid, p_pgrm->i_number );
1292 intf_DbgMsg( "Added ES %d not added to the definition of any pgrm\n",
1299 /******************************************************************************
1301 ******************************************************************************
1303 ******************************************************************************/
1304 static void DestroyESDescr(input_thread_t* p_input,
1305 pgrm_descriptor_t* p_pgrm, u16 i_pid)
1309 /* Look for the description of the ES */
1310 for(i_index = 0; i_index < INPUT_MAX_ES; i_index++)
1312 if( p_input->p_es[i_index].i_id == i_pid )
1314 /* The table of stream descriptors is static, so don't free memory
1315 but just mark the slot as unused */
1316 p_input->p_es[i_index].i_id = EMPTY_PID;
1321 /* Remove this ES from the description of the program if it is associated to
1325 for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
1327 if( p_input->p_es[i_index].i_id == i_pid )
1329 p_pgrm->i_es_number--;
1330 p_pgrm->ap_es[i_index] = p_pgrm->ap_es[p_pgrm->i_es_number];
1331 p_pgrm->ap_es = realloc(p_pgrm->ap_es, p_pgrm->i_es_number);