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 *******************************************************************************/
15 #include <sys/uio.h> /* iovec */
16 #include <stdlib.h> /* atoi(), malloc(), free() */
18 #include <netinet/in.h> /* ntohs */
27 #include "input_ctrl.h"
28 #include "input_psi.h"
31 * Precalculated 32-bits CRC table, shared by all instances of the PSI decoder
33 boolean_t b_crc_initialised = 0;
34 u32 i_crc_32_table[256];
37 * Locale type definitions
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
45 #define PSI_SERVICE_DESCRIPTOR 0x48
48 /* That info must be stored in the version field since it contains
50 #define PSI_UNINITIALISED 0xFF
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 );
63 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input,
65 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id);
66 static pgrm_descriptor_t* AddPgrmDescr(stream_descriptor_t* p_stream,
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,
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 );
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 )
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 )
96 b_crc_initialised = 1;
99 /* Init the structure that describes the stream we are receiving */
100 AddStreamDescr( p_input, PSI_UNINITIALISED );
102 /* Request for reception of the program association table */
103 input_AddPsiPID( p_input, 0 );
105 #ifdef DVB_EXTENSIONS
106 /* Request for reception of the service description table */
107 input_AddPsiPID( p_input, 17 );
114 /******************************************************************************
115 * input_PsiClean: Clean PSI structures before dying
116 ******************************************************************************/
117 int input_PsiClean( input_thread_t *p_input )
121 /* Stop to receive all the PSI tables associated with that program */
122 /* TO DO ??? -> Not really usefull */
124 /* Clean also descriptors for programs associated with that stream */
125 /* TO DO ??? -> Not really usefull and maybe buggy */
127 /* Destroy the stream description */
128 DestroyStreamDescr( p_input, p_input->p_stream->i_stream_id );
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 /* ??? */ )
144 pgrm_descriptor_t* p_pgrm;
148 /* Lock the tables, since this method can be called from any thread */
149 //pthread_mutex_lock()
151 /* Check if the table is complete or not */
152 if( !p_input->p_stream->b_is_PMT_complete )
154 intf_IntfMsg( "Warning: PMT not yet complete\n" );
158 for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
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 );
164 for( i_index2 = 0; i_index2 < p_pgrm->i_es_number; i_index2++ )
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);
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);
176 /* Unock the tables */
177 //pthread_mutex_unlock()
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 )
190 ASSERT(p_psi_section);
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] );
195 /* Check the CRC validity if any CRC is carried */
196 if( p_psi_section->buffer[1] & 0x80 )
198 if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )
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" );
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 )
211 intf_DbgMsg( "PSI not yet applicable: trash it\n" );
215 /* Handle the packet according to it's type given it the table_id */
216 switch ( p_psi_section->buffer[0] )
219 //intf_DbgMsg("Program association section received\n");
220 DecodePgrmAssocSection(p_psi_section->buffer, p_input);
223 //intf_DbgMsg("Conditional access section received\n");
226 //intf_DbgMsg("Program map section received\n");
227 DecodePgrmMapSection(p_psi_section->buffer, p_input);
230 //intf_DbgMsg("Service description section received\n");
231 DecodeSrvDescrSection(p_psi_section->buffer, p_input);
234 //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",
235 // p_psi_section->buffer[0]);
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() /
248 ******************************************************************************/
249 static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input )
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 */
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 */
258 boolean_t b_is_invalid = 0;
260 u8 i_current_section;
269 #define p_descr (p_input->p_stream)
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);
277 /* Test if the stream has not changed by looking at the stream_id */
278 if( p_descr->i_stream_id != i_stream_id )
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");
285 intf_ErrMsg( "Stream Id has suddently changed ! Rebuilding PAT\n" );
287 /* Whatever it is, ask the PSI decoder to rebuild the table */
292 /* Stream has not changed, test if the PMT is up to date */
293 if( p_descr->i_PAT_version != i_version )
295 intf_Msg("PAT has been updated, rebuilding it\n");
296 /* Ask the PSI decoder to rebuild the table */
301 /* Clear the table if needed */
304 intf_DbgMsg("Updating PAT table\n");
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 */
310 /* Stop the reception of all programs and PSI informations
311 associated with this stream, excepted the PAT on PID 0 and the SDT
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++ )
316 if( p_input->pp_selected_es[i_es_index]->b_psi )
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
323 input_DelPsiPID( p_input, p_input->pp_selected_es[i_es_index]->i_id );
326 input_DelPgrmElem( p_input, p_input->pp_selected_es[i_es_index]->i_id );
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);
334 /* Record the new version for that table */
335 p_descr->i_PAT_version = i_version;
338 /* Build the table if not already complete or if it was cleared */
339 if( p_descr->b_is_PAT_complete )
342 //intf_DbgMsg("Table already complete\n");
346 /* Check if we already heard about that section */
347 i_last_section = p_pas[7];
348 i_current_section = p_pas[6];
350 // intf_DbgMsg( "Section %d (last section %d)\n",
351 // i_current_section, i_last_section );
353 if( Is_known(p_descr->a_known_PAT_sections, i_current_section) )
356 // intf_DbgMsg("Section already received, skipping\n");
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);
364 /* Start the reception of those program map PID */
365 for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ )
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);
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++ )
375 if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid)
377 intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid);
378 i_es_index = INPUT_MAX_ES+1;
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 );
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) */
391 intf_Msg("Adding program %d to the Program Map Table\n", i_pgrm_id);
392 AddPgrmDescr(p_descr, i_pgrm_id);
396 /* We now know the info carried in this section */
397 Set_known(p_descr->a_known_PAT_sections, i_current_section);
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;
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() /
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 )
424 u16 i_pgrm_number; /* Id of the program described in that section */
425 u8 i_version; /* Version of the description for that program */
428 u16 i_section_length;
432 u8 i_current_section;
437 pgrm_descriptor_t* p_pgrm;
438 es_descriptor_t* p_es;
440 #define p_descr (p_input->p_stream)
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 );
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++ );
450 if( i_index >= p_descr->i_pgrm_number )
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 );
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];
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);
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 )
472 intf_Msg("Updating PMT for program %d\n", i_pgrm_number);
474 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
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) )
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 );
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);
490 /* Update version number */
491 p_pgrm->i_version = i_version;
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 );
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 )
504 // intf_DbgMsg("Program description OK, nothing to do\n");
508 /* Check if we already heard about that section */
509 if( Is_known(p_descr->a_known_PMT_sections, i_current_section) )
512 // intf_DbgMsg("Section already received, skipping\n");
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);
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);
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);
531 while( i_offset < i_descr_end )
533 DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm);
534 i_offset += p_pms[i_offset+1] + 2;
537 /* Read all the ES descriptions */
538 while( i_offset < i_section_length )
540 /* Read type of that ES */
541 intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]);
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);
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);
552 intf_ErrMsg("Warning: definition of program %d will be uncomplete\n",
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 */
561 /* Store the description of that PID in the slot */
562 p_es->i_type = p_pms[i_offset];
564 if( i_es_pid == p_pgrm->i_pcr_pid )
569 /* Read additional info given by the descriptors */
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 )
577 DecodeESDescriptor(&p_pms[i_offset], p_es);
578 i_offset += p_pms[i_offset+1] + 2;
582 /* Jump to next ES description */
585 /* We now know the info carried in this section */
586 intf_Msg("Description of program %d complete\n", p_pgrm->i_number);
588 Set_known(p_descr->a_known_PMT_sections, i_current_section);
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;
602 /******************************************************************************
603 * DecodeSrvDescrSection
604 ******************************************************************************
605 * A finir et a refaire proprement ????
606 ******************************************************************************/
607 void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input )
615 boolean_t b_must_update = 0;
622 #define p_stream (p_input->p_stream)
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);
630 /* Take the descriptor into account only if it describes the streams we are
632 if( p_stream->i_stream_id != i_stream_id )
634 intf_DbgMsg("SDT doen't apply to our TS but to %s: aborting\n",
639 /* Section applyies to our TS, test if the SDT is up to date */
640 if( p_stream->i_SDT_version != i_version )
642 intf_Msg("SDT has been updated, NOT YET IMPLEMENTED\n");
644 /* Ask the PSI decoder to rebuild the table */
649 /* Rebuild the table if needed */
652 intf_DbgMsg("Updating SDT table\n");
654 i_length = p_sdt[1] & 0x0FFF;
657 while(i_offset < i_length)
660 /* Find the program to which the description applies */
661 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
663 if( p_stream->ap_programs[i_index]->i_number == U16_AT(&p_sdt[i_offset]) )
666 intf_Msg("FOUND: %d\n", p_stream->ap_programs[i_index]->i_number);
671 /* Copy the info to the description of that program */
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 )
679 DecodePgrmDescriptor(&p_sdt[i_offset], p_stream->ap_programs[i_index]);
680 i_offset += p_sdt[i_offset+1] + 2;
693 /******************************************************************************
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 )
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 */
706 ASSERT(p_descriptor);
709 /* Read type and length of the descriptor */
710 i_type = p_descriptor[0];
711 i_length = p_descriptor[1];
713 /* Handle specific descriptor info */
716 #ifdef DVB_EXTENSIONS
717 case PSI_SERVICE_DESCRIPTOR:
719 /* Store service type */
720 p_pgrm->i_srv_type = p_descriptor[2];
722 /* Jump to the beginning of the service name */
723 i_offset = p_descriptor[3] + 5;
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 )
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';
736 /* Indicate that the name couldn't be printed */
737 p_pgrm->psz_srv_name = "Ununderstandable :)";
743 // intf_DbgMsg("Unhandled program descriptor received (type: %d)\n", i_type);
744 // intf_Msg("Unhandled ES descriptor received (type: %d)\n", i_type);
751 /******************************************************************************
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 )
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 */
762 ASSERT(p_descriptor);
765 /* Read type and length of the descriptor */
766 i_type = p_descriptor[0];
767 i_length = p_descriptor[1];
771 case PSI_VIDEO_STREAM_DESCRIPTOR:
773 intf_DbgMsg("Video stream descriptor received\n");
776 case PSI_AUDIO_STREAM_DESCRIPTOR:
778 intf_DbgMsg("Audio stream descriptor received\n");
781 case PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR:
783 intf_DbgMsg("Target background descriptor received\n");
786 case PSI_VIDEO_WINDOW_DESCRIPTOR:
788 intf_DbgMsg("Video window descriptor received\n");
792 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
793 // intf_Msg("Unhandled ES descriptor received (type: %d)\n", i_type);
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 )
809 es_descriptor_t* p_psi_es;
812 /* Store the description of this stream in the input thread */
813 p_psi_es = AddESDescr(p_input, NULL, i_pid);
817 /* Precise this ES carries PSI */
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 )
824 intf_ErrMsg( "Malloc error\n" );
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;
833 /* Ask the input thread to demultiplex it: since the interface
834 can also access the table of selected es, lock the elementary
836 pthread_mutex_lock( &p_input->es_lock );
837 for( i_index = 0; i_index < INPUT_MAX_SELECTED_ES; i_index++ )
839 if( !p_input->pp_selected_es[i_index] )
841 intf_DbgMsg( "Free Selected ES slot found at offset %d: Will use it for PID %d\n",
843 p_input->pp_selected_es[i_index] = p_psi_es;
847 pthread_mutex_unlock( &p_input->es_lock );
849 if( i_index >= INPUT_MAX_SELECTED_ES )
851 intf_ErrMsg( "Stream carries to many PID for our decoder\n" );
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
870 ******************************************************************************/
871 static int input_DelPsiPID( input_thread_t *p_input, int i_pid )
873 int i_es_index, i_last_sel;
875 intf_DbgMsg( "Deleting PSI PID %d\n", i_pid );
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 );
881 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES; i_es_index++ )
883 if( p_input->pp_selected_es[i_es_index] &&
884 p_input->pp_selected_es[i_es_index]->i_id == i_pid )
886 /* Unmark the stream */
887 p_input->pp_selected_es[i_es_index] = NULL;
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;
899 pthread_mutex_unlock( &p_input->es_lock );
902 /* Check if the pp_selected_es table may be corrupted */
903 if( i_es_index >= INPUT_MAX_PROGRAM_ES )
905 intf_ErrMsg( "DelPsiPID error: PID %d is not currently received\n", i_pid );
909 /* Remove the desription of that ES from the table of ES */
910 DestroyESDescr(p_input, NULL, i_pid);
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( )
926 for( i = 0 ; i < 256 ; i++ )
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;
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)
946 u32 i_crc = 0xffffffff;
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]];
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 )
968 boolean_t b_is_known;
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;
974 /* Build mask to read the Is_known flag */
975 mask = 0x01 << i_bit_in_byte;
978 b_is_known = a_known_section[i_byte_in_table] & mask;
984 /******************************************************************************
985 * Set_known: mark a given section has having been received
986 ******************************************************************************
988 ******************************************************************************/
989 static void Set_known( byte_t* a_known_section, u8 i_section )
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;
997 /* Build mask to read the Is_known flag */
998 mask = 0x01 << i_bit_in_byte;
1001 a_known_section[i_byte_in_table] |= mask;
1005 /******************************************************************************
1006 * Unset_known: remove the 'received' mark for a given section
1007 ******************************************************************************
1009 ******************************************************************************/
1010 static void Unset_known( byte_t* a_known_section, u8 i_section )
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;
1018 /* Build mask to read the Is_known flag */
1019 mask = 0x01 << i_bit_in_byte;
1022 /* Unset the flag */
1023 a_known_section[i_byte_in_table] &= mask;
1027 /******************************************************************************
1028 * AddStreamDescr: add and init the stream descriptor of the given input
1029 ******************************************************************************
1031 ******************************************************************************/
1032 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1036 intf_DbgMsg("Adding description for stream %d\n", i_stream_id);
1038 p_input->p_stream = malloc( sizeof(stream_descriptor_t) );
1040 p_input->p_stream->i_stream_id = i_stream_id;
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;
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;
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;
1061 p_input->p_stream->i_pgrm_number = 0;
1062 p_input->p_stream->ap_programs = NULL;
1064 return p_input->p_stream;
1068 /******************************************************************************
1069 * DestroyStreamDescr: destroy the stream desciptor of the given input
1070 ******************************************************************************
1072 ******************************************************************************/
1073 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id)
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++ )
1082 DestroyPgrmDescr( p_input, p_input->p_stream,
1083 p_input->p_stream->ap_programs[i_index]->i_number );
1086 /* Free the table of pgrm descriptors */
1087 free( p_input->p_stream->ap_programs );
1089 /* Free the structure that describes the stream itself */
1090 free( p_input->p_stream );
1092 /* Input thread has no more stream descriptor */
1093 p_input->p_stream = NULL;
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)
1106 intf_DbgMsg("Adding description for pgrm %d\n", i_pgrm_id);
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*) );
1113 /* Allocate the structure to store this description */
1114 p_stream->ap_programs[p_stream->i_pgrm_number-1] = malloc(sizeof(pgrm_descriptor_t));
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;
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;
1124 /* descriptors ???? */
1126 return p_stream->ap_programs[p_stream->i_pgrm_number-1];
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)
1138 pgrm_descriptor_t* p_pgrm;
1142 /* Find where is described this program */
1143 for(i_index = 0; i_index < p_stream->i_pgrm_number; i_index++)
1145 if( p_stream->ap_programs[i_index]->i_number == i_pgrm_id )
1148 p_pgrm = p_stream->ap_programs[i_index];
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);
1157 /* Free the table of es descriptors */
1158 free( p_pgrm->ap_es );
1160 /* Free the description of this stream */
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);
1170 /******************************************************************************
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
1176 ******************************************************************************/
1177 static es_descriptor_t* AddESDescr(input_thread_t* p_input,
1178 pgrm_descriptor_t* p_pgrm, u16 i_es_pid)
1181 es_descriptor_t* p_es = NULL;
1185 intf_DbgMsg("Adding description for ES %d\n", i_es_pid);
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++ );
1191 if( i_index >= INPUT_MAX_ES )
1193 /* No slot is empty */
1194 intf_ErrMsg("Stream carries to many PID for our decoder\n");
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);
1203 /* Init its values */
1204 p_es->i_type = 0; /* ??? */
1208 p_es->p_pes_packet = NULL;
1209 // p_es->p_next_pes_packet = NULL;
1212 /* Add this ES to the program definition if one is given */
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);
1221 intf_DbgMsg("Added ES %d not added to the definition of any pgrm\n", i_es_pid);
1229 /******************************************************************************
1231 ******************************************************************************
1233 ******************************************************************************/
1234 static void DestroyESDescr(input_thread_t* p_input, pgrm_descriptor_t* p_pgrm, u16 i_pid)
1240 /* Look for the description of the ES */
1241 for(i_index = 0; i_index < INPUT_MAX_ES; i_index++)
1243 if( p_input->p_es[i_index].i_id == i_pid )
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;
1252 /* Remove this ES from the description of the program if it is associated to
1256 for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
1258 if( p_input->p_es[i_index].i_id == i_pid )
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);