コード例 #1
0
ファイル: pat.c プロジェクト: mwgoldsmith/dvbpsi
/*****************************************************************************
 * dvbpsi_pat_detach
 *****************************************************************************
 * Close a PAT decoder. The handle isn't valid any more.
 *****************************************************************************/
void dvbpsi_pat_detach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
    assert(p_dvbpsi);

    dvbpsi_pat_decoder_t *p_pat_decoder =
             (dvbpsi_pat_decoder_t*) dvbpsi_decoder_chain_get(p_dvbpsi, i_table_id, i_extension);
    if (!p_pat_decoder)
    {
        dvbpsi_error(p_dvbpsi, "PAT Decoder",
                     "No such PAT decoder (table_id == 0x%02x,"
                     "extension == 0x%02x)",
                     i_table_id, i_extension);
        return;
    }

    /* Remove table decoder from chain */
    if (!dvbpsi_decoder_chain_remove(p_dvbpsi, DVBPSI_DECODER(p_pat_decoder)))
    {
        dvbpsi_error(p_dvbpsi, "PAT Decoder",
                     "Failed to remove"
                     "extension == 0x%02x)",
                      i_table_id, i_extension);
        return;
    }

    if (p_pat_decoder->p_building_pat)
        dvbpsi_pat_delete(p_pat_decoder->p_building_pat);
    p_pat_decoder->p_building_pat = NULL;
    dvbpsi_decoder_delete(DVBPSI_DECODER(p_pat_decoder));
    p_pat_decoder = NULL;
}
コード例 #2
0
ファイル: nit.c プロジェクト: egan2015/tsmux
static bool dvbpsi_CheckNIT(dvbpsi_t *p_dvbpsi, dvbpsi_nit_decoder_t *p_nit_decoder,
                            dvbpsi_psi_section_t *p_section)
{
    assert(p_dvbpsi);
    assert(p_nit_decoder);

    bool b_reinit = false;

    if (p_nit_decoder->p_building_nit->i_version != p_section->i_version)
    {
        /* version_number */
        dvbpsi_error(p_dvbpsi, "NIT decoder",
                "'version_number' differs"
                " whereas no discontinuity has occurred");
        b_reinit = true;
    }
    else if (p_nit_decoder->i_last_section_number
                                    != p_section->i_last_number)
    {
        /* last_section_number */
        dvbpsi_error(p_dvbpsi, "NIT decoder",
                "'last_section_number' differs"
                " whereas no discontinuity has occurred");
        b_reinit = true;
    }

    return b_reinit;
}
コード例 #3
0
ファイル: tot.c プロジェクト: avble/libdvbpsi
static bool dvbpsi_CheckTOT(dvbpsi_t *p_dvbpsi, dvbpsi_tot_decoder_t *p_tot_decoder,
                            dvbpsi_psi_section_t *p_section)
{
    bool b_reinit = false;
    assert(p_dvbpsi);
    assert(p_tot_decoder);

    if (p_tot_decoder->p_building_tot->i_extension != p_section->i_extension)
    {
        /* transport_stream_id */
        dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
                "'transport_stream_id' differs"
                " whereas no TS discontinuity has occured");
        b_reinit = true;
    }
    else if (p_tot_decoder->p_building_tot->i_version != p_section->i_version)
    {
        /* version_number */
        dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
                "'version_number' differs"
                " whereas no discontinuity has occured");
        b_reinit = true;
    }
    else if (p_tot_decoder->i_last_section_number != p_section->i_last_number)
    {
        /* last_section_number */
        dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
                "'last_section_number' differs"
                " whereas no discontinuity has occured");
        b_reinit = true;
    }

    return b_reinit;
}
コード例 #4
0
ファイル: pmt.c プロジェクト: jianghong-023/linux_ydn
static bool dvbpsi_CheckPMT( dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section )
{
	bool b_reinit = false;
	assert( p_dvbpsi->p_decoder );

	dvbpsi_pmt_decoder_t* p_pmt_decoder;
	p_pmt_decoder = (dvbpsi_pmt_decoder_t *) p_dvbpsi->p_decoder;

	if ( p_pmt_decoder->p_building_pmt->i_version != p_section->i_version )
	{
		/* version_number */
		dvbpsi_error( p_dvbpsi, "PMT decoder",
			      "'version_number' differs"
			      " whereas no discontinuity has occured" );
		b_reinit = true;
	}else if ( p_pmt_decoder->i_last_section_number != p_section->i_last_number )
	{
		/* last_section_number */
		dvbpsi_error( p_dvbpsi, "PMT decoder",
			      "'last_section_number' differs"
			      " whereas no discontinuity has occured" );
		b_reinit = true;
	}

	return(b_reinit);
}
コード例 #5
0
ファイル: pat.c プロジェクト: jianghong-023/linux_ydn
static bool dvbpsi_CheckPAT( dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section )
{
	bool b_reinit = false;
	assert( p_dvbpsi->p_decoder );

	dvbpsi_pat_decoder_t* p_pat_decoder;
	p_pat_decoder = (dvbpsi_pat_decoder_t *) p_dvbpsi->p_decoder;

	/* Perform a few sanity checks */
	if ( p_pat_decoder->p_building_pat->i_ts_id != p_section->i_extension )
	{
		/* transport_stream_id */
		dvbpsi_error( p_dvbpsi, "PAT decoder",
			      "'transport_stream_id' differs"
			      " whereas no TS discontinuity has occured" );
		b_reinit = true;
	}else if ( p_pat_decoder->p_building_pat->i_version != p_section->i_version )
	{
		/* version_number */
		dvbpsi_error( p_dvbpsi, "PAT decoder",
			      "'version_number' differs"
			      " whereas no discontinuity has occured" );
		b_reinit = true;
	}else if ( p_pat_decoder->i_last_section_number != p_section->i_last_number )
	{
		/* last_section_number */
		dvbpsi_error( p_dvbpsi, "PAT decoder",
			      "'last_section_number' differs"
			      " whereas no discontinuity has occured" );
		b_reinit = true;
	}

	return(b_reinit);
}
コード例 #6
0
ファイル: nit.c プロジェクト: egan2015/tsmux
/*****************************************************************************
 * dvbpsi_nit_detach
 *****************************************************************************
 * Close a NIT decoder.
 *****************************************************************************/
