/***************************************************************************** * dvbpsi_GatherBATSections ***************************************************************************** * Callback for the subtable demultiplexor. *****************************************************************************/ void dvbpsi_GatherBATSections(dvbpsi_t *p_dvbpsi, void * p_private_decoder, dvbpsi_psi_section_t * p_section) { dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private; dvbpsi_bat_decoder_t * p_bat_decoder = (dvbpsi_bat_decoder_t*)p_private_decoder; bool b_reinit = false; assert(p_dvbpsi); assert(p_dvbpsi->p_private); if (!p_section->b_syntax_indicator) { /* Invalid section_syntax_indicator */ dvbpsi_error(p_dvbpsi, "BAT decoder", "invalid section (section_syntax_indicator == 0)"); dvbpsi_DeletePSISections(p_section); return; } dvbpsi_debug(p_dvbpsi, "BAT decoder", "Table version %2d, " "i_table_id %2d, " "i_extension %5d, " "section %3d up to %3d, " "current %1d", p_section->i_version, p_section->i_table_id, p_section->i_extension, p_section->i_number, p_section->i_last_number, p_section->b_current_next); /* We have a valid BAT section */ /* TS discontinuity check */ if (p_demux->b_discontinuity) { b_reinit = true; p_demux->b_discontinuity = false; } else { /* Perform a few sanity checks */ if (p_bat_decoder->p_building_bat) { if (p_bat_decoder->p_building_bat->i_bouquet_id != p_section->i_extension) { /* bouquet_id */ dvbpsi_error(p_dvbpsi, "BAT decoder", "'bouquet_id' differs" " whereas no TS discontinuity has occured"); b_reinit = true; } else if (p_bat_decoder->p_building_bat->i_version != p_section->i_version) { /* version_number */ dvbpsi_error(p_dvbpsi, "BAT decoder", "'version_number' differs" " whereas no discontinuity has occured"); b_reinit = true; } else if (p_bat_decoder->i_last_section_number != p_section->i_last_number) { /* last_section_number */ dvbpsi_error(p_dvbpsi, "BAT decoder", "'last_section_number' differs" " whereas no discontinuity has occured"); b_reinit = true; } } else { if ( (p_bat_decoder->b_current_valid) && (p_bat_decoder->current_bat.i_version == p_section->i_version) && (p_bat_decoder->current_bat.b_current_next == p_section->b_current_next)) { /* Don't decode since this version is already decoded */ dvbpsi_debug(p_dvbpsi, "BAT decoder", "ignoring already decoded section %d", p_section->i_number); } else if ( (!p_bat_decoder->current_bat.b_current_next) && (p_section->b_current_next)) { /* Signal a new BAT if the previous one wasn't active */ dvbpsi_bat_t *p_bat = (dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t)); if (p_bat) { p_bat_decoder->current_bat.b_current_next = true; memcpy(p_bat, &p_bat_decoder->current_bat, sizeof(dvbpsi_bat_t)); p_bat_decoder->pf_bat_callback(p_bat_decoder->p_cb_data, p_bat); } else dvbpsi_error(p_dvbpsi, "BAT decoder", "Could not signal new BAT."); } dvbpsi_DeletePSISections(p_section); return; } } /* Reinit the decoder if wanted */ if (b_reinit) { /* Force redecoding */ p_bat_decoder->b_current_valid = false; /* Free structures */ if (p_bat_decoder->p_building_bat) { free(p_bat_decoder->p_building_bat); p_bat_decoder->p_building_bat = NULL; } /* Clear the section array */ for (unsigned int i = 0; i < 256; i++) { if (p_bat_decoder->ap_sections[i] != NULL) { dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]); p_bat_decoder->ap_sections[i] = NULL; } } } /* Append the section to the list if wanted */ bool b_complete = false; /* Initialize the structures if it's the first section received */ if (!p_bat_decoder->p_building_bat) { p_bat_decoder->p_building_bat = (dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t)); if (p_bat_decoder->p_building_bat) dvbpsi_InitBAT(p_bat_decoder->p_building_bat, p_section->i_extension, p_section->i_version, p_section->b_current_next); else dvbpsi_error(p_dvbpsi, "BAT decoder", "failed decoding BAT section"); p_bat_decoder->i_last_section_number = p_section->i_last_number; } /* Fill the section array */ if (p_bat_decoder->ap_sections[p_section->i_number] != NULL) { dvbpsi_debug(p_dvbpsi, "BAT decoder", "overwrite section number %d", p_section->i_number); dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[p_section->i_number]); } p_bat_decoder->ap_sections[p_section->i_number] = p_section; /* Check if we have all the sections */ for (unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++) { if (!p_bat_decoder->ap_sections[i]) break; if (i == p_bat_decoder->i_last_section_number) b_complete = true; } if (b_complete) { /* Save the current information */ p_bat_decoder->current_bat = *p_bat_decoder->p_building_bat; p_bat_decoder->b_current_valid = true; /* Chain the sections */ if (p_bat_decoder->i_last_section_number) { for (int j = 0; j <= p_bat_decoder->i_last_section_number - 1; j++) p_bat_decoder->ap_sections[j]->p_next = p_bat_decoder->ap_sections[j + 1]; } /* Decode the sections */ dvbpsi_DecodeBATSections(p_bat_decoder->p_building_bat, p_bat_decoder->ap_sections[0]); /* Delete the sections */ dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[0]); /* signal the new BAT */ p_bat_decoder->pf_bat_callback(p_bat_decoder->p_cb_data, p_bat_decoder->p_building_bat); /* Reinitialize the structures */ p_bat_decoder->p_building_bat = NULL; for (unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++) p_bat_decoder->ap_sections[i] = NULL; } }
/***************************************************************************** * dvbpsi_GatherBATSections ***************************************************************************** * Callback for the PSI decoder. *****************************************************************************/ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_decoder, void * p_private_decoder, dvbpsi_psi_section_t * p_section) { dvbpsi_bat_decoder_t* p_bat_decoder = (dvbpsi_bat_decoder_t*)p_private_decoder; int b_append = 1; int b_reinit = 0; unsigned int i; DVBPSI_DEBUG_ARG("BAT 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 != 0x40 && p_section->i_table_id != 0x41) { /* Invalid table_id value */ DVBPSI_ERROR_ARG("BAT 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("BAT decoder", "invalid section (section_syntax_indicator == 0)"); b_append = 0; } /* Now if b_append is true then we have a valid BAT section */ if(b_append && (p_bat_decoder->i_bouquet_id != p_section->i_extension)) { /* Invalid program_number */ #if 0 DVBPSI_ERROR("BAT decoder", "'bouquet_id' 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_bat_decoder->p_building_bat) { if(p_bat_decoder->p_building_bat->i_version != p_section->i_version) { /* version_number */ DVBPSI_ERROR("BAT decoder", "'version_number' differs" " whereas no discontinuity has occured"); b_reinit = 1; } else if(p_bat_decoder->i_last_section_number != p_section->i_last_number) { /* last_section_number */ DVBPSI_ERROR("BAT decoder", "'last_section_number' differs" " whereas no discontinuity has occured"); b_reinit = 1; } } else { if( (p_bat_decoder->b_current_valid) && (p_bat_decoder->current_bat.i_version == p_section->i_version) && (p_bat_decoder->current_bat.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_bat_decoder->b_current_valid = 0; /* Free structures */ if(p_bat_decoder->p_building_bat) { free(p_bat_decoder->p_building_bat); p_bat_decoder->p_building_bat = NULL; } /* Clear the section array */ for(i = 0; i <= 255; i++) { if(p_bat_decoder->ap_sections[i] != NULL) { dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]); p_bat_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_bat_decoder->p_building_bat) { p_bat_decoder->p_building_bat = (dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t)); dvbpsi_InitBAT(p_bat_decoder->p_building_bat, p_bat_decoder->i_bouquet_id, p_section->i_version, p_section->b_current_next); p_bat_decoder->i_last_section_number = p_section->i_last_number; } /* Fill the section array */ if(p_bat_decoder->ap_sections[p_section->i_number] != NULL) { DVBPSI_DEBUG_ARG("BAT decoder", "overwrite section number %d", p_section->i_number); dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[p_section->i_number]); } p_bat_decoder->ap_sections[p_section->i_number] = p_section; /* Check if we have all the sections */ b_complete = 0; for(i = 0; i <= p_bat_decoder->i_last_section_number; i++) { if(!p_bat_decoder->ap_sections[i]) break; if(i == p_bat_decoder->i_last_section_number) b_complete = 1; } if(b_complete) { /* Save the current information */ p_bat_decoder->current_bat = *p_bat_decoder->p_building_bat; p_bat_decoder->b_current_valid = 1; /* Chain the sections */ if(p_bat_decoder->i_last_section_number) { for(i = 0; (int)i <= p_bat_decoder->i_last_section_number - 1; i++) p_bat_decoder->ap_sections[i]->p_next = p_bat_decoder->ap_sections[i + 1]; } /* Decode the sections */ dvbpsi_DecodeBATSections(p_bat_decoder->p_building_bat, p_bat_decoder->ap_sections[0]); /* Delete the sections */ dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[0]); /* signal the new BAT */ p_bat_decoder->pf_callback(p_bat_decoder->p_cb_data, p_bat_decoder->p_building_bat); /* Reinitialize the structures */ p_bat_decoder->p_building_bat = NULL; for(i = 0; i <= p_bat_decoder->i_last_section_number; i++) p_bat_decoder->ap_sections[i] = NULL; } } else { dvbpsi_DeletePSISections(p_section); } }