Exemple #1
0
/*****************************************************************************
 * 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;

}
Exemple #2
0
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);
}
Exemple #3
0
/*****************************************************************************
 * 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;
}
Exemple #4
0
/*****************************************************************************
 * 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;
}