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