Commit 4f3cfef2 authored by Jean-Paul Saman's avatar Jean-Paul Saman

ATSC tables: do not include stdint.h twice.

The stdint.h header file was included twice.
parent 387b7cf5
/*
Copyright (C) 2006 Adam Charrett
Copyright (C) 2006-2012 Adam Charrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -24,33 +24,44 @@ Decode PSIP Virtual Channel Table.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
#include "../descriptor.h"
#include "../demux.h"
#include "dvbpsi.h"
#include "dvbpsi_private.h"
#include "psi.h"
#include "descriptor.h"
#include "demux.h"
#include "atsc_eit.h"
typedef struct dvbpsi_atsc_eit_decoder_s
{
dvbpsi_atsc_eit_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_atsc_eit_t current_eit;
dvbpsi_atsc_eit_t * p_building_eit;
dvbpsi_atsc_eit_callback pf_eit_callback;
void * p_cb_data;
int b_current_valid;
dvbpsi_atsc_eit_t current_eit;
dvbpsi_atsc_eit_t * p_building_eit;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
bool b_current_valid;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_atsc_eit_decoder_t;
dvbpsi_atsc_eit_event_t *dvbpsi_atsc_EITAddEvent(dvbpsi_atsc_eit_t* p_eit,
static dvbpsi_atsc_eit_event_t *dvbpsi_atsc_EITAddEvent(dvbpsi_atsc_eit_t* p_eit,
uint16_t i_event_id,
uint32_t i_start_time,
uint8_t i_etm_location,
......@@ -58,16 +69,15 @@ dvbpsi_atsc_eit_event_t *dvbpsi_atsc_EITAddEvent(dvbpsi_atsc_eit_t* p_eit,
uint8_t i_title_length,
uint8_t *p_title);
dvbpsi_descriptor_t *dvbpsi_atsc_EITEventAddDescriptor(
static dvbpsi_descriptor_t *dvbpsi_atsc_EITChannelAddDescriptor(
dvbpsi_atsc_eit_event_t *p_table,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
void dvbpsi_atsc_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
void * p_private_decoder,
dvbpsi_psi_section_t * p_section);
static void dvbpsi_atsc_GatherEITSections(dvbpsi_t* p_dvbpsi,
void* p_private_decoder, dvbpsi_psi_section_t* p_section);
void dvbpsi_atsc_DecodeEITSections(dvbpsi_atsc_eit_t* p_eit,
static void dvbpsi_atsc_DecodeEITSections(dvbpsi_atsc_eit_t* p_eit,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
......@@ -75,55 +85,55 @@ void dvbpsi_atsc_DecodeEITSections(dvbpsi_atsc_eit_t* p_eit,
*****************************************************************************
* Initialize a EIT subtable decoder.
*****************************************************************************/
int dvbpsi_atsc_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_atsc_eit_callback pf_callback, void* p_cb_data)
bool dvbpsi_atsc_AttachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_atsc_eit_callback pf_callback, void* p_cb_data)
{
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_atsc_eit_decoder_t* p_eit_decoder;
unsigned int i;
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
DVBPSI_ERROR_ARG("EIT decoder",
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_atsc_eit_decoder_t* p_eit_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(p_dvbpsi, "ATSC EIT decoder",
"Already a decoder for (table_id == 0x%02x extension == 0x%04x)",
i_table_id, i_extension);
return 1;
}
return false;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
{
return 1;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if (p_subdec == NULL)
return false;
p_eit_decoder = (dvbpsi_atsc_eit_decoder_t*)malloc(sizeof(dvbpsi_atsc_eit_decoder_t));
if(p_eit_decoder == NULL)
{
free(p_subdec);
return 1;
}
p_eit_decoder = (dvbpsi_atsc_eit_decoder_t*)malloc(sizeof(dvbpsi_atsc_eit_decoder_t));
if (p_eit_decoder == NULL)
{
free(p_subdec);
return false;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherEITSections;
p_subdec->p_cb_data = p_eit_decoder;
p_subdec->i_id = ((uint32_t)i_table_id << 16) | i_extension;
p_subdec->pf_detach = dvbpsi_atsc_DetachEIT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* EIT decoder information */
p_eit_decoder->pf_eit_callback = pf_callback;
p_eit_decoder->p_cb_data = p_cb_data;
/* EIT decoder initial state */
p_eit_decoder->b_current_valid = false;
p_eit_decoder->p_building_eit = NULL;
for (int i = 0; i < 256; i++)
p_eit_decoder->ap_sections[i] = NULL;
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherEITSections;
p_subdec->p_cb_data = p_eit_decoder;
p_subdec->i_id = ((uint32_t)i_table_id << 16) | i_extension;
p_subdec->pf_detach = dvbpsi_atsc_DetachEIT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* EIT decoder information */
p_eit_decoder->pf_callback = pf_callback;
p_eit_decoder->p_cb_data = p_cb_data;
/* EIT decoder initial state */
p_eit_decoder->b_current_valid = 0;
p_eit_decoder->p_building_eit = NULL;
for(i = 0; i <= 255; i++)
p_eit_decoder->ap_sections[i] = NULL;
return 0;
return true;
}
/*****************************************************************************
......@@ -131,43 +141,47 @@ int dvbpsi_atsc_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
*****************************************************************************
* Close a EIT decoder.
*****************************************************************************/
void dvbpsi_atsc_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_t i_extension)
void dvbpsi_atsc_DetachEIT(dvbpsi_t * p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_atsc_eit_decoder_t* p_eit_decoder;
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_subdec == NULL)
{
DVBPSI_ERROR_ARG("EIT Decoder",
"No such EIT decoder (table_id == 0x%02x,"
"extension == 0x%04x)",
i_table_id, i_extension);
return;
}
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;
p_eit_decoder = (dvbpsi_atsc_eit_decoder_t*)p_subdec->p_cb_data;
if (!p_eit_decoder)
return;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if (p_subdec == NULL)
{
dvbpsi_error(p_dvbpsi, "ATSC EIT Decoder",
"No such EIT decoder (table_id == 0x%02x,"
"extension == 0x%04x)",
i_table_id, i_extension);
return;
}
if (p_eit_decoder->p_building_eit)
free(p_eit_decoder->p_building_eit);
dvbpsi_atsc_eit_decoder_t* p_eit_decoder;
p_eit_decoder = (dvbpsi_atsc_eit_decoder_t*)p_subdec->p_cb_data;
if (!p_eit_decoder)
return;
for(unsigned int i = 0; i <= 255; i++)
{
if(p_eit_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
}
if (p_eit_decoder->p_building_eit)
free(p_eit_decoder->p_building_eit);
free(p_subdec->p_cb_data);
for (unsigned int i = 0; i < 256; i++)
{
if (p_eit_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
}
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_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);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
}
/*****************************************************************************
......@@ -175,14 +189,27 @@ void dvbpsi_atsc_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_
*****************************************************************************
* Initialize a pre-allocated dvbpsi_atsc_eit_t structure.
*****************************************************************************/
void dvbpsi_atsc_InitEIT(dvbpsi_atsc_eit_t* p_eit,uint8_t i_version, int b_current_next,
uint8_t i_protocol, uint16_t i_source_id)
void dvbpsi_atsc_InitEIT(dvbpsi_atsc_eit_t* p_eit, uint8_t i_version, uint8_t i_protocol,
uint16_t i_source_id, bool b_current_next)
{
p_eit->i_version = i_version;
p_eit->b_current_next = b_current_next;
p_eit->i_protocol = i_protocol;
p_eit->i_source_id = i_source_id;
p_eit->p_first_event = NULL;
assert(p_eit);
p_eit->i_version = i_version;
p_eit->b_current_next = b_current_next;
p_eit->i_protocol = i_protocol;
p_eit->i_source_id = i_source_id;
p_eit->p_first_event = NULL;
// FIXME: p_eit->p_first_descriptor = NULL;
}
dvbpsi_atsc_eit_t *dvbpsi_atsc_NewEIT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_source_id, bool b_current_next)
{
dvbpsi_atsc_eit_t *p_eit;
p_eit = (dvbpsi_atsc_eit_t*) malloc(sizeof(dvbpsi_atsc_eit_t));
if (p_eit != NULL)
dvbpsi_atsc_InitEIT(p_eit, i_version, b_current_next, i_protocol, i_source_id);
return p_eit;
}
/*****************************************************************************
......@@ -204,12 +231,20 @@ void dvbpsi_atsc_EmptyEIT(dvbpsi_atsc_eit_t* p_eit)
p_eit->p_first_event = NULL;
}
void dvbpsi_atsc_DeleteEIT(dvbpsi_atsc_eit_t *p_eit)
{
if (p_eit)
dvbpsi_atsc_EmptyEIT(p_eit);
free(p_eit);
p_eit = NULL;
}
/*****************************************************************************
* dvbpsi_atsc_EITAddChannel
*****************************************************************************
* Add a Channel description at the end of the EIT.
*****************************************************************************/
dvbpsi_atsc_eit_event_t *dvbpsi_atsc_EITAddEvent(dvbpsi_atsc_eit_t* p_eit,
static dvbpsi_atsc_eit_event_t *dvbpsi_atsc_EITAddEvent(dvbpsi_atsc_eit_t* p_eit,
uint16_t i_event_id,
uint32_t i_start_time,
uint8_t i_etm_location,
......@@ -253,7 +288,7 @@ dvbpsi_atsc_eit_event_t *dvbpsi_atsc_EITAddEvent(dvbpsi_atsc_eit_t* p_eit,
*****************************************************************************
* Add a descriptor in the EIT table description.
*****************************************************************************/
dvbpsi_descriptor_t *dvbpsi_atsc_EITChannelAddDescriptor(
static dvbpsi_descriptor_t *dvbpsi_atsc_EITChannelAddDescriptor(
dvbpsi_atsc_eit_event_t *p_event,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data)
......@@ -284,193 +319,196 @@ dvbpsi_descriptor_t *dvbpsi_atsc_EITChannelAddDescriptor(
*****************************************************************************
* Callback for the subtable demultiplexor.
*****************************************************************************/
void dvbpsi_atsc_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
void * p_private_decoder,
static void dvbpsi_atsc_GatherEITSections(dvbpsi_t * p_dvbpsi, void * p_private_decoder,
dvbpsi_psi_section_t * p_section)
{
dvbpsi_atsc_eit_decoder_t * p_eit_decoder
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_atsc_eit_decoder_t * p_eit_decoder
= (dvbpsi_atsc_eit_decoder_t*)p_private_decoder;
int b_append = 1;
int b_reinit = 0;
unsigned int i;
DVBPSI_DEBUG_ARG("EIT 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("EIT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
if (!p_eit_decoder)
{
dvbpsi_error(p_dvbpsi, "ATSC EIT decoder", "No decoder specified");
dvbpsi_DeletePSISections(p_section);
return;
}
/* Now if b_append is true then we have a valid EIT section */
if(b_append)
{
if (!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "ATSC EIT decoder",
"invalid section (section_syntax_indicator == 0)");
dvbpsi_DeletePSISections(p_section);
return;
}
dvbpsi_debug(p_dvbpsi,"ATSC EIT 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);
bool b_reinit = false;
/* We have a valid EIT section */
/* TS discontinuity check */
if(p_psi_decoder->b_discontinuity)
if (p_demux->b_discontinuity)
{
b_reinit = 1;
p_psi_decoder->b_discontinuity = 0;
b_reinit = true;
p_demux->b_discontinuity = true;
}
else
{
/* Perform a few sanity checks */
if(p_eit_decoder->p_building_eit)
{
if(p_eit_decoder->p_building_eit->i_source_id != p_section->i_extension)
/* Perform a few sanity checks */
if (p_eit_decoder->p_building_eit)
{
/* transport_stream_id */
DVBPSI_ERROR("EIT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
if (p_eit_decoder->p_building_eit->i_source_id != p_section->i_extension)
{
/* transport_stream_id */
dvbpsi_error(p_dvbpsi, "EIT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = true;
}
else if (p_eit_decoder->p_building_eit->i_version != p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "ATSC EIT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = true;
}
else if (p_eit_decoder->i_last_section_number != p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "ATSC EIT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = true;
}
}
else if(p_eit_decoder->p_building_eit->i_version
!= p_section->i_version)
else
{
/* version_number */
DVBPSI_ERROR("EIT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
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;
}
else if(p_eit_decoder->i_last_section_number !=
p_section->i_last_number)
}
/* Reinit the decoder if wanted */
if (b_reinit)
{
/* Force redecoding */
p_eit_decoder->b_current_valid = false;
/* Free structures */
if (p_eit_decoder->p_building_eit)
{
/* last_section_number */
DVBPSI_ERROR("EIT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
free(p_eit_decoder->p_building_eit);
p_eit_decoder->p_building_eit = NULL;
}
}
else
{
if( (p_eit_decoder->b_current_valid)
&& (p_eit_decoder->current_eit.i_version == p_section->i_version))
/* Clear the section array */
for (unsigned int i = 0; i <= 255; i++)
{
/* 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));
p_eit_decoder->current_eit.b_current_next = 1;
*p_eit = p_eit_decoder->current_eit;
p_eit_decoder->pf_callback(p_eit_decoder->p_cb_data, p_eit);
}
/* Don't decode since this version is already decoded */
b_append = 0;
if (p_eit_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
p_eit_decoder->ap_sections[i] = NULL;
}
}
}
}
}
/* Reinit the decoder if wanted */
if(b_reinit)
{
/* Force redecoding */
p_eit_decoder->b_current_valid = 0;
/* Free structures */
if(p_eit_decoder->p_building_eit)
{
free(p_eit_decoder->p_building_eit);
p_eit_decoder->p_building_eit = NULL;
}
/* Clear the section array */
for(i = 0; i <= 255; i++)
{
if(p_eit_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
p_eit_decoder->ap_sections[i] = NULL;
}
}
}
/* Append the section to the list if wanted */
if(b_append)
{
int b_complete;
/* Append the section to the list if wanted */
bool b_complete = false;
/* Initialize the structures if it's the first section received */
if(!p_eit_decoder->p_building_eit)
if (!p_eit_decoder->p_building_eit)
{
dvbpsi_atsc_NewEIT(p_eit_decoder->p_building_eit,
p_section->i_version,
p_section->b_current_next,
p_section->p_payload_start[0],
p_section->i_extension);
p_eit_decoder->i_last_section_number = p_section->i_last_number;
p_eit_decoder->p_building_eit = dvbpsi_atsc_NewEIT(
p_section->i_version,
p_section->p_payload_start[0],
p_section->i_extension,
p_section->b_current_next);
if (p_eit_decoder->p_building_eit)
p_eit_decoder->i_last_section_number = p_section->i_last_number;
else
dvbpsi_error(p_dvbpsi, "ATSC EIT decoder",
"failed decoding ATSC EIT section");
}
/* Fill the section array */
if(p_eit_decoder->ap_sections[p_section->i_number] != NULL)
if (p_eit_decoder->ap_sections[p_section->i_number] != NULL)
{
DVBPSI_DEBUG_ARG("EIT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[p_section->i_number]);
dvbpsi_debug(p_dvbpsi, "ATSC EIT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[p_section->i_number]);
}
p_eit_decoder->ap_sections[p_section->i_number] = p_section;
/* Check if we have all the sections */
b_complete = 0;
for(i = 0; i <= p_eit_decoder->i_last_section_number; i++)
b_complete = false;
for (unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
{
if(!p_eit_decoder->ap_sections[i])
break;
if (!p_eit_decoder->ap_sections[i])
break;
if(i == p_eit_decoder->i_last_section_number)
b_complete = 1;
if (i == p_eit_decoder->i_last_section_number)
b_complete = true;
}
if(b_complete)
if (b_complete)
{
/* Save the current information */
p_eit_decoder->current_eit = *p_eit_decoder->p_building_eit;
p_eit_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_eit_decoder->i_last_section_number)
{
for(i = 0; i <= p_eit_decoder->i_last_section_number - 1; i++)
p_eit_decoder->ap_sections[i]->p_next =
p_eit_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_atsc_DecodeEITSections(p_eit_decoder->p_building_eit,
p_eit_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[0]);
/* signal the new EIT */
p_eit_decoder->pf_callback(p_eit_decoder->p_cb_data,
p_eit_decoder->p_building_eit);
/* Reinitialize the structures */
p_eit_decoder->p_building_eit = NULL;
for(i = 0; i <= p_eit_decoder->i_last_section_number; i++)
p_eit_decoder->ap_sections[i] = NULL;
/* Save the current information */
p_eit_decoder->current_eit = *p_eit_decoder->p_building_eit;
p_eit_decoder->b_current_valid = true;
/* Chain the sections */
if (p_eit_decoder->i_last_section_number)
{
for (uint8_t i = 0; i <= p_eit_decoder->i_last_section_number - 1; i++)
p_eit_decoder->ap_sections[i]->p_next =
p_eit_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_atsc_DecodeEITSections(p_eit_decoder->p_building_eit,
p_eit_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[0]);
/* 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 */
p_eit_decoder->p_building_eit = NULL;
for (unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
p_eit_decoder->ap_sections[i] = NULL;
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_DecodeEITSection
*****************************************************************************
* EIT decoder.
*****************************************************************************/
void dvbpsi_atsc_DecodeEITSections(dvbpsi_atsc_eit_t* p_eit,
static void dvbpsi_atsc_DecodeEITSections(dvbpsi_atsc_eit_t* p_eit,
dvbpsi_psi_section_t* p_section)
{
uint8_t *p_byte, *p_end;
......@@ -511,10 +549,10 @@ void dvbpsi_atsc_DecodeEITSections(dvbpsi_atsc_eit_t* p_eit,
while(p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end - p_byte)
dvbpsi_atsc_EITChannelAddDescriptor(p_event, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
uint8_t i_len = p_byte[1];
if(i_len + 2 <= p_end - p_byte)
dvbpsi_atsc_EITChannelAddDescriptor(p_event, i_tag, i_len, p_byte + 2);
p_byte += 2 + i_len;
}
}
......
......@@ -71,7 +71,7 @@ typedef struct dvbpsi_atsc_eit_event_s
typedef struct dvbpsi_atsc_eit_s
{
uint8_t i_version; /*!< version_number */
int b_current_next; /*!< current_next_indicator */
bool b_current_next; /*!< current_next_indicator */
uint16_t i_source_id; /*!< Source id used to match against channels */
uint8_t i_protocol; /*!< PSIP Protocol version */
......@@ -93,33 +93,33 @@ typedef void (* dvbpsi_atsc_eit_callback)(void* p_cb_data, dvbpsi_atsc_eit_t* p_
* dvbpsi_atsc_AttachEIT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_AttachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
* \fn bool dvbpsi_atsc_AttachEIT(dvbpsi_t * p_dvbpsi, uint8_t i_table_id,
dvbpsi_atsc_eit_callback pf_callback, void* p_cb_data)
*
* \brief Creation and initialization of a EIT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached
* \param i_table_id Table ID, 0xCB.
* \param i_extension Table ID extension, here TS ID.
* \param pf_callback function to call back on new EIT.
* \param p_cb_data private data given in argument to the callback.
* \return 0 if everything went ok.
* \return true if everything went ok, false otherwise
*/
int dvbpsi_atsc_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
bool dvbpsi_atsc_AttachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_atsc_eit_callback pf_callback, void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachEIT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id)
*
* \fn void dvbpsi_atsc_DetachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id)
* \brief Destroy a EIT decoder.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param i_table_id Table ID, 0xCB.
* \param i_extension Table ID extension, here TS ID.
* \return nothing.
*/
void dvbpsi_atsc_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
void dvbpsi_atsc_DetachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension);
/*****************************************************************************
......@@ -131,35 +131,27 @@ void dvbpsi_atsc_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
* \brief Initialize a user-allocated dvbpsi_atsc_eit_t structure.
* \param p_eit pointer to the EIT structure
* \param i_version EIT version
* \param b_current_next current next indicator
* \param i_protocol PSIP Protocol version.
* \param i_source_id Source id.
* \param b_current_next current next indicator
* \return nothing.
*/
void dvbpsi_atsc_InitEIT(dvbpsi_atsc_eit_t* p_eit,uint8_t i_version, int b_current_next,
uint8_t i_protocol, uint16_t i_source_id);
void dvbpsi_atsc_InitEIT(dvbpsi_atsc_eit_t* p_eit, uint8_t i_version, uint8_t i_protocol,
uint16_t i_source_id, bool b_current_next);
/*!
* \def dvbpsi_atsc_NewEIT(p_eit, i_network_id, i_version, b_current_next,
i_protocol i_source_id)
* \fn dvbpsi_atsc_eit_t *dvbpsi_atsc_NewEIT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_source_id, bool b_current_next)
* \brief Allocate and initialize a new dvbpsi_eit_t structure. Use ObjectRefDec to delete it.
* \param p_eit pointer to the EIT structure
* \param i_network_id network id
* \param i_version EIT version
* \param b_current_next current next indicator
* \param i_protocol PSIP Protocol version.
* \param b_cable_eit Whether this is CEIT or a TEIT.
* \return nothing.
* \return p_eit pointer to the EIT structure or NULL on error
*/
#define dvbpsi_atsc_NewEIT(p_eit, i_version, b_current_next, i_protocol, \
i_source_id) \
do { \
p_eit = (dvbpsi_atsc_eit_t*)malloc(sizeof(dvbpsi_atsc_eit_t)); \
if(p_eit != NULL) \
dvbpsi_atsc_InitEIT(p_eit, i_version, b_current_next, i_protocol, \
i_source_id); \
} while(0);
dvbpsi_atsc_eit_t *dvbpsi_atsc_NewEIT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_source_id, bool b_current_next);
/*****************************************************************************
* dvbpsi_atsc_EmptyEIT
......@@ -173,16 +165,12 @@ do { \
void dvbpsi_atsc_EmptyEIT(dvbpsi_atsc_eit_t *p_eit);
/*!
* \def dvbpsi_atsc_DeleteEIT(p_eit)
* \fn void dvbpsi_atsc_DeleteEIT(dvbpsi_atsc_eit_t *p_eit)
* \brief Clean and free a dvbpsi_eit_t structure.
* \param p_vct pointer to the EIT structure
* \param p_eit pointer to the EIT structure
* \return nothing.
*/
#define dvbpsi_atsc_DeleteEIT(p_eit) \
do { \
dvbpsi_atsc_EmptyEIT(p_eit); \
free(p_eit); \
} while(0);
void dvbpsi_atsc_DeleteEIT(dvbpsi_atsc_eit_t *p_eit);
#ifdef __cplusplus
};
......
/*
Copyright (C) 2006 Adam Charrett
Copyright (C) 2006-2012 Adam Charrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -22,14 +22,23 @@ Decode PSIP Extended Text Table.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "dvbpsi.h"
#include "dvbpsi_private.h"
#include "psi.h"
#include "descriptor.h"
#include "demux.h"
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
#include "../descriptor.h"
#include "../demux.h"
#include "atsc_ett.h"
/*****************************************************************************
......@@ -51,9 +60,11 @@ typedef struct dvbpsi_atsc_ett_etm_version_s
*****************************************************************************/
typedef struct dvbpsi_atsc_ett_decoder_s
{
dvbpsi_atsc_ett_callback pf_callback;
void * p_cb_data;
dvbpsi_atsc_ett_etm_version_t * p_etm_versions;
DVBPSI_DECODER_COMMON
dvbpsi_atsc_ett_callback pf_ett_callback;
void * p_cb_data;
dvbpsi_atsc_ett_etm_version_t * p_etm_versions;
} dvbpsi_atsc_ett_decoder_t;
/*****************************************************************************
......@@ -61,15 +72,16 @@ typedef struct dvbpsi_atsc_ett_decoder_s
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_atsc_GatherETTSections(dvbpsi_decoder_t * p_psi_decoder,
static void dvbpsi_atsc_GatherETTSections(dvbpsi_t * p_dvbpsi,
void * p_private_decoder,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_atsc_DecodeETTSection
*****************************************************************************
* TDT decoder.
*****************************************************************************/
void dvbpsi_atsc_DecodeETTSection(dvbpsi_atsc_ett_t* p_ett,
static void dvbpsi_atsc_DecodeETTSection(dvbpsi_atsc_ett_t* p_ett,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
......@@ -77,50 +89,51 @@ void dvbpsi_atsc_DecodeETTSection(dvbpsi_atsc_ett_t* p_ett,
*****************************************************************************
* Initialize a ETT decoder and return a handle on it.
*****************************************************************************/
int dvbpsi_atsc_AttachETT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, uint16_t i_extension,
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)
{
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_atsc_ett_decoder_t* p_ett_decoder;
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
DVBPSI_ERROR_ARG("ETT decoder",
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_atsc_ett_decoder_t* p_ett_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 1;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
{
return 1;
}
p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*)malloc(sizeof(dvbpsi_atsc_ett_decoder_t));
if(p_ett_decoder == NULL)
{
free(p_subdec);
return 1;
}
return false;
}
/* PSI decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherETTSections;
p_subdec->p_cb_data = p_ett_decoder;
p_subdec->i_id = ((uint32_t)i_table_id << 16) | i_extension;
p_subdec->pf_detach = dvbpsi_atsc_DetachETT;
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
return false;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*)malloc(sizeof(dvbpsi_atsc_ett_decoder_t));
if(p_ett_decoder == NULL)
{
free(p_subdec);
return false;
}
/* ETT decoder information */
p_ett_decoder->pf_callback = pf_callback;
p_ett_decoder->p_cb_data = p_cb_data;
p_ett_decoder->p_etm_versions = NULL;
/* PSI decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherETTSections;
p_subdec->p_cb_data = p_ett_decoder;
p_subdec->i_id = ((uint32_t)i_table_id << 16) | i_extension;
p_subdec->pf_detach = dvbpsi_atsc_DetachETT;
return 0;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = 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_etm_versions = NULL;
return true;
}
/*****************************************************************************
......@@ -128,41 +141,45 @@ int dvbpsi_atsc_AttachETT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
*****************************************************************************
* Close a ETT decoder. The handle isn't valid any more.
*****************************************************************************/
void dvbpsi_atsc_DetachETT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_t i_extension)
void dvbpsi_atsc_DetachETT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_atsc_ett_decoder_t* p_ett_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_subdec == NULL)
{
DVBPSI_ERROR_ARG("ETT Decoder",
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
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;
}
return;
}
p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*)p_subdec->p_cb_data;
if(!p_ett_decoder)
return;
dvbpsi_atsc_ett_decoder_t* p_ett_decoder;
p_ett_decoder = (dvbpsi_atsc_ett_decoder_t*)p_subdec->p_cb_data;
if (!p_ett_decoder)
return;
dvbpsi_atsc_ett_etm_version_t *p_etm_version, *p_next;
for (p_etm_version = p_ett_decoder->p_etm_versions; p_etm_version; p_etm_version = p_next)
{
p_next = p_etm_version->p_next;
free(p_etm_version);
}
dvbpsi_atsc_ett_etm_version_t *p_etm_version, *p_next;
for (p_etm_version = p_ett_decoder->p_etm_versions; p_etm_version; p_etm_version = p_next)
{
p_next = p_etm_version->p_next;
free(p_etm_version);
}
free(p_subdec->p_cb_data);
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_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);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
}
/*****************************************************************************
......@@ -171,12 +188,14 @@ void dvbpsi_atsc_DetachETT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_
* Initialize a pre-allocated dvbpsi_ett_t structure.
*****************************************************************************/
void dvbpsi_atsc_InitETT(dvbpsi_atsc_ett_t *p_ett,
uint8_t i_version,
int b_current_next,
uint8_t i_protocol,
uint16_t i_ett_table_id,
uint32_t i_etm_id)
uint8_t i_version,
uint8_t i_protocol,
uint16_t i_ett_table_id,
uint32_t i_etm_id,
bool b_current_next)
{
assert(p_ett);
p_ett->i_version = i_version;
p_ett->b_current_next = b_current_next;
p_ett->i_protocol = i_protocol;
......@@ -184,6 +203,17 @@ void dvbpsi_atsc_InitETT(dvbpsi_atsc_ett_t *p_ett,
p_ett->i_etm_id = i_etm_id;
}
dvbpsi_atsc_ett_t *dvbpsi_atsc_NewETT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_ett_table_id, uint32_t i_etm_id, bool b_current_next)
{
dvbpsi_atsc_ett_t *p_ett;
p_ett = (dvbpsi_atsc_ett_t*)malloc(sizeof(dvbpsi_atsc_ett_t));
if (p_ett != NULL)
dvbpsi_atsc_InitETT(p_ett, i_version, b_current_next, i_protocol,
i_ett_table_id, i_etm_id);
return p_ett;
}
/*****************************************************************************
* dvbpsi_atsc_EmptyETT
*****************************************************************************
......@@ -199,67 +229,124 @@ void dvbpsi_atsc_EmptyETT(dvbpsi_atsc_ett_t *p_ett)
}
}
#ifndef TRUE
#define TRUE (1 == 1)
#endif /* TRUE */
#ifndef FALSE
#define FALSE (0 == 1)
#endif /* FALSE */
void dvbpsi_atsc_DeleteETT(dvbpsi_atsc_ett_t *p_ett)
{
if (p_ett)
dvbpsi_atsc_EmptyETT(p_ett);
free(p_ett);
p_ett = NULL;
}
/*****************************************************************************
* dvbpsi_atsc_GatherETTSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_atsc_GatherETTSections(dvbpsi_decoder_t* p_psi_decoder,
static void dvbpsi_atsc_GatherETTSections(dvbpsi_t* p_dvbpsi,
void * p_private_decoder,
dvbpsi_psi_section_t* p_section)
{
dvbpsi_atsc_ett_decoder_t* p_ett_decoder
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
// FIXME: Gather*Sections needs updating
// dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_atsc_ett_decoder_t* p_ett_decoder
= (dvbpsi_atsc_ett_decoder_t*)p_private_decoder;
if(!p_ett_decoder)
return;
if (!p_ett_decoder)
{
dvbpsi_error(p_dvbpsi, "ATSC ETT decoder", "No decoder specified");
dvbpsi_DeletePSISections(p_section);
return;
}
if (!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "ATSC ETT decoder",
"invalid section (section_syntax_indicator == 0)");
dvbpsi_DeletePSISections(p_section);
return;
}
if (p_section->i_table_id != 0xCC)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "ATSC ETT decoder",
"invalid table id (0x%x)", p_section->i_table_id);
dvbpsi_DeletePSISections(p_section);
return;
}
dvbpsi_debug(p_dvbpsi,"ATSC ETT 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 0
/* We have a valid ETT section */
/* TS discontinuity check */
if (p_demux->b_discontinuity)
{
b_reinit = true;
p_demux->b_discontinuity = true;
}
#endif
if(p_section->i_table_id == 0xCC)
{
dvbpsi_atsc_ett_t* p_ett;
dvbpsi_atsc_ett_etm_version_t *p_etm_version;
int b_found = FALSE;
bool b_found = false;
uint32_t i_etm_id = ((uint32_t)p_section->p_payload_start[1] << 24) |
((uint32_t)p_section->p_payload_start[2] << 16) |
((uint32_t)p_section->p_payload_start[3] << 8) |
((uint32_t)p_section->p_payload_start[4] << 0);
((uint32_t)p_section->p_payload_start[2] << 16) |
((uint32_t)p_section->p_payload_start[3] << 8) |
((uint32_t)p_section->p_payload_start[4] << 0);
for (p_etm_version = p_ett_decoder->p_etm_versions; p_etm_version; p_etm_version=p_etm_version->p_next)
for (p_etm_version = p_ett_decoder->p_etm_versions; p_etm_version;
p_etm_version = p_etm_version->p_next)
{
if (p_etm_version->i_etm_id == i_etm_id)
{
b_found = TRUE;
b_found = true;
break;
}
}
if (!b_found || (p_etm_version->i_version != p_section->i_version))
{
dvbpsi_atsc_NewETT(p_ett, p_section->i_version,
p_section->b_current_next,
p_section->p_payload_start[0],
p_section->i_extension,
i_etm_id
);
dvbpsi_atsc_DecodeETTSection(p_ett, p_section);
p_ett_decoder->pf_callback(p_ett_decoder->p_cb_data, p_ett);
p_ett = dvbpsi_atsc_NewETT(p_section->i_version,
p_section->p_payload_start[0],
p_section->i_extension,
i_etm_id,
p_section->b_current_next);
if (p_ett)
{
dvbpsi_atsc_DecodeETTSection(p_ett, p_section);
p_ett_decoder->pf_ett_callback(p_ett_decoder->p_cb_data, p_ett);
}
else
{
dvbpsi_error(p_dvbpsi, "ATSC ETT decoder", "Could not signal new ATSC ETT.");
dvbpsi_DeletePSISections(p_section);
return;
}
}
if (!b_found)
{
p_etm_version = malloc(sizeof(dvbpsi_atsc_ett_etm_version_t));
p_etm_version->i_etm_id = i_etm_id;
p_etm_version->p_next = p_ett_decoder->p_etm_versions;
p_ett_decoder->p_etm_versions = p_etm_version;
if (p_etm_version)
{
p_etm_version->i_etm_id = i_etm_id;
p_etm_version->p_next = p_ett_decoder->p_etm_versions;
p_ett_decoder->p_etm_versions = p_etm_version;
}
}
p_etm_version->i_version = p_section->i_version;
}
dvbpsi_DeletePSISections(p_section);
dvbpsi_DeletePSISections(p_section);
}
/*****************************************************************************
......@@ -267,7 +354,7 @@ void dvbpsi_atsc_GatherETTSections(dvbpsi_decoder_t* p_psi_decoder,
*****************************************************************************
* ETT decoder.
*****************************************************************************/
void dvbpsi_atsc_DecodeETTSection(dvbpsi_atsc_ett_t* p_ett,
static void dvbpsi_atsc_DecodeETTSection(dvbpsi_atsc_ett_t* p_ett,
dvbpsi_psi_section_t* p_section)
{
uint16_t i_etm_length = p_section->i_length - 14;
......
......@@ -43,7 +43,7 @@ extern "C" {
typedef struct dvbpsi_atsc_ett_s
{
uint8_t i_version; /*!< version_number */
int b_current_next; /*!< current_next_indicator */
bool b_current_next; /*!< current_next_indicator */
uint8_t i_protocol; /*!< PSIP Protocol version */
uint16_t i_ett_table_id; /*!< ETT Table ID extension, normally 0x0000 */
uint32_t i_etm_id; /*!< ETM Identifier, made up of source id and event id (or 0 for channel ETT) */
......@@ -65,31 +65,33 @@ typedef void (* dvbpsi_atsc_ett_callback)(void* p_cb_data, dvbpsi_atsc_ett_t* p_
* dvbpsi_atsc_AttachETT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_AttachETT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
dvbpsi_atsc_ett_callback pf_callback, void* p_cb_data)
* \fn 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)
*
* \brief Creation and initialization of a ETT decoder.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached
* \param i_table_id Table ID, 0xCC.
* \param i_extension Table ID extension, normally 0x0000.
* \param pf_callback function to call back on new ETT.
* \param p_cb_data private data given in argument to the callback.
* \return 0 if everything went ok.
* \return true if everything went ok, else it returns false.
*/
int dvbpsi_atsc_AttachETT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
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);
/*****************************************************************************
* dvbpsi_atsc_DetachETT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_DetachETT(dvbpsi_demux_t * p_demux, uint8_t i_table_id)
* \fn void dvbpsi_atsc_DetachETT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
*
* \brief Destroy a ETT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached
* \param i_table_id Table ID, 0xCD.
* \param i_extension Table ID extension, normally 0x0000.
* \return nothing.
*/
void dvbpsi_atsc_DetachETT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
void dvbpsi_atsc_DetachETT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension);
/*****************************************************************************
......@@ -97,34 +99,31 @@ void dvbpsi_atsc_DetachETT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_InitETT(dvbpsi_atsc_ett_t* p_ett, uint8_t i_version,
int b_current_next, uint8_t i_protocol)
uint8_t i_protocol, bool b_current_next)
* \brief Initialize a user-allocated dvbpsi_atsc_ett_t structure.
* \param p_ett pointer to the ETT structure
* \param i_version version
* \param b_current_next current next indicator
* \param i_protocol PSIP Protocol version.
* \param i_ett_table_id Table ID (Normally 0x0000)
* \param i_etm_id ETM Identifier.
* \param b_current_next current next indicator
* \return nothing.
*/
void dvbpsi_atsc_InitETT(dvbpsi_atsc_ett_t *p_ett, uint8_t i_version, int b_current_next,
uint8_t i_protocol, uint16_t i_ett_table_id, uint32_t i_etm_id);
void dvbpsi_atsc_InitETT(dvbpsi_atsc_ett_t *p_ett, uint8_t i_version, uint8_t i_protocol,
uint16_t i_ett_table_id, uint32_t i_etm_id, bool b_current_next);
/*!
* \def dvbpsi_NewETT(p_ett, i_network_id, i_version, b_current_next)
\ * \fn dvbpsi_atsc_ett_t *dvbpsi_atsc_NewETT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_ett_table_id, uint32_t i_etm_id, bool b_current_next)
* \brief Allocate and initialize a new dvbpsi_atsc_ett_t structure. Use ObjectRefDec to delete it.
* \param p_ett pointer to the ETT structure
* \param i_protocol PSIP Protocol version.
* \param i_ett_table_id Table ID (Normally 0x0000)
* \param i_etm_id ETM Identifier.
* \return nothing.
* \param b_current_next current next indicator
* \returns p_ett pointer to the ETT structure, NULL otherwise
*/
#define dvbpsi_atsc_NewETT(p_ett, i_version, b_current_next, i_protocol, i_ett_table_id, i_etm_id) \
do { \
p_ett = (dvbpsi_atsc_ett_t*)malloc(sizeof(dvbpsi_atsc_ett_t)); \
if(p_ett != NULL) \
dvbpsi_atsc_InitETT(p_ett, i_version, b_current_next, i_protocol, i_ett_table_id, i_etm_id); \
} while(0);
dvbpsi_atsc_ett_t *dvbpsi_atsc_NewETT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_ett_table_id, uint32_t i_etm_id, bool b_current_next);
/*****************************************************************************
* dvbpsi_atsc_EmptyETT/dvbpsi_atsc_DeleteETT
......@@ -138,16 +137,12 @@ do { \
void dvbpsi_atsc_EmptyETT(dvbpsi_atsc_ett_t *p_ett);
/*!
* \def dvbpsi_atsc_DeleteETT(p_ett)
* \fn void dvbpsi_atsc_DeleteETT(dvbpsi_atsc_ett_t *p_ett);
* \brief Clean and free a dvbpsi_atsc_ett_t structure.
* \param p_ett pointer to the ETT structure
* \return nothing.
*/
#define dvbpsi_atsc_DeleteETT(p_ett) \
do { \
dvbpsi_atsc_EmptyETT(p_ett); \
free(p_ett); \
} while(0);
void dvbpsi_atsc_DeleteETT(dvbpsi_atsc_ett_t *p_ett);
#ifdef __cplusplus
};
......
/*
Copyright (C) 2006 Adam Charrett
Copyright (C) 2011 Michael Krufky
Copyright (C) 2011-2012 Michael Krufky
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -25,52 +25,63 @@ Decode PSIP Master Guide Table.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
#include "../descriptor.h"
#include "../demux.h"
#include "dvbpsi.h"
#include "dvbpsi_private.h"
#include "psi.h"
#include "descriptor.h"
#include "demux.h"
#include "atsc_mgt.h"
typedef struct dvbpsi_atsc_mgt_decoder_s
{
dvbpsi_atsc_mgt_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_atsc_mgt_t current_mgt;
dvbpsi_atsc_mgt_t * p_building_mgt;
dvbpsi_atsc_mgt_callback pf_mgt_callback;
void * p_cb_data;
int b_current_valid;
dvbpsi_atsc_mgt_t current_mgt;
dvbpsi_atsc_mgt_t * p_building_mgt;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
bool b_current_valid;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_atsc_mgt_decoder_t;
dvbpsi_descriptor_t *dvbpsi_atsc_MGTAddDescriptor(
static dvbpsi_descriptor_t *dvbpsi_atsc_MGTAddDescriptor(
dvbpsi_atsc_mgt_t *p_mgt,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
dvbpsi_atsc_mgt_table_t *dvbpsi_atsc_MGTAddTable(dvbpsi_atsc_mgt_t* p_mgt,
static dvbpsi_atsc_mgt_table_t *dvbpsi_atsc_MGTAddTable(dvbpsi_atsc_mgt_t* p_mgt,
uint16_t i_table_type,
uint16_t i_table_type_pid,
uint8_t i_table_type_version,
uint32_t i_number_bytes);
dvbpsi_descriptor_t *dvbpsi_atsc_MGTTableAddDescriptor(
static dvbpsi_descriptor_t *dvbpsi_atsc_MGTTableAddDescriptor(
dvbpsi_atsc_mgt_table_t *p_table,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
void dvbpsi_atsc_GatherMGTSections(dvbpsi_decoder_t * p_psi_decoder,
static void dvbpsi_atsc_GatherMGTSections(dvbpsi_t * p_dvbpsi,
void * p_private_decoder,
dvbpsi_psi_section_t * p_section);
void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
static void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
......@@ -78,56 +89,55 @@ void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
*****************************************************************************
* Initialize a MGT subtable decoder.
*****************************************************************************/
int dvbpsi_atsc_AttachMGT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_atsc_mgt_callback pf_callback, void* p_cb_data)
bool dvbpsi_atsc_AttachMGT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_atsc_mgt_callback pf_callback, void* p_cb_data)
{
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_atsc_mgt_decoder_t* p_mgt_decoder;
unsigned int i;
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
DVBPSI_ERROR_ARG("MGT decoder",
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t *p_subdec;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder",
"Already a decoder for (table_id == 0x%02x extension == 0x%04x)",
i_table_id, i_extension);
return false;
}
return 1;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if (p_subdec == NULL)
return false;
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
{
return 1;
}
dvbpsi_atsc_mgt_decoder_t* p_mgt_decoder;
p_mgt_decoder = (dvbpsi_atsc_mgt_decoder_t*)malloc(sizeof(dvbpsi_atsc_mgt_decoder_t));
if(p_mgt_decoder == NULL)
{
free(p_subdec);
return false;
}
p_mgt_decoder = (dvbpsi_atsc_mgt_decoder_t*)malloc(sizeof(dvbpsi_atsc_mgt_decoder_t));
if(p_mgt_decoder == NULL)
{
free(p_subdec);
return 1;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherMGTSections;
p_subdec->p_cb_data = p_mgt_decoder;
p_subdec->i_id = ((uint32_t)i_table_id << 16) | i_extension;
p_subdec->pf_detach = dvbpsi_atsc_DetachMGT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* MGT decoder information */
p_mgt_decoder->pf_mgt_callback = pf_callback;
p_mgt_decoder->p_cb_data = p_cb_data;
/* MGT decoder initial state */
p_mgt_decoder->b_current_valid = false;
p_mgt_decoder->p_building_mgt = NULL;
for (unsigned int i = 0; i < 256; i++)
p_mgt_decoder->ap_sections[i] = NULL;
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherMGTSections;
p_subdec->p_cb_data = p_mgt_decoder;
p_subdec->i_id = ((uint32_t)i_table_id << 16) | i_extension;
p_subdec->pf_detach = dvbpsi_atsc_DetachMGT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* MGT decoder information */
p_mgt_decoder->pf_callback = pf_callback;
p_mgt_decoder->p_cb_data = p_cb_data;
/* MGT decoder initial state */
p_mgt_decoder->b_current_valid = 0;
p_mgt_decoder->p_building_mgt = NULL;
for(i = 0; i <= 255; i++)
p_mgt_decoder->ap_sections[i] = NULL;
return 0;
return true;
}
/*****************************************************************************
......@@ -135,47 +145,49 @@ int dvbpsi_atsc_AttachMGT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
*****************************************************************************
* Close a MGT decoder.
*****************************************************************************/
void dvbpsi_atsc_DetachMGT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_t i_extension)
void dvbpsi_atsc_DetachMGT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_atsc_mgt_decoder_t* p_mgt_decoder;
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
unsigned int i;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_subdec == NULL)
{
DVBPSI_ERROR_ARG("MGT Decoder",
"No such MGT decoder (table_id == 0x%02x,"
"extension == 0x%04x)",
i_table_id, i_extension);
return;
}
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if (p_subdec == NULL)
{
dvbpsi_error(p_dvbpsi, "ATSC MGT Decoder",
"No such MGT decoder (table_id == 0x%02x,"
"extension == 0x%04x)",
i_table_id, i_extension);
return;
}
p_mgt_decoder = (dvbpsi_atsc_mgt_decoder_t*)p_subdec->p_cb_data;
if(!p_mgt_decoder)
return;
dvbpsi_atsc_mgt_decoder_t* p_mgt_decoder;
p_mgt_decoder = (dvbpsi_atsc_mgt_decoder_t*)p_subdec->p_cb_data;
if(!p_mgt_decoder)
return;
if (p_mgt_decoder->p_building_mgt)
{
free(p_mgt_decoder->p_building_mgt);
}
if (p_mgt_decoder->p_building_mgt)
{
free(p_mgt_decoder->p_building_mgt);
}
for(i = 0; i <= 255; i++)
{
if(p_mgt_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[i]);
}
for (unsigned int i = 0; i < 256; i++)
{
if(p_mgt_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[i]);
}
free(p_subdec->p_cb_data);
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_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);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
}
/*****************************************************************************
......@@ -183,15 +195,28 @@ void dvbpsi_atsc_DetachMGT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_
*****************************************************************************
* Initialize a pre-allocated dvbpsi_atsc_mgt_t structure.
*****************************************************************************/
void dvbpsi_atsc_InitMGT(dvbpsi_atsc_mgt_t* p_mgt,uint8_t i_version, int b_current_next,
uint8_t i_protocol, uint16_t i_table_id_extension)
void dvbpsi_atsc_InitMGT(dvbpsi_atsc_mgt_t* p_mgt,uint8_t i_version,
uint8_t i_protocol, uint16_t i_table_id_extension, bool b_current_next)
{
p_mgt->i_version = i_version;
p_mgt->b_current_next = b_current_next;
p_mgt->i_protocol = i_protocol;
p_mgt->i_table_id_ext = i_table_id_extension;
p_mgt->p_first_table = NULL;
p_mgt->p_first_descriptor = NULL;
assert(p_mgt);
p_mgt->i_version = i_version;
p_mgt->b_current_next = b_current_next;
p_mgt->i_protocol = i_protocol;
p_mgt->i_table_id_ext = i_table_id_extension;
p_mgt->p_first_table = NULL;
p_mgt->p_first_descriptor = NULL;
}
dvbpsi_atsc_mgt_t *dvbpsi_atsc_NewMGT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_table_id_extension, bool b_current_next)
{
dvbpsi_atsc_mgt_t* p_mgt;
p_mgt = (dvbpsi_atsc_mgt_t*)malloc(sizeof(dvbpsi_atsc_mgt_t));
if (p_mgt != NULL)
dvbpsi_atsc_InitMGT(p_mgt, i_version, b_current_next, i_protocol,
i_table_id_extension);
return p_mgt;
}
/*****************************************************************************
......@@ -215,12 +240,20 @@ void dvbpsi_atsc_EmptyMGT(dvbpsi_atsc_mgt_t* p_mgt)
p_mgt->p_first_descriptor = NULL;
}
void dvbpsi_atsc_DeleteMGT(dvbpsi_atsc_mgt_t *p_mgt)
{
if (p_mgt)
dvbpsi_atsc_EmptyMGT(p_mgt);
free(p_mgt);
p_mgt = NULL;
}
/*****************************************************************************
* dvbpsi_atsc_MGTAddDescriptor
*****************************************************************************
* Add a descriptor to the MGT table.
*****************************************************************************/
dvbpsi_descriptor_t *dvbpsi_atsc_MGTAddDescriptor(
static dvbpsi_descriptor_t *dvbpsi_atsc_MGTAddDescriptor(
dvbpsi_atsc_mgt_t *p_mgt,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data)
......@@ -244,12 +277,13 @@ dvbpsi_descriptor_t *dvbpsi_atsc_MGTAddDescriptor(
return p_descriptor;
}
/*****************************************************************************
* dvbpsi_atsc_MGTAddTable
*****************************************************************************
* Add a Table description at the end of the MGT.
*****************************************************************************/
dvbpsi_atsc_mgt_table_t *dvbpsi_atsc_MGTAddTable(dvbpsi_atsc_mgt_t* p_mgt,
static dvbpsi_atsc_mgt_table_t *dvbpsi_atsc_MGTAddTable(dvbpsi_atsc_mgt_t* p_mgt,
uint16_t i_table_type,
uint16_t i_table_type_pid,
uint8_t i_table_type_version,
......@@ -288,7 +322,7 @@ dvbpsi_atsc_mgt_table_t *dvbpsi_atsc_MGTAddTable(dvbpsi_atsc_mgt_t* p_mgt,
*****************************************************************************
* Add a descriptor in the MGT table description.
*****************************************************************************/
dvbpsi_descriptor_t *dvbpsi_atsc_MGTTableAddDescriptor(
static dvbpsi_descriptor_t *dvbpsi_atsc_MGTTableAddDescriptor(
dvbpsi_atsc_mgt_table_t *p_table,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data)
......@@ -318,186 +352,193 @@ dvbpsi_descriptor_t *dvbpsi_atsc_MGTTableAddDescriptor(
*****************************************************************************
* Callback for the subtable demultiplexor.
*****************************************************************************/
void dvbpsi_atsc_GatherMGTSections(dvbpsi_decoder_t * p_psi_decoder,
static void dvbpsi_atsc_GatherMGTSections(dvbpsi_t * p_dvbpsi,
void * p_private_decoder,
dvbpsi_psi_section_t * p_section)
{
dvbpsi_atsc_mgt_decoder_t * p_mgt_decoder
= (dvbpsi_atsc_mgt_decoder_t*)p_private_decoder;
int b_append = 1;
int b_reinit = 0;
unsigned int i;
DVBPSI_DEBUG_ARG("MGT 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("MGT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
/* Now if b_append is true then we have a valid MGT section */
if(b_append)
{
dvbpsi_atsc_mgt_decoder_t * p_mgt_decoder
= (dvbpsi_atsc_mgt_decoder_t*)p_private_decoder;
if (!p_mgt_decoder)
{
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder", "No decoder specified");
dvbpsi_DeletePSISections(p_section);
return;
}
if(!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder",
"invalid section (section_syntax_indicator == 0)");
dvbpsi_DeletePSISections(p_section);
return;
}
dvbpsi_debug(p_dvbpsi, "ATSC MGT 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);
bool b_reinit = false;
/* We have a valid MGT section */
/* TS discontinuity check */
if(p_psi_decoder->b_discontinuity)
if (p_demux->b_discontinuity)
{
b_reinit = 1;
p_psi_decoder->b_discontinuity = 0;
b_reinit = true;
p_demux->b_discontinuity = false;
}
else
{
/* Perform a few sanity checks */
if(p_mgt_decoder->p_building_mgt)
{
if(p_mgt_decoder->p_building_mgt->i_table_id_ext != p_section->i_extension)
/* Perform a few sanity checks */
if(p_mgt_decoder->p_building_mgt)
{
/* transport_stream_id */
DVBPSI_ERROR("MGT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
if(p_mgt_decoder->p_building_mgt->i_table_id_ext != p_section->i_extension)
{
/* transport_stream_id */
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = true;
}
else if(p_mgt_decoder->p_building_mgt->i_version
!= p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = true;
}
else if(p_mgt_decoder->i_last_section_number !=
p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = true;
}
}
else if(p_mgt_decoder->p_building_mgt->i_version
!= p_section->i_version)
else
{
/* version_number */
DVBPSI_ERROR("MGT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
if ((p_mgt_decoder->b_current_valid) &&
(p_mgt_decoder->current_mgt.i_version == p_section->i_version))
{
/* Signal a new MGT if the previous one wasn't active */
if ((!p_mgt_decoder->current_mgt.b_current_next) &&
(p_section->b_current_next))
{
dvbpsi_atsc_mgt_t * p_mgt = (dvbpsi_atsc_mgt_t*)malloc(sizeof(dvbpsi_atsc_mgt_t));
if (p_mgt)
{
p_mgt_decoder->current_mgt.b_current_next = true;
*p_mgt = p_mgt_decoder->current_mgt;
p_mgt_decoder->pf_mgt_callback(p_mgt_decoder->p_cb_data, p_mgt);
}
else
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder", "Could not signal new ATSC MGT.");
}
}
dvbpsi_DeletePSISections(p_section);
return;
}
else if(p_mgt_decoder->i_last_section_number !=
p_section->i_last_number)
}
/* Reinit the decoder if wanted */
if (b_reinit)
{
/* Force redecoding */
p_mgt_decoder->b_current_valid = false;
/* Free structures */
if(p_mgt_decoder->p_building_mgt)
{
/* last_section_number */
DVBPSI_ERROR("MGT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
free(p_mgt_decoder->p_building_mgt);
p_mgt_decoder->p_building_mgt = NULL;
}
}
else
{
if( (p_mgt_decoder->b_current_valid)
&& (p_mgt_decoder->current_mgt.i_version == p_section->i_version))
/* Clear the section array */
for (unsigned int i = 0; i < 256; i++)
{
/* Signal a new MGT if the previous one wasn't active */
if( (!p_mgt_decoder->current_mgt.b_current_next)
&& (p_section->b_current_next))
{
dvbpsi_atsc_mgt_t * p_mgt = (dvbpsi_atsc_mgt_t*)malloc(sizeof(dvbpsi_atsc_mgt_t));
p_mgt_decoder->current_mgt.b_current_next = 1;
*p_mgt = p_mgt_decoder->current_mgt;
p_mgt_decoder->pf_callback(p_mgt_decoder->p_cb_data, p_mgt);
}
/* Don't decode since this version is already decoded */
b_append = 0;
if(p_mgt_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[i]);
p_mgt_decoder->ap_sections[i] = NULL;
}
}
}
}
}
/* Reinit the decoder if wanted */
if(b_reinit)
{
/* Force redecoding */
p_mgt_decoder->b_current_valid = 0;
/* Free structures */
if(p_mgt_decoder->p_building_mgt)
{
free(p_mgt_decoder->p_building_mgt);
p_mgt_decoder->p_building_mgt = NULL;
}
/* Clear the section array */
for(i = 0; i <= 255; i++)
{
if(p_mgt_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[i]);
p_mgt_decoder->ap_sections[i] = NULL;
}
}
}
/* Append the section to the list if wanted */
if(b_append)
{
int b_complete;
/* Append the section to the list if wanted */
bool b_complete = false;
/* Initialize the structures if it's the first section received */
if(!p_mgt_decoder->p_building_mgt)
{
p_mgt_decoder->p_building_mgt =
(dvbpsi_atsc_mgt_t*)malloc(sizeof(dvbpsi_atsc_mgt_t));
dvbpsi_atsc_InitMGT(p_mgt_decoder->p_building_mgt,
p_section->i_version,
p_section->b_current_next,
p_section->p_payload_start[0],
p_section->i_extension);
p_mgt_decoder->i_last_section_number = p_section->i_last_number;
p_mgt_decoder->p_building_mgt =
(dvbpsi_atsc_mgt_t*)malloc(sizeof(dvbpsi_atsc_mgt_t));
if (p_mgt_decoder)
{
dvbpsi_atsc_InitMGT(p_mgt_decoder->p_building_mgt,
p_section->i_version,
p_section->p_payload_start[0],
p_section->i_extension,
p_section->b_current_next);
p_mgt_decoder->i_last_section_number = p_section->i_last_number;
}
else
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder", "failed decoding ATSC MGT section");
}
/* Fill the section array */
if(p_mgt_decoder->ap_sections[p_section->i_number] != NULL)
{
DVBPSI_DEBUG_ARG("MGT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[p_section->i_number]);
dvbpsi_error(p_dvbpsi, "ATSC MGT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[p_section->i_number]);
}
p_mgt_decoder->ap_sections[p_section->i_number] = p_section;
/* Check if we have all the sections */
b_complete = 0;
for(i = 0; i <= p_mgt_decoder->i_last_section_number; i++)
b_complete = false;
for (uint8_t i = 0; i <= p_mgt_decoder->i_last_section_number; i++)
{
if(!p_mgt_decoder->ap_sections[i])
break;
if (!p_mgt_decoder->ap_sections[i])
break;
if(i == p_mgt_decoder->i_last_section_number)
b_complete = 1;
if (i == p_mgt_decoder->i_last_section_number)
b_complete = true;
}
if(b_complete)
if (b_complete)
{
/* Save the current information */
p_mgt_decoder->current_mgt = *p_mgt_decoder->p_building_mgt;
p_mgt_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_mgt_decoder->i_last_section_number)
{
for(i = 0; i <= p_mgt_decoder->i_last_section_number - 1; i++)
p_mgt_decoder->ap_sections[i]->p_next =
p_mgt_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_atsc_DecodeMGTSections(p_mgt_decoder->p_building_mgt,
p_mgt_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[0]);
/* signal the new MGT */
p_mgt_decoder->pf_callback(p_mgt_decoder->p_cb_data,
p_mgt_decoder->p_building_mgt);
/* Reinitialize the structures */
p_mgt_decoder->p_building_mgt = NULL;
for(i = 0; i <= p_mgt_decoder->i_last_section_number; i++)
p_mgt_decoder->ap_sections[i] = NULL;
/* Save the current information */
p_mgt_decoder->current_mgt = *p_mgt_decoder->p_building_mgt;
p_mgt_decoder->b_current_valid = true;
/* Chain the sections */
if(p_mgt_decoder->i_last_section_number)
{
for (uint8_t i = 0; i <= p_mgt_decoder->i_last_section_number - 1; i++)
p_mgt_decoder->ap_sections[i]->p_next =
p_mgt_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_atsc_DecodeMGTSections(p_mgt_decoder->p_building_mgt,
p_mgt_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_mgt_decoder->ap_sections[0]);
/* signal the new MGT */
p_mgt_decoder->pf_mgt_callback(p_mgt_decoder->p_cb_data,
p_mgt_decoder->p_building_mgt);
/* Reinitialize the structures */
p_mgt_decoder->p_building_mgt = NULL;
for (uint8_t i = 0; i <= p_mgt_decoder->i_last_section_number; i++)
p_mgt_decoder->ap_sections[i] = NULL;
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
......@@ -505,8 +546,8 @@ void dvbpsi_atsc_GatherMGTSections(dvbpsi_decoder_t * p_psi_decoder,
*****************************************************************************
* MGT decoder.
*****************************************************************************/
void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
dvbpsi_psi_section_t* p_section)
static void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
dvbpsi_psi_section_t* p_section)
{
uint8_t *p_byte, *p_end;
......@@ -547,10 +588,10 @@ void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
while(p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end - p_byte)
dvbpsi_atsc_MGTTableAddDescriptor(p_table, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
uint8_t i_len = p_byte[1];
if(i_len + 2 <= p_end - p_byte)
dvbpsi_atsc_MGTTableAddDescriptor(p_table, i_tag, i_len, p_byte + 2);
p_byte += 2 + i_len;
}
}
......@@ -562,10 +603,10 @@ void dvbpsi_atsc_DecodeMGTSections(dvbpsi_atsc_mgt_t* p_mgt,
while(p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
uint8_t i_len = p_byte[1];
if(i_length + 2 <= p_end - p_byte)
dvbpsi_atsc_MGTAddDescriptor(p_mgt, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
dvbpsi_atsc_MGTAddDescriptor(p_mgt, i_tag, i_len, p_byte + 2);
p_byte += 2 + i_len;
}
p_section = p_section->p_next;
}
......
/*
Copyright (C) 2006 Adam Charrett
Copyright (C) 2011 Michael Krufky
Copyright (C) 2011-2012 Michael Krufky
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -69,7 +69,7 @@ typedef struct dvbpsi_atsc_mgt_table_s
typedef struct dvbpsi_atsc_mgt_s
{
uint8_t i_version; /*!< version_number */
int b_current_next; /*!< current_next_indicator */
bool b_current_next; /*!< current_next_indicator */
uint16_t i_table_id_ext; /*!< 0x0000 */
uint8_t i_protocol; /*!< PSIP Protocol version */
......@@ -96,66 +96,58 @@ typedef void (* dvbpsi_atsc_mgt_callback)(void* p_cb_data, dvbpsi_atsc_mgt_t* p_
dvbpsi_atsc_mgt_callback pf_callback, void* p_cb_data)
*
* \brief Creation and initialization of a MGT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached
* \param i_table_id Table ID, 0xC7.
* \param i_extension Table ID extension, here 0x0000.
* \param pf_callback function to call back on new MGT.
* \param p_cb_data private data given in argument to the callback.
* \return 0 if everything went ok.
* \return true if everything went ok, false otherwise
*/
int dvbpsi_atsc_AttachMGT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_atsc_mgt_callback pf_callback, void* p_cb_data);
bool dvbpsi_atsc_AttachMGT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_atsc_mgt_callback pf_callback, void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachMGT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_DetachMGT(dvbpsi_demux_t * p_demux, uint8_t i_table_id)
* \fn void dvbpsi_atsc_DetachMGT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
*
* \brief Destroy a MGT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached
* \param i_table_id Table ID, 0xC7.
* \param i_extension Table ID extension, here 0x0000.
* \return nothing.
*/
void dvbpsi_atsc_DetachMGT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension);
void dvbpsi_atsc_DetachMGT(dvbpsi_t * p_dvbpsi, uint8_t i_table_id, uint16_t i_extension);
/*****************************************************************************
* dvbpsi_atsc_InitMGT/dvbpsi_atsc_NewMGT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_InitMGT(dvbpsi_atsc_mgt_t* p_mgt, uint8_t i_version,
int b_current_next, uint8_t i_protocol)
* \fn void dvbpsi_atsc_InitMGT(dvbpsi_atsc_mgt_t* p_mgt,uint8_t i_version, uint8_t i_protocol,
uint16_t i_table_id_extension, bool b_current_next);
* \brief Initialize a user-allocated dvbpsi_atsc_mgt_t structure.
* \param p_mgt pointer to the MGT structure
* \param i_version MGT version
* \param b_current_next current next indicator
* \param i_protocol PSIP Protocol version.
* \param i_table_id_extension 0x0000.
* \param b_current_next current next indicator
* \return nothing.
*/
void dvbpsi_atsc_InitMGT(dvbpsi_atsc_mgt_t* p_mgt,uint8_t i_version, int b_current_next,
uint8_t i_protocol, uint16_t i_table_id_extension);
void dvbpsi_atsc_InitMGT(dvbpsi_atsc_mgt_t* p_mgt,uint8_t i_version, uint8_t i_protocol,
uint16_t i_table_id_extension, bool b_current_next);
/*!
* \def dvbpsi_atsc_NewMGT(p_mgt, i_network_id, i_version, b_current_next)
* \brief Allocate and initialize a new dvbpsi_mgt_t structure.
* \param p_mgt pointer to the MGT structure
* \param i_network_id network id
* \param i_version MGT version
* \param b_current_next current next indicator
* \param i_protocol PSIP Protocol version.
* \return nothing.
* \param b_current_next current next indicator
* \return p_mgt pointer to the MGT structure, or NULL on failure
*/
#define dvbpsi_atsc_NewMGT(p_mgt, i_version, b_current_next, i_protocol, \
i_table_id_extension) \
do { \
p_mgt = (dvbpsi_atsc_mgt_t*)malloc(sizeof(dvbpsi_atsc_mgt_t)); \
if(p_mgt != NULL) \
dvbpsi_atsc_InitMGT(p_mgt, i_version, b_current_next, i_protocol, \
i_table_id_extension); \
} while(0);
dvbpsi_atsc_mgt_t *dvbpsi_atsc_NewMGT(uint8_t i_version, uint8_t i_protocol,
uint16_t i_table_id_extension, bool b_current_next);
/*****************************************************************************
* dvbpsi_atsc_EmptyMGT/dvbpsi_atsc_DeleteMGT
......@@ -169,16 +161,12 @@ do { \
void dvbpsi_atsc_EmptyMGT(dvbpsi_atsc_mgt_t *p_mgt);
/*!
* \def dvbpsi_atsc_DeleteMGT(p_mgt)
* \fn void dvbpsi_atsc_DeleteMGT(dvbpsi_atsc_mgt_t *p_mgt);
* \brief Clean and free a dvbpsi_mgt_t structure.
* \param p_mgt pointer to the MGT structure
* \return nothing.
*/
#define dvbpsi_atsc_DeleteMGT(p_mgt) \
do { \
dvbpsi_atsc_EmptyMGT(p_mgt); \
free(p_mgt); \
} while(0);
void dvbpsi_atsc_DeleteMGT(dvbpsi_atsc_mgt_t *p_mgt);
#ifdef __cplusplus
};
......
/*
Copyright (C) 2006 Adam Charrett
Copyright (C) 2006-2012 Adam Charrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -24,20 +24,31 @@ Decode PSIP System Time Table.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
#include "../descriptor.h"
#include "../demux.h"
#include "dvbpsi.h"
#include "dvbpsi_private.h"
#include "psi.h"
#include "descriptor.h"
#include "demux.h"
#include "atsc_stt.h"
typedef struct dvbpsi_atsc_stt_decoder_s
{
dvbpsi_atsc_stt_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_atsc_stt_callback pf_stt_callback;
void * p_cb_data;
} dvbpsi_atsc_stt_decoder_t;
......@@ -46,62 +57,61 @@ dvbpsi_descriptor_t *dvbpsi_atsc_STTAddDescriptor(
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
void dvbpsi_atsc_GatherSTTSections(dvbpsi_decoder_t * p_psi_decoder,
void * p_private_decoder,
dvbpsi_psi_section_t * p_section);
static void dvbpsi_atsc_GatherSTTSections(dvbpsi_t* p_dvbpsi,
void* p_private_decoder, dvbpsi_psi_section_t* p_section);
void dvbpsi_atsc_DecodeSTTSections(dvbpsi_atsc_stt_t* p_stt,
dvbpsi_psi_section_t* p_section);
static void dvbpsi_atsc_DecodeSTTSections(dvbpsi_atsc_stt_t* p_stt,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_atsc_AttachSTT
*****************************************************************************
* Initialize a STT subtable decoder.
*****************************************************************************/
int dvbpsi_atsc_AttachSTT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
dvbpsi_atsc_stt_callback pf_callback, void* p_cb_data)
bool dvbpsi_atsc_AttachSTT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
dvbpsi_atsc_stt_callback pf_stt_callback, void* p_cb_data)
{
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_atsc_stt_decoder_t* p_stt_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0))
{
DVBPSI_ERROR_ARG("STT decoder",
"Already a decoder for (table_id == 0x%02x)",
i_table_id);
return 1;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
{
return 1;
}
p_stt_decoder = (dvbpsi_atsc_stt_decoder_t*)malloc(sizeof(dvbpsi_atsc_stt_decoder_t));
if(p_stt_decoder == NULL)
{
free(p_subdec);
return 1;
}
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_atsc_stt_decoder_t* p_stt_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0))
{
dvbpsi_error(p_dvbpsi, "STT decoder",
"Already a decoder for (table_id == 0x%02x)",
i_table_id);
return false;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
return false;
p_stt_decoder = (dvbpsi_atsc_stt_decoder_t*)malloc(sizeof(dvbpsi_atsc_stt_decoder_t));
if(p_stt_decoder == NULL)
{
free(p_subdec);
return false;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherSTTSections;
p_subdec->p_cb_data = p_stt_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16;
p_subdec->pf_detach = dvbpsi_atsc_DetachSTT;
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_atsc_GatherSTTSections;
p_subdec->p_cb_data = p_stt_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16;
p_subdec->pf_detach = dvbpsi_atsc_DetachSTT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* STT decoder information */
p_stt_decoder->pf_callback = pf_callback;
p_stt_decoder->p_cb_data = p_cb_data;
/* STT decoder information */
p_stt_decoder->pf_stt_callback = pf_stt_callback;
p_stt_decoder->p_cb_data = p_cb_data;
return 0;
return true;
}
/*****************************************************************************
......@@ -109,34 +119,38 @@ int dvbpsi_atsc_AttachSTT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
*****************************************************************************
* Close a STT decoder.
*****************************************************************************/
void dvbpsi_atsc_DetachSTT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_t i_extension)
void dvbpsi_atsc_DetachSTT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_atsc_stt_decoder_t* p_stt_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0);
if(p_subdec == NULL)
{
DVBPSI_ERROR_ARG("STT Decoder",
"No such STT decoder (table_id == 0x%02x,"
"extension == 0x00)",
i_table_id);
return;
}
p_stt_decoder = (dvbpsi_atsc_stt_decoder_t*)p_subdec->p_cb_data;
if(!p_stt_decoder)
return;
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);
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;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0);
if (p_subdec == NULL)
{
dvbpsi_error(p_dvbpsi, "STT Decoder",
"No such STT decoder (table_id == 0x%02x,"
"extension == 0x00)",
i_table_id);
return;
}
dvbpsi_atsc_stt_decoder_t* p_stt_decoder;
p_stt_decoder = (dvbpsi_atsc_stt_decoder_t*)p_subdec->p_cb_data;
if(!p_stt_decoder)
return;
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);
}
/*****************************************************************************
......@@ -144,10 +158,26 @@ void dvbpsi_atsc_DetachSTT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_
*****************************************************************************
* Initialize a pre-allocated dvbpsi_atsc_stt_t structure.
*****************************************************************************/
void dvbpsi_atsc_InitSTT(dvbpsi_atsc_stt_t *p_stt, uint8_t i_protocol)
void dvbpsi_atsc_InitSTT(dvbpsi_atsc_stt_t *p_stt, uint8_t i_version)
{
p_stt->i_protocol = i_protocol;
p_stt->p_first_descriptor = NULL;
assert(p_stt);
p_stt->i_version = i_version;
p_stt->p_first_descriptor = NULL;
}
/*****************************************************************************
* dvbpsi_atsc_NewSTT
*****************************************************************************
* Allocate and initialize a dvbpsi_atsc_stt_t structure.
*****************************************************************************/
dvbpsi_atsc_stt_t *dvbpsi_atsc_NewSTT(uint8_t i_version, bool b_current_next)
{
dvbpsi_atsc_stt_t *p_stt;
p_stt = (dvbpsi_atsc_stt_t*)malloc(sizeof(dvbpsi_atsc_stt_t));
if (p_stt != NULL)
dvbpsi_atsc_InitSTT(p_stt, i_version);
return p_stt;
}
/*****************************************************************************
......@@ -161,34 +191,46 @@ void dvbpsi_atsc_EmptySTT(dvbpsi_atsc_stt_t* p_stt)
p_stt->p_first_descriptor = NULL;
}
/*****************************************************************************
* dvbpsi_atsc_DeleteSTT
*****************************************************************************
* Empty and Delere a dvbpsi_atsc_stt_t structure.
*****************************************************************************/
void dvbpsi_atsc_DeleteSTT(dvbpsi_atsc_stt_t *p_stt)
{
if (p_stt)
dvbpsi_atsc_EmptySTT(p_stt);
free(p_stt);
p_stt = NULL;
}
/*****************************************************************************
* dvbpsi_atsc_STTAddDescriptor
*****************************************************************************
* Add a descriptor to the STT table.
*****************************************************************************/
dvbpsi_descriptor_t *dvbpsi_atsc_STTAddDescriptor(
dvbpsi_atsc_stt_t *p_stt,
dvbpsi_descriptor_t *dvbpsi_atsc_STTAddDescriptor( dvbpsi_atsc_stt_t *p_stt,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data)
{
dvbpsi_descriptor_t * p_descriptor
= dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if(p_descriptor)
{
if(p_stt->p_first_descriptor == NULL)
{
p_stt->p_first_descriptor = p_descriptor;
}
else
dvbpsi_descriptor_t * p_descriptor
= dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if(p_descriptor)
{
dvbpsi_descriptor_t * p_last_descriptor = p_stt->p_first_descriptor;
while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor;
if(p_stt->p_first_descriptor == NULL)
{
p_stt->p_first_descriptor = p_descriptor;
}
else
{
dvbpsi_descriptor_t * p_last_descriptor = p_stt->p_first_descriptor;
while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor;
}
}
}
return p_descriptor;
return p_descriptor;
}
/*****************************************************************************
......@@ -196,38 +238,50 @@ dvbpsi_descriptor_t *dvbpsi_atsc_STTAddDescriptor(
*****************************************************************************
* Callback for the subtable demultiplexor.
*****************************************************************************/
void dvbpsi_atsc_GatherSTTSections(dvbpsi_decoder_t * p_psi_decoder,
void * p_private_decoder,
static void dvbpsi_atsc_GatherSTTSections(dvbpsi_t *p_dvbpsi, void *p_private_decoder,
dvbpsi_psi_section_t * p_section)
{
dvbpsi_atsc_stt_decoder_t * p_stt_decoder
= (dvbpsi_atsc_stt_decoder_t*)p_private_decoder;
if(!p_stt_decoder)
return;
dvbpsi_atsc_stt_t *p_stt;
if(!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
DVBPSI_ERROR("STT decoder",
"invalid section (section_syntax_indicator == 0)");
}
else
{
dvbpsi_atsc_NewSTT(p_stt, p_section->p_payload_start[0]);
if (p_stt)
{
/* Decode the sections */
dvbpsi_atsc_DecodeSTTSections(p_stt, p_section);
/* Delete the sections */
dvbpsi_DeletePSISections(p_section);
/* signal the new STT */
p_stt_decoder->pf_callback(p_stt_decoder->p_cb_data,
p_stt);
}
}
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
dvbpsi_atsc_stt_decoder_t *p_stt_decoder =
(dvbpsi_atsc_stt_decoder_t*)p_private_decoder;
if (!p_stt_decoder)
{
dvbpsi_error(p_dvbpsi, "EIT decoder", "No decoder specified");
dvbpsi_DeletePSISections(p_section);
return;
}
if (!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "STT decoder",
"invalid section (section_syntax_indicator == 0)");
dvbpsi_DeletePSISections(p_section);
return;
}
/* FIXME: looks different then from other tables decoders */
dvbpsi_debug(p_dvbpsi, "STT 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);
dvbpsi_atsc_stt_t *p_stt;
p_stt = dvbpsi_atsc_NewSTT(p_section->i_version, p_section->b_current_next);
if (p_stt)
{
/* Decode the sections */
dvbpsi_atsc_DecodeSTTSections(p_stt, p_section);
/* Delete the sections */
dvbpsi_DeletePSISections(p_section);
/* signal the new STT */
p_stt_decoder->pf_stt_callback(p_stt_decoder->p_cb_data, p_stt);
}
}
/*****************************************************************************
......@@ -235,7 +289,7 @@ void dvbpsi_atsc_GatherSTTSections(dvbpsi_decoder_t * p_psi_decoder,
*****************************************************************************
* STT decoder.
*****************************************************************************/
void dvbpsi_atsc_DecodeSTTSections(dvbpsi_atsc_stt_t* p_stt,
static void dvbpsi_atsc_DecodeSTTSections(dvbpsi_atsc_stt_t* p_stt,
dvbpsi_psi_section_t* p_section)
{
uint8_t *p_byte, *p_end;
......@@ -257,9 +311,9 @@ void dvbpsi_atsc_DecodeSTTSections(dvbpsi_atsc_stt_t* p_stt,
while(p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end - p_byte)
dvbpsi_atsc_STTAddDescriptor(p_stt, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
uint8_t i_len = p_byte[1];
if (i_len + 2 <= p_end - p_byte)
dvbpsi_atsc_STTAddDescriptor(p_stt, i_tag, i_len, p_byte + 2);
p_byte += 2 + i_len;
}
}
/*
Copyright (C) 2006 Adam Charrett
Copyright (C) 2006-2012 Adam Charrett
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
......@@ -42,7 +42,7 @@ extern "C" {
*/
typedef struct dvbpsi_atsc_stt_s
{
uint8_t i_protocol; /*!< PSIP Protocol version */
uint8_t i_version; /*!< PSIP Protocol version */
uint32_t i_system_time; /*!< GPS seconds since 1 January 1980 00:00:00 UTC. */
uint8_t i_gps_utc_offset; /*!< Seconds offset between GPS and UTC time. */
......@@ -56,7 +56,7 @@ typedef struct dvbpsi_atsc_stt_s
*****************************************************************************/
/*!
* \typedef void (* dvbpsi_atsc_stt_callback)(void* p_cb_data,
dvbpsi_atsc_stt_t* p_new_stt)
dvbpsi_atsc_stt_t* p_new_stt)
* \brief Callback type definition.
*/
typedef void (* dvbpsi_atsc_stt_callback)(void* p_cb_data, dvbpsi_atsc_stt_t* p_new_stt);
......@@ -65,18 +65,18 @@ typedef void (* dvbpsi_atsc_stt_callback)(void* p_cb_data, dvbpsi_atsc_stt_t* p_
* dvbpsi_atsc_AttachSTT
*****************************************************************************/
/*!
* \fn void dvbpsi_atsc_AttachSTT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
dvbpsi_atsc_stt_callback pf_callback, void* p_cb_data)
* \fn bool dvbpsi_atsc_AttachSTT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
dvbpsi_atsc_stt_callback pf_stt_callback, void* p_cb_data);
*
* \brief Creation and initialization of a STT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached
* \param i_table_id Table ID, 0xCD.
* \param pf_callback function to call back on new STT.
* \param pf_stt_callback function to call back on new STT.
* \param p_cb_data private data given in argument to the callback.
* \return 0 if everything went ok.
* \return true if everything went ok else false
*/
int dvbpsi_atsc_AttachSTT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
dvbpsi_atsc_stt_callback pf_callback, void* p_cb_data);
bool dvbpsi_atsc_AttachSTT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
dvbpsi_atsc_stt_callback pf_stt_callback, void* p_cb_data);
/*****************************************************************************
* dvbpsi_atsc_DetachSTT
......@@ -85,13 +85,13 @@ int dvbpsi_atsc_AttachSTT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
* \fn void dvbpsi_atsc_DetachSTT(dvbpsi_demux_t * p_demux, uint8_t i_table_id)
*
* \brief Destroy a STT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached.
* \param i_table_id Table ID, 0xCD.
* \param i_extension Table extension, ignored as this should always be 0.
* (Required to match prototype for demux)
* \return nothing.
*/
void dvbpsi_atsc_DetachSTT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_t i_externsion);
void dvbpsi_atsc_DetachSTT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_externsion);
/*****************************************************************************
* dvbpsi_atsc_InitSTT/dvbpsi_atsc_NewSTT
......@@ -101,24 +101,21 @@ void dvbpsi_atsc_DetachSTT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, uint16_
int b_current_next, uint8_t i_protocol)
* \brief Initialize a user-allocated dvbpsi_atsc_stt_t structure.
* \param p_stt pointer to the STT structure
* \param i_protocol PSIP Protocol version.
* \param i_version PSIP Protocol version.
* \return nothing.
*/
void dvbpsi_atsc_InitSTT(dvbpsi_atsc_stt_t *p_stt,uint8_t i_protocol);
void dvbpsi_atsc_InitSTT(dvbpsi_atsc_stt_t *p_stt, uint8_t i_protocol);
/*!
* \def dvbpsi_NewSTT(p_stt, i_network_id, i_version, b_current_next)
* \fn dvbpsi_atsc_stt_t *dvbpsi_NewSTTT(uint8_t i_protocol, uint8_t i_version,
* bool b_current_next)
* \brief Allocate and initialize a new dvbpsi_atsc_stt_t structure. Use ObjectRefDec to delete it.
* \param p_stt pointer to the STT structure
* \param i_protocol PSIP Protocol version.
* \return nothing.
* \param i_version PSIP Protocol version.
* \param b_current_next current next indicator
* \return p_stt pointer to the STT structure
*/
#define dvbpsi_atsc_NewSTT(p_stt, i_protocol) \
do { \
p_stt = (dvbpsi_atsc_stt_t*)malloc(sizeof(dvbpsi_atsc_stt_t)); \
if(p_stt != NULL) \
dvbpsi_atsc_InitSTT(p_stt, i_protocol); \
} while(0);
dvbpsi_atsc_stt_t *dvbpsi_atsc_NewSTT(uint8_t i_version, bool b_current_next);
/*****************************************************************************
* dvbpsi_atsc_EmptySTT
......@@ -132,16 +129,12 @@ do { \
void dvbpsi_atsc_EmptySTT(dvbpsi_atsc_stt_t *p_stt);
/*!
* \def dvbpsi_atsc_DeleteSTT(p_vct)
* \brief Clean and free a dvbpsi_stt_t structure.
* \param p_vct pointer to the STT structure
* \fn dvbpsi_atsc_DeleteSTT(dvbpsi_atsc_stt_t *p_stt)
* \brief Clean and free a dvbpsi_atsc_stt_t structure.
* \param p_stt pointer to the STT structure
* \return nothing.
*/
#define dvbpsi_atsc_DeleteSTT(p_stt) \
do { \
dvbpsi_atsc_EmptySTT(p_stt); \
free(p_stt); \
} while(0);
void dvbpsi_atsc_DeleteSTT(dvbpsi_atsc_stt_t *p_stt);
#ifdef __cplusplus
};
......
......@@ -98,7 +98,7 @@ static void dvbpsi_atsc_DecodeVCTSections(dvbpsi_atsc_vct_t* p_vct,
* Initialize a VCT subtable decoder.
*****************************************************************************/
bool dvbpsi_atsc_AttachVCT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_atsc_vct_callback pf_callback, void* p_cb_data)
dvbpsi_atsc_vct_callback pf_vct_callback, void* p_cb_data)
{
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
......@@ -138,7 +138,7 @@ bool dvbpsi_atsc_AttachVCT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_ex
p_demux->p_first_subdec = p_subdec;
/* VCT decoder information */
p_vct_decoder->pf_vct_callback = pf_callback;
p_vct_decoder->pf_vct_callback = pf_vct_callback;
p_vct_decoder->p_cb_data = p_cb_data;
/* VCT decoder initial state */
p_vct_decoder->b_current_valid = false;
......
......@@ -113,12 +113,12 @@ typedef void (* dvbpsi_atsc_vct_callback)(void* p_cb_data, dvbpsi_atsc_vct_t* p_
* \param p_dvbpsi dvbpsi handle to Subtable demultiplexor to which the decoder is attached.
* \param i_table_id Table ID, 0xC8 or 0xC9.
* \param i_extension Table ID extension, here TS ID.
* \param pf_callback function to call back on new VCT.
* \param pf_vct_callback function to call back on new VCT.
* \param p_cb_data private data given in argument to the callback.
* \return true if everything went ok, else false.
*/
bool dvbpsi_atsc_AttachVCT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_atsc_vct_callback pf_callback,
uint16_t i_extension, dvbpsi_atsc_vct_callback pf_vct_callback,
void* p_cb_data);
/*****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment