/***************************************************************************** * dvbpsi_GenNITSections ***************************************************************************** * Generate NIT sections based on the dvbpsi_nit_t structure. *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit, uint8_t i_table_id) { dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_prev; dvbpsi_descriptor_t* p_descriptor = p_nit->p_first_descriptor; dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts; uint16_t i_network_descriptors_length, i_transport_stream_loop_length; uint8_t * p_transport_stream_loop_length; p_current->i_table_id = i_table_id; p_current->b_syntax_indicator = 1; p_current->b_private_indicator = 0; p_current->i_length = 13; /* including CRC_32 */ p_current->i_extension = p_nit->i_network_id; p_current->i_version = p_nit->i_version; p_current->b_current_next = p_nit->b_current_next; p_current->i_number = 0; p_current->p_payload_end += 10; p_current->p_payload_start = p_current->p_data + 8; /* NIT descriptors */ while(p_descriptor != NULL) { /* New section if needed */ /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */ if( (p_current->p_payload_end - p_current->p_data) + p_descriptor->i_length > 1018) { /* network_descriptors_length */ i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2; p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0; p_current->p_data[9] = i_network_descriptors_length; /* transport_stream_loop_length */ p_current->p_payload_end[0] = 0; p_current->p_payload_end[1] = 0; p_current->p_payload_end += 2; p_prev = p_current; p_current = dvbpsi_NewPSISection(1024); p_prev->p_next = p_current; p_current->i_table_id = i_table_id; p_current->b_syntax_indicator = 1; p_current->b_private_indicator = 0; p_current->i_length = 13; /* including CRC_32 */ p_current->i_extension = p_nit->i_network_id; p_current->i_version = p_nit->i_version; p_current->b_current_next = p_nit->b_current_next; p_current->i_number = p_prev->i_number + 1; p_current->p_payload_end += 10; p_current->p_payload_start = p_current->p_data + 8; } /* p_payload_end is where the descriptor begins */ p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[1] = p_descriptor->i_length; memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length); /* Increase length by descriptor_length + 2 */ p_current->p_payload_end += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2; p_descriptor = p_descriptor->p_next; }
/***************************************************************************** * dvbpsi_GenCATSections ***************************************************************************** * Generate CAT sections based on the dvbpsi_cat_t structure. *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat) { dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_prev; dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor; p_current->i_table_id = 0x01; p_current->b_syntax_indicator = 1; p_current->b_private_indicator = 0; p_current->i_length = 9; /* header + CRC_32 */ p_current->i_extension = 0; /* Not used in the CAT */ p_current->i_version = p_cat->i_version; p_current->b_current_next = p_cat->b_current_next; p_current->i_number = 0; p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_start = p_current->p_data + 8; /* CAT descriptors */ while(p_descriptor != NULL) { /* New section if needed */ /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */ if( (p_current->p_payload_end - p_current->p_data) + p_descriptor->i_length > 1018) { p_prev = p_current; p_current = dvbpsi_NewPSISection(1024); p_prev->p_next = p_current; p_current->i_table_id = 0x01; p_current->b_syntax_indicator = 1; p_current->b_private_indicator = 0; p_current->i_length = 9; /* header + CRC_32 */ p_current->i_extension = 0; /* Not used in the CAT */ p_current->i_version = p_cat->i_version; p_current->b_current_next = p_cat->b_current_next; p_current->i_number = p_prev->i_number + 1; p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_start = p_current->p_data + 8; } /* p_payload_end is where the descriptor begins */ p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[1] = p_descriptor->i_length; memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length); /* Increase length by descriptor_length + 2 */ p_current->p_payload_end += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2; p_descriptor = p_descriptor->p_next; } /* Finalization */ p_prev = p_result; while(p_prev != NULL) { p_prev->i_last_number = p_current->i_number; dvbpsi_BuildPSISection(p_prev); p_prev = p_prev->p_next; } return p_result; }
/***************************************************************************** * dvbpsi_GenPATSections ***************************************************************************** * Generate PAT sections based on the dvbpsi_pat_t structure. The third * argument is used to limit the number of program in each section (max: 253). *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat, int i_max_pps) { dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_prev; dvbpsi_pat_program_t* p_program = p_pat->p_first_program; int i_count = 0; /* A PAT section can carry up to 253 programs */ if((i_max_pps <= 0) || (i_max_pps > 253)) i_max_pps = 253; p_current->i_table_id = 0; p_current->b_syntax_indicator = 1; p_current->b_private_indicator = 0; p_current->i_length = 9; /* header + CRC_32 */ p_current->i_extension = p_pat->i_ts_id; p_current->i_version = p_pat->i_version; p_current->b_current_next = p_pat->b_current_next; p_current->i_number = 0; p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_start = p_current->p_payload_end; /* PAT programs */ while(p_program != NULL) { /* New section if needed */ if(++i_count > i_max_pps) { p_prev = p_current; p_current = dvbpsi_NewPSISection(1024); p_prev->p_next = p_current; i_count = 1; p_current->i_table_id = 0; p_current->b_syntax_indicator = 1; p_current->b_private_indicator = 0; p_current->i_length = 9; /* header + CRC_32 */ p_current->i_extension = p_pat->i_ts_id; p_current->i_version = p_pat->i_version; p_current->b_current_next = p_pat->b_current_next; p_current->i_number = p_prev->i_number + 1; p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_start = p_current->p_payload_end; } /* p_payload_end is where the program begins */ p_current->p_payload_end[0] = p_program->i_number >> 8; p_current->p_payload_end[1] = p_program->i_number; p_current->p_payload_end[2] = (p_program->i_pid >> 8) | 0xe0; p_current->p_payload_end[3] = p_program->i_pid; /* Increase length by 4 */ p_current->p_payload_end += 4; p_current->i_length += 4; p_program = p_program->p_next; } /* Finalization */ p_prev = p_result; while(p_prev != NULL) { p_prev->i_last_number = p_current->i_number; dvbpsi_BuildPSISection(p_prev); p_prev = p_prev->p_next; } return p_result; }
/***************************************************************************** * dvbpsi_packet_push ***************************************************************************** * Injection of a TS packet into a PSI decoder. *****************************************************************************/ bool dvbpsi_packet_push(dvbpsi_t *p_dvbpsi, uint8_t* p_data) { uint8_t i_expected_counter; /* Expected continuity counter */ dvbpsi_psi_section_t* p_section; /* Current section */ uint8_t* p_payload_pos; /* Where in the TS packet */ uint8_t* p_new_pos = NULL; /* Beginning of the new section, updated to NULL when the new section is handled */ int i_available; /* Byte count available in the packet */ dvbpsi_decoder_t *p_decoder = p_dvbpsi->p_decoder; assert(p_decoder); /* TS start code */ if (p_data[0] != 0x47) { dvbpsi_error(p_dvbpsi, "PSI decoder", "not a TS packet"); return false; } /* Continuity check */ bool b_first = (p_decoder->i_continuity_counter == DVBPSI_INVALID_CC); if (b_first) p_decoder->i_continuity_counter = p_data[3] & 0xf; else { i_expected_counter = (p_decoder->i_continuity_counter + 1) & 0xf; p_decoder->i_continuity_counter = p_data[3] & 0xf; if (i_expected_counter == ((p_decoder->i_continuity_counter + 1) & 0xf) && !p_decoder->b_discontinuity) { dvbpsi_error(p_dvbpsi, "PSI decoder", "TS duplicate (received %d, expected %d) for PID %d", p_decoder->i_continuity_counter, i_expected_counter, ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]); return false; } if (i_expected_counter != p_decoder->i_continuity_counter) { dvbpsi_error(p_dvbpsi, "PSI decoder", "TS discontinuity (received %d, expected %d) for PID %d", p_decoder->i_continuity_counter, i_expected_counter, ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]); p_decoder->b_discontinuity = true; if (p_decoder->p_current_section) { dvbpsi_DeletePSISections(p_decoder->p_current_section); p_decoder->p_current_section = NULL; } } } /* Return if no payload in the TS packet */ if (!(p_data[3] & 0x10)) return false; /* Skip the adaptation_field if present */ if (p_data[3] & 0x20) p_payload_pos = p_data + 5 + p_data[4]; else p_payload_pos = p_data + 4; /* Unit start -> skip the pointer_field and a new section begins */ if (p_data[1] & 0x40) { p_new_pos = p_payload_pos + *p_payload_pos + 1; p_payload_pos += 1; } p_section = p_decoder->p_current_section; /* If the psi decoder needs a beginning of a section and a new section begins in the packet then initialize the dvbpsi_psi_section_t structure */ if (p_section == NULL) { if (p_new_pos) { /* Allocation of the structure */ p_decoder->p_current_section = p_section = dvbpsi_NewPSISection(p_decoder->i_section_max_size); if (!p_section) return false; /* Update the position in the packet */ p_payload_pos = p_new_pos; /* New section is being handled */ p_new_pos = NULL; /* Just need the header to know how long is the section */ p_decoder->i_need = 3; p_decoder->b_complete_header = false; } else { /* No new section => return */ return false; } } /* Remaining bytes in the payload */ i_available = 188 + p_data - p_payload_pos; while (i_available > 0) { if (i_available >= p_decoder->i_need) { /* There are enough bytes in this packet to complete the header/section */ memcpy(p_section->p_payload_end, p_payload_pos, p_decoder->i_need); p_payload_pos += p_decoder->i_need; p_section->p_payload_end += p_decoder->i_need; i_available -= p_decoder->i_need; if (!p_decoder->b_complete_header) { /* Header is complete */ p_decoder->b_complete_header = true; /* Compute p_section->i_length and update p_decoder->i_need */ p_decoder->i_need = p_section->i_length = ((uint16_t)(p_section->p_data[1] & 0xf)) << 8 | p_section->p_data[2]; /* Check that the section isn't too long */ if (p_decoder->i_need > p_decoder->i_section_max_size - 3) { dvbpsi_error(p_dvbpsi, "PSI decoder", "PSI section too long"); dvbpsi_DeletePSISections(p_section); p_decoder->p_current_section = NULL; /* If there is a new section not being handled then go forward in the packet */ if (p_new_pos) { p_decoder->p_current_section = p_section = dvbpsi_NewPSISection(p_decoder->i_section_max_size); if (!p_section) return false; p_payload_pos = p_new_pos; p_new_pos = NULL; p_decoder->i_need = 3; p_decoder->b_complete_header = false; i_available = 188 + p_data - p_payload_pos; } else { i_available = 0; } } } else { bool b_valid_crc32 = false; bool has_crc32; /* PSI section is complete */ p_section->i_table_id = p_section->p_data[0]; p_section->b_syntax_indicator = p_section->p_data[1] & 0x80; p_section->b_private_indicator = p_section->p_data[1] & 0x40; /* Update the end of the payload if CRC_32 is present */ has_crc32 = dvbpsi_has_CRC32(p_section); if (p_section->b_syntax_indicator || has_crc32) p_section->p_payload_end -= 4; /* Check CRC32 if present */ if (has_crc32) b_valid_crc32 = dvbpsi_ValidPSISection(p_section); if (!has_crc32 || b_valid_crc32) { /* PSI section is valid */ if (p_section->b_syntax_indicator) { p_section->i_extension = (p_section->p_data[3] << 8) | p_section->p_data[4]; p_section->i_version = (p_section->p_data[5] & 0x3e) >> 1; p_section->b_current_next = p_section->p_data[5] & 0x1; p_section->i_number = p_section->p_data[6]; p_section->i_last_number = p_section->p_data[7]; p_section->p_payload_start = p_section->p_data + 8; } else { p_section->i_extension = 0; p_section->i_version = 0; p_section->b_current_next = true; p_section->i_number = 0; p_section->i_last_number = 0; p_section->p_payload_start = p_section->p_data + 3; } if (p_decoder->pf_gather) p_decoder->pf_gather(p_dvbpsi, p_section); p_decoder->p_current_section = NULL; } else { if (has_crc32 && !dvbpsi_ValidPSISection(p_section))
/***************************************************************************** * dvbpsi_pat_sections_generate ***************************************************************************** * Generate PAT sections based on the dvbpsi_pat_t structure. The third * argument is used to limit the number of program in each section (max: 253). *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_pat_sections_generate( dvbpsi_t *p_dvbpsi, dvbpsi_pat_t* p_pat, int i_max_pps ) { dvbpsi_psi_section_t * p_result = dvbpsi_NewPSISection( 1024 ); dvbpsi_psi_section_t * p_current = p_result; dvbpsi_psi_section_t * p_prev; dvbpsi_pat_program_t * p_program = p_pat->p_first_program; int i_count = 0; if ( p_current == NULL ) { dvbpsi_error( p_dvbpsi, "PAT encoder", "failed to allocate new PSI section" ); return(NULL); } /* A PAT section can carry up to 253 programs */ if ( (i_max_pps <= 0) || (i_max_pps > 253) ) i_max_pps = 253; p_current->i_table_id = 0; p_current->b_syntax_indicator = true; p_current->b_private_indicator = false; p_current->i_length = 9; /* header + CRC_32 */ p_current->i_extension = p_pat->i_ts_id; p_current->i_version = p_pat->i_version; p_current->b_current_next = p_pat->b_current_next; p_current->i_number = 0; p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_start = p_current->p_payload_end; /* PAT programs */ while ( p_program != NULL ) { /* New section if needed */ if ( ++i_count > i_max_pps ) { p_prev = p_current; p_current = dvbpsi_NewPSISection( 1024 ); if ( p_current == NULL ) { dvbpsi_error( p_dvbpsi, "PAT encoder", "failed to allocate new PSI section" ); goto error; } p_prev->p_next = p_current; i_count = 1; p_current->i_table_id = 0; p_current->b_syntax_indicator = true; p_current->b_private_indicator = false; p_current->i_length = 9; /* header + CRC_32 */ p_current->i_extension = p_pat->i_ts_id; p_current->i_version = p_pat->i_version; p_current->b_current_next = p_pat->b_current_next; p_current->i_number = p_prev->i_number + 1; p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_start = p_current->p_payload_end; } /* p_payload_end is where the program begins */ p_current->p_payload_end[0] = p_program->i_number >> 8; p_current->p_payload_end[1] = p_program->i_number; p_current->p_payload_end[2] = (p_program->i_pid >> 8) | 0xe0; p_current->p_payload_end[3] = p_program->i_pid; /* Increase length by 4 */ p_current->p_payload_end += 4; p_current->i_length += 4; p_program = p_program->p_next; } /* Finalization */ p_prev = p_result; while ( p_prev != NULL ) { p_prev->i_last_number = p_current->i_number; dvbpsi_BuildPSISection( p_dvbpsi, p_prev ); p_prev = p_prev->p_next; } return(p_result); error: /* Cleanup on error */ p_prev = p_result; dvbpsi_DeletePSISections( p_prev ); return(NULL); }
/***************************************************************************** * dvbpsi_pmt_sections_generate ***************************************************************************** * Generate PMT sections based on the dvbpsi_pmt_t structure. *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_pmt_sections_generate( dvbpsi_t *p_dvbpsi, dvbpsi_pmt_t* p_pmt ) { dvbpsi_psi_section_t * p_result = dvbpsi_NewPSISection( 1024 ); dvbpsi_psi_section_t * p_current = p_result; dvbpsi_psi_section_t * p_prev; dvbpsi_descriptor_t * p_descriptor = p_pmt->p_first_descriptor; dvbpsi_pmt_es_t * p_es = p_pmt->p_first_es; uint16_t i_info_length; p_current->i_table_id = 0x02; p_current->b_syntax_indicator = true; p_current->b_private_indicator = false; p_current->i_length = 13; /* header + CRC_32 */ p_current->i_extension = p_pmt->i_program_number; p_current->i_version = p_pmt->i_version; p_current->b_current_next = p_pmt->b_current_next; p_current->i_number = 0; p_current->p_payload_end += 12; /* just after the header */ p_current->p_payload_start = p_current->p_data + 8; /* PCR_PID */ p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; p_current->p_data[9] = p_pmt->i_pcr_pid; /* PMT descriptors */ while ( p_descriptor != NULL ) { /* New section if needed */ /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */ if ( (p_current->p_payload_end - p_current->p_data) + p_descriptor->i_length > 1018 ) { /* program_info_length */ i_info_length = (p_current->p_payload_end - p_current->p_data) - 12; p_current->p_data[10] = (i_info_length >> 8) | 0xf0; p_current->p_data[11] = i_info_length; p_prev = p_current; p_current = dvbpsi_NewPSISection( 1024 ); p_prev->p_next = p_current; p_current->i_table_id = 0x02; p_current->b_syntax_indicator = true; p_current->b_private_indicator = false; p_current->i_length = 13; /* header + CRC_32 */ p_current->i_extension = p_pmt->i_program_number; p_current->i_version = p_pmt->i_version; p_current->b_current_next = p_pmt->b_current_next; p_current->i_number = p_prev->i_number + 1; p_current->p_payload_end += 12; /* just after the header */ p_current->p_payload_start = p_current->p_data + 8; /* PCR_PID */ p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; p_current->p_data[9] = p_pmt->i_pcr_pid; } /* p_payload_end is where the descriptor begins */ p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[1] = p_descriptor->i_length; memcpy( p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length ); /* Increase length by descriptor_length + 2 */ p_current->p_payload_end += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2; p_descriptor = p_descriptor->p_next; }
/***************************************************************************** * dvbpsi_tot_sections_generate ***************************************************************************** * Generate TDT/TOT sections based on the dvbpsi_tot_t structure. *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_tot_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_tot_t* p_tot) { dvbpsi_psi_section_t* p_result; dvbpsi_descriptor_t* p_descriptor = p_tot->p_first_descriptor; /* If it has descriptors, it must be a TOT, otherwise a TDT */ p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8); p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70; p_result->b_syntax_indicator = false; p_result->b_private_indicator = false; p_result->i_length = 5; p_result->p_payload_start = p_result->p_data + 3; p_result->p_payload_end = p_result->p_data + 8; p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff; p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff; p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff; p_result->p_data[6] = (p_tot->i_utc_time >> 8) & 0xff; p_result->p_data[7] = p_tot->i_utc_time & 0xff; if (p_result->i_table_id == 0x73) { /* Special handling for TOT only (A TDT doesn't have descriptors!) */ /* Reserve two bytes for descriptors_loop_length */ p_result->p_payload_end += 2; p_result->i_length += 2; /* TOT descriptors */ while (p_descriptor != NULL) { /* A TOT cannot have multiple sections! */ if( (p_result->p_payload_end - p_result->p_data) + p_descriptor->i_length > 4090) { dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "TOT does not fit into one section as it ought to be !!!"); break; } /* p_payload_end is where the descriptor begins */ p_result->p_payload_end[0] = p_descriptor->i_tag; p_result->p_payload_end[1] = p_descriptor->i_length; memcpy(p_result->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length); /* Increase length by descriptor_length + 2 */ p_result->p_payload_end += p_descriptor->i_length + 2; p_result->i_length += p_descriptor->i_length + 2; p_descriptor = p_descriptor->p_next; } /* descriptors_loop_length */ p_result->p_payload_start[5] = ((p_result->i_length - 7) << 8) | 0xf0; p_result->p_payload_start[6] = (p_result->i_length - 7) & 0xff; } /* Build the PSI section including the CRC32 on the playload. * NOTE: The p_payload_end pointer should point to the last byte * of the payload without the CRC32 field. */ dvbpsi_BuildPSISection(p_dvbpsi, p_result); if (p_result->i_table_id == 0x73) { /* A TOT has a CRC_32 although it's a private section, but the CRC_32 is part of the payload! */ p_result->p_payload_end += 4; p_result->i_length += 4; } if (!dvbpsi_tot_section_valid(p_dvbpsi, p_result)) { dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************"); dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* Generated TDT/TOT section is invalid. *"); dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *"); dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* --- [email protected] --- *"); dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************"); } return p_result; }
/***************************************************************************** * dvbpsi_GenBATSections ***************************************************************************** * Generate BAT sections based on the dvbpsi_bat_t structure. * similar to dvbpsi_GenNITSections *****************************************************************************/ dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_t *p_dvbpsi, dvbpsi_bat_t* p_bat) { dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_prev; dvbpsi_descriptor_t* p_descriptor = p_bat->p_first_descriptor; dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts; uint16_t i_bouquet_descriptors_length, i_transport_stream_loop_length; uint8_t * p_transport_stream_loop_length; if (p_current == NULL) { dvbpsi_error(p_dvbpsi, "BAT encoder", "failed to allocate new PSI section"); return NULL; } p_current->i_table_id = 0x4a; p_current->b_syntax_indicator = true; p_current->b_private_indicator = true; p_current->i_length = 13; /* including CRC_32 */ p_current->i_extension = p_bat->i_bouquet_id; p_current->i_version = p_bat->i_version; p_current->b_current_next = p_bat->b_current_next; p_current->i_number = 0; p_current->p_payload_end += 10; p_current->p_payload_start = p_current->p_data + 8; /* first loop descriptors */ while (p_descriptor != NULL) { /* New section if needed */ /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */ if( (p_current->p_payload_end - p_current->p_data) + p_descriptor->i_length > 1018) { /* bouquet_descriptors_length */ i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2; p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0; p_current->p_data[9] = i_bouquet_descriptors_length; /* transport_stream_loop_length */ p_current->p_payload_end[0] = 0; p_current->p_payload_end[1] = 0; p_current->p_payload_end += 2; p_prev = p_current; p_current = dvbpsi_NewPSISection(1024); if (p_current == NULL) { dvbpsi_error(p_dvbpsi, "BAT encoder", "failed to allocate new PSI section"); goto error; } p_prev->p_next = p_current; p_current->i_table_id = 0x4a; p_current->b_syntax_indicator = true; p_current->b_private_indicator = true; p_current->i_length = 13; /* including CRC_32 */ p_current->i_extension = p_bat->i_bouquet_id; p_current->i_version = p_bat->i_version; p_current->b_current_next = p_bat->b_current_next; p_current->i_number = p_prev->i_number + 1; p_current->p_payload_end += 10; p_current->p_payload_start = p_current->p_data + 8; } /* p_payload_end is where the descriptor begins */ p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[1] = p_descriptor->i_length; memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length); /* Increase length by descriptor_length + 2 */ p_current->p_payload_end += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2; p_descriptor = p_descriptor->p_next; }
/***************************************************************************** * dvbpsi_sis_sections_generate ***************************************************************************** * Generate SIS sections based on the dvbpsi_sis_t structure. *****************************************************************************/ dvbpsi_psi_section_t *dvbpsi_sis_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_sis_t* p_sis) { dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024); p_current->i_table_id = 0xFC; p_current->b_syntax_indicator = false; p_current->b_private_indicator = false; p_current->i_length = 3; /* header + CRC_32 */ /* FIXME: looks weird */ p_current->p_payload_end += 2; /* just after the header */ p_current->p_payload_start = p_current->p_data + 3; p_current->p_data[3] = p_sis->i_protocol_version; p_current->p_data[4] = p_sis->b_encrypted_packet ? 0x80 : 0x0; /* NOTE: cannot handle encrypted packet */ assert(p_sis->b_encrypted_packet); p_current->p_data[4] |= ((p_sis->i_encryption_algorithm << 1) & 0x7E); p_current->p_data[4] |= ((p_sis->i_pts_adjustment & 0x00800) >> 32); p_current->p_data[5] = (p_sis->i_pts_adjustment >> 24); p_current->p_data[6] = (p_sis->i_pts_adjustment >> 16); p_current->p_data[7] = (p_sis->i_pts_adjustment >> 8); p_current->p_data[8] = p_sis->i_pts_adjustment; p_current->p_data[9] = p_sis->cw_index; p_current->p_data[11] = 0x00; p_current->p_data[11]|= ((p_sis->i_splice_command_length >> 8) & 0x0F); p_current->p_data[12] = (uint8_t) (p_sis->i_splice_command_length & 0xFF); p_current->p_data[13] = p_sis->i_splice_command_type; uint32_t i_desc_start = 13 + p_sis->i_splice_command_length; if (p_sis->i_splice_command_length == 0xfff) { /* FIXME: size 0xfff of splice_command_section is undefined */ assert(p_sis->i_splice_command_length != 0xfff); } /* FIXME: handle splice_command_sections */ /* Service descriptors */ p_current->p_data[i_desc_start] = (p_sis->i_descriptors_length >> 8); p_current->p_data[i_desc_start+1] = (uint8_t)(p_sis->i_descriptors_length & 0xFF); p_current->p_payload_end += (i_desc_start + 1); uint32_t i_desc_length = 0; dvbpsi_descriptor_t * p_descriptor = p_sis->p_first_descriptor; while ((p_descriptor != NULL) && (p_current->i_length <= 1018)) { i_desc_length += p_descriptor->i_length + 2; p_descriptor = p_descriptor->p_next; /* p_payload_end is where the descriptor begins */ p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[1] = p_descriptor->i_length; memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length); /* Increase length by descriptor_length + 2 */ p_current->p_payload_end += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2; } /* Coding error if this condition is not met */ assert( i_desc_length == p_sis->i_descriptors_length); /* Finalization */ dvbpsi_BuildPSISection(p_dvbpsi, p_current); return p_current; }