void dvbpsi_nit_detach(dvbpsi_t * p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;

    dvbpsi_demux_subdec_t* p_subdec;
    p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
    if (p_subdec == NULL)
    {
        dvbpsi_error(p_dvbpsi, "NIT Decoder",
                     "No such NIT decoder (table_id == 0x%02x,"
                     "extension == 0x%02x)",
                     i_table_id, i_extension);
        return;
    }

    dvbpsi_nit_decoder_t* p_nit_decoder;
    p_nit_decoder = (dvbpsi_nit_decoder_t*)p_subdec->p_decoder;
    if (p_nit_decoder->p_building_nit)
        dvbpsi_nit_delete(p_nit_decoder->p_building_nit);
    p_nit_decoder->p_building_nit = NULL;

    /* Free demux sub table decoder */
    dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec);
    dvbpsi_DeleteDemuxSubDecoder(p_subdec);
}
コード例 #7
0
ファイル: tot.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * dvbpsi_tot_detach
 *****************************************************************************
 * Close a TDT/TOT decoder.
 *****************************************************************************/
void dvbpsi_tot_detach(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
                      uint16_t i_extension)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_decoder;
    dvbpsi_demux_subdec_t* p_subdec;

    i_extension = 0; /* NOTE: force to 0 when handling TDT/TOT */
    p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
    if (p_demux == NULL)
    {
        dvbpsi_error(p_dvbpsi, "TDT/TOT Decoder",
                     "No such TDT/TOT decoder (table_id == 0x%02x,"
                     "extension == 0x%02x)",
                     i_table_id, i_extension);
        return;
    }

    assert(p_subdec->p_decoder);

    dvbpsi_tot_decoder_t* p_tot_decoder;
    p_tot_decoder = (dvbpsi_tot_decoder_t*)p_subdec->p_decoder;
    if (p_tot_decoder->p_building_tot)
        dvbpsi_tot_delete(p_tot_decoder->p_building_tot);
    p_tot_decoder->p_building_tot = NULL;

    dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec);
    dvbpsi_DeleteDemuxSubDecoder(p_subdec);
}
コード例 #8
0
ファイル: atsc_ett.c プロジェクト: egan2015/tsmux
/*****************************************************************************
 * dvbpsi_atsc_DetachETT
 *****************************************************************************
 * Close a ETT decoder. The handle isn't valid any more.
 *****************************************************************************/
void dvbpsi_atsc_DetachETT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;

    dvbpsi_demux_subdec_t* p_subdec;
    p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
    if (p_subdec == NULL)
    {
        dvbpsi_error(p_dvbpsi, "ATSC ETT Decoder",
                     "No such ETT decoder (table_id == 0x%02x,"
                     "extension == 0x%04x)",
                     i_table_id, i_extension);
        return;
    }

    dvbpsi_atsc_ett_decoder_t* p_ett_decoder;
    p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*)p_subdec->p_decoder;
    if (!p_ett_decoder)
        return;

    if (p_ett_decoder->p_building_ett)
        dvbpsi_atsc_DeleteETT(p_ett_decoder->p_building_ett);
    p_ett_decoder->p_building_ett = NULL;

    dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec);
    dvbpsi_DeleteDemuxSubDecoder(p_subdec);
}
コード例 #9
0
ファイル: sis.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * dvbpsi_sis_detach
 *****************************************************************************
 * Close a SIS decoder.
 *****************************************************************************/
void dvbpsi_sis_detach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;

    i_extension = 0;
    dvbpsi_demux_subdec_t* p_subdec;
    p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
    if (p_demux == NULL)
    {
        dvbpsi_error(p_dvbpsi, "SIS Decoder",
                         "No such SIS decoder (table_id == 0x%02x,"
                         "extension == 0x%02x)",
                         i_table_id, i_extension);
        return;
    }

    assert(p_subdec->p_decoder);

    dvbpsi_sis_decoder_t* p_sis_decoder;
    p_sis_decoder = (dvbpsi_sis_decoder_t*)p_subdec->p_decoder;
    if (p_sis_decoder->p_building_sis)
        dvbpsi_sis_delete(p_sis_decoder->p_building_sis);
    p_sis_decoder->p_building_sis = NULL;

    dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec);
    dvbpsi_DeleteDemuxSubDecoder(p_subdec);
}
コード例 #10
0
ファイル: sis.c プロジェクト: avble/libdvbpsi
static bool dvbpsi_CheckSIS(dvbpsi_t *p_dvbpsi, dvbpsi_sis_decoder_t* p_sis_decoder,
                            dvbpsi_psi_section_t *p_section)
{
    bool b_reinit = false;
    assert(p_dvbpsi);
    assert(p_sis_decoder);

    if (p_sis_decoder->p_building_sis->i_protocol_version != 0)
    {
        dvbpsi_error(p_dvbpsi, "SIS decoder",
                     "'protocol_version' differs"
                     " while no discontinuity has occured");
        b_reinit = true;
    }
    else if (p_sis_decoder->p_building_sis->i_extension != p_section->i_extension)
    {
        dvbpsi_error(p_dvbpsi, "SIS decoder",
                "'transport_stream_id' differs"
                " whereas no discontinuity has occured");
        b_reinit = true;
    }
    else if (p_sis_decoder->p_building_sis->i_version != p_section->i_version)
    {
        /* version_number */
        dvbpsi_error(p_dvbpsi, "SIS decoder",
                "'version_number' differs"
                " whereas no discontinuity has occured");
        b_reinit = true;
    }
    else if (p_sis_decoder->i_last_section_number != p_section->i_last_number)
    {
        /* last_section_number */
        dvbpsi_error(p_dvbpsi, "SIS decoder",
                "'last_section_number' differs"
                " whereas no discontinuity has occured");
        b_reinit = true;
    }

    return b_reinit;
}
コード例 #11
0
ファイル: vct.c プロジェクト: Boxee/libdvbpsi
/*****************************************************************************
 * dvbpsi_AttachVCT
 *****************************************************************************
 * Initialize a VCT subtable decoder.
 *****************************************************************************/
bool dvbpsi_AttachVCT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
                      dvbpsi_vct_callback pf_callback, void* p_cb_data)
{
     assert(p_dvbpsi);
     assert(p_dvbpsi->p_private);

     dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
     dvbpsi_demux_subdec_t* p_subdec;
     dvbpsi_vct_decoder_t*  p_vct_decoder;

     if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
     {
         dvbpsi_error(p_dvbpsi, "VCT decoder",
                      "Already a decoder for (table_id == 0x%02x,"
                      "extension == 0x%02x)",
                      i_table_id, i_extension);
         return false;
     }

     p_subdec = (dvbpsi_demux_subdec_t*)calloc(1, sizeof(dvbpsi_demux_subdec_t));
     if(p_subdec == NULL)
         return false;

     p_vct_decoder = (dvbpsi_vct_decoder_t*)calloc(1, sizeof(dvbpsi_vct_decoder_t));
     if (p_vct_decoder == NULL)
     {
         free(p_subdec);
         return false;
     }

     /* subtable decoder configuration */
     p_subdec->pf_callback = &dvbpsi_GatherVCTSections;
     p_subdec->p_cb_data = p_vct_decoder;
     p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
     p_subdec->pf_detach = &dvbpsi_DetachVCT;

     /* Attach the subtable decoder to the demux */
     p_subdec->p_next = p_demux->p_first_subdec;
     p_demux->p_first_subdec = p_subdec;

     /* vct decoder information */
     p_vct_decoder->pf_vct_callback = pf_callback;
     p_vct_decoder->p_cb_data = p_cb_data;

     /* vct decoder initial state */
     p_vct_decoder->b_current_valid = false;
     p_vct_decoder->p_building_vct = NULL;
     for (unsigned int i = 0; i <= 255; i++)
         p_vct_decoder->ap_sections[i] = NULL;

     return true;
}
コード例 #12
0
ファイル: nit.c プロジェクト: egan2015/tsmux
/*****************************************************************************
 * dvbpsi_nit_attach
 *****************************************************************************
 * Initialize a NIT subtable decoder.
 *****************************************************************************/
