📄 input_psi.c
字号:
for( i_es_index = 0; i_es_index < INPUT_MAX_SELECTED_ES && p_input->pp_selected_es[i_es_index]; i_es_index++ ) { if( p_input->pp_selected_es[i_es_index]->b_psi ) { if( p_input->pp_selected_es[i_es_index]->i_id != 0#ifdef DVB_EXTENSIONS && p_input->pp_selected_es[i_es_index]->i_id != 17#endif ) input_DelPsiPID( p_input, p_input->pp_selected_es[i_es_index]->i_id ); } else input_DelPgrmElem( p_input, p_input->pp_selected_es[i_es_index]->i_id ); } /* Recreate a new stream description. Since it is virgin, the decoder will rebuild it entirely on is own */ DestroyStreamDescr(p_input, p_descr->i_stream_id); AddStreamDescr(p_input, i_stream_id); /* Record the new version for that table */ p_descr->i_PAT_version = i_version; } /* Build the table if not already complete or if it was cleared */ if( p_descr->b_is_PAT_complete ) { /* Nothing to do */ if( b_is_invalid ) intf_DbgMsg("Bug: table invalid but PAT said to be complete\n"); } else { /* Check if we already heard about that section */ i_last_section = p_pas[7]; i_current_section = p_pas[6];// intf_DbgMsg( "Section %d (last section %d)\n",// i_current_section, i_last_section ); if( Is_known(p_descr->a_known_PAT_sections, i_current_section) ) { /* Nothing to do */// intf_DbgMsg("Section already received, skipping\n"); } else { /* Compute the number of program_map PID carried in this section */ i_pgrm_number = ((U16_AT(&p_pas[1]) & 0xFFF) - 9) / 4; intf_DbgMsg("Number of Pgrm in that section: %d\n", i_pgrm_number); /* Start the reception of those program map PID */ for( i_pgrm_index = 0; i_pgrm_index < i_pgrm_number; i_pgrm_index++ ) { i_pgrm_id = U16_AT(&p_pas[8+4*i_pgrm_index]); i_pgrm_map_pid = U16_AT(&p_pas[8+4*i_pgrm_index+2]) & 0x1fff; intf_DbgMsg("Pgrm %d described on pid %d\n", i_pgrm_id, i_pgrm_map_pid); /* Check we are not already receiving that pid because it carries info for another program */ for( i_es_index = 0; i_es_index < INPUT_MAX_ES; i_es_index++ ) { if( p_input->p_es[i_es_index].i_id == i_pgrm_map_pid) { intf_DbgMsg("Already receiving pid %d", i_pgrm_map_pid); i_es_index = INPUT_MAX_ES+1; break; } } /* Start to receive that PID if we're not already doing it */ if( i_es_index <= INPUT_MAX_ES ) input_AddPsiPID( p_input, i_pgrm_map_pid ); /* Append an entry to the pgrm_descriptor table to later store the description of this program, unless program number is 0 (Network information table) */ if( i_pgrm_id != 0 ) { intf_DbgMsg("Adding program %d to the PMT\n", i_pgrm_id); AddPgrmDescr(p_descr, i_pgrm_id); } } /* We now know the info carried in this section */ Set_known(p_descr->a_known_PAT_sections, i_current_section); /* Check if the table is now complete */ p_descr->i_known_PAT_sections++; if( p_descr->i_known_PAT_sections >= i_last_section) p_descr->b_is_PAT_complete = 1; } }#undef p_descr}/***************************************************************************** * DecodePgrmMapSection: Decode a PMS ***************************************************************************** * No check is made to known if the table is currently applicable or not, so * that unapplicable sections must be filtered before calling this function * The Program Map Table can be segmented to occupy multiple sections so that * we have to know which sections we have already received (IsKnown() / * SetKnown() calls) * Note that the processing of those sections is different from the one of the * others since here a section refers to a single program, and a program cannot * be segmented into multiple sections *****************************************************************************/static void DecodePgrmMapSection( u8* p_pms, input_thread_t* p_input ){ u16 i_pgrm_number; /* Id of the program described in that section */ u8 i_version; /* Version of the description for that program */ u16 i_offset; u16 i_section_length; u16 i_descr_end; u8 i_last_section; u8 i_current_section; u16 i_es_pid; int i_index = 0;#ifdef AUTO_SPAWN int i_es_loop;#endif pgrm_descriptor_t* p_pgrm; es_descriptor_t* p_es;#define p_descr (p_input->p_stream) /* Read the id of the program described in that section */ i_pgrm_number = U16_AT(&p_pms[3]);// intf_DbgMsg( "PMT section received for program %d\n", i_pgrm_number ); /* Find where is stored the description of this program */ for( i_index = 0; i_index < p_descr->i_pgrm_number && i_pgrm_number != p_descr->ap_programs[i_index]->i_number; i_index++ ); if( i_index >= p_descr->i_pgrm_number ) { /* If none entry exists, this simply means that the PAT is not complete, so skip this section since it is the responsability of the PAT decoder to add pgrm_descriptor slots to the table of known pgrms */ intf_DbgMsg( "Unknown pgrm %d: skipping its description\n", i_pgrm_number ); return; } /* We now have the slot which is the program described: we can begin with the decoding of its description */ p_pgrm = p_descr->ap_programs[i_index]; /* Which section of the description of that program did we receive ? */ i_last_section = p_pms[7]; i_current_section = p_pms[6];// intf_DbgMsg("Section %d (last section %d)\n", i_current_section, i_last_section); /* Is this an update of the description for this program ? */ i_version = (p_pms[5] >> 1) & 0x1F; if( p_pgrm->i_version != i_version ) { intf_DbgMsg("Updating PMT for program %d\n", i_pgrm_number); for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ ) { /* Stop the reception of the ES if needed by calling the function normally used by the interface to manage this */ if( input_IsElemRecv(p_input, p_pgrm->ap_es[i_index]->i_id) ) { intf_DbgMsg( "PID %d is no more valid: stopping its reception\n", p_pgrm->ap_es[i_index]->i_id ); input_DelPgrmElem( p_input, p_pgrm->ap_es[i_index]->i_id ); } /* Remove the descriptor associated to the es of this programs */ intf_DbgMsg( "Invalidating PID %d\n", p_pgrm->ap_es[i_index]->i_id ); DestroyESDescr(p_input, p_pgrm, p_pgrm->ap_es[i_index]->i_id); } /* Update version number */ p_pgrm->i_version = i_version; /* Ask the decoder to update the description of that program */ p_descr->i_known_PMT_sections--; Unset_known( p_descr->a_known_PMT_sections, i_current_section ); p_pgrm->b_is_ok = 0; } /* Read the info for that pgrm is the one we have is not up to date or if we don't have any */ if( p_pgrm->b_is_ok ) { /* Nothing to do */// intf_DbgMsg("Program description OK, nothing to do\n"); } else { /* Check if we already heard about that section */ if( Is_known(p_descr->a_known_PMT_sections, i_current_section) ) { /* Nothing to do */// intf_DbgMsg("Section already received, skipping\n"); } else { /* Read the corresponding PCR */ p_pgrm->i_pcr_pid = U16_AT(&p_pms[8]) & 0x1fff; intf_DbgMsg("PCR at PID: %d\n", p_pgrm->i_pcr_pid); /* Compute the length of the section minus the final CRC */ i_section_length = (U16_AT(&p_pms[1]) & 0xfff) + 3 - 4; intf_DbgMsg("Section length (without CRC): %d\n", i_section_length); /* Read additional info stored in the descriptors if any */ intf_DbgMsg("Description length for program %d: %d\n", p_pgrm->i_number, (U16_AT(&p_pms[10]) & 0x0fff)); i_descr_end = (U16_AT(&p_pms[10]) & 0x0fff) + 12; intf_DbgMsg("description ends at offset: %d\n", i_descr_end); i_offset = 12; while( i_offset < i_descr_end ) { DecodePgrmDescriptor(&p_pms[i_offset], p_pgrm); i_offset += p_pms[i_offset+1] + 2; } /* Read all the ES descriptions */ while( i_offset < i_section_length ) { /* Read type of that ES */ intf_DbgMsg("ES Type: %d\n", p_pms[i_offset]); /* Read PID of that ES */ i_es_pid = U16_AT(&p_pms[i_offset+1]) & 0x1fff; intf_DbgMsg("ES PID: %d\n", i_es_pid); /* Add the ES to the program description and reserve a slot in the table of ES to store its description */ p_es = AddESDescr(p_input, p_pgrm, i_es_pid); if (!p_es) { intf_ErrMsg("Warning: definition for pgrm %d won't be complete\n", p_pgrm->i_number); /* The best way to handle this is to stop decoding the info for that section but do as if everything is ok. Thus we will eventually have an uncomplete ES table marked as being complete and some error msgs */ break; } else { /* Store the description of that PID in the slot */ p_es->i_type = p_pms[i_offset]; p_es->b_psi = 0; if( i_es_pid == p_pgrm->i_pcr_pid ) p_es->b_pcr = 1; else p_es->b_pcr = 0; /* Read additional info given by the descriptors */ i_offset += 5; intf_DbgMsg("description length for PID %d: %d\n", p_es->i_id, (U16_AT(&p_pms[i_offset-2]) & 0x0fff)); i_descr_end = (U16_AT(&p_pms[i_offset-2]) & 0x0fff) + i_offset; intf_DbgMsg("description ends at offset: %d\n", i_descr_end); while( i_offset < i_descr_end ) { DecodeESDescriptor(&p_pms[i_offset], p_es); i_offset += p_pms[i_offset+1] + 2; } } /* Jump to next ES description */ } /* We now know the info carried in this section */ intf_DbgMsg("Description of program %d complete\n", p_pgrm->i_number); p_pgrm->b_is_ok = 1; Set_known(p_descr->a_known_PMT_sections, i_current_section); /* Check if the PMT is now complete */ p_descr->i_known_PMT_sections++; if( p_descr->i_known_PMT_sections >= i_last_section) { p_descr->b_is_PMT_complete = 1;#ifdef AUTO_SPAWN /* Spawn an audio and a video thread, if possible. */ for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ ) { switch( p_input->p_es[i_es_loop].i_type ) { case MPEG1_VIDEO_ES: case MPEG2_VIDEO_ES: if( p_main->b_video ) { /* Spawn a video thread */ input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id ); } break; case AC3_AUDIO_ES: if ( p_main->b_audio ) { /* Spawn an ac3 thread */ input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id ); } break; case LPCM_AUDIO_ES: if ( p_main->b_audio ) { /* Spawn an lpcm thread */ input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id ); } break; case DVD_SPU_ES: if ( p_main->b_video ) { /* Spawn a spu decoder thread */ input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id ); } break; case MPEG1_AUDIO_ES: case MPEG2_AUDIO_ES: if( p_main->b_audio ) { /* Spawn an audio thread */ input_AddPgrmElem( p_input, p_input->p_es[i_es_loop].i_id );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -