/***************************************************************************** * dvbpsi_DecodeParentalRatingDr *****************************************************************************/ dvbpsi_parental_rating_dr_t * dvbpsi_DecodeParentalRatingDr( dvbpsi_descriptor_t * p_descriptor) { int i_ratings_number, i; dvbpsi_parental_rating_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x55) { DVBPSI_ERROR_ARG("dr_55 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_parental_rating_dr_t*)malloc(sizeof(dvbpsi_parental_rating_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_55 decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if(p_descriptor->i_length % 4) { DVBPSI_ERROR_ARG("dr_55 decoder", "length not multiple of 4 (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } i_ratings_number = p_descriptor->i_length / 4; p_decoded->i_ratings_number = i_ratings_number; for (i=0; i < i_ratings_number; i++) { p_decoded->p_parental_rating[i].i_country_code = ((uint32_t)p_descriptor->p_data[4 * i] << 16) | ((uint32_t)p_descriptor->p_data[4 * i + 1] << 8) | p_descriptor->p_data[4 * i + 2]; p_decoded->p_parental_rating[i].i_rating = p_descriptor->p_data[4 * i + 3]; } p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeCUEIDr *****************************************************************************/ dvbpsi_cuei_dr_t * dvbpsi_DecodeCUEIDr(dvbpsi_descriptor_t * p_descriptor) { dvbpsi_cuei_dr_t *p_decoded; /* Check the tag */ if (p_descriptor->i_tag != 0x8a) { DVBPSI_ERROR_ARG("dr_8a decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if (p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_cuei_dr_t*)malloc(sizeof(dvbpsi_cuei_dr_t)); if (!p_decoded) { DVBPSI_ERROR("dr_8a decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if (p_descriptor->i_length == 0x01) { DVBPSI_ERROR_ARG("dr_8a decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } /* cue_stream_type according to: SCTE 35 2004 - p15 - table 6.3 * cue_stream_type PID usage * 0x00 splice_insert, splice_null, splice_schedule * 0x01 All Commands * 0x02 Segmentation * 0x03 Tiered Splicing * 0x04 Tiered Segmentation * 0x05 - 0x7f Reserved * 0x80 - 0xff User Defined */ p_decoded->i_cue_stream_type = p_descriptor->p_data[0]; p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeRegistrationDr *****************************************************************************/ dvbpsi_registration_dr_t * dvbpsi_DecodeRegistrationDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_registration_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x05) { DVBPSI_ERROR_ARG("dr_05 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_registration_dr_t*) malloc(sizeof(dvbpsi_registration_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_05 decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if(p_descriptor->i_length < 4) { DVBPSI_ERROR_ARG("dr_05 decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } p_decoded->i_format_identifier = ((uint32_t)(p_descriptor->p_data[0]) << 24) | ((uint32_t)(p_descriptor->p_data[1]) << 16) | ((uint32_t)(p_descriptor->p_data[2]) << 8) | (uint32_t)(p_descriptor->p_data[3]); p_decoded->i_additional_length = p_descriptor->i_length - 4; if(p_decoded->i_additional_length) memcpy(p_decoded->i_additional_info, p_descriptor->p_data + 4, p_decoded->i_additional_length); p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeShortEventDr *****************************************************************************/ dvbpsi_short_event_dr_t * dvbpsi_DecodeShortEventDr(dvbpsi_descriptor_t * p_descriptor) { dvbpsi_short_event_dr_t * p_decoded; int i_len1; int i_len2; /* Check the tag */ if(p_descriptor->i_tag != 0x4d || p_descriptor->i_length < 5 ) { DVBPSI_ERROR_ARG("dr_4d decoder", "bad tag or corrupted(0x%x)", p_descriptor->i_tag); return NULL; } /* Check length */ i_len1 = p_descriptor->p_data[3]; i_len2 = p_descriptor->p_data[4+i_len1]; if( p_descriptor->i_length < 5 + i_len1 + i_len2 ) { DVBPSI_ERROR_ARG("dr_4d decoder", "invalid length/content (tag=0x%x)", p_descriptor->i_tag ); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = malloc(sizeof(dvbpsi_short_event_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_4d decoder", "out of memory"); return NULL; } /* Decode data and check the length */ memcpy( p_decoded->i_iso_639_code, &p_descriptor->p_data[0], 3 ); p_decoded->i_event_name_length = i_len1; if( i_len1 > 0 ) memcpy( p_decoded->i_event_name, &p_descriptor->p_data[3+1], i_len1 ); p_decoded->i_text_length = i_len2; if( i_len2 > 0 ) memcpy( p_decoded->i_text, &p_descriptor->p_data[4+i_len1+1], i_len2 ); p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeISO639Dr *****************************************************************************/ dvbpsi_iso639_dr_t * dvbpsi_DecodeISO639Dr(dvbpsi_descriptor_t * p_descriptor) { dvbpsi_iso639_dr_t * p_decoded; int i; /* Check the tag */ if(p_descriptor->i_tag != 0x0a) { DVBPSI_ERROR_ARG("dr_0a decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_iso639_dr_t*)malloc(sizeof(dvbpsi_iso639_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_0a decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if((p_descriptor->i_length < 1) || (p_descriptor->i_length % 4 != 0)) { DVBPSI_ERROR_ARG("dr_0a decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } p_decoded->i_code_count = p_descriptor->i_length / 4; i = 0; while( i < p_decoded->i_code_count ) { p_decoded->code[i].iso_639_code[0] = p_descriptor->p_data[i*4]; p_decoded->code[i].iso_639_code[1] = p_descriptor->p_data[i*4+1]; p_decoded->code[i].iso_639_code[2] = p_descriptor->p_data[i*4+2]; p_decoded->code[i].i_audio_type = p_descriptor->p_data[i*4+3]; i++; } p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeTerrDelivSysDr *****************************************************************************/ dvbpsi_terr_deliv_sys_dr_t * dvbpsi_DecodeTerrDelivSysDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_terr_deliv_sys_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x5a) { DVBPSI_ERROR_ARG("dr_5a decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_terr_deliv_sys_dr_t*)malloc(sizeof(dvbpsi_terr_deliv_sys_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_5a decoder", "out of memory"); return NULL; } /* Decode data */ p_decoded->i_centre_frequency = (uint32_t)(p_descriptor->p_data[0] << 24) | (uint32_t)(p_descriptor->p_data[1] << 16) | (uint32_t)(p_descriptor->p_data[2] << 8) | (uint32_t)(p_descriptor->p_data[3]); p_decoded->i_bandwidth = (p_descriptor->p_data[4] >> 5) & 0x07; p_decoded->i_priority = (p_descriptor->p_data[4] >> 4) & 0x01; p_decoded->i_time_slice_indicator = (p_descriptor->p_data[4] >> 3) & 0x01; p_decoded->i_mpe_fec_indicator = (p_descriptor->p_data[4] >> 2) & 0x01; p_decoded->i_constellation = (p_descriptor->p_data[5] >> 6) & 0x03; p_decoded->i_hierarchy_information = (p_descriptor->p_data[5] >> 3) & 0x07; p_decoded->i_code_rate_hp_stream = p_descriptor->p_data[5] & 0x07; p_decoded->i_code_rate_lp_stream = (p_descriptor->p_data[6] >> 5) & 0x07; p_decoded->i_guard_interval = (p_descriptor->p_data[6] >> 3) & 0x03; p_decoded->i_transmission_mode = (p_descriptor->p_data[6] >> 1) & 0x03; p_decoded->i_other_frequency_flag = p_descriptor->p_data[6] & 0x01; p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeSystemClockDr *****************************************************************************/ dvbpsi_system_clock_dr_t * dvbpsi_DecodeSystemClockDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_system_clock_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x0b) { DVBPSI_ERROR_ARG("dr_0b decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_system_clock_dr_t*)malloc(sizeof(dvbpsi_system_clock_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_0b decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if(p_descriptor->i_length != 2) { DVBPSI_ERROR_ARG("dr_0b decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } p_decoded->b_external_clock_ref = (p_descriptor->p_data[0] & 0x80) ? 1 : 0; p_decoded->i_clock_accuracy_integer = p_descriptor->p_data[0] & 0x3f; p_decoded->i_clock_accuracy_exponent = (p_descriptor->p_data[1] & 0xe0) >> 5; p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeDSAlignmentDr *****************************************************************************/ dvbpsi_ds_alignment_dr_t * dvbpsi_DecodeDSAlignmentDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_ds_alignment_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x06) { DVBPSI_ERROR_ARG("dr_06 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_ds_alignment_dr_t*) malloc(sizeof(dvbpsi_ds_alignment_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_06 decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if(p_descriptor->i_length != 1) { DVBPSI_ERROR_ARG("dr_06 decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } p_decoded->i_alignment_type = p_descriptor->p_data[0]; p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeStreamIdentifierDr *****************************************************************************/ dvbpsi_stream_identifier_dr_t * dvbpsi_DecodeStreamIdentifierDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_stream_identifier_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x52) { DVBPSI_ERROR_ARG("dr_52 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_stream_identifier_dr_t*)malloc(sizeof(dvbpsi_stream_identifier_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_52 decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if(p_descriptor->i_length < 1) { DVBPSI_ERROR_ARG("dr_52 decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } p_decoded->i_component_tag = p_descriptor->p_data[0]; p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeBouquetNameDr *****************************************************************************/ dvbpsi_bouquet_name_dr_t * dvbpsi_DecodeBouquetNameDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_bouquet_name_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x47) { DVBPSI_ERROR_ARG("dr_47 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_bouquet_name_dr_t*)malloc(sizeof(dvbpsi_bouquet_name_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_47 decoder", "out of memory"); return NULL; } /* Decode data */ p_decoded->i_name_length = p_descriptor->i_length; if(p_decoded->i_name_length) memcpy(p_decoded->i_char, p_descriptor->p_data, p_decoded->i_name_length); p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeStuffingDr *****************************************************************************/ dvbpsi_stuffing_dr_t * dvbpsi_DecodeStuffingDr( dvbpsi_descriptor_t * p_descriptor) { dvbpsi_stuffing_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x42) { DVBPSI_ERROR_ARG("dr_42 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_stuffing_dr_t*)malloc(sizeof(dvbpsi_stuffing_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_42 decoder", "out of memory"); return NULL; } /* Decode data */ p_decoded->i_stuffing_length = p_descriptor->i_length; if(p_decoded->i_stuffing_length) memcpy(p_decoded->i_stuffing_byte, p_descriptor->p_data, p_decoded->i_stuffing_length); p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_GatherCATSections ***************************************************************************** * Callback for the PSI decoder. *****************************************************************************/ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder, dvbpsi_psi_section_t* p_section) { dvbpsi_cat_decoder_t* p_cat_decoder = (dvbpsi_cat_decoder_t*)p_decoder->p_private_decoder; int b_append = 1; int b_reinit = 0; unsigned int i; DVBPSI_DEBUG_ARG("CAT decoder", "Table version %2d, " "i_extension %5d, " "section %3d up to %3d, " "current %1d", p_section->i_version, p_section->i_extension, p_section->i_number, p_section->i_last_number, p_section->b_current_next); if(p_section->i_table_id != 0x01) { /* Invalid table_id value */ DVBPSI_ERROR_ARG("CAT decoder", "invalid section (table_id == 0x%02x)", p_section->i_table_id); b_append = 0; } if(b_append && !p_section->b_syntax_indicator) { /* Invalid section_syntax_indicator */ DVBPSI_ERROR("CAT decoder", "invalid section (section_syntax_indicator == 0)"); b_append = 0; } if(b_append) { /* TS discontinuity check */ if(p_decoder->b_discontinuity) { b_reinit = 1; p_decoder->b_discontinuity = 0; } else { /* Perform some few sanity checks */ if(p_cat_decoder->p_building_cat) { if(p_cat_decoder->p_building_cat->i_version != p_section->i_version) { /* version_number */ DVBPSI_ERROR("CAT decoder", "'version_number' differs" " whereas no discontinuity has occured"); b_reinit = 1; } else if(p_cat_decoder->i_last_section_number != p_section->i_last_number) { /* last_section_number */ DVBPSI_ERROR("CAT decoder", "'last_section_number' differs" " whereas no discontinuity has occured"); b_reinit = 1; } } else { if( (p_cat_decoder->b_current_valid) && (p_cat_decoder->current_cat.i_version == p_section->i_version) && (p_cat_decoder->current_cat.b_current_next == p_section->b_current_next)) { /* Don't decode since this version is already decoded */ b_append = 0; } } } } /* Reinit the decoder if wanted */ if(b_reinit) { /* Force redecoding */ p_cat_decoder->b_current_valid = 0; /* Free structures */ if(p_cat_decoder->p_building_cat) { free(p_cat_decoder->p_building_cat); p_cat_decoder->p_building_cat = NULL; } /* Clear the section array */ for(i = 0; i <= 255; i++) { if(p_cat_decoder->ap_sections[i] != NULL) { dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[i]); p_cat_decoder->ap_sections[i] = NULL; } } } /* Append the section to the list if wanted */ if(b_append) { int b_complete; /* Initialize the structures if it's the first section received */ if(!p_cat_decoder->p_building_cat) { p_cat_decoder->p_building_cat = (dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t)); dvbpsi_InitCAT(p_cat_decoder->p_building_cat, p_section->i_version, p_section->b_current_next); p_cat_decoder->i_last_section_number = p_section->i_last_number; } /* Fill the section array */ if(p_cat_decoder->ap_sections[p_section->i_number] != NULL) { DVBPSI_DEBUG_ARG("CAT decoder", "overwrite section number %d", p_section->i_number); dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[p_section->i_number]); } p_cat_decoder->ap_sections[p_section->i_number] = p_section; /* Check if we have all the sections */ b_complete = 0; for(i = 0; i <= p_cat_decoder->i_last_section_number; i++) { if(!p_cat_decoder->ap_sections[i]) break; if(i == p_cat_decoder->i_last_section_number) b_complete = 1; } if(b_complete) { /* Save the current information */ p_cat_decoder->current_cat = *p_cat_decoder->p_building_cat; p_cat_decoder->b_current_valid = 1; /* Chain the sections */ if(p_cat_decoder->i_last_section_number) { for(i = 0; (int)i <= p_cat_decoder->i_last_section_number - 1; i++) p_cat_decoder->ap_sections[i]->p_next = p_cat_decoder->ap_sections[i + 1]; } /* Decode the sections */ dvbpsi_DecodeCATSections(p_cat_decoder->p_building_cat, p_cat_decoder->ap_sections[0]); /* Delete the sections */ dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[0]); /* signal the new CAT */ p_cat_decoder->pf_callback(p_cat_decoder->p_cb_data, p_cat_decoder->p_building_cat); /* Reinitialize the structures */ p_cat_decoder->p_building_cat = NULL; for(i = 0; i <= p_cat_decoder->i_last_section_number; i++) p_cat_decoder->ap_sections[i] = NULL; } } else { dvbpsi_DeletePSISections(p_section); } }
/***************************************************************************** * dvbpsi_GatherPMTSections ***************************************************************************** * Callback for the PSI decoder. *****************************************************************************/ void DMA_dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, dvbpsi_psi_section_t* p_section) { dvbpsi_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t*)p_decoder->p_private_decoder; int b_append = 1; int b_reinit = 0; unsigned int i; #if 0 DVBPSI_DEBUG_ARG("PMT decoder", "Table version %2d, " "i_extension %5d, " "section %3d up to %3d, " "current %1d", p_section->i_version, p_section->i_extension, p_section->i_number, p_section->i_last_number, p_section->b_current_next); #endif if(p_section->i_table_id != 0x02) { /* Invalid table_id value */ #if 0 DVBPSI_ERROR_ARG("PMT decoder", "invalid section (table_id == 0x%02x)", p_section->i_table_id); #endif b_append = 0; } if(b_append && !p_section->b_syntax_indicator) { /* Invalid section_syntax_indicator */ #if 0 DMA_DVBPSI_ERROR("PMT decoder", "invalid section (section_syntax_indicator == 0)"); #endif b_append = 0; } /* Now if b_append is true then we have a valid PMT section */ if(b_append && (p_pmt_decoder->i_program_number != p_section->i_extension)) { /* Invalid program_number */ #if 0 DMA_DMA_DVBPSI_ERROR("PMT decoder", "'program_number' don't match"); #endif b_append = 0; } if(b_append) { /* TS discontinuity check */ if(p_decoder->b_discontinuity) { b_reinit = 1; p_decoder->b_discontinuity = 0; } else { /* Perform some few sanity checks */ if(p_pmt_decoder->p_building_pmt) { if(p_pmt_decoder->p_building_pmt->i_version != p_section->i_version) { /* version_number */ #if 0 DMA_DMA_DVBPSI_ERROR("PMT decoder", "'version_number' differs" " whereas no discontinuity has occured"); #endif b_reinit = 1; } else if(p_pmt_decoder->i_last_section_number != p_section->i_last_number) { /* last_section_number */ #if 0 DVBPSI_ERROR("PMT decoder", "'last_section_number' differs" " whereas no discontinuity has occured"); #endif b_reinit = 1; } } else { if( (p_pmt_decoder->b_current_valid) && (p_pmt_decoder->current_pmt.i_version == p_section->i_version)) { /* Signal a new PMT if the previous one wasn't active */ if( (!p_pmt_decoder->current_pmt.b_current_next) && (p_section->b_current_next)) { dvbpsi_pmt_t* p_pmt = (dvbpsi_pmt_t*)malloc(sizeof(dvbpsi_pmt_t)); p_pmt_decoder->current_pmt.b_current_next = 1; *p_pmt = p_pmt_decoder->current_pmt; p_pmt_decoder->pf_callback(p_pmt_decoder->p_cb_data, p_pmt); } /* Don't decode since this version is already decoded */ b_append = 0; } } } } /* Reinit the decoder if wanted */ if(b_reinit) { /* Force redecoding */ p_pmt_decoder->b_current_valid = 0; /* Free structures */ if(p_pmt_decoder->p_building_pmt) { free(p_pmt_decoder->p_building_pmt); p_pmt_decoder->p_building_pmt = NULL; } /* Clear the section array */ for(i = 0; i <= 255; i++) { if(p_pmt_decoder->ap_sections[i] != NULL) { DMA_dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[i]); p_pmt_decoder->ap_sections[i] = NULL; } } } /* Append the section to the list if wanted */ if(b_append) { int b_complete; /* Initialize the structures if it's the first section received */ if(!p_pmt_decoder->p_building_pmt) { p_pmt_decoder->p_building_pmt = (dvbpsi_pmt_t*)malloc(sizeof(dvbpsi_pmt_t)); DMA_dvbpsi_InitPMT(p_pmt_decoder->p_building_pmt, p_pmt_decoder->i_program_number, p_section->i_version, p_section->b_current_next, ((unsigned short)(p_section->p_payload_start[0] & 0x1f) << 8) | p_section->p_payload_start[1]); p_pmt_decoder->i_last_section_number = p_section->i_last_number; } /* Fill the section array */ if(p_pmt_decoder->ap_sections[p_section->i_number] != NULL) { #if 0 DMA_DVBPSI_DEBUG_ARG("PMT decoder", "overwrite section number %d", p_section->i_number); #endif DMA_dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[p_section->i_number]); } p_pmt_decoder->ap_sections[p_section->i_number] = p_section; /* Check if we have all the sections */ b_complete = 0; for(i = 0; i <= p_pmt_decoder->i_last_section_number; i++) { if(!p_pmt_decoder->ap_sections[i]) break; if(i == p_pmt_decoder->i_last_section_number) b_complete = 1; } if(b_complete) { /* Save the current information */ p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt; p_pmt_decoder->b_current_valid = 1; /* Chain the sections */ if(p_pmt_decoder->i_last_section_number) { for(i = 0; i <= p_pmt_decoder->i_last_section_number - 1; i++) p_pmt_decoder->ap_sections[i]->p_next = p_pmt_decoder->ap_sections[i + 1]; } /* Decode the sections */ DMA_dvbpsi_DecodePMTSections(p_pmt_decoder->p_building_pmt, p_pmt_decoder->ap_sections[0]); /* Delete the sections */ DMA_dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[0]); /* signal the new PMT */ p_pmt_decoder->pf_callback(p_pmt_decoder->p_cb_data, p_pmt_decoder->p_building_pmt); /* Reinitialize the structures */ p_pmt_decoder->p_building_pmt = NULL; for(i = 0; i <= p_pmt_decoder->i_last_section_number; i++) p_pmt_decoder->ap_sections[i] = NULL; } } else { DMA_dvbpsi_DeletePSISections(p_section); } }
/***************************************************************************** * dvbpsi_DecodeVBIDataDr *****************************************************************************/ dvbpsi_vbi_dr_t * dvbpsi_DecodeVBIDataDr( dvbpsi_descriptor_t * p_descriptor) { int i_services_number, i; dvbpsi_vbi_dr_t * p_decoded; /* Check the tag */ if( p_descriptor->i_tag != 0x45 ) { DVBPSI_ERROR_ARG("dr_45 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Decode data and check the length */ if(p_descriptor->i_length < 3) { DVBPSI_ERROR_ARG("dr_45 decoder", "bad length (%d)", p_descriptor->i_length); return NULL; } if(p_descriptor->i_length % 2) { DVBPSI_ERROR_ARG("dr_45 decoder", "length not multiple of 3(%d)", p_descriptor->i_length); return NULL; } i_services_number = p_descriptor->i_length / 2; /* Allocate memory */ p_decoded = (dvbpsi_vbi_dr_t*)malloc(sizeof(dvbpsi_vbi_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_45 decoder", "out of memory"); return NULL; } p_decoded->i_services_number = i_services_number; for(i=0; i < i_services_number; i++) { int n, i_lines = 0, i_data_service_id; i_data_service_id = ((uint8_t)(p_descriptor->p_data[3 * i + 2 + i_lines])); p_decoded->p_services[i].i_data_service_id = i_data_service_id; i_lines = ((uint8_t)(p_descriptor->p_data[3 * i + 3])); p_decoded->p_services[i].i_lines = i_lines; for(n=0; n < i_lines; n++ ) { if( (i_data_service_id >= 0x01) && (i_data_service_id <= 0x07) ) { p_decoded->p_services[i].p_lines[n].i_parity = ((uint8_t)((p_descriptor->p_data[3 * i + 3 + n])&0x20)>>5); p_decoded->p_services[i].p_lines[n].i_line_offset = ((uint8_t)(p_descriptor->p_data[3 * i + 3 + n])&0x1f); } } }
/***************************************************************************** * dvbpsi_DecodeSubtitlingDr *****************************************************************************/ dvbpsi_subtitling_dr_t * dvbpsi_DecodeSubtitlingDr( dvbpsi_descriptor_t * p_descriptor) { int i_subtitles_number, i; dvbpsi_subtitling_dr_t * p_decoded; /* Check the tag */ if(p_descriptor->i_tag != 0x59) { DVBPSI_ERROR_ARG("dr_59 decoder", "bad tag (0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = (dvbpsi_subtitling_dr_t*)malloc(sizeof(dvbpsi_subtitling_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_59 decoder", "out of memory"); return NULL; } /* Decode data and check the length */ if(p_descriptor->i_length < 3) { DVBPSI_ERROR_ARG("dr_59 decoder", "bad length (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } if(p_descriptor->i_length % 8) { DVBPSI_ERROR_ARG("dr_59 decoder", "length not multiple of 8 (%d)", p_descriptor->i_length); free(p_decoded); return NULL; } i_subtitles_number = p_descriptor->i_length / 8; p_decoded->i_subtitles_number = i_subtitles_number; for (i=0; i < i_subtitles_number; i++) { memcpy(p_decoded->p_subtitle[i].i_iso6392_language_code, p_descriptor->p_data + 8 * i, 3); p_decoded->p_subtitle[i].i_subtitling_type = p_descriptor->p_data[8 * i + 3]; p_decoded->p_subtitle[i].i_composition_page_id = ((uint16_t)(p_descriptor->p_data[8 * i + 4]) << 8) | p_descriptor->p_data[8 * i + 5]; p_decoded->p_subtitle[i].i_ancillary_page_id = ((uint16_t)(p_descriptor->p_data[8 * i + 6]) << 8) | p_descriptor->p_data[8 * i + 7]; } p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }
/***************************************************************************** * dvbpsi_DecodeExtendedEventDr *****************************************************************************/ dvbpsi_extended_event_dr_t * dvbpsi_DecodeExtendedEventDr(dvbpsi_descriptor_t * p_descriptor) { dvbpsi_extended_event_dr_t * p_decoded; int i_len; int i_pos; uint8_t *p; /* Check the tag */ if(p_descriptor->i_tag != 0x4e || p_descriptor->i_length < 6 ) { DVBPSI_ERROR_ARG("dr_4e decoder", "bad tag or corrupted(0x%x)", p_descriptor->i_tag); return NULL; } /* Don't decode twice */ if(p_descriptor->p_decoded) return p_descriptor->p_decoded; /* Allocate memory */ p_decoded = malloc(sizeof(dvbpsi_extended_event_dr_t)); if(!p_decoded) { DVBPSI_ERROR("dr_4e decoder", "out of memory"); return NULL; } /* Decode */ p_decoded->i_descriptor_number = (p_descriptor->p_data[0] >> 4)&0xf; p_decoded->i_last_descriptor_number = p_descriptor->p_data[0]&0x0f; memcpy( &p_decoded->i_iso_639_code[0], &p_descriptor->p_data[1], 3 ); p_decoded->i_entry_count = 0; i_len = p_descriptor->p_data[4]; i_pos = 0; for( p = &p_descriptor->p_data[5]; p < &p_descriptor->p_data[5+i_len]; ) { int idx = p_decoded->i_entry_count; p_decoded->i_item_description_length[idx] = p[0]; p_decoded->i_item_description[idx] = &p_decoded->i_buffer[i_pos]; memcpy( &p_decoded->i_buffer[i_pos], &p[1], p[0] ); i_pos += p[0]; p += 1 + p[0]; p_decoded->i_item_length[idx] = p[0]; p_decoded->i_item[idx] = &p_decoded->i_buffer[i_pos]; memcpy( &p_decoded->i_buffer[i_pos], &p[1], p[0] ); i_pos += p[0]; p += 1 + p[0]; p_decoded->i_entry_count++; } p_decoded->i_text_length = p_descriptor->p_data[5+i_len]; if( p_decoded->i_text_length > 0 ) memcpy( &p_decoded->i_buffer[i_pos], &p_descriptor->p_data[5+i_len+1], p_decoded->i_text_length ); p_decoded->i_text = &p_decoded->i_buffer[i_pos]; p_descriptor->p_decoded = (void*)p_decoded; return p_decoded; }