/*****************************************************************************
* ts_decoders.c: TS Demux custom tables decoders
*****************************************************************************
* Copyright (C) 2016 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#ifndef _DVBPSI_DVBPSI_H_
#include
#endif
#ifndef _DVBPSI_DEMUX_H_
#include
#endif
#include
#include "ts_decoders.h"
typedef struct
{
DVBPSI_DECODER_COMMON
ts_dvbpsi_rawsections_callback_t pf_callback;
void * p_cb_data;
} ts_dvbpsi_rawtable_decoder_t;
static void ts_dvbpsi_RawSubDecoderGatherSections( dvbpsi_t *p_dvbpsi,
dvbpsi_decoder_t *p_decoder,
dvbpsi_psi_section_t * p_section )
{
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
ts_dvbpsi_rawtable_decoder_t *p_tabledec = (ts_dvbpsi_rawtable_decoder_t*)p_decoder;
if ( !p_tabledec )
{
dvbpsi_DeletePSISections( p_section );
return;
}
if ( p_demux->b_discontinuity )
{
dvbpsi_decoder_reset( DVBPSI_DECODER(p_decoder), true );
p_tabledec->b_discontinuity = false;
p_demux->b_discontinuity = false;
}
else if( p_decoder->i_last_section_number != p_section->i_last_number )
{
dvbpsi_decoder_reset( DVBPSI_DECODER(p_decoder), true );
}
/* Add to linked list of sections */
(void) dvbpsi_decoder_psi_section_add( DVBPSI_DECODER(p_decoder), p_section );
p_decoder->i_last_section_number = p_section->i_last_number;
/* Check if we have all the sections */
if ( dvbpsi_decoder_psi_sections_completed( DVBPSI_DECODER(p_decoder) ) )
{
p_tabledec->b_current_valid = true;
p_tabledec->pf_callback( p_dvbpsi,
p_decoder->p_sections,
p_tabledec->p_cb_data );
/* Delete sections */
dvbpsi_decoder_reset( DVBPSI_DECODER(p_decoder), false );
}
}
static void ts_dvbpsi_RawDecoderGatherSections( dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t * p_section )
{
ts_dvbpsi_RawSubDecoderGatherSections( p_dvbpsi, p_dvbpsi->p_decoder, p_section );
}
void ts_dvbpsi_DetachRawSubDecoder( 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 || !p_subdec->p_decoder )
return;
dvbpsi_DetachDemuxSubDecoder( p_demux, p_subdec );
dvbpsi_DeleteDemuxSubDecoder( p_subdec );
}
bool ts_dvbpsi_AttachRawSubDecoder( dvbpsi_t* p_dvbpsi,
uint8_t i_table_id, uint16_t i_extension,
ts_dvbpsi_rawsections_callback_t pf_callback,
void *p_cb_data )
{
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_decoder;
if ( dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension) )
return false;
ts_dvbpsi_rawtable_decoder_t *p_decoder;
p_decoder = (ts_dvbpsi_rawtable_decoder_t *) dvbpsi_decoder_new( NULL, 0, true, sizeof(*p_decoder) );
if ( p_decoder == NULL )
return false;
/* subtable decoder configuration */
dvbpsi_demux_subdec_t* p_subdec;
p_subdec = dvbpsi_NewDemuxSubDecoder( i_table_id, i_extension,
ts_dvbpsi_DetachRawSubDecoder,
ts_dvbpsi_RawSubDecoderGatherSections,
DVBPSI_DECODER(p_decoder) );
if (p_subdec == NULL)
{
dvbpsi_decoder_delete( DVBPSI_DECODER(p_decoder) );
return false;
}
/* Attach the subtable decoder to the demux */
dvbpsi_AttachDemuxSubDecoder( p_demux, p_subdec );
p_decoder->pf_callback = pf_callback;
p_decoder->p_cb_data = p_cb_data;
return true;
}
bool ts_dvbpsi_AttachRawDecoder( dvbpsi_t* p_dvbpsi,
ts_dvbpsi_rawsections_callback_t pf_callback,
void *p_cb_data )
{
if ( p_dvbpsi->p_decoder )
return false;
ts_dvbpsi_rawtable_decoder_t *p_decoder = dvbpsi_decoder_new( NULL, 4096, true, sizeof(*p_decoder) );
if ( p_decoder == NULL )
return false;
p_dvbpsi->p_decoder = DVBPSI_DECODER(p_decoder);
p_decoder->pf_gather = ts_dvbpsi_RawDecoderGatherSections;
p_decoder->pf_callback = pf_callback;
p_decoder->p_cb_data = p_cb_data;
return true;
}
void ts_dvbpsi_DetachRawDecoder( dvbpsi_t *p_dvbpsi )
{
if( dvbpsi_decoder_present( p_dvbpsi ) )
dvbpsi_decoder_delete( p_dvbpsi->p_decoder );
p_dvbpsi->p_decoder = NULL;
}