bool dvbpsi_nit_attach(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
                      uint16_t i_extension, dvbpsi_nit_callback pf_callback,
                      void* p_cb_data)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_decoder;

    if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
    {
        dvbpsi_error(p_dvbpsi, "NIT decoder",
                     "Already a decoder for (table_id == 0x%02x,"
                     "extension == 0x%02x)",
                     i_table_id, i_extension);
        return false;
    }

    dvbpsi_nit_decoder_t*  p_nit_decoder;
    p_nit_decoder = (dvbpsi_nit_decoder_t*) dvbpsi_decoder_new(NULL,
                                             0, true, sizeof(dvbpsi_nit_decoder_t));
    if (p_nit_decoder == NULL)
        return false;

    /* subtable decoder configuration */
    dvbpsi_demux_subdec_t* p_subdec;
    p_subdec = dvbpsi_NewDemuxSubDecoder(i_table_id, i_extension, dvbpsi_nit_detach,
                                         dvbpsi_nit_sections_gather, DVBPSI_DECODER(p_nit_decoder));
    if (p_subdec == NULL)
    {
        dvbpsi_decoder_delete(DVBPSI_DECODER(p_nit_decoder));
        return false;
    }

    /* Attach the subtable decoder to the demux */
    dvbpsi_AttachDemuxSubDecoder(p_demux, p_subdec);

    /* NIT decoder information */
    p_nit_decoder->i_network_id = i_extension;
    p_nit_decoder->pf_nit_callback = pf_callback;
    p_nit_decoder->p_cb_data = p_cb_data;
    p_nit_decoder->p_building_nit = NULL;

    return true;
}
コード例 #13
0
ファイル: tot.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * dvbpsi_tot_section_valid
 *****************************************************************************
 * Check the CRC_32 if the section has b_syntax_indicator set.
 *****************************************************************************/
static bool dvbpsi_tot_section_valid(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t* p_section)
{
    /* TDT table */
    if (p_section->i_table_id == 0x70)
    {
        /* A TDT (table_id 0x70) always has a length of 5 bytes (which is only the UTC time) */
        if (p_section->i_length != 5)
        {
            dvbpsi_error(p_dvbpsi, "TDT decoder",
                         "TDT has an invalid payload size (%d bytes) !!!",
                          p_section->i_length);
            return false;
        }
    }

    /* CRC32 has already been checked by dvbpsi_packet_push()
     * and by dvbpsi_BuildPSISection(). */
    return true;
}
コード例 #14
0
ファイル: atsc_ett.c プロジェクト: egan2015/tsmux
/*****************************************************************************
 * dvbpsi_atsc_AttachETT
 *****************************************************************************
 * Initialize a ETT decoder and return a handle on it.
 *****************************************************************************/
bool dvbpsi_atsc_AttachETT(dvbpsi_t * p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
                          dvbpsi_atsc_ett_callback pf_callback, void* p_cb_data)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_decoder;

    if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
    {
        dvbpsi_error(p_dvbpsi, "ATSC ETT decoder",
                     "Already a decoder for (table_id == 0x%02x extension == 0x%04x)",
                     i_table_id, i_extension);
        return false;
    }

    dvbpsi_atsc_ett_decoder_t* p_ett_decoder;
    p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*) dvbpsi_decoder_new(NULL,
                                                  0, true, sizeof(dvbpsi_atsc_ett_decoder_t));
    if (p_ett_decoder == NULL)
        return false;

    /* PSI decoder configuration */
    dvbpsi_demux_subdec_t* p_subdec;
    p_subdec = dvbpsi_NewDemuxSubDecoder(i_table_id, i_extension, dvbpsi_atsc_DetachETT,
                                         dvbpsi_atsc_GatherETTSections, DVBPSI_DECODER(p_ett_decoder));
    if (p_subdec == NULL)
    {
        dvbpsi_decoder_delete(DVBPSI_DECODER(p_ett_decoder));
        return false;
    }

    /* Attach the subtable decoder to the demux */
    dvbpsi_AttachDemuxSubDecoder(p_demux, p_subdec);

    /* ETT decoder information */
    p_ett_decoder->pf_ett_callback = pf_callback;
    p_ett_decoder->p_cb_data = p_cb_data;
    p_ett_decoder->p_building_ett = NULL;

    return true;
}
コード例 #15
0
ファイル: vct.c プロジェクト: Boxee/libdvbpsi
/*****************************************************************************
 * dvbpsi_DetachVCT
 *****************************************************************************
 * Close a VCT decoder. The handle isn't valid any more.
 *****************************************************************************/
void dvbpsi_DetachVCT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_private);

    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
    dvbpsi_demux_subdec_t* p_subdec;
    dvbpsi_demux_subdec_t** pp_prev_subdec;
    dvbpsi_vct_decoder_t* p_vct_decoder;

    p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
    if (p_subdec == NULL)
    {
        dvbpsi_error(p_dvbpsi, "VCT Decoder",
                     "No such VCT decoder (table_id == 0x%02x,"
                     "extension == 0x%02x)",
                     i_table_id, i_extension);
        return;
    }

    p_vct_decoder = (dvbpsi_vct_decoder_t*)p_subdec->p_cb_data;
    free(p_vct_decoder->p_building_vct);

    for (unsigned int i = 0; i <= 255; i++)
    {
        if (p_vct_decoder->ap_sections[i])
        {
            dvbpsi_DeletePSISections(p_vct_decoder->ap_sections[i]);
            p_vct_decoder->ap_sections[i] = NULL;
        }
    }
    free(p_subdec->p_cb_data);

    pp_prev_subdec = &p_demux->p_first_subdec;
    while(*pp_prev_subdec != p_subdec)
        pp_prev_subdec = &(*pp_prev_subdec)->p_next;

    *pp_prev_subdec = p_subdec->p_next;
    free(p_subdec);
    p_subdec = NULL;
}
コード例 #16
0
ファイル: pat.c プロジェクト: mwgoldsmith/dvbpsi
/*****************************************************************************
 * dvbpsi_pat_attach
 *****************************************************************************
 * Initialize a PAT decoder and return a handle on it.
 *****************************************************************************/
