/***************************************************************************** * psi_pack_sections: return psi sections as array * Note: Allocates the return value. The caller must free it. *****************************************************************************/ uint8_t *psi_pack_sections( uint8_t **pp_sections, unsigned int *pi_size ) { uint8_t i_last_section; uint8_t *p_flat_section; unsigned int i, i_pos = 0; if ( !psi_table_validate( pp_sections ) ) return NULL; i_last_section = psi_table_get_lastsection( pp_sections ); /* Calculate total size */ *pi_size = 0; for ( i = 0; i <= i_last_section; i++ ) { uint8_t *p_section = psi_table_get_section( pp_sections, i ); *pi_size += psi_get_length( p_section ) + PSI_HEADER_SIZE; } p_flat_section = malloc( *pi_size ); if ( !p_flat_section ) return NULL; for ( i = 0; i <= i_last_section; i++ ) { uint8_t *p_section = psi_table_get_section( pp_sections, i ); uint16_t psi_length = psi_get_length( p_section ) + PSI_HEADER_SIZE; memcpy( p_flat_section + i_pos, p_section, psi_length ); i_pos += psi_length; } return p_flat_section; }
/***************************************************************************** * handle_pat *****************************************************************************/ static void handle_pat(void) { PSI_TABLE_DECLARE(pp_old_pat_sections); uint8_t i_last_section = psi_table_get_lastsection(pp_next_pat_sections); uint8_t i; if (psi_table_validate(pp_current_pat_sections) && psi_table_compare(pp_current_pat_sections, pp_next_pat_sections)) { /* Identical PAT. Shortcut. */ psi_table_free(pp_next_pat_sections); psi_table_init(pp_next_pat_sections); return; } if (!pat_table_validate(pp_next_pat_sections)) { printf("<ERROR type=\"invalid_pat\"/>\n"); psi_table_free(pp_next_pat_sections); psi_table_init(pp_next_pat_sections); return; } /* Switch tables. */ psi_table_copy(pp_old_pat_sections, pp_current_pat_sections); psi_table_copy(pp_current_pat_sections, pp_next_pat_sections); psi_table_init(pp_next_pat_sections); for (i = 0; i <= i_last_section; i++) { uint8_t *p_section = psi_table_get_section(pp_current_pat_sections, i); const uint8_t *p_program; int j = 0; while ((p_program = pat_get_program(p_section, j)) != NULL) { const uint8_t *p_old_program = NULL; uint16_t i_sid = patn_get_program(p_program); uint16_t i_pid = patn_get_pid(p_program); j++; if (i_sid == 0) { if (i_pid != NIT_PID) fprintf(stderr, "NIT is carried on PID %hu which isn't DVB compliant\n", i_pid); continue; /* NIT */ } if (!psi_table_validate(pp_old_pat_sections) || (p_old_program = pat_table_find_program(pp_old_pat_sections, i_sid)) == NULL || patn_get_pid(p_old_program) != i_pid) { sid_t *p_sid; int i_pmt; if (p_old_program != NULL) p_pids[patn_get_pid(p_old_program)].i_psi_refcount--; p_pids[i_pid].i_psi_refcount++; for (i_pmt = 0; i_pmt < i_nb_sids; i_pmt++) if (pp_sids[i_pmt]->i_sid == i_sid || pp_sids[i_pmt]->i_sid == 0) break; if (i_pmt == i_nb_sids) { p_sid = malloc(sizeof(sid_t)); pp_sids = realloc(pp_sids, ++i_nb_sids * sizeof(sid_t *)); pp_sids[i_pmt] = p_sid; p_sid->p_current_pmt = NULL; psi_table_init(p_sid->pp_eit_sections); } else p_sid = pp_sids[i_pmt]; p_sid->i_sid = i_sid; p_sid->i_pmt_pid = i_pid; } } } if (psi_table_validate(pp_old_pat_sections)) { i_last_section = psi_table_get_lastsection( pp_old_pat_sections ); for (i = 0; i <= i_last_section; i++) { uint8_t *p_section = psi_table_get_section(pp_old_pat_sections, i); const uint8_t *p_program; int j = 0; while ((p_program = pat_get_program(p_section, j)) != NULL) { uint16_t i_sid = patn_get_program(p_program); j++; if (i_sid == 0) continue; /* NIT */ if (pat_table_find_program(pp_current_pat_sections, i_sid) == NULL) { int i_pmt; for (i_pmt = 0; i_pmt < i_nb_sids; i_pmt++) if (pp_sids[i_pmt]->i_sid == i_sid) { pp_sids[i_pmt]->i_sid = 0; free(pp_sids[i_pmt]->p_current_pmt); pp_sids[i_pmt]->p_current_pmt = NULL; psi_table_free(pp_sids[i]->pp_eit_sections); psi_table_init(pp_sids[i]->pp_eit_sections); break; } } } } psi_table_free(pp_old_pat_sections); } if (pb_print_table[TABLE_PAT]) pat_table_print(pp_current_pat_sections, print_wrapper, NULL, i_print_type); }