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 );
80 /******************************************************************************
81 * input_PsiInit: Initialize PSI decoder
82 ******************************************************************************
83 * Init the structures in which the PSI decoder will put the informations it
84 * got from PSI tables and request for the reception of the PAT.
85 ******************************************************************************/
86 int input_PsiInit( input_thread_t *p_input )
90 /* Precalculate the 32-bit CRC table if not already done ???
91 TO DO -> Put a lock or do that at pgrm init */
92 if( !b_crc_initialised )
95 b_crc_initialised = 1;
98 /* Init the structure that describes the stream we are receiving */
99 AddStreamDescr( p_input, PSI_UNINITIALISED );
101 /* Request for reception of the program association table */
102 input_AddPsiPID( p_input, 0 );
104 #ifdef DVB_EXTENSIONS
105 /* Request for reception of the service description table */
106 input_AddPsiPID( p_input, 17 );
112 /******************************************************************************
113 * input_PsiClean: Clean PSI structures before dying
114 ******************************************************************************/
115 int input_PsiClean( input_thread_t *p_input )
119 /* Stop to receive all the PSI tables associated with that program */
120 /* TO DO ??? -> Not really usefull */
122 /* Clean also descriptors for programs associated with that stream */
123 /* TO DO ??? -> Not really usefull and maybe buggy */
125 /* Destroy the stream description */
126 DestroyStreamDescr( p_input, p_input->p_stream->i_stream_id );
131 /******************************************************************************
132 * input_PsiRead: Read the table of programs
133 ******************************************************************************
134 * Ugly debugging function at that time ???????
135 ******************************************************************************/
136 void input_PsiRead( input_thread_t *p_input /* ??? */ )
140 pgrm_descriptor_t* p_pgrm;
144 /* Lock the tables, since this method can be called from any thread */
145 //pthread_mutex_lock()
147 /* Check if the table is complete or not */
148 if( !p_input->p_stream->b_is_PMT_complete )
150 intf_IntfMsg( "Warning: PMT not yet complete\n" );
154 for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
156 p_pgrm = p_input->p_stream->ap_programs[i_index];
157 intf_Msg("Printing info for program %d\n", p_pgrm->i_number );
158 intf_IntfMsg("Printing info for program %d\n", p_pgrm->i_number );
160 for( i_index2 = 0; i_index2 < p_pgrm->i_es_number; i_index2++ )
162 intf_Msg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n", p_pgrm->ap_es[i_index2]->i_id,
163 p_pgrm->ap_es[i_index2]->i_type, p_pgrm->ap_es[i_index2]->b_pcr,
164 p_pgrm->ap_es[i_index2]->b_psi);
166 intf_IntfMsg( " ->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);
172 /* Unock the tables */
173 //pthread_mutex_unlock()
176 /******************************************************************************
177 * input_PsiDecode: Decode a PSI section
178 ******************************************************************************
179 * This funtion is essentially a wrapper that will perform basic checks on
180 * the section and then call the right function according to its type.
181 ******************************************************************************/
182 void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section )
185 ASSERT(p_psi_section);
187 /* Hexa dump of the beginning of the section (for real men) */
188 //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] );
190 /* Check the CRC validity if any CRC is carried */
191 if( p_psi_section->buffer[1] & 0x80 )
193 if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )
195 intf_DbgMsg("iSize: %d, CRC: %d\n", p_psi_section->i_length,
196 U32_AT(&p_psi_section->buffer[p_psi_section->i_length-4]));
197 intf_DbgMsg( "Invalid CRC for PSI\n" );
202 /* If the section is not immediatly applicable, trash it (DVB drafts disallow
203 transmission of such sections, so we didn't implement it) */
204 if( !p_psi_section->buffer[5] & 0x01 )
206 intf_DbgMsg( "PSI not yet applicable: trash it\n" );
210 /* Handle the packet according to it's type given it the table_id */
211 switch ( p_psi_section->buffer[0] )
214 //intf_DbgMsg("Program association section received\n");
215 DecodePgrmAssocSection(p_psi_section->buffer, p_input);
218 //intf_DbgMsg("Conditional access section received\n");
221 //intf_DbgMsg("Program map section received\n");
222 DecodePgrmMapSection(p_psi_section->buffer, p_input);
225 //intf_DbgMsg("Service description section received\n");
226 DecodeSrvDescrSection(p_psi_section->buffer, p_input);
229 //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",
230 // p_psi_section->buffer[0]);
234 /******************************************************************************
235 * DecodeAssocSection: Decode a PAS
236 ******************************************************************************
237 * No check is made to known if the table is currently applicable or not, so
238 * that unapplicable sections must be filtered before calling this function
239 * The Program Association Table can be segmented to occupy multiple sections
240 * so that we have to know which sections we have already received (IsKnown() /
242 ******************************************************************************/
243 static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input )
245 u8 i_stream_id; /* Id of the stream described in that section */
246 u8 i_version; /* Version of the table carried in the section */
248 u16 i_pgrm_id; /* Id of the current described pgrm */
249 u16 i_pgrm_map_pid; /* PID of the associated program map table */
250 int i_pgrm_number; /* Number of programs described in the section */
252 boolean_t b_is_invalid = 0;
254 u8 i_current_section;
263 #define p_descr (p_input->p_stream)
265 /* Read stream id and version number immediately, to be sure they will be
266 initialised in all cases we will need it */
267 i_stream_id = U16_AT(&p_pas[3]);
268 i_version = (p_pas[5] >> 1) & 0x1F;
269 //intf_DbgMsg("TS Id: %d, version: %d\n", U16_AT(&p_pas[3]),(p_pas[5] >> 1) & 0x1F);
271 /* Test if the stream has not changed by looking at the stream_id */
272 if( p_descr->i_stream_id != i_stream_id )
274 /* This can either mean that the PSI decoder has just started or that
275 the stream has changed */
276 if( p_descr->i_PAT_version== PSI_UNINITIALISED )
277 intf_Msg("Building Program Association table\n");
279 intf_ErrMsg( "Stream Id has suddently changed ! Rebuilding PAT\n" );
281 /* Whatever it is, ask the PSI decoder to rebuild the table */
286 /* Stream has not changed, test if the PMT is up to date */
287 if( p_descr->i_PAT_version != i_version )
289 intf_Msg("PAT has been updated, rebuilding it\n");
290 /* Ask the PSI decoder to rebuild the table */
295 /* Clear the table if needed */
298 intf_DbgMsg("Updating PAT table\n");
300 /* Any program in the stream may have disapeared, or a new one
301 can have been added. The good way to handle such a case would be
302 to build a temporary table and to make a diff */
304 /* Stop the reception of all programs and PSI informations
305 associated with this stream, excepted the PAT on PID 0 and the SDT
307 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES &&
308 p_input->pp_selected_es[i_es_index]; i_es_index++ )
310 if( p_input->pp_selected_es[i_es_index]->b_psi )
312 if( p_input->pp_selected_es[i_es_index]->i_id != 0
313 #ifdef DVB_EXTENSIONS
314 && p_input->pp_selected_es[i_es_index]->i_id != 17
317 input_DelPsiPID( p_input, p_input->pp_selected_es[i_es_index]->i_id );
320 input_DelPgrmElem( p_input, p_input->pp_selected_es[i_es_index]->i_id );
323 /* Recreate a new stream description. Since it is virgin, the decoder
324 will on is own rebuild it entirely */
325 DestroyStreamDescr(p_input, p_descr->i_stream_id);
326 AddStreamDescr(p_input, i_stream_id);
328 /* Record the new version for that table */
329 p_descr->i_PAT_version = i_version;
332 /* Build the table if not already complete or if it was cleared */
333 if( p_descr->b_is_PAT_complete )
336 //intf_DbgMsg("Table already complete\n");
340 /* Check if we already heard about that section */
341 i_last_section = p_pas[7];
342 i_current_section = p_pas[6];
344 // intf_DbgMsg( "Section %d (last section %d)\n",
345 // i_current_section, i_last_section );
347 if( Is_known(p_descr->a_known_PAT_sections, i_current_section) )
350 // intf_DbgMsg("Section already received, skipping\n");
354 /* Compute the number of program_map PID carried in this section */
355 i_pgrm_number = ((U16_AT(&p_pas[1]) & 0xFFF) - 9) / 4;
356 intf_DbgMsg("Number of Pgrm in that section: %d\n", i_pgrm_number);
358 /* Start the reception of those program map PID */
359 for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ )
361 i_pgrm_id = U16_AT(&p_pas[8+4*i_pgrm_index]);
362 i_pgrm_map_pid = U16_AT(&p_pas[8+4*i_pgrm_index+2]) & 0x1FFF;
363 intf_DbgMsg("Pgrm %d described on pid %d\n", i_pgrm_id, i_pgrm_map_pid);
365 /* Check we are not already receiving that pid because it carries info
366 for another program */
367 for( i_es_index = 0; i_es_index < INPUT_MAX_ES; i_es_index++ )
369 if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid)
371 intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid);
372 i_es_index = INPUT_MAX_ES+1;
376 /* Start to receive that PID if we're not already doing it */
377 if( i_es_index <= INPUT_MAX_ES )
378 input_AddPsiPID( p_input, i_pgrm_map_pid );
380 /* Append an entry to the pgrm_descriptor table to later store
381 the description of this program, unless program number is 0
382 (Network information table) */
385 intf_Msg("Adding program %d to the Program Map Table\n", i_pgrm_id);
386 AddPgrmDescr(p_descr, i_pgrm_id);
390 /* We now know the info carried in this section */
391 Set_known(p_descr->a_known_PAT_sections, i_current_section);
393 /* Check if the table is now complete */
394 p_descr->i_known_PAT_sections++;
395 if( p_descr->i_known_PAT_sections >= i_last_section)
396 p_descr->b_is_PAT_complete = 1;
403 /******************************************************************************
404 * DecodePgrmMapSection: Decode a PMS
405 ******************************************************************************
406 * No check is made to known if the table is currently applicable or not, so
407 * that unapplicable sections must be filtered before calling this function
408 * The Program Map Table can be segmented to occupy multiple sections so that
409 * we have to know which sections we have already received (IsKnown() /
411 * Note that the processing of those sections is different from the one of the
412 * others since here a section refers to a single program, and a program cannot
413 * be segmented into multiple sections
414 ******************************************************************************/
415 static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input )
417 u16 i_pgrm_number; /* Id of the program described in that section */
418 u8 i_version; /* Version of the description for that program */
421 u16 i_section_length;
425 u8 i_current_section;
433 pgrm_descriptor_t* p_pgrm;
434 es_descriptor_t* p_es;
436 #define p_descr (p_input->p_stream)
438 /* Read the id of the program described in that section */
439 i_pgrm_number = U16_AT(&p_pms[3]);
440 // intf_DbgMsg( "PMT section received for program %d\n", i_pgrm_number );
442 /* Find where is stored the description of this program */
443 for( i_index = 0; i_index < p_descr->i_pgrm_number &&
444 i_pgrm_number != p_descr->ap_programs[i_index]->i_number; i_index++ );
446 if( i_index >= p_descr->i_pgrm_number )
448 /* If none entry exists, this simply means that the PAT is not complete,
449 so skip this section since it is the responsability of the PAT decoder
450 to add pgrm_descriptor slots to the table of known pgrms */
451 intf_DbgMsg( "Pgrm %d is unknown: skipping its description\n", i_pgrm_number );
455 /* We now have the slot which is the program described: we can begin with
456 the decoding of its description */
457 p_pgrm = p_descr->ap_programs[i_index];
459 /* Which section of the description of that program did we receive ? */
460 i_last_section = p_pms[7];
461 i_current_section = p_pms[6];
462 // intf_DbgMsg("Section %d (last section %d)\n", i_current_section, i_last_section);
464 /* Is this an update of the description for this program ? */
465 i_version = (p_pms[5] >> 1) && 0x1F;
466 if( p_pgrm->i_version != i_version )
468 intf_Msg("Updating PMT for program %d\n", i_pgrm_number);
470 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
472 /* Stop the reception of the ES if needed by calling the function
473 normally used by the interface to manage this */
474 if( input_IsElemRecv(p_input, p_pgrm->ap_es[i_index]->i_id) )
476 intf_Msg( "PID %d is no more valid: stopping its reception\n",
477 p_pgrm->ap_es[i_index]->i_id );
478 input_DelPgrmElem( p_input, p_pgrm->ap_es[i_index]->i_id );
481 /* Remove the descriptor associated to the es of this programs */
482 intf_DbgMsg( "Invalidating PID %d\n", p_pgrm->ap_es[i_index]->i_id );
483 DestroyESDescr(p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id);
486 /* Update version number */
487 p_pgrm->i_version = i_version;
489 /* Ask the decoder to update the description of that program */
490 p_descr->i_known_PMT_sections--;
491 Unset_known( p_descr->a_known_PMT_sections, i_current_section );
495 /* Read the info for that pgrm is the one we have is not up to date or
496 if we don't have any */
497 if( p_pgrm->b_is_ok )
500 // intf_DbgMsg("Program description OK, nothing to do\n");
504 /* Check if we already heard about that section */
505 if( Is_known(p_descr->a_known_PMT_sections, i_current_section) )
508 // intf_DbgMsg("Section already received, skipping\n");
512 /* Read the corresponding PCR */
513 p_pgrm->i_pcr_pid = U16_AT(&p_pms[8]) & 0x1fff;
514 intf_DbgMsg("PCR at PID: %d\n", p_pgrm->i_pcr_pid);
516 /* Compute the length of the section minus the final CRC */
517 i_section_length = (U16_AT(&p_pms[1]) & 0xFFF) + 3 - 4;
518 intf_DbgMsg("Section length (CRC not included): %d\n", i_section_length);
520 /* Read additional info stored in the descriptors if any */
521 intf_DbgMsg("description length for program %d: %d\n", p_pgrm->i_number,
522 (U16_AT(&p_pms[10]) & 0x0FFF));
523 i_descr_end = (U16_AT(&p_pms[10]) & 0x0FFF) + 12;
524 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
527 while( i_offset < i_descr_end )
529 DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm);
530 i_offset += p_pms[i_offset+1] + 2;
533 /* Read all the ES descriptions */
534 while( i_offset < i_section_length )
536 /* Read type of that ES */
537 intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]);
539 /* Read PID of that ES */
540 i_es_pid = U16_AT(&p_pms[i_offset+1]) & 0x1FF;
541 intf_DbgMsg("ES PID: %d\n", i_es_pid);
543 /* Add the ES to the program description and reserve a slot in the
544 table of ES to store its description */
545 p_es = AddESDescr(p_input, p_pgrm, i_es_pid);
548 intf_ErrMsg("Warning: definition of program %d will be uncomplete\n",
550 /* The best way to handle this is to stop decoding the info for that
551 section but do as if everything is ok. Thus we will eventually have
552 an uncomplete ES table marked as being complete and some error msgs */
557 /* Store the description of that PID in the slot */
558 p_es->i_type = p_pms[i_offset];
560 if( i_es_pid == p_pgrm->i_pcr_pid )
565 /* Read additional info given by the descriptors */
567 intf_DbgMsg("description length for PID %d: %d\n", p_es->i_id,
568 (U16_AT(&p_pms[i_offset-2]) & 0x0FFF));
569 i_descr_end = (U16_AT(&p_pms[i_offset-2]) & 0x0FFF) + i_offset;
570 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
571 while( i_offset < i_descr_end )
573 DecodeESDescriptor(&p_pms[i_offset], p_es);
574 i_offset += p_pms[i_offset+1] + 2;
578 /* Jump to next ES description */
581 /* We now know the info carried in this section */
582 intf_Msg("Description of program %d complete\n", p_pgrm->i_number);
584 Set_known(p_descr->a_known_PMT_sections, i_current_section);
586 /* Check if the PMT is now complete */
587 p_descr->i_known_PMT_sections++;
588 if( p_descr->i_known_PMT_sections >= i_last_section)
590 p_descr->b_is_PMT_complete = 1;
593 /* Spawn an audio and a video thread, if possible. */
594 for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
596 switch( p_input->p_es[i_es_loop].i_type )
602 /* Spawn an audio thread */
603 input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id );
616 /******************************************************************************
617 * DecodeSrvDescrSection
618 ******************************************************************************
619 * A finir et a refaire proprement ????
620 ******************************************************************************/
621 void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input )
629 boolean_t b_must_update = 0;
636 #define p_stream (p_input->p_stream)
638 /* Read stream id and version number immediately, to be sure they will be
639 initialised in all the cases in which we will need them */
640 i_stream_id = U16_AT(&p_sdt[3]);
641 i_version = (p_sdt[5] >> 1) & 0x1F;
642 intf_DbgMsg("TS Id: %d, version: %d\n", i_stream_id, i_version);
644 /* Take the descriptor into account only if it describes the streams we are
646 if( p_stream->i_stream_id != i_stream_id )
648 intf_DbgMsg("SDT doen't apply to our TS but to %s: aborting\n",
653 /* Section applyies to our TS, test if the SDT is up to date */
654 if( p_stream->i_SDT_version != i_version )
656 intf_Msg("SDT has been updated, NOT YET IMPLEMENTED\n");
658 /* Ask the PSI decoder to rebuild the table */
663 /* Rebuild the table if needed */
666 intf_DbgMsg("Updating SDT table\n");
668 i_length = p_sdt[1] & 0x0FFF;
671 while(i_offset < i_length)
674 /* Find the program to which the description applies */
675 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
677 if( p_stream->ap_programs[i_index]->i_number == U16_AT(&p_sdt[i_offset]) )
680 intf_Msg("FOUND: %d\n", p_stream->ap_programs[i_index]->i_number);
685 /* Copy the info to the description of that program */
687 intf_DbgMsg("description length for SDT: %d\n",
688 (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF));
689 i_descr_end = (U16_AT(&p_sdt[i_offset-2]) & 0x0FFF) + i_offset;
690 intf_DbgMsg("description ends at offset: %d\n", i_descr_end);
691 while( i_offset < i_descr_end )
693 DecodePgrmDescriptor(&p_sdt[i_offset], p_stream->ap_programs[i_index]);
694 i_offset += p_sdt[i_offset+1] + 2;
701 /******************************************************************************
703 ******************************************************************************
704 * Decode any descriptor applying to the definition of a program
705 ******************************************************************************/
706 static void DecodePgrmDescriptor( byte_t* p_descriptor, pgrm_descriptor_t* p_pgrm )
708 u8 i_type; /* Type of the descriptor */
709 u8 i_length; /* Length of the descriptor */
710 #ifdef DVB_EXTENSIONS
711 int i_offset; /* Current position in the descriptor */
714 ASSERT(p_descriptor);
717 /* Read type and length of the descriptor */
718 i_type = p_descriptor[0];
719 i_length = p_descriptor[1];
721 /* Handle specific descriptor info */
724 #ifdef DVB_EXTENSIONS
725 case PSI_SERVICE_DESCRIPTOR:
727 /* Store service type */
728 p_pgrm->i_srv_type = p_descriptor[2];
730 /* Jump to the beginning of the service name */
731 i_offset = p_descriptor[3] + 5;
733 /* Check that the charset used is the normal one (latin) by testing the
734 first byte of the name */
735 if( p_descriptor[i_offset] >= 0x20 )
737 /* The charset is the one of our computer: just manually dup the string */
738 p_pgrm->psz_srv_name = malloc(i_length - i_offset +1);
739 memcpy(p_pgrm->psz_srv_name, &p_descriptor[i_offset], i_length - i_offset);
740 p_pgrm->psz_srv_name[i_length - i_offset + 1] = '\0';
744 /* Indicate that the name couldn't be printed */
745 p_pgrm->psz_srv_name = "Ununderstandable :)";
751 // intf_DbgMsg("Unhandled program descriptor received (type: %d)\n", i_type);
752 // intf_Msg("Unhandled ES descriptor received (type: %d)\n", i_type);
756 /******************************************************************************
758 ******************************************************************************
759 * Decode any descriptor applying to the definition of an ES
760 ******************************************************************************/
761 static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es )
763 u8 i_type; /* Type of the descriptor */
764 u8 i_length; /* Length of the descriptor */
765 // int i_offset; /* Current position in the descriptor */
767 ASSERT(p_descriptor);
770 /* Read type and length of the descriptor */
771 i_type = p_descriptor[0];
772 i_length = p_descriptor[1];
776 case PSI_VIDEO_STREAM_DESCRIPTOR:
778 intf_DbgMsg("Video stream descriptor received\n");
781 case PSI_AUDIO_STREAM_DESCRIPTOR:
783 intf_DbgMsg("Audio stream descriptor received\n");
786 case PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR:
788 intf_DbgMsg("Target background descriptor received\n");
791 case PSI_VIDEO_WINDOW_DESCRIPTOR:
793 intf_DbgMsg("Video window descriptor received\n");
797 // intf_DbgMsg("Unhandled ES descriptor received (type: %d)\n", i_type);
798 // intf_Msg("Unhandled ES descriptor received (type: %d)\n", i_type);
802 /******************************************************************************
803 * input_AddPsiPID: Start to receive the PSI info contained in a PID
804 ******************************************************************************
805 * Add a descriptor to the table of es descriptor for that es and mark the es
806 * as being to be received by the input (since all PSI must be received to
807 * build the description of the program)
808 ******************************************************************************/
809 static int input_AddPsiPID( input_thread_t *p_input, int i_pid )
812 es_descriptor_t* p_psi_es;
815 /* Store the description of this stream in the input thread */
816 p_psi_es = AddESDescr(p_input, NULL, i_pid);
820 /* Precise this ES carries PSI */
823 /* Create the buffer needed by the PSI decoder */
824 p_psi_es->p_psi_section = malloc( sizeof( psi_section_t) );
825 if( !p_psi_es->p_psi_section )
827 intf_ErrMsg( "Malloc error\n" );
832 /* Init the reception for that PID */
833 p_psi_es->p_psi_section->b_running_section = 0;
834 // p_psi_es->p_psi_section->b_discard_payload = 0;
836 /* Ask the input thread to demultiplex it: since the interface
837 can also access the table of selected es, lock the elementary
839 pthread_mutex_lock( &p_input->es_lock );
840 for( i_index = 0; i_index < INPUT_MAX_SELECTED_ES; i_index++ )
842 if( !p_input->pp_selected_es[i_index] )
844 intf_DbgMsg( "Free Selected ES slot found at offset %d: Will use it for PID %d\n",
846 p_input->pp_selected_es[i_index] = p_psi_es;
850 pthread_mutex_unlock( &p_input->es_lock );
852 if( i_index >= INPUT_MAX_SELECTED_ES )
854 intf_ErrMsg( "Stream carries to many PID for our decoder\n" );
863 /******************************************************************************
864 * input_DelPsiPID: Stop to receive the PSI info contained in a PID
865 ******************************************************************************
866 * Remove the PID from the list of ES descriptors and from the list of ES that
867 * the input must receive.
868 * Known PID for PSI should always be received, so that their description
869 * should be pointed out by a member of pp_selected_es. But as INPUT_MAX_ES
870 * can be different of INPUT_MAX_SELECTED_ES, this may happen, so that we must
872 ******************************************************************************/
873 static int input_DelPsiPID( input_thread_t *p_input, int i_pid )
875 int i_es_index, i_last_sel;
877 intf_DbgMsg( "Deleting PSI PID %d\n", i_pid );
879 /* Stop to receive the ES. Since the interface can also access the table
880 of selected es, lock the elementary stream structure */
881 pthread_mutex_lock( &p_input->es_lock );
883 for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES; i_es_index++ )
885 if( p_input->pp_selected_es[i_es_index] &&
886 p_input->pp_selected_es[i_es_index]->i_id == i_pid )
888 /* Unmark the stream */
889 p_input->pp_selected_es[i_es_index] = NULL;
891 /* There must not be any gap in the pp_selected_es, so move the last
892 selected stream to this slot */
893 for( i_last_sel = i_es_index; p_input->pp_selected_es[i_last_sel] &&
894 i_last_sel < INPUT_MAX_SELECTED_ES; i_last_sel++ );
895 p_input->pp_selected_es[i_es_index] = p_input->pp_selected_es[i_last_sel];
896 p_input->pp_selected_es[i_last_sel] = NULL;
901 pthread_mutex_unlock( &p_input->es_lock );
904 /* Check if the pp_selected_es table may be corrupted */
905 if( i_es_index >= INPUT_MAX_PROGRAM_ES )
907 intf_ErrMsg( "DelPsiPID error: PID %d is not currently received\n", i_pid );
911 /* Remove the desription of that ES from the table of ES */
912 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;
935 /******************************************************************************
936 * Test the validity of a checksum
937 ******************************************************************************
938 * The checksum must be stored at the end of the data, and the given size must
939 * include the 32 bits of the CRC.
940 * Return 0 if the checksum is OK, any other value if the data are corrupted
941 ******************************************************************************/
942 int CheckCRC32(byte_t* p_data, int i_data_size)
945 u32 i_crc = 0xffffffff;
949 for (i = 0; i < i_data_size; i++)
950 i_crc = (i_crc << 8) ^ i_crc_32_table[(i_crc >> 24) ^ p_data[i]];
955 /******************************************************************************
956 * Is_known: check if a given section has already been received
957 ******************************************************************************
958 * As a table cannot be segmented into more than 256 sections, we store a 256
959 * bits long table, each bit set to one indicating that the corresponding
960 * saction has been received
961 ******************************************************************************/
962 boolean_t Is_known( byte_t* a_known_section, u8 i_section )
965 boolean_t b_is_known;
967 /* Where to get the information ? */
968 int i_bit_in_byte = i_section % 8;
969 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
971 /* Build mask to read the Is_known flag */
972 mask = 0x01 << i_bit_in_byte;
975 b_is_known = a_known_section[i_byte_in_table] & mask;
980 /******************************************************************************
981 * Set_known: mark a given section has having been received
982 ******************************************************************************
984 ******************************************************************************/
985 static void Set_known( byte_t* a_known_section, u8 i_section )
989 /* Where to get the information ? */
990 int i_bit_in_byte = i_section % 8;
991 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
993 /* Build mask to read the Is_known flag */
994 mask = 0x01 << i_bit_in_byte;
997 a_known_section[i_byte_in_table] |= mask;
1000 /******************************************************************************
1001 * Unset_known: remove the 'received' mark for a given section
1002 ******************************************************************************
1004 ******************************************************************************/
1005 static void Unset_known( byte_t* a_known_section, u8 i_section )
1009 /* Where to get the information ? */
1010 int i_bit_in_byte = i_section % 8;
1011 int i_byte_in_table = (i_section - i_bit_in_byte) / 8;
1013 /* Build mask to read the Is_known flag */
1014 mask = 0x01 << i_bit_in_byte;
1017 /* Unset the flag */
1018 a_known_section[i_byte_in_table] &= mask;
1021 /******************************************************************************
1022 * AddStreamDescr: add and init the stream descriptor of the given input
1023 ******************************************************************************
1025 ******************************************************************************/
1026 static stream_descriptor_t* AddStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1030 intf_DbgMsg("Adding description for stream %d\n", i_stream_id);
1032 p_input->p_stream = malloc( sizeof(stream_descriptor_t) );
1034 p_input->p_stream->i_stream_id = i_stream_id;
1036 p_input->p_stream->i_PAT_version = PSI_UNINITIALISED;
1037 p_input->p_stream->i_known_PAT_sections = 0;
1038 bzero( p_input->p_stream->a_known_PAT_sections,
1039 sizeof(*p_input->p_stream->a_known_PAT_sections) );
1040 p_input->p_stream->b_is_PAT_complete = 0;
1042 p_input->p_stream->i_known_PMT_sections = 0;
1043 bzero( p_input->p_stream->a_known_PMT_sections,
1044 sizeof(*p_input->p_stream->a_known_PMT_sections) );
1045 p_input->p_stream->b_is_PMT_complete = 0;
1047 #ifdef DVB_EXTENSIONS
1048 p_input->p_stream->i_SDT_version = PSI_UNINITIALISED;
1049 p_input->p_stream->i_known_SDT_sections = 0;
1050 bzero( p_input->p_stream->a_known_SDT_sections,
1051 sizeof(*p_input->p_stream->a_known_SDT_sections) );
1052 p_input->p_stream->b_is_SDT_complete = 0;
1055 p_input->p_stream->i_pgrm_number = 0;
1056 p_input->p_stream->ap_programs = NULL;
1058 return p_input->p_stream;
1061 /******************************************************************************
1062 * DestroyStreamDescr: destroy the stream desciptor of the given input
1063 ******************************************************************************
1065 ******************************************************************************/
1066 static void DestroyStreamDescr(input_thread_t* p_input, u16 i_stream_id)
1072 /* Free the structures that describes the programs of that stream */
1073 for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )
1075 DestroyPgrmDescr( p_input, p_input->p_stream, p_input->p_stream->ap_programs[i_index]->i_number );
1078 /* Free the table of pgrm descriptors */
1079 free( p_input->p_stream->ap_programs );
1081 /* Free the structure that describes the stream itself */
1082 free( p_input->p_stream );
1084 /* Input thread has no more stream descriptor */
1085 p_input->p_stream = NULL;
1088 /******************************************************************************
1089 * AddPgrmDescr: add and init a program descriptor
1090 ******************************************************************************
1091 * This program descriptor will be referenced in the given stream descriptor
1092 ******************************************************************************/
1093 static pgrm_descriptor_t* AddPgrmDescr(stream_descriptor_t* p_stream, u16 i_pgrm_id)
1097 intf_DbgMsg("Adding description for pgrm %d\n", i_pgrm_id);
1099 /* Add an entry to the list of program associated with the stream */
1100 p_stream->i_pgrm_number++;
1101 p_stream->ap_programs = realloc( p_stream->ap_programs,
1102 p_stream->i_pgrm_number*sizeof(pgrm_descriptor_t*) );
1104 /* Allocate the structure to store this description */
1105 p_stream->ap_programs[p_stream->i_pgrm_number-1] = malloc(sizeof(pgrm_descriptor_t));
1107 /* Init this entry */
1108 p_stream->ap_programs[p_stream->i_pgrm_number-1]->i_number = i_pgrm_id;
1109 p_stream->ap_programs[p_stream->i_pgrm_number-1]->i_version = PSI_UNINITIALISED;
1110 p_stream->ap_programs[p_stream->i_pgrm_number-1]->b_is_ok = 0;
1112 p_stream->ap_programs[p_stream->i_pgrm_number-1]->i_es_number = 0;
1113 p_stream->ap_programs[p_stream->i_pgrm_number-1]->ap_es = NULL;
1115 /* descriptors ???? */
1117 return p_stream->ap_programs[p_stream->i_pgrm_number-1];
1120 /******************************************************************************
1121 * AddPgrmDescr: destroy a program descriptor
1122 ******************************************************************************
1123 * All ES descriptions referenced in the descriptor will be deleted.
1124 ******************************************************************************/
1125 static void DestroyPgrmDescr( input_thread_t * p_input, stream_descriptor_t * p_stream, u16 i_pgrm_id )
1127 int i_index, i_pgrm_index;
1128 pgrm_descriptor_t * p_pgrm;
1132 /* Find where this program is described */
1133 for( i_index = 0; i_index < p_stream->i_pgrm_number; i_index++ )
1135 if( p_stream->ap_programs[i_index]->i_number == i_pgrm_id )
1137 i_pgrm_index = i_index;
1138 p_pgrm = p_stream->ap_programs[ i_pgrm_index ];
1143 /* Free the structures that describe the es that belongs to that program */
1144 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
1146 DestroyESDescr( p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id );
1149 /* Free the table of es descriptors */
1150 free( p_pgrm->ap_es );
1152 /* Free the description of this stream */
1155 /* Remove this program from the stream's list of programs */
1156 p_stream->i_pgrm_number--;
1157 p_stream->ap_programs[ i_pgrm_index ] = p_stream->ap_programs[ p_stream->i_pgrm_number ];
1158 p_stream->ap_programs = realloc( p_stream->ap_programs, p_stream->i_pgrm_number * sizeof(pgrm_descriptor_t *) );
1161 /******************************************************************************
1163 ******************************************************************************
1164 * Reserve a slot in the table of ES descritors for the ES and add it to the
1165 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
1167 ******************************************************************************/
1168 static es_descriptor_t* AddESDescr(input_thread_t* p_input,
1169 pgrm_descriptor_t* p_pgrm, u16 i_es_pid)
1172 es_descriptor_t* p_es = NULL;
1176 intf_DbgMsg("Adding description for ES %d\n", i_es_pid);
1178 /* Find an empty slot to store the description of that es */
1179 for( i_index = 0; i_index < INPUT_MAX_ES &&
1180 p_input->p_es[i_index].i_id != EMPTY_PID; i_index++ );
1182 if( i_index >= INPUT_MAX_ES )
1184 /* No slot is empty */
1185 intf_ErrMsg("Stream carries to many PID for our decoder\n");
1189 /* Reserve the slot for that ES */
1190 p_es = &p_input->p_es[i_index];
1191 p_es->i_id = i_es_pid;
1192 intf_DbgMsg("Slot %d in p_es table reserved for ES %d\n", i_index, i_es_pid);
1194 /* Init its values */
1195 p_es->i_type = 0; /* ??? */
1199 p_es->p_pes_packet = NULL;
1200 // p_es->p_next_pes_packet = NULL;
1203 /* Add this ES to the program definition if one is given */
1206 p_pgrm->i_es_number++;
1207 p_pgrm->ap_es = realloc( p_pgrm->ap_es, p_pgrm->i_es_number*sizeof(es_descriptor_t *) );
1208 p_pgrm->ap_es[p_pgrm->i_es_number-1] = p_es;
1209 intf_DbgMsg("Added ES %d to definition of pgrm %d\n", i_es_pid, p_pgrm->i_number);
1212 intf_DbgMsg("Added ES %d not added to the definition of any pgrm\n", i_es_pid);
1218 /******************************************************************************
1220 ******************************************************************************
1222 ******************************************************************************/
1223 static void DestroyESDescr(input_thread_t* p_input, pgrm_descriptor_t* p_pgrm, u16 i_pid)
1229 /* Look for the description of the ES */
1230 for(i_index = 0; i_index < INPUT_MAX_ES; i_index++)
1232 if( p_input->p_es[i_index].i_id == i_pid )
1234 /* The table of stream descriptors is static, so don't free memory
1235 but just mark the slot as unused */
1236 p_input->p_es[i_index].i_id = EMPTY_PID;
1241 /* Remove this ES from the description of the program if it is associated to
1245 for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
1247 if( p_input->p_es[i_index].i_id == i_pid )
1249 p_pgrm->i_es_number--;
1250 p_pgrm->ap_es[i_index] = p_pgrm->ap_es[p_pgrm->i_es_number];
1251 p_pgrm->ap_es = realloc(p_pgrm->ap_es, p_pgrm->i_es_number);