bool dvbpsi_pat_attach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
                       dvbpsi_pat_callback pf_callback, void* p_priv)
{
    assert(p_dvbpsi);

    /* PSI decoder configuration and initial state */
    dvbpsi_decoder_t* p_dec = dvbpsi_decoder_chain_get(p_dvbpsi, i_table_id, i_extension);
    if (p_dec != NULL)
    {
        dvbpsi_error(p_dvbpsi, "PAT decoder",
                     "Already a decoder for (table_id == 0x%02x,"
                     "extension == 0x%02x)",
                     i_table_id, i_extension);
        return false;
    }
    dvbpsi_pat_decoder_t *p_pat_decoder;
    p_pat_decoder = (dvbpsi_pat_decoder_t*) dvbpsi_decoder_new(&dvbpsi_pat_sections_gather,
                                                1024, true, sizeof(dvbpsi_pat_decoder_t));
    if (p_pat_decoder == NULL)
        return false;

    /* PAT decoder information */
    p_pat_decoder->pf_pat_callback = pf_callback;
    p_pat_decoder->p_priv = p_priv;
    p_pat_decoder->p_building_pat = NULL;

    p_pat_decoder->i_table_id = i_table_id;
    p_pat_decoder->i_extension = i_extension;

    /* Add pat decoder to decoder chain */
    if (!dvbpsi_decoder_chain_add(p_dvbpsi, DVBPSI_DECODER(p_pat_decoder)))
    {
        dvbpsi_decoder_delete(DVBPSI_DECODER(p_pat_decoder));
        return false;
    }

    return true;
}
コード例 #17
0
ファイル: cat.c プロジェクト: UIKit0/libdvbpsi
/*****************************************************************************
 * dvbpsi_cat_sections_gather
 *****************************************************************************
 * Callback for the PSI decoder.
 *****************************************************************************/
void dvbpsi_cat_sections_gather(dvbpsi_t *p_dvbpsi,
                              dvbpsi_psi_section_t* p_section)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0x01, "CAT decoder"))
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* */
    dvbpsi_cat_decoder_t* p_cat_decoder
                          = (dvbpsi_cat_decoder_t*)p_dvbpsi->p_decoder;

    /* TS discontinuity check */
    if (p_cat_decoder->b_discontinuity)
    {
        dvbpsi_ReInitCAT(p_cat_decoder, true);
        p_cat_decoder->b_discontinuity = false;
    }
    else
    {
        /* Perform some few sanity checks */
        if (p_cat_decoder->p_building_cat)
        {
            if (dvbpsi_CheckCAT(p_dvbpsi, p_section))
                dvbpsi_ReInitCAT(p_cat_decoder, true);
        }
        else
        {
             if (   (p_cat_decoder->b_current_valid)
                 && (p_cat_decoder->current_cat.i_version == p_section->i_version)
                 && (p_cat_decoder->current_cat.b_current_next ==
                                                   p_section->b_current_next))
             {
                 /* Don't decode since this version is already decoded */
                 dvbpsi_debug(p_dvbpsi, "CAT decoder",
                              "ignoring already decoded section %d",
                              p_section->i_number);
                 dvbpsi_DeletePSISections(p_section);
                 return;
             }
        }
    }

    /* Add section to CAT */
    if (!dvbpsi_AddSectionCAT(p_dvbpsi, p_cat_decoder, p_section))
    {
        dvbpsi_error(p_dvbpsi, "CAT decoder", "failed decoding section %d",
                     p_section->i_number);
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Check if we have all the sections */
    if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_cat_decoder)))
    {
        assert(p_cat_decoder->pf_cat_callback);

        /* Save the current information */
        p_cat_decoder->current_cat = *p_cat_decoder->p_building_cat;
        p_cat_decoder->b_current_valid = true;
        /* Decode the sections */
        dvbpsi_cat_sections_decode(p_cat_decoder->p_building_cat,
                                   p_cat_decoder->p_sections);
        /* signal the new CAT */
        p_cat_decoder->pf_cat_callback(p_cat_decoder->p_cb_data,
                                       p_cat_decoder->p_building_cat);
        /* Delete sections and Reinitialize the structures */
        dvbpsi_ReInitCAT(p_cat_decoder, false);
        assert(p_cat_decoder->p_sections == NULL);
    }
}
コード例 #18
0
ファイル: dvbpsi.c プロジェクト: UIKit0/libdvbpsi
/*****************************************************************************
 * 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))
コード例 #19
0
ファイル: pat.c プロジェクト: jianghong-023/linux_ydn
/*****************************************************************************
* 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);
}
コード例 #20
0
ファイル: sis.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * dvbpsi_sis_sections_decode
 *****************************************************************************
 * SIS decoder.
 *****************************************************************************/
void dvbpsi_sis_sections_decode(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis,
                              dvbpsi_psi_section_t* p_section)
{
    uint8_t *p_byte, *p_end;

    while (p_section)
    {
        for (p_byte = p_section->p_payload_start + 3;
             p_byte < p_section->p_payload_end; )
        {
            p_sis->i_protocol_version = p_byte[3];
            p_sis->b_encrypted_packet = ((p_byte[4] & 0x80)>>8);
            /* NOTE: cannot handle encrypted packet */
            assert(p_sis->b_encrypted_packet);
            p_sis->i_encryption_algorithm = ((p_byte[4] & 0x7E) >> 1);
            p_sis->i_pts_adjustment = ((((uint64_t)p_byte[4] & 0x01) << 32) |
                                        ((uint64_t)p_byte[5] << 24) |
                                        ((uint64_t)p_byte[6] << 16) |
                                        ((uint64_t)p_byte[7] << 8)  |
                                         (uint64_t)p_byte[8]);
            p_sis->cw_index = p_byte[9];
            p_sis->i_splice_command_length = ((p_byte[11] & 0x0F) << 8) | p_byte[12];
            p_sis->i_splice_command_type = p_byte[13];

            uint32_t i_splice_command_length = 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 */
            switch(p_sis->i_splice_command_type)
            {
                case 0x00: /* splice_null */
                case 0x04: /* splice_schedule */
                case 0x05: /* splice_insert */
                case 0x06: /* time_signal */
                case 0x07: /* bandwidth_reservation */
                    break;
                default:
                    dvbpsi_error(p_dvbpsi, "SIS decoder", "invalid SIS Command found");
                    break;
            }

            /* Service descriptors */
            uint8_t *p_desc = p_byte + 13 + i_splice_command_length;
            p_sis->i_descriptors_length = (p_desc[0] << 8) | p_desc[1];

            p_desc += 1;
            p_end = p_desc + p_sis->i_descriptors_length;
            if (p_end > p_section->p_payload_end) break;

            while (p_desc + 2 <= p_end)
            {
                uint8_t i_tag = p_desc[0];
                uint8_t i_length = p_desc[1];
                if ((i_length <= 254) &&
                    (i_length + 2 <= p_end - p_desc))
                    dvbpsi_sis_descriptor_add(p_sis, i_tag, i_length, p_desc + 2);
                p_desc += 2 + i_length;
            }

            if (p_sis->b_encrypted_packet)
            {
                /* FIXME: Currently ignored */
                /* Calculate crc32 over decoded
                 * p_sis->i_splice_command_type till p_sis->i_ecrc,
                 * the result should be exactly p_sis->i_ecrc and indicates
                 * a successfull decryption.
                 */
                p_desc += 4; /* E CRC 32 */
            }

            /* point to next section */
            p_byte = p_desc + 4 /* CRC 32 */;
        }

        p_section = p_section->p_next;
    }
}
コード例 #21
0
ファイル: pmt.c プロジェクト: jianghong-023/linux_ydn
void dvbpsi_pmt_sections_gather( dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t* p_section )
{
	assert( p_dvbpsi );
	assert( p_dvbpsi->p_decoder );

	/* ¼ì²étable_id */
	if ( !dvbpsi_CheckPSISection( p_dvbpsi, p_section, 0x02, "PMT decoder" ) )
	{
		dvbpsi_DeletePSISections( p_section );
		return;
	}

	/* */
	dvbpsi_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t *) p_dvbpsi->p_decoder;
	assert( p_pmt_decoder );

	/* We have a valid PMT section */
	/* ½ÚÄ¿ºÅ¼ì²é*/
	if ( p_pmt_decoder->i_program_number != p_section->i_extension )
	{
		/* Invalid program_number */
		dvbpsi_debug( p_dvbpsi, "PMT decoder", "ignoring section %d not belonging to 'program_number' %d",
			      p_section->i_extension, p_pmt_decoder->i_program_number );
		dvbpsi_DeletePSISections( p_section );
		return;
	}

	/* TS discontinuity check */
	if ( p_pmt_decoder->b_discontinuity )
	{
		dvbpsi_ReInitPMT( p_pmt_decoder, true );
		p_pmt_decoder->b_discontinuity = false;
		
	}else  {
	
		/* Perform some few sanity checks */
		if ( p_pmt_decoder->p_building_pmt )
		{
			if ( dvbpsi_CheckPMT( p_dvbpsi, p_section ) )
				dvbpsi_ReInitPMT( p_pmt_decoder, true );
		}else  {
			if ( (p_pmt_decoder->b_current_valid)
			     && (p_pmt_decoder->current_pmt.i_version == p_section->i_version)
			     && (p_pmt_decoder->current_pmt.b_current_next ==
				 p_section->b_current_next) )
			{
				/* Don't decode since this version is already decoded */
				dvbpsi_debug( p_dvbpsi, "PMT decoder",
					      "ignoring already decoded section %d",
					      p_section->i_number );
				dvbpsi_DeletePSISections( p_section );
				return;
			}
		}
	}

	/* Add section to PMT */
	if ( !dvbpsi_AddSectionPMT( p_dvbpsi, p_pmt_decoder, p_section ) )
	{
		dvbpsi_error( p_dvbpsi, "PMT decoder", "failed decoding section %d",
			      p_section->i_number );
		dvbpsi_DeletePSISections( p_section );
		return;
	}

	if ( dvbpsi_decoder_psi_sections_completed( DVBPSI_DECODER( p_pmt_decoder ) ) )
	{
		assert( p_pmt_decoder->pf_pmt_callback );

		/* Save the current information */
		p_pmt_decoder->current_pmt	= *p_pmt_decoder->p_building_pmt;
		p_pmt_decoder->b_current_valid	= true;
		/* Decode the sections */
		dvbpsi_pmt_sections_decode( p_pmt_decoder->p_building_pmt,
					    p_pmt_decoder->p_sections );
		/* signal the new PMT */

		p_pmt_decoder->pf_pmt_callback( p_pmt_decoder->p_cb_data,
						p_pmt_decoder->p_building_pmt );
		/* Delete sections and Reinitialize the structures */
		dvbpsi_ReInitPMT( p_pmt_decoder, false );
		assert( p_pmt_decoder->p_sections == NULL );
	}
}
コード例 #22
0
ファイル: bat.c プロジェクト: Boxee/libdvbpsi
/*****************************************************************************
 * 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;
    }
}
コード例 #23
0
ファイル: bat.c プロジェクト: Boxee/libdvbpsi
/*****************************************************************************
 * 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;
    }
コード例 #24
0
ファイル: pat.c プロジェクト: mwgoldsmith/dvbpsi
/*****************************************************************************
 * dvbpsi_pat_sections_gather
 *****************************************************************************
 * Callback for the PSI decoder.
 *****************************************************************************/
void dvbpsi_pat_sections_gather(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section)
{

    assert(p_dvbpsi);

    if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0x00, "PAT decoder"))
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Now we have a valid PAT section */
    dvbpsi_decoder_t *p_dec = dvbpsi_decoder_chain_get(p_dvbpsi, p_section->i_table_id, p_section->i_extension);
    if (!p_dec)
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* TS discontinuity check */
    dvbpsi_pat_decoder_t *p_pat_decoder = (dvbpsi_pat_decoder_t *)p_dec;
    if (p_pat_decoder->b_discontinuity)
    {
        dvbpsi_ReInitPAT(p_pat_decoder, true);
        p_pat_decoder->b_discontinuity = false;
    }
    else
    {
        if (p_pat_decoder->p_building_pat)
        {
            if (dvbpsi_CheckPAT(p_dvbpsi, p_pat_decoder, p_section))
                dvbpsi_ReInitPAT(p_pat_decoder, true);
        }
        else
        {
            if(    (p_pat_decoder->b_current_valid)
                && (p_pat_decoder->current_pat.i_version == p_section->i_version)
                && (p_pat_decoder->current_pat.b_current_next ==
                                               p_section->b_current_next))
            {
                /* Don't decode since this version is already decoded */
                dvbpsi_debug(p_dvbpsi, "PAT decoder",
                             "ignoring already decoded section %d",
                             p_section->i_number);
                dvbpsi_DeletePSISections(p_section);
                return;
            }
        }
    }

    /* Add section to PAT */
    if (!dvbpsi_AddSectionPAT(p_dvbpsi, p_pat_decoder, p_section))
    {
        dvbpsi_error(p_dvbpsi, "PAT decoder", "failed decoding section %d",
                     p_section->i_number);
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Check if we have all the sections */
    if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_pat_decoder)))
    {
        assert(p_pat_decoder->pf_pat_callback);

        /* Save the current information */
        p_pat_decoder->current_pat = *p_pat_decoder->p_building_pat;

        /* Decode the sections */
        if (dvbpsi_pat_sections_decode(p_pat_decoder->p_building_pat,
                                       p_pat_decoder->p_sections))
            p_pat_decoder->b_current_valid = true;

        /* signal the new PAT */
        if (p_pat_decoder->b_current_valid)
            p_pat_decoder->pf_pat_callback(p_pat_decoder->p_priv,
                                           p_pat_decoder->p_building_pat);

        /* Delete sectioins and Reinitialize the structures */
        dvbpsi_ReInitPAT(p_pat_decoder, !p_pat_decoder->b_current_valid);
        assert(p_pat_decoder->p_sections == NULL);
    }
}
コード例 #25
0
ファイル: tot.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * 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;
}
コード例 #26
0
ファイル: atsc_eit.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * dvbpsi_atsc_GatherEITSections
 *****************************************************************************
 * Callback for the subtable demultiplexor.
 *****************************************************************************/
static void dvbpsi_atsc_GatherEITSections(dvbpsi_t * p_dvbpsi,
                                          dvbpsi_decoder_t *p_decoder,
                                          dvbpsi_psi_section_t * p_section)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0xCB, "ATSC EIT decoder"))
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* We have a valid EIT section */
    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
    dvbpsi_atsc_eit_decoder_t *p_eit_decoder = (dvbpsi_atsc_eit_decoder_t*)p_decoder;
    if (!p_eit_decoder)
    {
        dvbpsi_error(p_dvbpsi, "ATSC EIT decoder", "No decoder specified");
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* TS discontinuity check */
    if (p_demux->b_discontinuity)
    {
        dvbpsi_ReInitEIT(p_eit_decoder, true);
        p_eit_decoder->b_discontinuity = false;
        p_demux->b_discontinuity = false;
    }
    else
    {
        /* Perform a few sanity checks */
        if (p_eit_decoder->p_building_eit)
        {
            if (dvbpsi_CheckEIT(p_dvbpsi, p_eit_decoder, p_section))
                dvbpsi_ReInitEIT(p_eit_decoder, true);
        }
        else
        {
            if (   (p_eit_decoder->b_current_valid)
                && (p_eit_decoder->current_eit.i_version == p_section->i_version)
                && (p_eit_decoder->current_eit.b_current_next ==
                                               p_section->b_current_next))
            {
                /* Don't decode since this version is already decoded */
                dvbpsi_debug(p_dvbpsi, "ATSC EIT decoder",
                             "ignoring already decoded section %d",
                             p_section->i_number);
                dvbpsi_DeletePSISections(p_section);
                return;
            }
#if 0
            if ((p_eit_decoder->b_current_valid) &&
                (p_eit_decoder->current_eit.i_version == p_section->i_version))
            {
                /* Signal a new EIT if the previous one wasn't active */
                if ((!p_eit_decoder->current_eit.b_current_next) &&
                     (p_section->b_current_next))
                {
                    dvbpsi_atsc_eit_t * p_eit = (dvbpsi_atsc_eit_t*)malloc(sizeof(dvbpsi_atsc_eit_t));
                    if (p_eit)
                    {
                        p_eit_decoder->current_eit.b_current_next = true;
                        *p_eit = p_eit_decoder->current_eit;
                        p_eit_decoder->pf_eit_callback(p_eit_decoder->p_cb_data, p_eit);
                    }
                    else
                        dvbpsi_error(p_dvbpsi, "ATSC EIT decoder", "Could not signal new ATSC EIT.");
                }
            }
            dvbpsi_DeletePSISections(p_section);
            return;
#endif
        }
    }

    /* Add section to EIT */
    if (!dvbpsi_AddSectionEIT(p_dvbpsi, p_eit_decoder, p_section))
    {
        dvbpsi_error(p_dvbpsi, "ATSC EIT decoder", "failed decoding section %d",
                     p_section->i_number);
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Check if we have all the sections */
    if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_eit_decoder)))
    {
        assert(p_eit_decoder->pf_eit_callback);

        /* Save the current information */
        p_eit_decoder->current_eit = *p_eit_decoder->p_building_eit;
        p_eit_decoder->b_current_valid = true;
        /* Decode the sections */
        dvbpsi_atsc_DecodeEITSections(p_eit_decoder->p_building_eit,
                                      p_eit_decoder->p_sections);
        /* Delete the sections */
        dvbpsi_DeletePSISections(p_eit_decoder->p_sections);
        p_eit_decoder->p_sections = NULL;
        /* signal the new EIT */
        p_eit_decoder->pf_eit_callback(p_eit_decoder->p_cb_data,
                                       p_eit_decoder->p_building_eit);
        /* Reinitialize the structures */
        dvbpsi_ReInitEIT(p_eit_decoder, false);
    }
}
コード例 #27
0
ファイル: tot.c プロジェクト: avble/libdvbpsi
/*****************************************************************************
 * dvbpsi_tot_sections_gather
 *****************************************************************************
 * Callback for the PSI decoder.
 *****************************************************************************/
void dvbpsi_tot_sections_gather(dvbpsi_t* p_dvbpsi,
                                dvbpsi_decoder_t* p_decoder,
                                dvbpsi_psi_section_t* p_section)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    const uint8_t i_table_id = ((p_section->i_table_id == 0x70 ||  /* TDT */
                                 p_section->i_table_id == 0x73)) ? /* TOT */
                                    p_section->i_table_id : 0x70;

    if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, i_table_id, "TDT/TOT decoder"))
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Valid TDT/TOT section */
    dvbpsi_tot_decoder_t* p_tot_decoder = (dvbpsi_tot_decoder_t*)p_decoder;

    /* TS discontinuity check */
    if (p_tot_decoder->b_discontinuity)
    {
        /* We don't care about discontinuities with the TDT/TOT as it
           only consists of one section anyway */
        //dvbpsi_ReInitTOT(p_tot_decoder, true);
        p_tot_decoder->b_discontinuity = false;
    }
    else
    {
        /* Perform a few sanity checks */
        if (p_tot_decoder->p_building_tot)
        {
            if (dvbpsi_CheckTOT(p_dvbpsi, p_tot_decoder, p_section))
                dvbpsi_ReInitTOT(p_tot_decoder, true);
        }
#if 0
/* FIXME: Check TDT/TOT table definition for how the version numbering works for this table */
        else
        {
            if(    (p_tot_decoder->b_current_valid)
                && (p_tot_decoder->current_tot.i_version == p_section->i_version)
                && (p_tot_decoder->current_tot.b_current_next == p_section->b_current_next))
            {
                /* Don't decode since this version is already decoded */
                dvbpsi_debug(p_dvbpsi, "TOT decoder",
                             "ignoring already decoded section %d",
                             p_section->i_number);
                dvbpsi_DeletePSISections(p_section);
                return;
            }
        }
#endif
    }

    /* Add section to TOT */
    if (!dvbpsi_AddSectionTOT(p_dvbpsi, p_tot_decoder, p_section))
    {
        dvbpsi_error(p_dvbpsi, "TOT decoder", "failed decoding section %d",
                     p_section->i_number);
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Check if we have all the sections */
    if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_tot_decoder)))
    {
        assert(p_tot_decoder->pf_tot_callback);

        /* Save the current information */
        p_tot_decoder->current_tot = *p_tot_decoder->p_building_tot;
        p_tot_decoder->b_current_valid = true;

        /* Decode the sections */
        dvbpsi_tot_sections_decode(p_dvbpsi, p_tot_decoder->p_building_tot,
                                   p_tot_decoder->p_sections);
        /* Delete the sections */
        dvbpsi_DeletePSISections(p_tot_decoder->p_sections);
        p_tot_decoder->p_sections = NULL;
        /* signal the new TOT */
        p_tot_decoder->pf_tot_callback(p_tot_decoder->p_cb_data,
                                       p_tot_decoder->p_building_tot);
        /* Reinitialize the structures */
        dvbpsi_ReInitTOT(p_tot_decoder, false);
    }
}
コード例 #28
0
ファイル: vct.c プロジェクト: Boxee/libdvbpsi
/*****************************************************************************
 * dvbpsi_GatherVCTSections
 *****************************************************************************
 * Callback for the PSI decoder.
 *****************************************************************************/
