/***************************************************************************** * 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; }
static void sdt_pid_parse(uint8_t *psi, void *arg) { uint8_t *section; int section_len; struct epgdump_s *epgd = arg; if (!sdt_validate(psi)) return; if (!psi_get_current(psi)) return; if (psi_get_tableid(psi) != SDT_TABLE_ID_ACTUAL) return; section_len = psi_get_length(psi) + PSI_HEADER_SIZE; section = malloc(section_len); if (!section) critical_error("Memory allocation failed\n"); memcpy(section, psi, section_len); if (!psi_table_section(epgd->sdt.sdt_current, section)) return; epgd->sdt.complete = 1; epgd->sdt.original_network_id = sdt_get_onid(epgd->sdt.sdt_current[0]); epgd->sdt.current_ts_id = sdt_get_tsid(epgd->sdt.sdt_current[0]); demux_del_psi_pid(&epgd->demux, SDT_PID); }
/***************************************************************************** * psi_pack_section: return psi section * Note: Allocates the return value. The caller must free it. *****************************************************************************/ uint8_t *psi_pack_section( uint8_t *p_section, unsigned int *pi_size ) { uint8_t *p_flat_section; uint16_t psi_length = psi_get_length( p_section ) + PSI_HEADER_SIZE; *pi_size = 0; p_flat_section = malloc( psi_length ); if ( !p_flat_section ) return NULL; *pi_size = psi_length; memcpy( p_flat_section, p_section, psi_length ); return p_flat_section; }
/***************************************************************************** * UpdateTable: *****************************************************************************/ static void UpdateTable( ts_table_t *p_table ) { ts_packetizer_sys_t *p_sys = p_table->p_sys; ts_stream_t *p_ts_stream = p_table->p_ts_stream; block_t **pp_section; uint8_t *p_section; uint8_t *p_ts; uint8_t *p_header2; block_ChainRelease( p_table->p_last_table ); p_table->p_last_table = NULL; pp_section = &p_table->p_last_table; /* please that there can only be one section per tsid, and we declare * only one tsid */ *pp_section = block_New( p_table, PSI_MAX_SIZE + PSI_HEADER_SIZE + 1 ); (*pp_section)->p_buffer[0] = 0; /* pointer_field */ p_section = (*pp_section)->p_buffer + 1; nit_init( p_section, true ); /* set length later */ psi_set_length( p_section, PSI_MAX_SIZE ); nit_set_nid( p_section, p_ts_stream->i_nid ); psi_set_version( p_section, p_sys->i_version ); psi_set_current( p_section ); psi_set_section( p_section, 0 ); psi_set_lastsection( p_section, 0 ); if ( p_sys->p_network_name != NULL ) { uint8_t *p_descs; uint8_t *p_desc; /* Cannot overflow because the network name is necessarily smaller * than a section */ nit_set_desclength( p_section, DESCS_MAX_SIZE ); p_descs = nit_get_descs( p_section ); p_desc = descs_get_desc( p_descs, 0 ); desc40_init( p_desc ); desc40_set_networkname( p_desc, p_sys->p_network_name, p_sys->i_network_name_size ); p_desc = descs_get_desc( p_descs, 1 ); descs_set_length( p_descs, p_desc - p_descs - DESCS_HEADER_SIZE ); } else nit_set_desclength( p_section, 0 ); p_header2 = nit_get_header2( p_section ); nith_init( p_header2 ); nith_set_tslength( p_header2, NIT_TS_SIZE ); p_ts = nit_get_ts( p_section, 0 ); nitn_init( p_ts ); nitn_set_tsid( p_ts, p_ts_stream->i_tsid ); nitn_set_onid( p_ts, p_ts_stream->i_nid ); nitn_set_desclength( p_ts, 0 ); p_ts = nit_get_ts( p_section, 1 ); if ( p_ts == NULL ) /* This shouldn't happen */ nit_set_length( p_section, 0 ); else nit_set_length( p_section, p_ts - p_section - NIT_HEADER_SIZE ); (*pp_section)->i_buffer = psi_get_length( p_section ) + PSI_HEADER_SIZE + 1; psi_set_crc( p_section ); tstable_UpdateTotalBitrate( p_table ); msg_Dbg( p_table, "new NIT version %u", p_sys->i_version ); }
/** @internal @This merges a PSI section. * * @param upipe description structure of the pipe * @param uref uref pointing to (part of) a PSI section * @param upump_p reference to pump that generated the buffer * @return false if the uref has been entirely consumed */ static bool upipe_ts_psim_merge(struct upipe *upipe, struct uref *uref, struct upump **upump_p) { struct upipe_ts_psim *upipe_ts_psim = upipe_ts_psim_from_upipe(upipe); if (upipe_ts_psim->next_uref != NULL) { struct ubuf *ubuf = ubuf_dup(uref->ubuf); if (unlikely(ubuf == NULL || !ubase_check(uref_block_append(upipe_ts_psim->next_uref, ubuf)))) { upipe_ts_psim_flush(upipe); if (ubuf != NULL) ubuf_free(ubuf); upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } } else { /* Check for stuffing */ uint8_t table_id; if (unlikely(!ubase_check(uref_block_extract(uref, 0, 1, &table_id)) || table_id == 0xff)) { return false; } upipe_ts_psim->next_uref = uref_dup(uref); if (unlikely(upipe_ts_psim->next_uref == NULL)) { upipe_throw_fatal(upipe, UBASE_ERR_ALLOC); return false; } } size_t size = 0; UBASE_FATAL(upipe, uref_block_size(upipe_ts_psim->next_uref, &size)) if (size < PSI_HEADER_SIZE) return false; uint8_t buffer[PSI_HEADER_SIZE]; const uint8_t *psi_header = uref_block_peek(upipe_ts_psim->next_uref, 0, PSI_HEADER_SIZE, buffer); assert(psi_header != NULL); uint16_t length = psi_get_length(psi_header); UBASE_FATAL(upipe, uref_block_peek_unmap(upipe_ts_psim->next_uref, 0, buffer, psi_header)); if (unlikely(!psi_validate(psi_header) || length + PSI_HEADER_SIZE > PSI_PRIVATE_MAX_SIZE)) { upipe_warn(upipe, "wrong PSI header"); upipe_ts_psim_flush(upipe); return false; } if (length + PSI_HEADER_SIZE > size) return false; UBASE_FATAL(upipe, uref_block_resize(upipe_ts_psim->next_uref, 0, length + PSI_HEADER_SIZE)); upipe_ts_psim_output(upipe, upipe_ts_psim->next_uref, upump_p); upipe_ts_psim->next_uref = NULL; if (length + PSI_HEADER_SIZE == size) return false; size_t uref_size = 0; UBASE_FATAL(upipe, uref_block_size(uref, &uref_size)) UBASE_FATAL(upipe, uref_block_resize(uref, length + PSI_HEADER_SIZE - (size - uref_size), -1)); return true; }