void dvbpsi_GatherVCTSections(dvbpsi_t *p_dvbpsi,
                              void * p_private_decoder,
                              dvbpsi_psi_section_t * p_section)
{
   assert(p_dvbpsi);
   assert(p_dvbpsi->p_private);

   dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
   dvbpsi_vct_decoder_t *p_vct_decoder
                       = (dvbpsi_vct_decoder_t*)p_private_decoder;

   dvbpsi_debug(p_dvbpsi, "VCT 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);

   if (!p_section->b_syntax_indicator)
   {
       /* Invalid section_syntax_indicator */
       dvbpsi_error(p_dvbpsi, "VCT decoder",
                   "invalid section (section_syntax_indicator == 0)");
       dvbpsi_DeletePSISections(p_section);
       return;
   }

   bool b_reinit = false;

   /* TS discontinuity check */
   if (p_demux->b_discontinuity)
   {
       b_reinit = true;
       p_demux->b_discontinuity = false;
   }
   else
   {
       /* Perform a few sanity checks */
       if (p_vct_decoder->p_building_vct)
       {
           if (p_vct_decoder->p_building_vct->i_ts_id != p_section->i_extension)
           {
               /* transport_stream_id */
               dvbpsi_error(p_dvbpsi, "VCT decoder",
                       "'transport_stream_id' differs"
                       " whereas no TS discontinuity has occured");
               b_reinit = true;
           }
           else if (p_vct_decoder->p_building_vct->i_version != p_section->i_version)
           {
               /* version_number */
               dvbpsi_error(p_dvbpsi, "VCT decoder",
                       "'version_number' differs"
                       " whereas no discontinuity has occured");
               b_reinit = true;
           }
           else if (p_vct_decoder->i_last_section_number != p_section->i_last_number)
           {
               /* last_section_number */
               dvbpsi_error(p_dvbpsi, "VCT decoder",
                       "'last_section_number' differs"
                       " whereas no discontinuity has occured");
               b_reinit = true;
           }
       }
       else
       {
           if(    (p_vct_decoder->b_current_valid)
               && (p_vct_decoder->current_vct.i_version == p_section->i_version)
               && (p_vct_decoder->current_vct.b_current_next == p_section->b_current_next))
           {
               /* Don't decode since this version is already decoded */
               dvbpsi_DeletePSISections(p_section);
               return;
           }
       }
   }

   /* Reinit the decoder if wanted */
   if (b_reinit)
   {
       /* Force redecoding */
       p_vct_decoder->b_current_valid = false;
       /* Free structures */
       if (p_vct_decoder->p_building_vct)
       {
           free(p_vct_decoder->p_building_vct);
           p_vct_decoder->p_building_vct = NULL;
       }
       /* Clear the section array */
       for (unsigned int i = 0; i <= 255; i++)
       {
           if (p_vct_decoder->ap_sections[i] != NULL)
           {
               dvbpsi_DeletePSISections(p_vct_decoder->ap_sections[i]);
               p_vct_decoder->ap_sections[i] = NULL;
           }
       }
   }

   /* Initialize the structures if it's the first section received */
   if (!p_vct_decoder->p_building_vct)
   {
       p_vct_decoder->p_building_vct = (dvbpsi_vct_t*)calloc(1, sizeof(dvbpsi_vct_t));
       if (p_vct_decoder->p_building_vct)
       {
           dvbpsi_InitVCT(p_vct_decoder->p_building_vct,
                           p_section->i_extension,
                           p_section->i_version,
                           p_section->b_current_next,
                           p_section->i_table_id);
           p_vct_decoder->i_last_section_number = p_section->i_last_number;
       }
       else
           dvbpsi_debug(p_dvbpsi, "VCT decoder", "failed decoding section");
   }

   /* Fill the section array */
   if (p_vct_decoder->ap_sections[p_section->i_number] != NULL)
   {
       dvbpsi_debug(p_dvbpsi, "VCT decoder", "overwrite section number %d",
                    p_section->i_number);
       dvbpsi_DeletePSISections(p_vct_decoder->ap_sections[p_section->i_number]);
   }
   p_vct_decoder->ap_sections[p_section->i_number] = p_section;

   /* Check if we have all the sections */
   bool b_complete = false;
   for (unsigned int i = 0; i <= p_vct_decoder->i_last_section_number; i++)
   {
       if (!p_vct_decoder->ap_sections[i])
           break;

       if (i == p_vct_decoder->i_last_section_number)
           b_complete = true;
   }

   if (b_complete)
   {
       /* Save the current information */
       p_vct_decoder->current_vct = *p_vct_decoder->p_building_vct;
       p_vct_decoder->b_current_valid = true;
       /* Chain the sections */
       if (p_vct_decoder->i_last_section_number)
       {
           for (unsigned int i = 0; (int)i <= p_vct_decoder->i_last_section_number - 1; i++)
               p_vct_decoder->ap_sections[i]->p_next = p_vct_decoder->ap_sections[i + 1];
       }
       /* Decode the sections */
       dvbpsi_DecodeVCTSections(p_vct_decoder->p_building_vct,
                                p_vct_decoder->ap_sections[0]);
       /* Delete the sections */
       dvbpsi_DeletePSISections(p_vct_decoder->ap_sections[0]);
       p_vct_decoder->ap_sections[0] = NULL;
       /* signal the new VCT */
       p_vct_decoder->pf_vct_callback(p_vct_decoder->p_cb_data,
                                      p_vct_decoder->p_building_vct);
       /* Reinitialize the structures */
       p_vct_decoder->p_building_vct = NULL;
       for (unsigned int i = 0; i <= p_vct_decoder->i_last_section_number; i++)
           p_vct_decoder->ap_sections[i] = NULL;
   }
}
コード例 #29
0
ファイル: nit.c プロジェクト: egan2015/tsmux
/*****************************************************************************
 * dvbpsi_nit_sections_gather
 *****************************************************************************
 * Callback for the PSI decoder.
 *****************************************************************************/
void dvbpsi_nit_sections_gather(dvbpsi_t *p_dvbpsi,
                                dvbpsi_decoder_t *p_private_decoder,
                                dvbpsi_psi_section_t *p_section)
{
    assert(p_dvbpsi);

    const uint8_t i_table_id = ((p_section->i_table_id == 0x40) ||
                                (p_section->i_table_id == 0x41)) ?
                                    p_section->i_table_id : 0x40;

    if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, i_table_id, "NIT decoder"))
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* */
    dvbpsi_nit_decoder_t* p_nit_decoder
                        = (dvbpsi_nit_decoder_t*)p_private_decoder;

    /* We have a valid NIT section */
    if (p_nit_decoder->i_network_id != p_section->i_extension)
    {
        /* Invalid program_number */
        dvbpsi_error(p_dvbpsi, "NIT decoder", "'network_id' don't match");
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* TS discontinuity check */
    if (p_nit_decoder->b_discontinuity)
    {
        dvbpsi_ReInitNIT(p_nit_decoder, true);
        p_nit_decoder->b_discontinuity = false;
    }
    else
    {
        /* Perform some few sanity checks */
        if (p_nit_decoder->p_building_nit)
        {
            if (dvbpsi_CheckNIT(p_dvbpsi, p_nit_decoder, p_section))
                dvbpsi_ReInitNIT(p_nit_decoder, true);
        }
        else
        {
            if (   (p_nit_decoder->b_current_valid)
                && (p_nit_decoder->current_nit.i_version == p_section->i_version)
                && (p_nit_decoder->current_nit.b_current_next == p_section->b_current_next))
            {
                /* Don't decode since this version is already decoded */
                dvbpsi_debug(p_dvbpsi, "NIT decoder",
                             "ignoring already decoded section %d",
                             p_section->i_number);
                dvbpsi_DeletePSISections(p_section);
                return;;
            }
        }
    }

    /* Add section to NIT */
    if (!dvbpsi_AddSectionNIT(p_dvbpsi, p_nit_decoder, p_section))
    {
        dvbpsi_error(p_dvbpsi, "NIT decoder", "failed decoding section %d",
                     p_section->i_number);
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Check if we have all the sections */
    if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_nit_decoder)))
    {
        assert(p_nit_decoder->pf_nit_callback);

        /* Save the current information */
        p_nit_decoder->current_nit = *p_nit_decoder->p_building_nit;
        p_nit_decoder->b_current_valid = true;

        /* Decode the sections */
        dvbpsi_nit_sections_decode(p_nit_decoder->p_building_nit,
                                   p_nit_decoder->p_sections);
        /* signal the new NIT */
        p_nit_decoder->pf_nit_callback(p_nit_decoder->p_cb_data,
                                       p_nit_decoder->p_building_nit);
        /* Delete sections and Reinitialize the structures */
        dvbpsi_ReInitNIT(p_nit_decoder, false);
        assert(p_nit_decoder->p_sections == NULL);
    }
}
コード例 #30
0
ファイル: atsc_ett.c プロジェクト: egan2015/tsmux
/*****************************************************************************
 * dvbpsi_atsc_GatherETTSections
 *****************************************************************************
 * Callback for the PSI decoder.
 *****************************************************************************/
static void dvbpsi_atsc_GatherETTSections(dvbpsi_t* p_dvbpsi,
                                          dvbpsi_decoder_t *p_decoder,
                                          dvbpsi_psi_section_t* p_section)
{
    assert(p_dvbpsi);
    assert(p_dvbpsi->p_decoder);

    if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0xCC, "ATSC ETT decoder"))
    {
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* We have a valid ETT section */
    dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
    dvbpsi_atsc_ett_decoder_t* p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*)p_decoder;
    if (!p_ett_decoder)
    {
        dvbpsi_error(p_dvbpsi, "ATSC ETT decoder", "No decoder specified");
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* TS discontinuity check */
    if (p_demux->b_discontinuity)
    {
        dvbpsi_ReInitETT(p_ett_decoder, true);
        p_ett_decoder->b_discontinuity = false;
        p_demux->b_discontinuity = false;
    }
    else
    {
        /* Perform a few sanity checks */
        if (p_ett_decoder->p_building_ett)
        {
            if (dvbpsi_CheckETT(p_dvbpsi, p_ett_decoder, p_section))
                dvbpsi_ReInitETT(p_ett_decoder, true);
        }
        else
        {
            if (   (p_ett_decoder->b_current_valid)
                && (p_ett_decoder->current_ett.i_version == p_section->i_version)
                && (p_ett_decoder->current_ett.b_current_next ==
                                               p_section->b_current_next))
            {
                /* Don't decode since this version is already decoded */
                dvbpsi_debug(p_dvbpsi, "ATSC ETT decoder",
                             "ignoring already decoded section %d",
                             p_section->i_number);
                dvbpsi_DeletePSISections(p_section);
                return;
            }
        }
    }

    /* Add section to ETT */
    if (!dvbpsi_AddSectionETT(p_dvbpsi, p_ett_decoder, p_section))
    {
        dvbpsi_error(p_dvbpsi, "ATSC ETT decoder", "failed decoding section %d",
                     p_section->i_number);
        dvbpsi_DeletePSISections(p_section);
        return;
    }

    /* Check if we have all the sections */
    if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_ett_decoder)))
    {
        assert(p_ett_decoder->pf_ett_callback);

        /* Save the current information */
        p_ett_decoder->current_ett = *p_ett_decoder->p_building_ett;
        p_ett_decoder->b_current_valid = true;
        /* Decode the sections */
        dvbpsi_atsc_DecodeETTSections(p_ett_decoder->p_building_ett,
                                      p_ett_decoder->p_sections);
        /* signal the new ETT */
        p_ett_decoder->pf_ett_callback(p_ett_decoder->p_cb_data,
                                       p_ett_decoder->p_building_ett);
        /* Delete sections and Reinitialize the structures */
        dvbpsi_ReInitETT(p_ett_decoder, false);
        assert(p_ett_decoder->p_sections == NULL);
    }
}