Commit 19a31474 authored by Jean-Paul Saman's avatar Jean-Paul Saman

src/tables/*: Privatize dvbpsi_decoder_t in dvbpsi_t

All dvbpsi decoders now use dvbpsi_t as handle instead of
dvbpsi_decoder_t *. The pointer to dvbpsi_decoder_t is privatized
and accessible through (dvbpsi_t *)->p_private member. The user
must make sure to cast it to the correct dvbpsi_*_decoder_t type
before accessing structure members.

Dvbpsi decoder developers should use the define DVBPSI_DECODER_COMMON
at the start of a new dvbpsi_*_decoder_t.

WARNING: THIS COMMIT BREAKS THE EXISTING API IN A MAJOR WAY !!!

- most public APIs requires a pointer to existing dvbpsi_t
- new functions to obtain and delete a pointer to dvbpsi_t structure:
  dvbpsi_NewHandle() and dvbpsi_DeleteHandle()
- subtable descriptors fixes
- indentations
parent f6de3f79
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Johan Bilien <jobi@via.ecp.fr> * Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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,7 +25,6 @@ ...@@ -24,7 +25,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
#include <assert.h>
#include "dvbpsi.h" #include "dvbpsi.h"
#include "dvbpsi_private.h" #include "dvbpsi_private.h"
#include "psi.h" #include "psi.h"
...@@ -46,39 +48,33 @@ ...@@ -46,39 +48,33 @@
***************************************************************************** *****************************************************************************
* Creation of the demux structure * Creation of the demux structure
*****************************************************************************/ *****************************************************************************/
dvbpsi_handle dvbpsi_AttachDemux(dvbpsi_demux_new_cb_t pf_new_cb, dvbpsi_t *dvbpsi_AttachDemux(dvbpsi_t * p_dvbpsi,
void * p_new_cb_data) dvbpsi_demux_new_cb_t pf_new_cb,
void * p_new_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t)); assert(p_dvbpsi);
dvbpsi_demux_t * p_demux; assert(p_dvbpsi->p_private);
if(h_dvbpsi == NULL) dvbpsi_demux_t *p_demux = (dvbpsi_demux_t*)malloc(sizeof(dvbpsi_demux_t));
return NULL; if (p_demux == NULL)
return NULL;
p_demux = (dvbpsi_demux_t*)malloc(sizeof(dvbpsi_demux_t));
/* PSI decoder configuration */
if(p_demux == NULL) p_demux->pf_callback = &dvbpsi_Demux;
{ p_demux->i_section_max_size = 4096;
free(h_dvbpsi);
return NULL; /* PSI decoder initial state */
} p_demux->i_continuity_counter = 31;
p_demux->b_discontinuity = 1;
/* PSI decoder configuration */ p_demux->p_current_section = NULL;
h_dvbpsi->pf_callback = &dvbpsi_Demux;
h_dvbpsi->p_private_decoder = p_demux; /* Subtables demux configuration */
h_dvbpsi->i_section_max_size = 4096; p_demux->p_first_subdec = NULL;
/* PSI decoder initial state */ p_demux->pf_new_callback = pf_new_cb;
h_dvbpsi->i_continuity_counter = 31; p_demux->p_new_cb_data = p_new_cb_data;
h_dvbpsi->b_discontinuity = 1;
h_dvbpsi->p_current_section = NULL; p_dvbpsi->p_private = (void *)p_demux;
return p_dvbpsi;
/* Sutables demux configuration */
p_demux->p_decoder = h_dvbpsi;
p_demux->p_first_subdec = NULL;
p_demux->pf_new_callback = pf_new_cb;
p_demux->p_new_cb_data = p_new_cb_data;
return h_dvbpsi;
} }
/***************************************************************************** /*****************************************************************************
...@@ -90,18 +86,18 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux, ...@@ -90,18 +86,18 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux,
uint8_t i_table_id, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
{ {
uint32_t i_id = (uint32_t)i_table_id << 16 |(uint32_t)i_extension; uint32_t i_id = (uint32_t)i_table_id << 16 |(uint32_t)i_extension;
dvbpsi_demux_subdec_t * p_subdec = p_demux->p_first_subdec; dvbpsi_demux_subdec_t * p_subdec = p_demux->p_first_subdec;
while(p_subdec) while (p_subdec)
{ {
if(p_subdec->i_id == i_id) if (p_subdec->i_id == i_id)
break; break;
p_subdec = p_subdec->p_next; p_subdec = p_subdec->p_next;
} }
return p_subdec; return p_subdec;
} }
/***************************************************************************** /*****************************************************************************
...@@ -109,37 +105,35 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux, ...@@ -109,37 +105,35 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux,
***************************************************************************** *****************************************************************************
* Sends a PSI section to the right subtable decoder * Sends a PSI section to the right subtable decoder
*****************************************************************************/ *****************************************************************************/
void dvbpsi_Demux(dvbpsi_handle p_decoder, dvbpsi_psi_section_t * p_section) void dvbpsi_Demux(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section)
{ {
dvbpsi_demux_t * p_demux; assert(p_dvbpsi);
dvbpsi_demux_subdec_t * p_subdec; assert(p_dvbpsi->p_private);
p_demux = (dvbpsi_demux_t *)p_decoder->p_private_decoder; dvbpsi_demux_t * p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t * p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
p_section->i_extension);
p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
p_section->i_extension); if (p_subdec == NULL)
{
if(p_subdec == NULL) /* Tell the application we found a new subtable, so that it may attach a
{ * subtable decoder */
/* Tell the application we found a new subtable, so that it may attach a p_demux->pf_new_callback(p_demux->p_new_cb_data, (dvbpsi_decoder_t *)p_demux,
* subtable decoder */ p_section->i_table_id, p_section->i_extension);
p_demux->pf_new_callback(p_demux->p_new_cb_data, p_decoder,
p_section->i_table_id, /* Check if a new subtable decoder is available */
p_section->i_extension); p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
/* Check if a new subtable decoder is available */ p_section->i_extension);
p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id, }
p_section->i_extension);
} if (p_subdec)
{
if(p_subdec) p_subdec->pf_callback(p_dvbpsi, p_subdec->p_cb_data, p_section);
{ }
p_subdec->pf_callback(p_demux->p_decoder, p_subdec->p_cb_data, p_section); else
} {
else dvbpsi_DeletePSISections(p_section);
{ }
dvbpsi_DeletePSISections(p_section);
}
} }
/***************************************************************************** /*****************************************************************************
...@@ -147,26 +141,28 @@ void dvbpsi_Demux(dvbpsi_handle p_decoder, dvbpsi_psi_section_t * p_section) ...@@ -147,26 +141,28 @@ void dvbpsi_Demux(dvbpsi_handle p_decoder, dvbpsi_psi_section_t * p_section)
***************************************************************************** *****************************************************************************
* Destroys a demux structure * Destroys a demux structure
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachDemux(dvbpsi_handle h_dvbpsi) void dvbpsi_DetachDemux(dvbpsi_t *p_dvbpsi)
{ {
dvbpsi_demux_t* p_demux assert(p_dvbpsi);
= (dvbpsi_demux_t*)h_dvbpsi->p_private_decoder; assert(p_dvbpsi->p_private);
dvbpsi_demux_subdec_t* p_subdec
= p_demux->p_first_subdec; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec_temp; dvbpsi_demux_subdec_t* p_subdec = p_demux->p_first_subdec;
while(p_subdec) while (p_subdec)
{ {
p_subdec_temp = p_subdec; dvbpsi_demux_subdec_t* p_subdec_temp = p_subdec;
p_subdec = p_subdec->p_next; p_subdec = p_subdec->p_next;
if(p_subdec_temp->pf_detach)
p_subdec_temp->pf_detach(p_demux, (p_subdec_temp->i_id >> 16) & 0xFFFF, if (p_subdec_temp->pf_detach)
p_subdec_temp->i_id & 0xFFFF); p_subdec_temp->pf_detach(p_dvbpsi, (p_subdec_temp->i_id >> 16) & 0xFFFF,
else free(p_subdec_temp); p_subdec_temp->i_id & 0xFFFF);
} else free(p_subdec_temp);
}
free(p_demux);
if(h_dvbpsi->p_current_section) if (p_demux->p_current_section)
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); dvbpsi_DeletePSISections(p_demux->p_current_section);
free(h_dvbpsi);
p_dvbpsi->p_private = NULL;
free(p_demux);
} }
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Johan Bilien <jobi@via.ecp.fr> * Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -37,19 +38,18 @@ ...@@ -37,19 +38,18 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_demux_new_cb_t * dvbpsi_demux_new_cb_t
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \typedef void(* dvbpsi_demux_new_cb_t) (void * p_cb_data, * \typedef void(* dvbpsi_demux_new_cb_t) (void * p_cb_data,
dvbpsi_handle h_dvbpsi, dvbpsi_decoder_t *p_decoder,
uint8_t i_table_id, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
* \brief Callback used in case of a new subtable detected. * \brief Callback used in case of a new subtable detected.
*/ */
typedef void (*dvbpsi_demux_new_cb_t) (void * p_cb_data, typedef void (*dvbpsi_demux_new_cb_t) (void * p_cb_data,
dvbpsi_handle h_dvbpsi, dvbpsi_decoder_t *p_decoder,
uint8_t i_table_id, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
...@@ -58,15 +58,15 @@ typedef void (*dvbpsi_demux_new_cb_t) (void * p_cb_data, ...@@ -58,15 +58,15 @@ typedef void (*dvbpsi_demux_new_cb_t) (void * p_cb_data,
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \typedef void (*dvbpsi_demux_subdec_cb_t) * \typedef void (*dvbpsi_demux_subdec_cb_t)
(dvbpsi_decoder_t* p_psi_decoder, (dvbpsi_t *p_dvbpsi,
void* p_private_decoder, void *p_private_decoder,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t *p_section);
* \brief Subtable specific decoder. * \brief Subtable specific decoder.
*/ */
typedef void (*dvbpsi_demux_subdec_cb_t) typedef void (*dvbpsi_demux_subdec_cb_t)
(dvbpsi_decoder_t* p_psi_decoder, (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_demux_subdec_t * dvbpsi_demux_subdec_t
...@@ -90,12 +90,12 @@ typedef struct dvbpsi_demux_subdec_s ...@@ -90,12 +90,12 @@ typedef struct dvbpsi_demux_subdec_s
void * p_cb_data; void * p_cb_data;
struct dvbpsi_demux_subdec_s * p_next; struct dvbpsi_demux_subdec_s * p_next;
void (*pf_detach)(struct dvbpsi_demux_s *, uint8_t, uint16_t); void (*pf_detach)(dvbpsi_t *, uint8_t, uint16_t);
} dvbpsi_demux_subdec_t; } dvbpsi_demux_subdec_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_demux_t * dvbpsi_demux_s
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \struct dvbpsi_demux_s * \struct dvbpsi_demux_s
...@@ -108,41 +108,44 @@ typedef struct dvbpsi_demux_subdec_s ...@@ -108,41 +108,44 @@ typedef struct dvbpsi_demux_subdec_s
* \typedef struct dvbpsi_demux_s dvbpsi_demux_t * \typedef struct dvbpsi_demux_s dvbpsi_demux_t
* \brief dvbpsi_demux_t type definition. * \brief dvbpsi_demux_t type definition.
*/ */
typedef struct dvbpsi_demux_s typedef struct dvbpsi_demux_s dvbpsi_demux_t;
struct dvbpsi_demux_s
{ {
dvbpsi_handle p_decoder; /*!< Parent PSI Decoder */ DVBPSI_DECODER_COMMON
dvbpsi_demux_subdec_t * p_first_subdec; /*!< First subtable decoder */
/* New subtable callback */
dvbpsi_demux_new_cb_t pf_new_callback; /*!< New subtable callback */
void * p_new_cb_data; /*!< Data provided to the
previous callback */
} dvbpsi_demux_t; dvbpsi_demux_subdec_t * p_first_subdec; /*!< First subtable decoder */
/* New subtable callback */
dvbpsi_demux_new_cb_t pf_new_callback; /*!< New subtable callback */
void * p_new_cb_data; /*!< Data provided to the
previous callback */
};
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachDemux * dvbpsi_AttachDemux
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_handle_t dvbpsi_NewPSISection(dvbpsi_demux_new_cb_t pf_new_cb, void * p_new_cb_data) * \fn dvbpsi_t *dvbpsi_NewPSISection(dvbpsi_t *p_dvbpsi, dvbpsi_demux_new_cb_t pf_new_cb, void * p_new_cb_data)
* \brief Creates a new demux structure. * \brief Creates a new demux structure.
* \param p_dvbpsi pointer to dvbpsi_t handle
* \param pf_new_cb A callcack called when a new type of subtable is found. * \param pf_new_cb A callcack called when a new type of subtable is found.
* \param p_new_cb_data Data given to the previous callback. * \param p_new_cb_data Data given to the previous callback.
* \return a handle to the new demux structure. * \return a handle to the new attached demux structure.
*/ */
dvbpsi_handle dvbpsi_AttachDemux(dvbpsi_demux_new_cb_t pf_new_cb, dvbpsi_t *dvbpsi_AttachDemux(dvbpsi_t * p_dvbpsi,
void * p_new_cb_data); dvbpsi_demux_new_cb_t pf_new_cb,
void * p_new_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachDemux * dvbpsi_DetachDemux
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_DetachDemux(dvbpsi_handle h_dvbpsi) * \fn void dvbpsi_DetachDemux(dvbpsi_decoder_t *p_decoder)
* \brief Destroys a demux structure. * \brief Destroys a demux structure.
* \param h_dvbpsi The handle of the demux to be destroyed. * \param h_dvbpsi The handle of the demux to be destroyed.
*/ */
void dvbpsi_DetachDemux(dvbpsi_t *p_dvbpsi);
void dvbpsi_DetachDemux(dvbpsi_handle h_dvbpsi);
/***************************************************************************** /*****************************************************************************
* dvbpsi_demuxGetSubDec * dvbpsi_demuxGetSubDec
...@@ -163,14 +166,13 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux, ...@@ -163,14 +166,13 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux,
* dvbpsi_Demux * dvbpsi_Demux
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_Demux(dvbpsi_handle h_dvbpsi, * \fn void dvbpsi_Demux(dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t * p_section) dvbpsi_psi_section_t * p_section)
* \brief Sends the PSI sections to the right subtable decoder according to their table ID and extension. * \brief Sends the PSI sections to the right subtable decoder according to their table ID and extension.
* \param h_dvbpsi PSI decoder handle. * \param p_dvbpsi PSI decoder handle.
* \param p_section PSI section. * \param p_section PSI section.
*/ */
void dvbpsi_Demux(dvbpsi_handle h_dvbpsi, void dvbpsi_Demux(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section);
dvbpsi_psi_section_t * p_section);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -30,6 +31,7 @@ ...@@ -30,6 +31,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#if defined(HAVE_INTTYPES_H) #if defined(HAVE_INTTYPES_H)
#include <inttypes.h> #include <inttypes.h>
...@@ -37,6 +39,8 @@ ...@@ -37,6 +39,8 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
#include <assert.h>
#include "dvbpsi.h" #include "dvbpsi.h"
#include "dvbpsi_private.h" #include "dvbpsi_private.h"
#include "psi.h" #include "psi.h"
...@@ -137,13 +141,66 @@ uint32_t dvbpsi_crc32_table[256] = ...@@ -137,13 +141,66 @@ uint32_t dvbpsi_crc32_table[256] =
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
}; };
/*****************************************************************************
* dvbpsi_NewHandle
*****************************************************************************/
dvbpsi_t *dvbpsi_NewHandle(dvbpsi_message_cb callback, int level)
{
dvbpsi_t *handle = calloc(1, sizeof(dvbpsi_t));
if (handle != NULL)
{
handle->p_private = NULL;
handle->pf_message = callback;
handle->i_msg_level = level;
}
return handle;
}
/*****************************************************************************
* dvbpsi_DeleteHandle
*****************************************************************************/
void dvbpsi_DeleteHandle(dvbpsi_t *handle)
{
assert(handle->p_private != NULL);
handle->pf_message = NULL;
free(handle);
}
/*****************************************************************************
* dvbpsi_NewDecoder
*****************************************************************************/
dvbpsi_decoder_t *dvbpsi_NewDecoder(dvbpsi_t *handle, dvbpsi_callback *callback)
{
dvbpsi_decoder_t *p_decoder = calloc(1, sizeof(dvbpsi_decoder_t));
if (p_decoder == NULL)
return NULL;
p_decoder->pf_callback = NULL;
p_decoder->p_current_section = NULL;
return p_decoder;
}
/*****************************************************************************
* dvbpsi_DeletDecoder
*****************************************************************************/
void dvbpsi_DeleteDecoder(dvbpsi_t *handle)
{
assert(handle);
assert(handle->p_private);
dvbpsi_decoder_t *p_decoder = (dvbpsi_decoder_t *) handle->p_private;
handle->p_private = NULL;
free(p_decoder);
}
/***************************************************************************** /*****************************************************************************
* dvbpsi_PushPacket * dvbpsi_PushPacket
***************************************************************************** *****************************************************************************
* Injection of a TS packet into a PSI decoder. * Injection of a TS packet into a PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) void dvbpsi_PushPacket(dvbpsi_t *handle, uint8_t* p_data)
{ {
uint8_t i_expected_counter; /* Expected continuity counter */ uint8_t i_expected_counter; /* Expected continuity counter */
dvbpsi_psi_section_t* p_section; /* Current section */ dvbpsi_psi_section_t* p_section; /* Current section */
...@@ -154,38 +211,41 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -154,38 +211,41 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
int i_available; /* Byte count available in the int i_available; /* Byte count available in the
packet */ packet */
dvbpsi_decoder_t *p_decoder = (dvbpsi_decoder_t *)handle->p_private;
assert(p_decoder);
/* TS start code */ /* TS start code */
if(p_data[0] != 0x47) if(p_data[0] != 0x47)
{ {
dvbpsi_error(h_dvbpsi, "PSI decoder", "not a TS packet"); dvbpsi_error(handle, "PSI decoder", "not a TS packet");
return; return;
} }
/* Continuity check */ /* Continuity check */
i_expected_counter = (h_dvbpsi->i_continuity_counter + 1) & 0xf; i_expected_counter = (p_decoder->i_continuity_counter + 1) & 0xf;
h_dvbpsi->i_continuity_counter = p_data[3] & 0xf; p_decoder->i_continuity_counter = p_data[3] & 0xf;
if(i_expected_counter == ((h_dvbpsi->i_continuity_counter + 1) & 0xf) if(i_expected_counter == ((p_decoder->i_continuity_counter + 1) & 0xf)
&& !h_dvbpsi->b_discontinuity) && !p_decoder->b_discontinuity)
{ {
dvbpsi_error(h_dvbpsi, "PSI decoder", dvbpsi_error(handle, "PSI decoder",
"TS duplicate (received %d, expected %d) for PID %d", "TS duplicate (received %d, expected %d) for PID %d",
h_dvbpsi->i_continuity_counter, i_expected_counter, p_decoder->i_continuity_counter, i_expected_counter,
((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]); ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]);
return; return;
} }
if(i_expected_counter != h_dvbpsi->i_continuity_counter) if(i_expected_counter != p_decoder->i_continuity_counter)
{ {
dvbpsi_error(h_dvbpsi, "PSI decoder", dvbpsi_error(handle, "PSI decoder",
"TS discontinuity (received %d, expected %d) for PID %d", "TS discontinuity (received %d, expected %d) for PID %d",
h_dvbpsi->i_continuity_counter, i_expected_counter, p_decoder->i_continuity_counter, i_expected_counter,
((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]); ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]);
h_dvbpsi->b_discontinuity = 1; p_decoder->b_discontinuity = 1;
if(h_dvbpsi->p_current_section) if(p_decoder->p_current_section)
{ {
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); dvbpsi_DeletePSISections(p_decoder->p_current_section);
h_dvbpsi->p_current_section = NULL; p_decoder->p_current_section = NULL;
} }
} }
...@@ -208,7 +268,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -208,7 +268,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
p_payload_pos += 1; p_payload_pos += 1;
} }
p_section = h_dvbpsi->p_current_section; p_section = p_decoder->p_current_section;
/* If the psi decoder needs a begginning of section and a new section /* If the psi decoder needs a begginning of section and a new section
begins in the packet then initialize the dvbpsi_psi_section_t structure */ begins in the packet then initialize the dvbpsi_psi_section_t structure */
...@@ -217,16 +277,16 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -217,16 +277,16 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
if(p_new_pos) if(p_new_pos)
{ {
/* Allocation of the structure */ /* Allocation of the structure */
h_dvbpsi->p_current_section p_decoder->p_current_section
= p_section = p_section
= dvbpsi_NewPSISection(h_dvbpsi->i_section_max_size); = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
/* Update the position in the packet */ /* Update the position in the packet */
p_payload_pos = p_new_pos; p_payload_pos = p_new_pos;
/* New section is being handled */ /* New section is being handled */
p_new_pos = NULL; p_new_pos = NULL;
/* Just need the header to know how long is the section */ /* Just need the header to know how long is the section */
h_dvbpsi->i_need = 3; p_decoder->i_need = 3;
h_dvbpsi->b_complete_header = 0; p_decoder->b_complete_header = 0;
} }
else else
{ {
...@@ -240,40 +300,40 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -240,40 +300,40 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
while(i_available > 0) while(i_available > 0)
{ {
if(i_available >= h_dvbpsi->i_need) if(i_available >= p_decoder->i_need)
{ {
/* There are enough bytes in this packet to complete the /* There are enough bytes in this packet to complete the
header/section */ header/section */
memcpy(p_section->p_payload_end, p_payload_pos, h_dvbpsi->i_need); memcpy(p_section->p_payload_end, p_payload_pos, p_decoder->i_need);
p_payload_pos += h_dvbpsi->i_need; p_payload_pos += p_decoder->i_need;
p_section->p_payload_end += h_dvbpsi->i_need; p_section->p_payload_end += p_decoder->i_need;
i_available -= h_dvbpsi->i_need; i_available -= p_decoder->i_need;
if(!h_dvbpsi->b_complete_header) if(!p_decoder->b_complete_header)
{ {
/* Header is complete */ /* Header is complete */
h_dvbpsi->b_complete_header = 1; p_decoder->b_complete_header = 1;
/* Compute p_section->i_length and update h_dvbpsi->i_need */ /* Compute p_section->i_length and update p_decoder->i_need */
h_dvbpsi->i_need = p_section->i_length p_decoder->i_need = p_section->i_length
= ((uint16_t)(p_section->p_data[1] & 0xf)) << 8 = ((uint16_t)(p_section->p_data[1] & 0xf)) << 8
| p_section->p_data[2]; | p_section->p_data[2];
/* Check that the section isn't too long */ /* Check that the section isn't too long */
if(h_dvbpsi->i_need > h_dvbpsi->i_section_max_size - 3) if(p_decoder->i_need > p_decoder->i_section_max_size - 3)
{ {
dvbpsi_error(h_dvbpsi, "PSI decoder", "PSI section too long"); dvbpsi_error(handle, "PSI decoder", "PSI section too long");
dvbpsi_DeletePSISections(p_section); dvbpsi_DeletePSISections(p_section);
h_dvbpsi->p_current_section = NULL; p_decoder->p_current_section = NULL;
/* If there is a new section not being handled then go forward /* If there is a new section not being handled then go forward
in the packet */ in the packet */
if(p_new_pos) if(p_new_pos)
{ {
h_dvbpsi->p_current_section p_decoder->p_current_section
= p_section = p_section
= dvbpsi_NewPSISection(h_dvbpsi->i_section_max_size); = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
p_payload_pos = p_new_pos; p_payload_pos = p_new_pos;
p_new_pos = NULL; p_new_pos = NULL;
h_dvbpsi->i_need = 3; p_decoder->i_need = 3;
h_dvbpsi->b_complete_header = 0; p_decoder->b_complete_header = 0;
i_available = 188 + p_data - p_payload_pos; i_available = 188 + p_data - p_payload_pos;
} }
else else
...@@ -315,16 +375,16 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -315,16 +375,16 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
p_section->p_payload_start = p_section->p_data + 3; p_section->p_payload_start = p_section->p_data + 3;
} }
h_dvbpsi->pf_callback(h_dvbpsi, p_section); p_decoder->pf_callback(handle, p_section);
h_dvbpsi->p_current_section = NULL; p_decoder->p_current_section = NULL;
} }
else else
{ {
dvbpsi_error(h_dvbpsi, "misc PSI", "Bad CRC_32 !!!"); dvbpsi_error(handle, "misc PSI", "Bad CRC_32 !!!");
/* PSI section isn't valid => trash it */ /* PSI section isn't valid => trash it */
dvbpsi_DeletePSISections(p_section); dvbpsi_DeletePSISections(p_section);
h_dvbpsi->p_current_section = NULL; p_decoder->p_current_section = NULL;
} }
/* A TS packet may contain any number of sections, only the first /* A TS packet may contain any number of sections, only the first
...@@ -337,13 +397,13 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -337,13 +397,13 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
in the packet */ in the packet */
if(p_new_pos) if(p_new_pos)
{ {
h_dvbpsi->p_current_section p_decoder->p_current_section
= p_section = p_section
= dvbpsi_NewPSISection(h_dvbpsi->i_section_max_size); = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
p_payload_pos = p_new_pos; p_payload_pos = p_new_pos;
p_new_pos = NULL; p_new_pos = NULL;
h_dvbpsi->i_need = 3; p_decoder->i_need = 3;
h_dvbpsi->b_complete_header = 0; p_decoder->b_complete_header = 0;
i_available = 188 + p_data - p_payload_pos; i_available = 188 + p_data - p_payload_pos;
} }
else else
...@@ -358,7 +418,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -358,7 +418,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
header/section */ header/section */
memcpy(p_section->p_payload_end, p_payload_pos, i_available); memcpy(p_section->p_payload_end, p_payload_pos, i_available);
p_section->p_payload_end += i_available; p_section->p_payload_end += i_available;
h_dvbpsi->i_need -= i_available; p_decoder->i_need -= i_available;
i_available = 0; i_available = 0;
} }
} }
...@@ -375,7 +435,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data) ...@@ -375,7 +435,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
#define DVBPSI_MSG_FORMAT "libdvbpsi (%s): " #define DVBPSI_MSG_FORMAT "libdvbpsi (%s): "
#ifdef HAVE_VARIADIC_MACROS #ifdef HAVE_VARIADIC_MACROS
void message(dvbpsi_handle dvbpsi, const int level, const char *fmt, ...) void message(dvbpsi_t *dvbpsi, const int level, const char *fmt, ...)
{ {
if ((dvbpsi->i_msg_level > DVBPSI_MSG_NONE) && if ((dvbpsi->i_msg_level > DVBPSI_MSG_NONE) &&
(level <= dvbpsi->i_msg_level)) (level <= dvbpsi->i_msg_level))
...@@ -400,7 +460,7 @@ void message(dvbpsi_handle dvbpsi, const int level, const char *fmt, ...) ...@@ -400,7 +460,7 @@ void message(dvbpsi_handle dvbpsi, const int level, const char *fmt, ...)
} }
} }
#else #else
void dvbpsi_error(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...) void dvbpsi_error(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...)
{ {
if (DVBPSI_MSG_ERROR <= dvbpsi->i_msg_level) if (DVBPSI_MSG_ERROR <= dvbpsi->i_msg_level)
{ {
...@@ -430,7 +490,7 @@ void dvbpsi_error(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...) ...@@ -430,7 +490,7 @@ void dvbpsi_error(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...)
} }
} }
void dvbpsi_warning(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...) void dvbpsi_warning(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...)
{ {
if (DVBPSI_MSG_WARNING <= dvbpsi->i_msg_level) if (DVBPSI_MSG_WARNING <= dvbpsi->i_msg_level)
{ {
...@@ -460,7 +520,7 @@ void dvbpsi_warning(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...) ...@@ -460,7 +520,7 @@ void dvbpsi_warning(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...)
} }
} }
void dvbpsi_debug(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...) void dvbpsi_debug(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...)
{ {
if (DVBPSI_MSG_DEBUG <= dvbpsi->i_msg_level) if (DVBPSI_MSG_DEBUG <= dvbpsi->i_msg_level)
{ {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* $Id$ * $Id$
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -40,16 +41,82 @@ ...@@ -40,16 +41,82 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_handle * dvbpsi_handle
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \typedef struct dvbpsi_decoder_s * dvbpsi_handle * \typedef struct dvbpsi_s dvbpsi_t
* \brief Decoder abstration. * \brief DVBPSI handle structure abstration.
*/ */
typedef struct dvbpsi_decoder_s * dvbpsi_handle; typedef struct dvbpsi_s dvbpsi_t;
/*****************************************************************************
* dvbpsi_message_cb
*****************************************************************************/
/*!
* \typedef void (* dvbpsi_message_cb)(dvbpsi_handle p_decoder,
* const char* msg)
* \brief Callback type definition.
*/
typedef void (* dvbpsi_message_cb)(dvbpsi_t *handle,
const char* msg);
/*****************************************************************************
* dvbpsi_t
*****************************************************************************/
/*!
* \struct dvbpsi_s
* \brief DVBPSI handle structure
*
* This structure provides a handle to libdvbpsi API and should be used instead
* of dvbpsi_decoder_t.
*/
/*!
* \typedef struct dvbpsi_s dvbpsi_t
* \brief dvbpsi_t type definition.
*/
struct dvbpsi_s
{
void *p_private; /*!< private pointer to
specific decoder or
encoder */
/* Messages callback */
dvbpsi_message_cb pf_message; /*!< Log message callback */
int i_msg_level; /*!< Log level -1, 0, 1 or 2
(-1=none, 0=error, 1=warning,
2=debug) */
};
/*****************************************************************************
* dvbpsi_NewHandle
*****************************************************************************/
/*!
* \fn dvbpsi_t *dvbpsi_NewHandle(dvbpsi_message_cb *callback)
* \brief Create a new dvbpsi_t handle to be used by PSI decoders or encoders
* \param callback message callback handler, if NULL then no errors, warnings
* or debug messages will be sent to the caller application
* \param level for filtering logging messages, possible values are:
* -1=none, 0=error, 1=warning, 2=debug.
* \return pointer to dvbpsi_t malloced data
*
* Creates a handle to use with PSI decoder and encoder API functions. The
* handle must be freed with dvbpsi_DeleteHandle().
*/
dvbpsi_t *dvbpsi_NewHandle(dvbpsi_message_cb callback, int level);
/*****************************************************************************
* dvbpsi_DeleteHandle
*****************************************************************************/
/*!
* \fn void dvbpsi_NewHandle(dvbpsi_t *handle)
* \brief Deletes a dvbpsi_t handle created with dvbpsi_NewHandle
* \param pointer to dvbpsi_t malloced data
* \return nothing
*
* Delets a dvbpsi_t handle by calling free(handle). Make sure to detach any
* decoder of encoder before deleting the dvbpsi handle.
*/
void dvbpsi_DeleteHandle(dvbpsi_t *handle);
/***************************************************************************** /*****************************************************************************
* dvbpsi_PushPacket * dvbpsi_PushPacket
...@@ -63,8 +130,7 @@ typedef struct dvbpsi_decoder_s * dvbpsi_handle; ...@@ -63,8 +130,7 @@ typedef struct dvbpsi_decoder_s * dvbpsi_handle;
* *
* Injection of a TS packet into a PSI decoder. * Injection of a TS packet into a PSI decoder.
*/ */
void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data); void dvbpsi_PushPacket(dvbpsi_t * h_dvbpsi, uint8_t* p_data);
/***************************************************************************** /*****************************************************************************
* The following definitions are just here to allow external decoders but * The following definitions are just here to allow external decoders but
...@@ -77,30 +143,23 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data); ...@@ -77,30 +143,23 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data);
*/ */
typedef struct dvbpsi_psi_section_s dvbpsi_psi_section_t; typedef struct dvbpsi_psi_section_s dvbpsi_psi_section_t;
/*!
* \typedef struct dvbpsi_decoder_s dvbpsi_decoder_t
* \brief dvbpsi_decoder_t type definition.
*/
typedef struct dvbpsi_decoder_s dvbpsi_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_callback * dvbpsi_callback
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \typedef void (* dvbpsi_callback)(dvbpsi_handle p_decoder, * \typedef void (* dvbpsi_callback)(dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
* \brief Callback type definition. * \brief Callback type definition.
*/ */
typedef void (* dvbpsi_callback)(dvbpsi_handle p_decoder, typedef void (* dvbpsi_callback)(dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_message_cb
*****************************************************************************/
/*!
* \typedef void (* dvbpsi_message_cb)(dvbpsi_handle p_decoder,
* const char* msg)
* \brief Callback type definition.
*/
typedef void (* dvbpsi_message_cb)(dvbpsi_handle p_decoder,
const char* msg);
/***************************************************************************** /*****************************************************************************
* dvbpsi_decoder_t * dvbpsi_decoder_t
*****************************************************************************/ *****************************************************************************/
...@@ -111,39 +170,47 @@ typedef void (* dvbpsi_message_cb)(dvbpsi_handle p_decoder, ...@@ -111,39 +170,47 @@ typedef void (* dvbpsi_message_cb)(dvbpsi_handle p_decoder,
* This structure shouldn't be used but if you want to write an external * This structure shouldn't be used but if you want to write an external
* decoder. * decoder.
*/ */
/*! #define DVBPSI_DECODER_COMMON \
* \typedef struct dvbpsi_decoder_s dvbpsi_decoder_t dvbpsi_callback pf_callback; /*!< PSI decoder's callback */ \
* \brief dvbpsi_decoder_t type definition. int i_section_max_size; /*!< Max size of a section for this decoder */ \
*/ uint8_t i_continuity_counter; /*!< Continuity counter */ \
typedef struct dvbpsi_decoder_s int b_discontinuity; /*!< Discontinuity flag */ \
dvbpsi_psi_section_t *p_current_section; /*!< Current section */ \
int i_need; /*!< Bytes needed */ \
int b_complete_header; /*!< Flag for header completion */
struct dvbpsi_decoder_s
{ {
dvbpsi_callback pf_callback; /*!< PSI decoder's DVBPSI_DECODER_COMMON
callback */ };
void * p_private_decoder; /*!< specific
decoder */
int i_section_max_size; /*!< Max size of a
section for this
decoder */
uint8_t i_continuity_counter; /*!< Continuity
counter */
int b_discontinuity; /*!< Discontinuity
flag */
dvbpsi_psi_section_t * p_current_section; /*!< Current section */
int i_need; /*!< Bytes needed */
int b_complete_header; /*!< Flag for header
completion */
/* Messages callback */ /*****************************************************************************
dvbpsi_message_cb pf_message; /*!< Log message callback */ * dvbpsi_NewDecoder
int i_msg_level; /*!< Log level -1, 0, 1 or 2 *****************************************************************************/
(-1=none, 0=error, 1=warning, /*!
2=debug) */ * \fn dvbpsi_decoder_t *dvbpsi_NewDecoder(dvbpsi_t *handle, dvbpsi_callback *callback)
} dvbpsi_decoder_t; * \brief Create a new dvbpsi_decoder_t.
* \param callback dvbpsi_callback handler
* \return pointer to dvbpsi_decoder_t&
*
* Creates a dvbpsi_decoder_t pointer to struct dvbpsi_decoder_s. It should be
* delete with dvbpsi_DeleteDecoder() function.
*/
dvbpsi_decoder_t *dvbpsi_NewDecoder(dvbpsi_t *handle, dvbpsi_callback *callback);
/*****************************************************************************
* dvbpsi_DeletDecoder
*****************************************************************************/
/*!
* \fn void dvbpsi_DeleteDecoder(dvbpsi_t *handle);
* \brief Deletes attached decoder struct from dvbpsi_t handle and frees its memory
* \param pointer to dvbpsi_t malloced data
* \return nothing
*
* Delets a dvbpsi_t handle by calling free(handle). Make sure to detach any
* decoder of encoder before deleting the dvbpsi handle.
*/
void dvbpsi_DeleteDecoder(dvbpsi_t *handle);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -52,9 +53,9 @@ void message(dvbpsi_handle dvbpsi, const int level, const char *fmt, ...); ...@@ -52,9 +53,9 @@ void message(dvbpsi_handle dvbpsi, const int level, const char *fmt, ...);
# define dvbpsi_debug(hnd, str, x...) \ # define dvbpsi_debug(hnd, str, x...) \
message(hnd, DVBPSI_MSG_DEBUG, "libdvbpsi debug ("src"): " str, x) message(hnd, DVBPSI_MSG_DEBUG, "libdvbpsi debug ("src"): " str, x)
#else #else
void dvbpsi_error(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...); void dvbpsi_error(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...);
void dvbpsi_warning(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...); void dvbpsi_warning(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...);
void dvbpsi_debug(dvbpsi_handle dvbpsi, const char *src, const char *fmt, ...); void dvbpsi_debug(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...);
#endif #endif
#else #else
......
...@@ -114,18 +114,14 @@ int dvbpsi_ValidPSISection(dvbpsi_psi_section_t* p_section) ...@@ -114,18 +114,14 @@ int dvbpsi_ValidPSISection(dvbpsi_psi_section_t* p_section)
} }
if(i_crc == 0) if(i_crc == 0)
{
return 1; return 1;
}
else else
{
return 0; return 0;
}
} }
else else
{ {
/* No check to do if b_syntax_indicator is 0 */ /* No check to do if b_syntax_indicator is 0 */
return 1; return 0;
} }
} }
...@@ -180,14 +176,15 @@ void dvbpsi_BuildPSISection(dvbpsi_psi_section_t* p_section) ...@@ -180,14 +176,15 @@ void dvbpsi_BuildPSISection(dvbpsi_psi_section_t* p_section)
p_section->p_payload_end[1] = (p_section->i_crc >> 16) & 0xff; p_section->p_payload_end[1] = (p_section->i_crc >> 16) & 0xff;
p_section->p_payload_end[2] = (p_section->i_crc >> 8) & 0xff; p_section->p_payload_end[2] = (p_section->i_crc >> 8) & 0xff;
p_section->p_payload_end[3] = p_section->i_crc & 0xff; p_section->p_payload_end[3] = p_section->i_crc & 0xff;
#if 0 #if 0
if(!dvbpsi_ValidPSISection(p_section)) if(!dvbpsi_ValidPSISection(p_section))
{ {
dvbpsi_error(h_dvbpsi,"misc PSI", "********************************************"); dvbpsi_error(handle,"misc PSI", "********************************************");
dvbpsi_error(h_dvbpsi,"misc PSI", "* Generated PSI section has a bad CRC_32. *"); dvbpsi_error(handle,"misc PSI", "* Generated PSI section has a bad CRC_32. *");
dvbpsi_error(h_dvbpsi,"misc PSI", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *"); dvbpsi_error(handle,"misc PSI", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
dvbpsi_error(h_dvbpsi,"misc PSI", "* --- libdvbpsi-devel@videolan.org --- *"); dvbpsi_error(handle,"misc PSI", "* --- libdvbpsi-devel@videolan.org --- *");
dvbpsi_error(h_dvbpsi,"misc PSI", "********************************************"); dvbpsi_error(handle,"misc PSI", "********************************************");
} }
#endif #endif
} }
......
...@@ -130,7 +130,7 @@ void dvbpsi_DeletePSISections(dvbpsi_psi_section_t * p_section); ...@@ -130,7 +130,7 @@ void dvbpsi_DeletePSISections(dvbpsi_psi_section_t * p_section);
* \fn int dvbpsi_ValidPSISection(dvbpsi_psi_section_t* p_section) * \fn int dvbpsi_ValidPSISection(dvbpsi_psi_section_t* p_section)
* \brief Validity check of a PSI section. * \brief Validity check of a PSI section.
* \param p_section pointer to the PSI section structure * \param p_section pointer to the PSI section structure
* \return boolean value (0 if the section is not valid). * \return boolean value (false if the section is not valid).
* *
* Check the CRC_32 if the section has b_syntax_indicator set. * Check the CRC_32 if the section has b_syntax_indicator set.
*/ */
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Zhu zhenglu <zhuzlu@gmail.com> * Authors: Zhu zhenglu <zhuzlu@gmail.com>
* heavily based on nit.c which was written by * heavily based on nit.c which was written by
* Johann Hanne * Johann Hanne
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -46,64 +47,61 @@ ...@@ -46,64 +47,61 @@
#include "bat.h" #include "bat.h"
#include "bat_private.h" #include "bat_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachBAT * dvbpsi_AttachBAT
***************************************************************************** *****************************************************************************
* Initialize a BAT subtable decoder. * Initialize a BAT subtable decoder.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_AttachBAT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_bat_callback pf_callback, void* p_cb_data) uint16_t i_extension, dvbpsi_bat_callback pf_callback, void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_bat_decoder_t* p_bat_decoder;
dvbpsi_bat_decoder_t* p_bat_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{ {
dvbpsi_error(h_dvbpsi, "BAT decoder", dvbpsi_error(p_dvbpsi, "BAT decoder",
"Already a decoder for (table_id == 0x%02x," "Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return 1;
}
return 1; 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 1;
}
p_bat_decoder = (dvbpsi_bat_decoder_t*)malloc(sizeof(dvbpsi_bat_decoder_t)); p_bat_decoder = (dvbpsi_bat_decoder_t*)malloc(sizeof(dvbpsi_bat_decoder_t));
if(p_bat_decoder == NULL) if (p_bat_decoder == NULL)
{ {
free(p_subdec); free(p_subdec);
return 1; return 1;
} }
/* subtable decoder configuration */ /* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherBATSections; p_subdec->pf_callback = &dvbpsi_GatherBATSections;
p_subdec->p_cb_data = p_bat_decoder; p_subdec->p_cb_data = p_bat_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension; p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachBAT; p_subdec->pf_detach = dvbpsi_DetachBAT;
/* 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;
/* BAT decoder information */ /* BAT decoder information */
p_bat_decoder->pf_callback = pf_callback; p_bat_decoder->pf_bat_callback = pf_callback;
p_bat_decoder->p_cb_data = p_cb_data; p_bat_decoder->p_cb_data = p_cb_data;
/* BAT decoder initial state */ /* BAT decoder initial state */
p_bat_decoder->b_current_valid = 0; p_bat_decoder->b_current_valid = 0;
p_bat_decoder->p_building_bat = NULL; p_bat_decoder->p_building_bat = NULL;
for(unsigned int i = 0; i < 256; i++) for (unsigned int i = 0; i < 256; i++)
p_bat_decoder->ap_sections[i] = NULL; p_bat_decoder->ap_sections[i] = NULL;
return 0; return 0;
} }
/***************************************************************************** /*****************************************************************************
...@@ -111,41 +109,40 @@ int dvbpsi_AttachBAT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, ...@@ -111,41 +109,40 @@ int dvbpsi_AttachBAT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
***************************************************************************** *****************************************************************************
* Close a BAT decoder. * Close a BAT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
uint16_t i_extension)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec; dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_bat_decoder_t* p_bat_decoder; dvbpsi_bat_decoder_t* p_bat_decoder;
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(h_dvbpsi, "BAT Decoder", dvbpsi_error(p_dvbpsi, "BAT Decoder",
"No such BAT decoder (table_id == 0x%02x," "No such BAT decoder (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return; return;
} }
p_bat_decoder = (dvbpsi_bat_decoder_t*)p_subdec->p_cb_data;
free(p_bat_decoder->p_building_bat);
for(unsigned int i = 0; i < 256; i++) p_bat_decoder = (dvbpsi_bat_decoder_t*)p_subdec->p_cb_data;
{ free(p_bat_decoder->p_building_bat);
if(p_bat_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]);
}
free(p_subdec->p_cb_data); for (unsigned int i = 0; i < 256; i++)
{
if (p_bat_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_bat_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);
p_subdec = NULL;
} }
/***************************************************************************** /*****************************************************************************
...@@ -156,11 +153,11 @@ void dvbpsi_DetachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -156,11 +153,11 @@ void dvbpsi_DetachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
void dvbpsi_InitBAT(dvbpsi_bat_t* p_bat, uint16_t i_bouquet_id, uint8_t i_version, void dvbpsi_InitBAT(dvbpsi_bat_t* p_bat, uint16_t i_bouquet_id, uint8_t i_version,
int b_current_next) int b_current_next)
{ {
p_bat->i_bouquet_id = i_bouquet_id; p_bat->i_bouquet_id = i_bouquet_id;
p_bat->i_version = i_version; p_bat->i_version = i_version;
p_bat->b_current_next = b_current_next; p_bat->b_current_next = b_current_next;
p_bat->p_first_ts = NULL; p_bat->p_first_ts = NULL;
p_bat->p_first_descriptor = NULL; p_bat->p_first_descriptor = NULL;
} }
/***************************************************************************** /*****************************************************************************
...@@ -170,20 +167,19 @@ void dvbpsi_InitBAT(dvbpsi_bat_t* p_bat, uint16_t i_bouquet_id, uint8_t i_versio ...@@ -170,20 +167,19 @@ void dvbpsi_InitBAT(dvbpsi_bat_t* p_bat, uint16_t i_bouquet_id, uint8_t i_versio
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyBAT(dvbpsi_bat_t* p_bat) void dvbpsi_EmptyBAT(dvbpsi_bat_t* p_bat)
{ {
dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts; dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
dvbpsi_DeleteDescriptors(p_bat->p_first_descriptor); dvbpsi_DeleteDescriptors(p_bat->p_first_descriptor);
p_bat->p_first_descriptor = NULL; p_bat->p_first_descriptor = NULL;
while(p_ts != NULL)
{
dvbpsi_bat_ts_t* p_tmp = p_ts->p_next;
dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor);
free(p_ts);
p_ts = p_tmp;
}
p_bat->p_first_ts = NULL; while (p_ts != NULL)
{
dvbpsi_bat_ts_t* p_tmp = p_ts->p_next;
dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor);
free(p_ts);
p_ts = p_tmp;
}
p_bat->p_first_ts = NULL;
} }
/***************************************************************************** /*****************************************************************************
...@@ -194,29 +190,27 @@ void dvbpsi_EmptyBAT(dvbpsi_bat_t* p_bat) ...@@ -194,29 +190,27 @@ void dvbpsi_EmptyBAT(dvbpsi_bat_t* p_bat)
dvbpsi_bat_ts_t *dvbpsi_BATAddTS(dvbpsi_bat_t* p_bat, dvbpsi_bat_ts_t *dvbpsi_BATAddTS(dvbpsi_bat_t* p_bat,
uint16_t i_ts_id, uint16_t i_orig_network_id) uint16_t i_ts_id, uint16_t i_orig_network_id)
{ {
dvbpsi_bat_ts_t * p_ts dvbpsi_bat_ts_t * p_ts
= (dvbpsi_bat_ts_t*)malloc(sizeof(dvbpsi_bat_ts_t)); = (dvbpsi_bat_ts_t*)malloc(sizeof(dvbpsi_bat_ts_t));
if(p_ts) if (p_ts == NULL)
{ return NULL;
p_ts->i_ts_id = i_ts_id; p_ts->i_ts_id = i_ts_id;
p_ts->i_orig_network_id = i_orig_network_id; p_ts->i_orig_network_id = i_orig_network_id;
p_ts->p_next = NULL; p_ts->p_next = NULL;
p_ts->p_first_descriptor = NULL; p_ts->p_first_descriptor = NULL;
if(p_bat->p_first_ts == NULL) if (p_bat->p_first_ts == NULL)
{ p_bat->p_first_ts = p_ts;
p_bat->p_first_ts = p_ts;
}
else else
{ {
dvbpsi_bat_ts_t * p_last_ts = p_bat->p_first_ts; dvbpsi_bat_ts_t * p_last_ts = p_bat->p_first_ts;
while(p_last_ts->p_next != NULL) while(p_last_ts->p_next != NULL)
p_last_ts = p_last_ts->p_next; p_last_ts = p_last_ts->p_next;
p_last_ts->p_next = p_ts; p_last_ts->p_next = p_ts;
} }
}
return p_ts; return p_ts;
} }
/***************************************************************************** /*****************************************************************************
...@@ -230,24 +224,21 @@ dvbpsi_descriptor_t *dvbpsi_BATBouquetAddDescriptor( ...@@ -230,24 +224,21 @@ dvbpsi_descriptor_t *dvbpsi_BATBouquetAddDescriptor(
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 == NULL)
{ return NULL;
if(p_bat->p_first_descriptor == NULL)
{ if (p_bat->p_first_descriptor == NULL)
p_bat->p_first_descriptor = p_descriptor; p_bat->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t * p_last_descriptor = p_bat->p_first_descriptor; dvbpsi_descriptor_t * p_last_descriptor = p_bat->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
...@@ -260,24 +251,21 @@ dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor( ...@@ -260,24 +251,21 @@ dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor(
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 == NULL)
{ return NULL;
if(p_ts->p_first_descriptor == NULL)
{ if (p_ts->p_first_descriptor == NULL)
p_ts->p_first_descriptor = p_descriptor; p_ts->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t *p_last_descriptor = p_ts->p_first_descriptor; dvbpsi_descriptor_t *p_last_descriptor = p_ts->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
...@@ -285,17 +273,17 @@ dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor( ...@@ -285,17 +273,17 @@ dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor(
***************************************************************************** *****************************************************************************
* Callback for the subtable demultiplexor. * Callback for the subtable demultiplexor.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder, void dvbpsi_GatherBATSections(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_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_bat_decoder_t * p_bat_decoder dvbpsi_bat_decoder_t * p_bat_decoder
= (dvbpsi_bat_decoder_t*)p_private_decoder; = (dvbpsi_bat_decoder_t*)p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "BAT decoder", dvbpsi_debug(p_dvbpsi, "BAT decoder",
"Table version %2d, " "i_table_id %2d, " "i_extension %5d, " "Table version %2d, " "i_table_id %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id, p_section->i_version, p_section->i_table_id,
...@@ -303,166 +291,164 @@ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -303,166 +291,164 @@ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
if(!p_section->b_syntax_indicator) if (!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "BAT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
/* Now if b_append is true then we have a valid BAT section */
if(b_append)
{
/* TS discontinuity check */
if(p_psi_decoder->b_discontinuity)
{ {
b_reinit = 1; /* Invalid section_syntax_indicator */
p_psi_decoder->b_discontinuity = 0; dvbpsi_error(p_dvbpsi, "BAT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
} }
else
/* Now if b_append is true then we have a valid BAT section */
if (b_append)
{ {
/* Perform a few sanity checks */ /* TS discontinuity check */
if(p_bat_decoder->p_building_bat) if (p_demux->b_discontinuity)
{
if(p_bat_decoder->p_building_bat->i_bouquet_id != p_section->i_extension)
{ {
/* bouquet_id */ b_reinit = 1;
dvbpsi_error(h_dvbpsi, "BAT decoder", p_demux->b_discontinuity = 0;
"'bouquet_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
} }
else if(p_bat_decoder->p_building_bat->i_version else
!= p_section->i_version)
{ {
/* version_number */ /* Perform a few sanity checks */
dvbpsi_error(h_dvbpsi, "BAT decoder", if (p_bat_decoder->p_building_bat)
"'version_number' differs" {
" whereas no discontinuity has occured"); if (p_bat_decoder->p_building_bat->i_bouquet_id != p_section->i_extension)
b_reinit = 1; {
} /* bouquet_id */
else if(p_bat_decoder->i_last_section_number != dvbpsi_error(p_dvbpsi, "BAT decoder",
"'bouquet_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
}
else if (p_bat_decoder->p_building_bat->i_version
!= p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "BAT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
else if (p_bat_decoder->i_last_section_number !=
p_section->i_last_number) p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "BAT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
}
else
{
if ( (p_bat_decoder->b_current_valid)
&& (p_bat_decoder->current_bat.i_version == p_section->i_version))
{
/* Signal a new BAT if the previous one wasn't active */
if ( (!p_bat_decoder->current_bat.b_current_next)
&& (p_section->b_current_next))
{
dvbpsi_bat_t *p_bat = NULL;
p_bat_decoder->current_bat.b_current_next = 1;
*p_bat = p_bat_decoder->current_bat;
p_bat_decoder->pf_bat_callback(p_bat_decoder->p_cb_data, p_bat);
}
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
}
}
/* Reinit the decoder if wanted */
if (b_reinit)
{
/* Force redecoding */
p_bat_decoder->b_current_valid = 0;
/* Free structures */
if (p_bat_decoder->p_building_bat)
{ {
/* last_section_number */ free(p_bat_decoder->p_building_bat);
dvbpsi_error(h_dvbpsi, "BAT decoder", p_bat_decoder->p_building_bat = 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_bat_decoder->b_current_valid)
&& (p_bat_decoder->current_bat.i_version == p_section->i_version))
{ {
/* Signal a new BAT if the previous one wasn't active */ if (p_bat_decoder->ap_sections[i] != NULL)
if( (!p_bat_decoder->current_bat.b_current_next) {
&& (p_section->b_current_next)) dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]);
{ p_bat_decoder->ap_sections[i] = NULL;
dvbpsi_bat_t *p_bat = NULL; }
p_bat_decoder->current_bat.b_current_next = 1;
*p_bat = p_bat_decoder->current_bat;
p_bat_decoder->pf_callback(p_bat_decoder->p_cb_data, p_bat);
}
/* 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) if (b_append)
{
/* Force redecoding */
p_bat_decoder->b_current_valid = 0;
/* Free structures */
if(p_bat_decoder->p_building_bat)
{
free(p_bat_decoder->p_building_bat);
p_bat_decoder->p_building_bat = NULL;
}
/* Clear the section array */
for(unsigned int i = 0; i < 256; i++)
{ {
if(p_bat_decoder->ap_sections[i] != NULL) int b_complete = 0;
{
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]);
p_bat_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_bat_decoder->p_building_bat) if (!p_bat_decoder->p_building_bat)
{ {
p_bat_decoder->p_building_bat = p_bat_decoder->p_building_bat =
(dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t)); (dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t));
dvbpsi_InitBAT(p_bat_decoder->p_building_bat, dvbpsi_InitBAT(p_bat_decoder->p_building_bat,
p_section->i_extension, p_section->i_extension,
p_section->i_version, p_section->i_version,
p_section->b_current_next); p_section->b_current_next);
p_bat_decoder->i_last_section_number = p_section->i_last_number; p_bat_decoder->i_last_section_number = p_section->i_last_number;
} }
/* Fill the section array */ /* Fill the section array */
if(p_bat_decoder->ap_sections[p_section->i_number] != NULL) if (p_bat_decoder->ap_sections[p_section->i_number] != NULL)
{ {
dvbpsi_debug(h_dvbpsi, "BAT decoder", "overwrite section number %d", dvbpsi_debug(p_dvbpsi, "BAT decoder", "overwrite section number %d",
p_section->i_number); p_section->i_number);
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[p_section->i_number]); dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[p_section->i_number]);
} }
p_bat_decoder->ap_sections[p_section->i_number] = p_section; p_bat_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; for (unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++)
for(unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++) {
{ if (!p_bat_decoder->ap_sections[i])
if(!p_bat_decoder->ap_sections[i]) break;
break; if (i == p_bat_decoder->i_last_section_number)
b_complete = 1;
}
if(i == p_bat_decoder->i_last_section_number) if (b_complete)
b_complete = 1; {
/* Save the current information */
p_bat_decoder->current_bat = *p_bat_decoder->p_building_bat;
p_bat_decoder->b_current_valid = 1;
/* Chain the sections */
if (p_bat_decoder->i_last_section_number)
{
for (int j = 0; j <= p_bat_decoder->i_last_section_number - 1; j++)
p_bat_decoder->ap_sections[j]->p_next =
p_bat_decoder->ap_sections[j + 1];
}
/* Decode the sections */
dvbpsi_DecodeBATSections(p_dvbpsi, p_bat_decoder->p_building_bat,
p_bat_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[0]);
/* signal the new BAT */
p_bat_decoder->pf_bat_callback(p_bat_decoder->p_cb_data,
p_bat_decoder->p_building_bat);
/* Reinitialize the structures */
p_bat_decoder->p_building_bat = NULL;
for (unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++)
p_bat_decoder->ap_sections[i] = NULL;
}
} }
else
if(b_complete)
{ {
/* Save the current information */ dvbpsi_DeletePSISections(p_section);
p_bat_decoder->current_bat = *p_bat_decoder->p_building_bat;
p_bat_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_bat_decoder->i_last_section_number)
{
for(int j = 0; j <= p_bat_decoder->i_last_section_number - 1; j++)
p_bat_decoder->ap_sections[j]->p_next =
p_bat_decoder->ap_sections[j + 1];
}
/* Decode the sections */
dvbpsi_DecodeBATSections(p_bat_decoder->p_building_bat,
p_bat_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[0]);
/* signal the new BAT */
p_bat_decoder->pf_callback(p_bat_decoder->p_cb_data,
p_bat_decoder->p_building_bat);
/* Reinitialize the structures */
p_bat_decoder->p_building_bat = NULL;
for(unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++)
p_bat_decoder->ap_sections[i] = NULL;
} }
}
else
{
dvbpsi_DeletePSISections(p_section);
}
} }
/***************************************************************************** /*****************************************************************************
...@@ -473,7 +459,7 @@ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -473,7 +459,7 @@ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder,
* p_section as the input parameter * p_section as the input parameter
* similar to dvbpsi_DecodeNITSection * similar to dvbpsi_DecodeNITSection
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeBATSections(dvbpsi_bat_t* p_bat, void dvbpsi_DecodeBATSections(dvbpsi_t *p_dvbpsi, dvbpsi_bat_t* p_bat,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t* p_byte, * p_end, * p_end2; uint8_t* p_byte, * p_end, * p_end2;
...@@ -536,197 +522,196 @@ void dvbpsi_DecodeBATSections(dvbpsi_bat_t* p_bat, ...@@ -536,197 +522,196 @@ void dvbpsi_DecodeBATSections(dvbpsi_bat_t* p_bat,
* Generate BAT sections based on the dvbpsi_bat_t structure. * Generate BAT sections based on the dvbpsi_bat_t structure.
* similar to dvbpsi_GenNITSections * similar to dvbpsi_GenNITSections
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_bat_t* p_bat) dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_t *p_dvbpsi, dvbpsi_bat_t* p_bat)
{ {
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev; dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_bat->p_first_descriptor; dvbpsi_descriptor_t* p_descriptor = p_bat->p_first_descriptor;
dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts; dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
uint16_t i_bouquet_descriptors_length, i_transport_stream_loop_length; uint16_t i_bouquet_descriptors_length, i_transport_stream_loop_length;
uint8_t * p_transport_stream_loop_length; uint8_t * p_transport_stream_loop_length;
p_current->i_table_id = 0x4a; p_current->i_table_id = 0x4a;
p_current->b_syntax_indicator = 1; p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 1; p_current->b_private_indicator = 1;
p_current->i_length = 13; /* including CRC_32 */ p_current->i_length = 13; /* including CRC_32 */
p_current->i_extension = p_bat->i_bouquet_id; p_current->i_extension = p_bat->i_bouquet_id;
p_current->i_version = p_bat->i_version; p_current->i_version = p_bat->i_version;
p_current->b_current_next = p_bat->b_current_next; p_current->b_current_next = p_bat->b_current_next;
p_current->i_number = 0; p_current->i_number = 0;
p_current->p_payload_end += 10; p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8; p_current->p_payload_start = p_current->p_data + 8;
/* first loop descriptors */ /* first loop descriptors */
while(p_descriptor != NULL) while (p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
{ {
/* bouquet_descriptors_length */ /* New section if needed */
i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2; /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0; if( (p_current->p_payload_end - p_current->p_data)
p_current->p_data[9] = i_bouquet_descriptors_length; + p_descriptor->i_length > 1018)
{
/* transport_stream_loop_length */ /* bouquet_descriptors_length */
p_current->p_payload_end[0] = 0; i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_current->p_payload_end[1] = 0; p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0;
p_current->p_payload_end += 2; p_current->p_data[9] = i_bouquet_descriptors_length;
p_prev = p_current; /* transport_stream_loop_length */
p_current = dvbpsi_NewPSISection(1024); p_current->p_payload_end[0] = 0;
p_prev->p_next = p_current; p_current->p_payload_end[1] = 0;
p_current->p_payload_end += 2;
p_current->i_table_id = 0x4a;
p_current->b_syntax_indicator = 1; p_prev = p_current;
p_current->b_private_indicator = 1; p_current = dvbpsi_NewPSISection(1024);
p_current->i_length = 13; /* including CRC_32 */ p_prev->p_next = p_current;
p_current->i_extension = p_bat->i_bouquet_id;
p_current->i_version = p_bat->i_version; p_current->i_table_id = 0x4a;
p_current->b_current_next = p_bat->b_current_next; p_current->b_syntax_indicator = 1;
p_current->i_number = p_prev->i_number + 1; p_current->b_private_indicator = 1;
p_current->p_payload_end += 10; p_current->i_length = 13; /* including CRC_32 */
p_current->p_payload_start = p_current->p_data + 8; p_current->i_extension = p_bat->i_bouquet_id;
} p_current->i_version = p_bat->i_version;
p_current->b_current_next = p_bat->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
}
/* p_payload_end is where the descriptor begins */ /* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length; p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2, memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data, p_descriptor->p_data,
p_descriptor->i_length); p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */ /* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2; p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next; p_descriptor = p_descriptor->p_next;
} }
/* bouquet_descriptors_length */
i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0;
p_current->p_data[9] = i_bouquet_descriptors_length;
/* Store the position of the transport_stream_loop_length field /* bouquet_descriptors_length */
and reserve two bytes for it */ i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_transport_stream_loop_length = p_current->p_payload_end; p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0;
p_current->p_payload_end += 2; p_current->p_data[9] = i_bouquet_descriptors_length;
/* second loop: BAT TSs */ /* Store the position of the transport_stream_loop_length field
while(p_ts != NULL) and reserve two bytes for it */
{ p_transport_stream_loop_length = p_current->p_payload_end;
uint8_t* p_ts_start = p_current->p_payload_end; p_current->p_payload_end += 2;
uint16_t i_transport_descriptors_length = 5;
/* Can the current section carry all the descriptors ? */ /* second loop: BAT TSs */
p_descriptor = p_ts->p_first_descriptor; while (p_ts != NULL)
while( (p_descriptor != NULL)
&& ((p_ts_start - p_current->p_data) + i_transport_descriptors_length <= 1020))
{ {
i_transport_descriptors_length += p_descriptor->i_length + 2; uint8_t* p_ts_start = p_current->p_payload_end;
p_descriptor = p_descriptor->p_next; uint16_t i_transport_descriptors_length = 5;
}
/* If _no_ and the current section isn't empty and an empty section /* Can the current section carry all the descriptors ? */
may carry one more descriptor p_descriptor = p_ts->p_first_descriptor;
then create a new section */ while( (p_descriptor != NULL)
if( (p_descriptor != NULL) && ((p_ts_start - p_current->p_data) + i_transport_descriptors_length <= 1020))
&& (p_ts_start - p_current->p_data != 12) {
&& (i_transport_descriptors_length <= 1008)) i_transport_descriptors_length += p_descriptor->i_length + 2;
{ p_descriptor = p_descriptor->p_next;
/* transport_stream_loop_length */ }
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
#if 0 /* FIXME: */
/* will put more descriptors in an empty section */
dvbpsi_debug(h_dvbpsi, "BAT generator",
"create a new section to carry more TS descriptors");
#endif
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x4a;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 1;
p_current->i_length = 13; /* including CRC_32 */
p_current->i_extension = p_bat->i_bouquet_id;
p_current->i_version = p_bat->i_version;
p_current->b_current_next = p_bat->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* bouquet_descriptors_length = 0 */
p_current->p_data[8] = 0xf0;
p_current->p_data[9] = 0x00;
/* Store the position of the transport_stream_loop_length field
and reserve two bytes for it */
p_transport_stream_loop_length = p_current->p_payload_end;
p_current->p_payload_end += 2;
p_ts_start = p_current->p_payload_end;
}
/* p_ts_start is where the TS begins */ /* If _no_ and the current section isn't empty and an empty section
p_ts_start[0] = p_ts->i_ts_id >> 8; may carry one more descriptor
p_ts_start[1] = p_ts->i_ts_id & 0xff; then create a new section */
p_ts_start[2] = p_ts->i_orig_network_id >> 8; if( (p_descriptor != NULL)
p_ts_start[3] = p_ts->i_orig_network_id & 0xff; && (p_ts_start - p_current->p_data != 12)
&& (i_transport_descriptors_length <= 1008))
/* Increase the length by 6 */ {
p_current->p_payload_end += 6; /* transport_stream_loop_length */
p_current->i_length += 6; i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
/* TS descriptors */ p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
p_descriptor = p_ts->p_first_descriptor;
while( (p_descriptor != NULL) /* will put more descriptors in an empty section */
&& ( (p_current->p_payload_end - p_current->p_data) dvbpsi_debug(p_dvbpsi, "BAT generator",
+ p_descriptor->i_length <= 1018)) "create a new section to carry more TS descriptors");
{
/* p_payload_end is where the descriptor begins */ p_prev = p_current;
p_current->p_payload_end[0] = p_descriptor->i_tag; p_current = dvbpsi_NewPSISection(1024);
p_current->p_payload_end[1] = p_descriptor->i_length; p_prev->p_next = p_current;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data, p_current->i_table_id = 0x4a;
p_descriptor->i_length); p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 1;
/* Increase length by descriptor_length + 2 */ p_current->i_length = 13; /* including CRC_32 */
p_current->p_payload_end += p_descriptor->i_length + 2; p_current->i_extension = p_bat->i_bouquet_id;
p_current->i_length += p_descriptor->i_length + 2; p_current->i_version = p_bat->i_version;
p_current->b_current_next = p_bat->b_current_next;
p_descriptor = p_descriptor->p_next; p_current->i_number = p_prev->i_number + 1;
} p_current->p_payload_end += 10;
#if 0 /* FIXME: */ p_current->p_payload_start = p_current->p_data + 8;
if(p_descriptor != NULL)
dvbpsi_error(h_dvbpsi, "BAT generator", "unable to carry all the TS descriptors"); /* bouquet_descriptors_length = 0 */
#endif p_current->p_data[8] = 0xf0;
/* transport_descriptors_length */ p_current->p_data[9] = 0x00;
i_transport_descriptors_length = p_current->p_payload_end - p_ts_start - 5;
p_ts_start[4] = (i_transport_descriptors_length >> 8) | 0xf0; /* Store the position of the transport_stream_loop_length field
p_ts_start[5] = i_transport_descriptors_length; and reserve two bytes for it */
p_transport_stream_loop_length = p_current->p_payload_end;
p_current->p_payload_end += 2;
p_ts_start = p_current->p_payload_end;
}
p_ts = p_ts->p_next; /* p_ts_start is where the TS begins */
} p_ts_start[0] = p_ts->i_ts_id >> 8;
p_ts_start[1] = p_ts->i_ts_id & 0xff;
p_ts_start[2] = p_ts->i_orig_network_id >> 8;
p_ts_start[3] = p_ts->i_orig_network_id & 0xff;
/* Increase the length by 6 */
p_current->p_payload_end += 6;
p_current->i_length += 6;
/* TS descriptors */
p_descriptor = p_ts->p_first_descriptor;
while( (p_descriptor != NULL)
&& ( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length <= 1018))
{
/* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* transport_stream_loop_length */ if (p_descriptor != NULL)
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2; dvbpsi_error(p_dvbpsi, "BAT generator", "unable to carry all the TS descriptors");
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
/* Finalization */ /* transport_descriptors_length */
p_prev = p_result; i_transport_descriptors_length = p_current->p_payload_end - p_ts_start - 5;
while(p_prev != NULL) p_ts_start[4] = (i_transport_descriptors_length >> 8) | 0xf0;
{ p_ts_start[5] = i_transport_descriptors_length;
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev); p_ts = p_ts->p_next;
p_prev = p_prev->p_next; }
}
/* transport_stream_loop_length */
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
return p_result; /* Finalization */
p_prev = p_result;
while (p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
return p_result;
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Authors: Zhu zhenglu <zhuzlu@gmail.com> * Authors: Zhu zhenglu <zhuzlu@gmail.com>
* heavily based on nit.h which was written by * heavily based on nit.h which was written by
* Johann Hanne * Johann Hanne
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -110,43 +111,40 @@ typedef struct dvbpsi_bat_s ...@@ -110,43 +111,40 @@ typedef struct dvbpsi_bat_s
*/ */
typedef void (* dvbpsi_bat_callback)(void* p_cb_data, dvbpsi_bat_t* p_new_bat); typedef void (* dvbpsi_bat_callback)(void* p_cb_data, dvbpsi_bat_t* p_new_bat);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachBAT * dvbpsi_AttachBAT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_AttachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn void dvbpsi_AttachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_bat_callback pf_callback, uint16_t i_extension, dvbpsi_bat_callback pf_callback,
void* p_cb_data) void* p_cb_data)
* \brief Creation and initialization of a BAT decoder. * \brief Creation and initialization of a BAT 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, 0x4a. * \param i_table_id Table ID, 0x4a.
* \param i_extension Table ID extension, here bouquet ID. * \param i_extension Table ID extension, here bouquet ID.
* \param pf_callback function to call back on new BAT. * \param pf_callback function to call back on new BAT.
* \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 0 if everything went ok.
*/ */
int dvbpsi_AttachBAT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_bat_callback pf_callback, uint16_t i_extension, dvbpsi_bat_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachBAT * dvbpsi_DetachBAT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_DetachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn void dvbpsi_DetachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
* \brief Destroy a BAT decoder. * \brief Destroy a BAT 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, 0x4a. * \param i_table_id Table ID, 0x4a.
* \param i_extension Table ID extension, here bouquet ID. * \param i_extension Table ID extension, here bouquet ID.
* \return nothing. * \return nothing.
*/ */
void dvbpsi_DetachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitBAT/dvbpsi_NewBAT * dvbpsi_InitBAT/dvbpsi_NewBAT
*****************************************************************************/ *****************************************************************************/
...@@ -181,7 +179,6 @@ do { \ ...@@ -181,7 +179,6 @@ do { \
dvbpsi_InitBAT(p_bat, i_bouquet_id, i_version, b_current_next); \ dvbpsi_InitBAT(p_bat, i_bouquet_id, i_version, b_current_next); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyBAT/dvbpsi_DeleteBAT * dvbpsi_EmptyBAT/dvbpsi_DeleteBAT
*****************************************************************************/ *****************************************************************************/
...@@ -207,8 +204,8 @@ do { \ ...@@ -207,8 +204,8 @@ do { \
/***************************************************************************** /*****************************************************************************
* dvbpsi_GenBATSections * dvbpsi_GenBATSections
***************************************************************************** *****************************************************************************/
*! /*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_bat_t* p_bat) * \fn dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_bat_t* p_bat)
* \brief BAT generator * \brief BAT generator
* \param p_bat BAT structure * \param p_bat BAT structure
...@@ -216,8 +213,7 @@ do { \ ...@@ -216,8 +213,7 @@ do { \
* *
* Generate BAT sections based on the dvbpsi_bat_t structure. * Generate BAT sections based on the dvbpsi_bat_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_GenBATSections(dvbpsi_bat_t * p_bat); dvbpsi_psi_section_t *dvbpsi_GenBATSections(dvbpsi_t *p_dvbpsi, dvbpsi_bat_t * p_bat);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id: bat_private.h 88 2004-02-24 14:31:18Z sam $ * $Id: bat_private.h 88 2004-02-24 14:31:18Z sam $
* *
* Authors: Zhu zhenglu <zhuzlu@gmail.com> * Authors: Zhu zhenglu <zhuzlu@gmail.com>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -28,7 +29,6 @@ ...@@ -28,7 +29,6 @@
#ifndef _DVBPSI_BAT_PRIVATE_H_ #ifndef _DVBPSI_BAT_PRIVATE_H_
#define _DVBPSI_BAT_PRIVATE_H_ #define _DVBPSI_BAT_PRIVATE_H_
/***************************************************************************** /*****************************************************************************
* dvbpsi_bat_decoder_t * dvbpsi_bat_decoder_t
***************************************************************************** *****************************************************************************
...@@ -36,39 +36,37 @@ ...@@ -36,39 +36,37 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_bat_decoder_s typedef struct dvbpsi_bat_decoder_s
{ {
dvbpsi_bat_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
dvbpsi_bat_t current_bat; dvbpsi_bat_callback pf_bat_callback;
dvbpsi_bat_t * p_building_bat; void * p_cb_data;
int b_current_valid; dvbpsi_bat_t current_bat;
dvbpsi_bat_t * p_building_bat;
uint8_t i_last_section_number; int b_current_valid;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_bat_decoder_t; uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_bat_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherBATSections * dvbpsi_GatherBATSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherBATSections(dvbpsi_decoder_t* p_psi_decoder, void dvbpsi_GatherBATSections(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_DecodeBATSections * dvbpsi_DecodeBATSections
***************************************************************************** *****************************************************************************
* BAT decoder. * BAT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeBATSections(dvbpsi_bat_t* p_bat, void dvbpsi_DecodeBATSections(dvbpsi_t* p_dvbpsi,dvbpsi_bat_t* p_bat,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
/***************************************************************************** /*****************************************************************************
* dvbpsi_BATAddTS * dvbpsi_BATAddTS
***************************************************************************** *****************************************************************************
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -26,7 +27,6 @@ ...@@ -26,7 +27,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
#include <assert.h>
#include "../dvbpsi.h" #include "../dvbpsi.h"
#include "../dvbpsi_private.h" #include "../dvbpsi_private.h"
#include "../psi.h" #include "../psi.h"
...@@ -46,76 +48,65 @@ ...@@ -46,76 +48,65 @@
#include "cat.h" #include "cat.h"
#include "cat_private.h" #include "cat_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachCAT * dvbpsi_AttachCAT
***************************************************************************** *****************************************************************************
* Initialize a CAT decoder and return a handle on it. * Initialize a CAT decoder and return a handle on it.
*****************************************************************************/ *****************************************************************************/
dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback, dvbpsi_t *dvbpsi_AttachCAT(dvbpsi_t *p_dvbpsi, dvbpsi_cat_callback pf_callback,
void* p_cb_data) void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t)); assert(p_dvbpsi);
dvbpsi_cat_decoder_t* p_cat_decoder;
dvbpsi_cat_decoder_t* p_cat_decoder;
if(h_dvbpsi == NULL) p_cat_decoder = (dvbpsi_cat_decoder_t*)calloc(1, sizeof(dvbpsi_cat_decoder_t));
return NULL; if (p_cat_decoder == NULL)
return NULL;
p_cat_decoder = (dvbpsi_cat_decoder_t*)malloc(sizeof(dvbpsi_cat_decoder_t));
/* PSI decoder configuration */
if(p_cat_decoder == NULL) p_cat_decoder->pf_callback = &dvbpsi_GatherCATSections;
{ p_dvbpsi->p_private = p_cat_decoder;
free(h_dvbpsi); p_cat_decoder->i_section_max_size = 1024;
return NULL; /* PSI decoder initial state */
} p_cat_decoder->i_continuity_counter = 31;
p_cat_decoder->b_discontinuity = 1;
/* PSI decoder configuration */ p_cat_decoder->p_current_section = NULL;
h_dvbpsi->pf_callback = &dvbpsi_GatherCATSections;
h_dvbpsi->p_private_decoder = p_cat_decoder; /* CAT decoder configuration */
h_dvbpsi->i_section_max_size = 1024; p_cat_decoder->pf_cat_callback = pf_callback;
/* PSI decoder initial state */ p_cat_decoder->p_cb_data = p_cb_data;
h_dvbpsi->i_continuity_counter = 31; /* CAT decoder initial state */
h_dvbpsi->b_discontinuity = 1; p_cat_decoder->b_current_valid = 0;
h_dvbpsi->p_current_section = NULL; p_cat_decoder->p_building_cat = NULL;
for (unsigned int i = 0; i <= 255; i++)
/* CAT decoder configuration */ p_cat_decoder->ap_sections[i] = NULL;
p_cat_decoder->pf_callback = pf_callback;
p_cat_decoder->p_cb_data = p_cb_data;
/* CAT decoder initial state */
p_cat_decoder->b_current_valid = 0;
p_cat_decoder->p_building_cat = NULL;
for(unsigned int i = 0; i <= 255; i++)
p_cat_decoder->ap_sections[i] = NULL;
return h_dvbpsi;
}
return p_dvbpsi;
}
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachCAT * dvbpsi_DetachCAT
***************************************************************************** *****************************************************************************
* Close a CAT decoder. The handle isn't valid any more. * Close a CAT decoder. The handle isn't valid any more.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi) void dvbpsi_DetachCAT(dvbpsi_t *p_dvbpsi)
{ {
dvbpsi_cat_decoder_t* p_cat_decoder dvbpsi_cat_decoder_t* p_cat_decoder
= (dvbpsi_cat_decoder_t*)h_dvbpsi->p_private_decoder; = (dvbpsi_cat_decoder_t*)p_dvbpsi->p_private;
free(p_cat_decoder->p_building_cat);
free(p_cat_decoder->p_building_cat); for (unsigned int i = 0; i <= 255; i++)
{
for(unsigned int i = 0; i <= 255; i++) if (p_cat_decoder->ap_sections[i])
{ free(p_cat_decoder->ap_sections[i]);
if(p_cat_decoder->ap_sections[i]) }
free(p_cat_decoder->ap_sections[i]);
}
free(h_dvbpsi->p_private_decoder); if (p_cat_decoder->p_current_section)
if(h_dvbpsi->p_current_section) dvbpsi_DeletePSISections(p_cat_decoder->p_current_section);
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); free(p_cat_decoder);
free(h_dvbpsi); p_dvbpsi->p_private = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitCAT * dvbpsi_InitCAT
***************************************************************************** *****************************************************************************
...@@ -124,12 +115,11 @@ void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi) ...@@ -124,12 +115,11 @@ void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi)
void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat, void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
uint8_t i_version, int b_current_next) uint8_t i_version, int b_current_next)
{ {
p_cat->i_version = i_version; p_cat->i_version = i_version;
p_cat->b_current_next = b_current_next; p_cat->b_current_next = b_current_next;
p_cat->p_first_descriptor = NULL; p_cat->p_first_descriptor = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyCAT * dvbpsi_EmptyCAT
***************************************************************************** *****************************************************************************
...@@ -137,12 +127,10 @@ void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat, ...@@ -137,12 +127,10 @@ void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat) void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat)
{ {
dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor); dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor);
p_cat->p_first_descriptor = NULL;
p_cat->p_first_descriptor = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_CATAddDescriptor * dvbpsi_CATAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -152,202 +140,194 @@ dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat, ...@@ -152,202 +140,194 @@ dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat,
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 == NULL)
return NULL;
if(p_descriptor) if (p_cat->p_first_descriptor == NULL)
{
if(p_cat->p_first_descriptor == NULL)
{
p_cat->p_first_descriptor = p_descriptor; p_cat->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_cat->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_cat->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherCATSections * dvbpsi_GatherCATSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherCATSections(dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_decoder; dvbpsi_cat_decoder_t* p_cat_decoder
dvbpsi_cat_decoder_t* p_cat_decoder = (dvbpsi_cat_decoder_t*)p_dvbpsi->p_private;
= (dvbpsi_cat_decoder_t*)p_decoder->p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "CAT decoder", dvbpsi_debug(p_dvbpsi, "CAT decoder",
"Table version %2d, " "i_extension %5d, " "Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension, p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
if(p_section->i_table_id != 0x01) if (p_section->i_table_id != 0x01)
{ {
/* Invalid table_id value */ /* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "CAT decoder", dvbpsi_error(p_dvbpsi, "CAT decoder",
"invalid section (table_id == 0x%02x)", "invalid section (table_id == 0x%02x)",
p_section->i_table_id); p_section->i_table_id);
b_append = 0; b_append = 0;
} }
if(b_append && !p_section->b_syntax_indicator) if (b_append && !p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "CAT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
if(b_append)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
{ {
b_reinit = 1; /* Invalid section_syntax_indicator */
p_decoder->b_discontinuity = 0; dvbpsi_error(p_dvbpsi, "CAT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
} }
else
if (b_append)
{ {
/* Perform some few sanity checks */ /* TS discontinuity check */
if(p_cat_decoder->p_building_cat) if (p_cat_decoder->b_discontinuity)
{
if(p_cat_decoder->p_building_cat->i_version != p_section->i_version)
{
/* version_number */
dvbpsi_error(h_dvbpsi, "CAT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
else if(p_cat_decoder->i_last_section_number
!= p_section->i_last_number)
{ {
/* last_section_number */ b_reinit = 1;
dvbpsi_error(h_dvbpsi, "CAT decoder", p_cat_decoder->b_discontinuity = 0;
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
} }
} else
else
{
if( (p_cat_decoder->b_current_valid)
&& (p_cat_decoder->current_cat.i_version == p_section->i_version)
&& (p_cat_decoder->current_cat.b_current_next ==
p_section->b_current_next))
{ {
/* Don't decode since this version is already decoded */ /* Perform some few sanity checks */
b_append = 0; if (p_cat_decoder->p_building_cat)
{
if (p_cat_decoder->p_building_cat->i_version != p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "CAT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
else if (p_cat_decoder->i_last_section_number
!= p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "CAT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
}
else
{
if ( (p_cat_decoder->b_current_valid)
&& (p_cat_decoder->current_cat.i_version == p_section->i_version)
&& (p_cat_decoder->current_cat.b_current_next ==
p_section->b_current_next))
{
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
} }
}
} }
}
/* Reinit the decoder if wanted */ /* Reinit the decoder if wanted */
if(b_reinit) if (b_reinit)
{
/* Force redecoding */
p_cat_decoder->b_current_valid = 0;
/* Free structures */
if(p_cat_decoder->p_building_cat)
{ {
free(p_cat_decoder->p_building_cat); /* Force redecoding */
p_cat_decoder->p_building_cat = NULL; p_cat_decoder->b_current_valid = 0;
} /* Free structures */
/* Clear the section array */ if (p_cat_decoder->p_building_cat)
for(unsigned int i = 0; i <= 255; i++) {
{ free(p_cat_decoder->p_building_cat);
if(p_cat_decoder->ap_sections[i] != NULL) p_cat_decoder->p_building_cat = NULL;
{ }
dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[i]); /* Clear the section array */
p_cat_decoder->ap_sections[i] = NULL; for (unsigned int i = 0; i <= 255; i++)
} {
if (p_cat_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[i]);
p_cat_decoder->ap_sections[i] = NULL;
}
}
} }
}
/* Append the section to the list if wanted */ /* Append the section to the list if wanted */
if(b_append) if (b_append)
{
int b_complete;
/* Initialize the structures if it's the first section received */
if(!p_cat_decoder->p_building_cat)
{ {
p_cat_decoder->p_building_cat = int b_complete = 0;
/* Initialize the structures if it's the first section received */
if (!p_cat_decoder->p_building_cat)
{
p_cat_decoder->p_building_cat =
(dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t)); (dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t));
dvbpsi_InitCAT(p_cat_decoder->p_building_cat, dvbpsi_InitCAT(p_cat_decoder->p_building_cat,
p_section->i_version, p_section->i_version,
p_section->b_current_next); p_section->b_current_next);
p_cat_decoder->i_last_section_number = p_section->i_last_number; p_cat_decoder->i_last_section_number = p_section->i_last_number;
} }
/* Fill the section array */ /* Fill the section array */
if(p_cat_decoder->ap_sections[p_section->i_number] != NULL) if (p_cat_decoder->ap_sections[p_section->i_number] != NULL)
{ {
dvbpsi_debug(h_dvbpsi, "CAT decoder", "overwrite section number %d", dvbpsi_debug(p_dvbpsi, "CAT decoder", "overwrite section number %d",
p_section->i_number); p_section->i_number);
dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[p_section->i_number]); dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[p_section->i_number]);
} }
p_cat_decoder->ap_sections[p_section->i_number] = p_section; p_cat_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; for (unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++)
for(unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++) {
{ if (!p_cat_decoder->ap_sections[i])
if(!p_cat_decoder->ap_sections[i]) break;
break;
if(i == p_cat_decoder->i_last_section_number) if (i == p_cat_decoder->i_last_section_number)
b_complete = 1; b_complete = 1;
} }
if(b_complete) if (b_complete)
{
/* Save the current information */
p_cat_decoder->current_cat = *p_cat_decoder->p_building_cat;
p_cat_decoder->b_current_valid = 1;
/* Chain the sections */
if (p_cat_decoder->i_last_section_number)
{
for (int i = 0; i <= p_cat_decoder->i_last_section_number - 1; i++)
p_cat_decoder->ap_sections[i]->p_next = p_cat_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_DecodeCATSections(p_cat_decoder->p_building_cat,
p_cat_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[0]);
/* signal the new CAT */
p_cat_decoder->pf_cat_callback(p_cat_decoder->p_cb_data,
p_cat_decoder->p_building_cat);
/* Reinitialize the structures */
p_cat_decoder->p_building_cat = NULL;
for (unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++)
p_cat_decoder->ap_sections[i] = NULL;
}
}
else
{ {
/* Save the current information */ dvbpsi_DeletePSISections(p_section);
p_cat_decoder->current_cat = *p_cat_decoder->p_building_cat;
p_cat_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_cat_decoder->i_last_section_number)
{
for(unsigned int i = 0; (int)i <= p_cat_decoder->i_last_section_number - 1; i++)
p_cat_decoder->ap_sections[i]->p_next =
p_cat_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_DecodeCATSections(p_cat_decoder->p_building_cat,
p_cat_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[0]);
/* signal the new CAT */
p_cat_decoder->pf_callback(p_cat_decoder->p_cb_data,
p_cat_decoder->p_building_cat);
/* Reinitialize the structures */
p_cat_decoder->p_building_cat = NULL;
for(unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++)
p_cat_decoder->ap_sections[i] = NULL;
} }
}
else
{
dvbpsi_DeletePSISections(p_section);
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeCATSections * dvbpsi_DecodeCATSections
***************************************************************************** *****************************************************************************
...@@ -356,96 +336,91 @@ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder, ...@@ -356,96 +336,91 @@ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat, void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t* p_byte; uint8_t* p_byte;
while(p_section) while (p_section)
{
/* CAT descriptors */
p_byte = p_section->p_payload_start;
while(p_byte + 5 <= p_section->p_payload_end)
{ {
uint8_t i_tag = p_byte[0]; /* CAT descriptors */
uint8_t i_length = p_byte[1]; p_byte = p_section->p_payload_start;
if(i_length + 2 <= p_section->p_payload_end - p_byte) while (p_byte + 5 <= p_section->p_payload_end)
dvbpsi_CATAddDescriptor(p_cat, i_tag, i_length, p_byte + 2); {
p_byte += 2 + i_length; uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if (i_length + 2 <= p_section->p_payload_end - p_byte)
dvbpsi_CATAddDescriptor(p_cat, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
p_section = p_section->p_next;
} }
p_section = p_section->p_next;
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GenCATSections * dvbpsi_GenCATSections
***************************************************************************** *****************************************************************************
* Generate CAT sections based on the dvbpsi_cat_t structure. * Generate CAT sections based on the dvbpsi_cat_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat) dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_t* p_dvbpsi, dvbpsi_cat_t* p_cat)
{ {
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev; dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor; dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor;
p_current->i_table_id = 0x01; p_current->i_table_id = 0x01;
p_current->b_syntax_indicator = 1; p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0; p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */ p_current->i_length = 9; /* header + CRC_32 */
p_current->i_extension = 0; /* Not used in the CAT */ p_current->i_extension = 0; /* Not used in the CAT */
p_current->i_version = p_cat->i_version; p_current->i_version = p_cat->i_version;
p_current->b_current_next = p_cat->b_current_next; p_current->b_current_next = p_cat->b_current_next;
p_current->i_number = 0; p_current->i_number = 0;
p_current->p_payload_end += 8; /* just after the header */ p_current->p_payload_end += 8; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8; p_current->p_payload_start = p_current->p_data + 8;
/* CAT descriptors */ /* CAT descriptors */
while(p_descriptor != NULL) while (p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
{ {
p_prev = p_current; /* New section if needed */
p_current = dvbpsi_NewPSISection(1024); /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
p_prev->p_next = p_current; if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
p_current->i_table_id = 0x01; {
p_current->b_syntax_indicator = 1; p_prev = p_current;
p_current->b_private_indicator = 0; p_current = dvbpsi_NewPSISection(1024);
p_current->i_length = 9; /* header + CRC_32 */ p_prev->p_next = p_current;
p_current->i_extension = 0; /* Not used in the CAT */
p_current->i_version = p_cat->i_version; p_current->i_table_id = 0x01;
p_current->b_current_next = p_cat->b_current_next; p_current->b_syntax_indicator = 1;
p_current->i_number = p_prev->i_number + 1; p_current->b_private_indicator = 0;
p_current->p_payload_end += 8; /* just after the header */ p_current->i_length = 9; /* header + CRC_32 */
p_current->p_payload_start = p_current->p_data + 8; p_current->i_extension = 0; /* Not used in the CAT */
p_current->i_version = p_cat->i_version;
p_current->b_current_next = p_cat->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 8; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
}
/* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data, p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
} }
/* p_payload_end is where the descriptor begins */ /* Finalization */
p_current->p_payload_end[0] = p_descriptor->i_tag; p_prev = p_result;
p_current->p_payload_end[1] = p_descriptor->i_length; while (p_prev != NULL)
memcpy(p_current->p_payload_end + 2, {
p_descriptor->p_data, p_prev->i_last_number = p_current->i_number;
p_descriptor->i_length); dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
/* Increase length by descriptor_length + 2 */ }
p_current->p_payload_end += p_descriptor->i_length + 2; return p_result;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* Finalization */
p_prev = p_result;
while(p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
return p_result;
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.h which was written by * heavily based on pmt.h which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -39,7 +40,6 @@ ...@@ -39,7 +40,6 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_cat_t * dvbpsi_cat_t
*****************************************************************************/ *****************************************************************************/
...@@ -63,7 +63,6 @@ typedef struct dvbpsi_cat_s ...@@ -63,7 +63,6 @@ typedef struct dvbpsi_cat_s
} dvbpsi_cat_t; } dvbpsi_cat_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_cat_callback * dvbpsi_cat_callback
*****************************************************************************/ *****************************************************************************/
...@@ -74,21 +73,20 @@ typedef struct dvbpsi_cat_s ...@@ -74,21 +73,20 @@ typedef struct dvbpsi_cat_s
*/ */
typedef void (* dvbpsi_cat_callback)(void* p_cb_data, dvbpsi_cat_t* p_new_cat); typedef void (* dvbpsi_cat_callback)(void* p_cb_data, dvbpsi_cat_t* p_new_cat);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachCAT * dvbpsi_AttachCAT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback, * \fn dvbpsi_t *dvbpsi_AttachCAT(dvbpsi_t *p_dvbpsi,
void* p_cb_data) dvbpsi_cat_callback pf_callback, void* p_cb_data)
* \brief Creation and initialization of a CAT decoder. * \brief Creation and initialization of a CAT decoder.
* \param p_dvbpsi is a pointer to dvbpsi_t which holds a pointer to the decoder
* \param pf_callback function to call back on new CAT * \param pf_callback function to call back on new CAT
* \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 a pointer to the decoder for future calls. * \return a pointer to dvbpsi_t holding the decoder for future calls.
*/ */
dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback, dvbpsi_t *dvbpsi_AttachCAT(dvbpsi_t *p_dvbpsi, dvbpsi_cat_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachCAT * dvbpsi_DetachCAT
...@@ -96,13 +94,12 @@ dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback, ...@@ -96,13 +94,12 @@ dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback,
/*! /*!
* \fn void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi) * \fn void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi)
* \brief Destroy a CAT decoder. * \brief Destroy a CAT decoder.
* \param h_dvbpsi handle to the decoder * \param p_dvbpsi handle holds the decoder pointer
* \return nothing. * \return nothing.
* *
* The handle isn't valid any more. * The handle isn't valid any more.
*/ */
void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi); void dvbpsi_DetachCAT(dvbpsi_t *p_dvbpsi);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitCAT/dvbpsi_NewCAT * dvbpsi_InitCAT/dvbpsi_NewCAT
...@@ -136,7 +133,6 @@ do { \ ...@@ -136,7 +133,6 @@ do { \
dvbpsi_InitCAT(p_cat, i_version, b_current_next); \ dvbpsi_InitCAT(p_cat, i_version, b_current_next); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyCAT/dvbpsi_DeleteCAT * dvbpsi_EmptyCAT/dvbpsi_DeleteCAT
*****************************************************************************/ *****************************************************************************/
...@@ -160,7 +156,6 @@ do { \ ...@@ -160,7 +156,6 @@ do { \
free(p_cat); \ free(p_cat); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_CATAddDescriptor * dvbpsi_CATAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -180,20 +175,19 @@ dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat, ...@@ -180,20 +175,19 @@ dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat,
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_GenCATSections * dvbpsi_GenCATSections
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat) * \fn dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat)
* \brief CAT generator * \brief CAT generator
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_cat CAT structure * \param p_cat CAT structure
* \return a pointer to the list of generated PSI sections. * \return a pointer to the list of generated PSI sections.
* *
* Generate CAT sections based on the dvbpsi_cat_t structure. * Generate CAT sections based on the dvbpsi_cat_t structure.
*/ */
dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat); dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_t *p_dvbpsi, dvbpsi_cat_t* p_cat);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt_private.h which was written by * heavily based on pmt_private.h which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -36,28 +37,27 @@ ...@@ -36,28 +37,27 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_cat_decoder_s typedef struct dvbpsi_cat_decoder_s
{ {
dvbpsi_cat_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
dvbpsi_cat_t current_cat; dvbpsi_cat_callback pf_cat_callback;
dvbpsi_cat_t * p_building_cat; void * p_cb_data;
int b_current_valid; dvbpsi_cat_t current_cat;
dvbpsi_cat_t * p_building_cat;
uint8_t i_last_section_number; int b_current_valid;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_cat_decoder_t; uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_cat_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherCATSections * dvbpsi_GatherCATSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherCATSections(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section);
dvbpsi_psi_section_t* p_section);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeCATSections * dvbpsi_DecodeCATSections
...@@ -67,7 +67,6 @@ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder, ...@@ -67,7 +67,6 @@ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat, void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of cat_private.h" #error "Multiple inclusions of cat_private.h"
#endif #endif
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Johan Bilien <jobi@via.ecp.fr> * Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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,7 +26,6 @@ ...@@ -25,7 +26,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -46,113 +46,102 @@ ...@@ -46,113 +46,102 @@
#include "eit.h" #include "eit.h"
#include "eit_private.h" #include "eit_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachEIT * dvbpsi_AttachEIT
***************************************************************************** *****************************************************************************
* Initialize a EIT subtable decoder. * Initialize a EIT subtable decoder.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, dvbpsi_t *dvbpsi_AttachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
uint16_t i_extension, dvbpsi_eit_callback pf_callback, dvbpsi_eit_callback pf_callback, void* p_cb_data)
void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_eit_decoder_t* p_eit_decoder;
dvbpsi_eit_decoder_t* p_eit_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension) != NULL)
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) {
{ dvbpsi_error(p_dvbpsi, "EIT decoder",
dvbpsi_error(h_dvbpsi, "EIT decoder",
"Already a decoder for (table_id == 0x%02x," "Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return NULL;
}
return 1; p_subdec = (dvbpsi_demux_subdec_t*)calloc(1, sizeof(dvbpsi_demux_subdec_t));
} if (p_subdec == NULL)
return NULL;
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t)); p_eit_decoder = (dvbpsi_eit_decoder_t*)calloc(1, sizeof(dvbpsi_eit_decoder_t));
if(p_subdec == NULL) if (p_eit_decoder == NULL)
{ {
return 1; free(p_subdec);
} return NULL;
}
p_eit_decoder = (dvbpsi_eit_decoder_t*)malloc(sizeof(dvbpsi_eit_decoder_t)); /* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherEITSections;
p_subdec->p_cb_data = p_eit_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachEIT;
if(p_eit_decoder == NULL) /* Attach the subtable decoder to the demux */
{ p_subdec->p_next = p_demux->p_first_subdec;
free(p_subdec); p_demux->p_first_subdec = p_subdec;
return 1;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherEITSections;
p_subdec->p_cb_data = p_eit_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_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(unsigned int i = 0; i <= 255; i++)
p_eit_decoder->ap_sections[i] = NULL;
return 0;
}
/* 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 = 0;
p_eit_decoder->p_building_eit = NULL;
for (unsigned int i = 0; i <= 255; i++)
p_eit_decoder->ap_sections[i] = NULL;
return p_dvbpsi;
}
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachEIT * dvbpsi_DetachEIT
***************************************************************************** *****************************************************************************
* Close a EIT decoder. * Close a EIT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec; dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_eit_decoder_t* p_eit_decoder; dvbpsi_eit_decoder_t* p_eit_decoder;
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_demux == NULL) {
{ dvbpsi_error(p_dvbpsi, "EIT Decoder",
dvbpsi_error(h_dvbpsi, "EIT Decoder",
"No such EIT decoder (table_id == 0x%02x," "No such EIT decoder (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return; return;
} }
p_eit_decoder = (dvbpsi_eit_decoder_t*)p_subdec->p_cb_data;
free(p_eit_decoder->p_building_eit);
for(unsigned int i = 0; i <= 255; i++) p_eit_decoder = (dvbpsi_eit_decoder_t*)p_subdec->p_cb_data;
{ 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 <= 255; 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);
p_subdec = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitEIT * dvbpsi_InitEIT
***************************************************************************** *****************************************************************************
...@@ -163,17 +152,16 @@ void dvbpsi_InitEIT(dvbpsi_eit_t* p_eit, uint16_t i_service_id, uint8_t i_versio ...@@ -163,17 +152,16 @@ void dvbpsi_InitEIT(dvbpsi_eit_t* p_eit, uint16_t i_service_id, uint8_t i_versio
uint8_t i_segment_last_section_number, uint8_t i_segment_last_section_number,
uint8_t i_last_table_id) uint8_t i_last_table_id)
{ {
p_eit->i_service_id = i_service_id; p_eit->i_service_id = i_service_id;
p_eit->i_version = i_version; p_eit->i_version = i_version;
p_eit->b_current_next = b_current_next; p_eit->b_current_next = b_current_next;
p_eit->i_ts_id = i_ts_id; p_eit->i_ts_id = i_ts_id;
p_eit->i_network_id = i_network_id; p_eit->i_network_id = i_network_id;
p_eit->i_segment_last_section_number = i_segment_last_section_number; p_eit->i_segment_last_section_number = i_segment_last_section_number;
p_eit->i_last_table_id = i_last_table_id; p_eit->i_last_table_id = i_last_table_id;
p_eit->p_first_event = NULL; p_eit->p_first_event = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyEIT * dvbpsi_EmptyEIT
***************************************************************************** *****************************************************************************
...@@ -181,20 +169,18 @@ void dvbpsi_InitEIT(dvbpsi_eit_t* p_eit, uint16_t i_service_id, uint8_t i_versio ...@@ -181,20 +169,18 @@ void dvbpsi_InitEIT(dvbpsi_eit_t* p_eit, uint16_t i_service_id, uint8_t i_versio
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyEIT(dvbpsi_eit_t* p_eit) void dvbpsi_EmptyEIT(dvbpsi_eit_t* p_eit)
{ {
dvbpsi_eit_event_t* p_event = p_eit->p_first_event; dvbpsi_eit_event_t* p_event = p_eit->p_first_event;
while(p_event != NULL) while(p_event != NULL)
{ {
dvbpsi_eit_event_t* p_tmp = p_event->p_next; dvbpsi_eit_event_t* p_tmp = p_event->p_next;
dvbpsi_DeleteDescriptors(p_event->p_first_descriptor); dvbpsi_DeleteDescriptors(p_event->p_first_descriptor);
free(p_event); free(p_event);
p_event = p_tmp; p_event = p_tmp;
} }
p_eit->p_first_event = NULL;
p_eit->p_first_event = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EITAddEvent * dvbpsi_EITAddEvent
***************************************************************************** *****************************************************************************
...@@ -204,11 +190,11 @@ dvbpsi_eit_event_t* dvbpsi_EITAddEvent(dvbpsi_eit_t* p_eit, ...@@ -204,11 +190,11 @@ dvbpsi_eit_event_t* dvbpsi_EITAddEvent(dvbpsi_eit_t* p_eit,
uint16_t i_event_id, uint64_t i_start_time, uint32_t i_duration, uint16_t i_event_id, uint64_t i_start_time, uint32_t i_duration,
uint8_t i_running_status,int b_free_ca) uint8_t i_running_status,int b_free_ca)
{ {
dvbpsi_eit_event_t* p_event dvbpsi_eit_event_t* p_event;
= (dvbpsi_eit_event_t*)malloc(sizeof(dvbpsi_eit_event_t)); p_event = (dvbpsi_eit_event_t*)calloc(1,sizeof(dvbpsi_eit_event_t));
if (p_event == NULL)
return NULL;
if(p_event)
{
p_event->i_event_id = i_event_id; p_event->i_event_id = i_event_id;
p_event->i_start_time = i_start_time; p_event->i_start_time = i_start_time;
p_event->i_duration = i_duration; p_event->i_duration = i_duration;
...@@ -217,71 +203,58 @@ dvbpsi_eit_event_t* dvbpsi_EITAddEvent(dvbpsi_eit_t* p_eit, ...@@ -217,71 +203,58 @@ dvbpsi_eit_event_t* dvbpsi_EITAddEvent(dvbpsi_eit_t* p_eit,
p_event->p_next = NULL; p_event->p_next = NULL;
p_event->p_first_descriptor = NULL; p_event->p_first_descriptor = NULL;
if(p_eit->p_first_event == NULL) if (p_eit->p_first_event == NULL)
{ p_eit->p_first_event = p_event;
p_eit->p_first_event = p_event;
}
else else
{ {
dvbpsi_eit_event_t* p_last_event = p_eit->p_first_event; dvbpsi_eit_event_t* p_last_event = p_eit->p_first_event;
while(p_last_event->p_next != NULL) while(p_last_event->p_next != NULL)
p_last_event = p_last_event->p_next; p_last_event = p_last_event->p_next;
p_last_event->p_next = p_event; p_last_event->p_next = p_event;
} }
} return p_event;
return p_event;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EITEventAddDescriptor * dvbpsi_EITEventAddDescriptor
***************************************************************************** *****************************************************************************
* Add a descriptor in the EIT event description. * Add a descriptor in the EIT event description.
*****************************************************************************/ *****************************************************************************/
dvbpsi_descriptor_t* dvbpsi_EITEventAddDescriptor( dvbpsi_descriptor_t* dvbpsi_EITEventAddDescriptor( dvbpsi_eit_event_t* p_event,
dvbpsi_eit_event_t* p_event, uint8_t i_tag, uint8_t i_length, uint8_t* p_data)
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data)
{ {
dvbpsi_descriptor_t* p_descriptor dvbpsi_descriptor_t* p_descriptor;
= dvbpsi_NewDescriptor(i_tag, i_length, p_data); p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if (p_descriptor == NULL)
return NULL;
if(p_descriptor) if (p_event->p_first_descriptor == NULL)
{
if(p_event->p_first_descriptor == NULL)
{
p_event->p_first_descriptor = p_descriptor; p_event->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_event->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_event->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherEITSections * dvbpsi_GatherEITSections
***************************************************************************** *****************************************************************************
* Callback for the subtable demultiplexor. * Callback for the subtable demultiplexor.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder, void dvbpsi_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_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_eit_decoder_t* p_eit_decoder dvbpsi_eit_decoder_t* p_eit_decoder
= (dvbpsi_eit_decoder_t*)p_private_decoder; = (dvbpsi_eit_decoder_t*)p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "EIT decoder", dvbpsi_debug(p_dvbpsi, "EIT decoder",
"Table version %2d, " "i_table_id %2d, " "i_extension %5d, " "Table version %2d, " "i_table_id %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id, p_section->i_version, p_section->i_table_id,
...@@ -289,102 +262,101 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -289,102 +262,101 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
if(!p_section->b_syntax_indicator) if (!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "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(b_append)
{
/* TS discontinuity check */
if(p_psi_decoder->b_discontinuity)
{ {
b_reinit = 1; /* Invalid section_syntax_indicator */
p_psi_decoder->b_discontinuity = 0; dvbpsi_error(p_dvbpsi, "EIT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
} }
else
/* Now if b_append is true then we have a valid EIT section */
if (b_append)
{ {
/* Perform a few sanity checks */ /* TS discontinuity check */
if(p_eit_decoder->p_building_eit) if (p_demux->b_discontinuity)
{
if(p_eit_decoder->p_building_eit->i_service_id != p_section->i_extension)
{ {
/* service_id */ b_reinit = 1;
dvbpsi_error(h_dvbpsi, "EIT decoder", p_demux->b_discontinuity = 0;
"'service_id' differs"
" whereas no TS discontinuity has occurred");
b_reinit = 1;
} }
else if(p_eit_decoder->p_building_eit->i_version else
!= p_section->i_version)
{ {
/* version_number */ /* Perform a few sanity checks */
dvbpsi_error(h_dvbpsi, "EIT decoder", if (p_eit_decoder->p_building_eit)
"'version_number' differs" {
" whereas no discontinuity has occurred"); if (p_eit_decoder->p_building_eit->i_service_id
b_reinit = 1; != p_section->i_extension)
{
/* service_id */
dvbpsi_error(p_dvbpsi, "EIT decoder",
"'service_id' differs"
" whereas no TS discontinuity has occurred");
b_reinit = 1;
}
else if (p_eit_decoder->p_building_eit->i_version
!= p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "EIT decoder",
"'version_number' differs"
" whereas no discontinuity has occurred");
b_reinit = 1;
}
else if (p_eit_decoder->i_last_section_number
!= p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "EIT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
}
else
{
if ( (p_eit_decoder->b_current_valid)
&& (p_eit_decoder->current_eit.i_version == p_section->i_version)
&& (p_eit_decoder->current_eit.b_current_next == p_section->b_current_next))
{
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
} }
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 = 0;
/* Free structures */
if (p_eit_decoder->p_building_eit)
{ {
/* last_section_number */ free(p_eit_decoder->p_building_eit);
dvbpsi_error(h_dvbpsi, "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)
&& (p_eit_decoder->current_eit.b_current_next ==
p_section->b_current_next))
{ {
/* Don't decode since this version is already decoded */ if(p_eit_decoder->ap_sections[i] != NULL)
b_append = 0; {
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
p_eit_decoder->ap_sections[i] = NULL;
}
} }
}
} }
}
/* Reinit the decoder if wanted */ /* Append the section to the list if wanted */
if(b_reinit) if (b_append)
{
/* 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); int b_complete;
p_eit_decoder->p_building_eit = NULL;
}
/* Clear the section array */
for(unsigned int 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 */ /* Initialize the structures if it's the first section received */
if(b_append) if (!p_eit_decoder->p_building_eit)
{ {
int b_complete; p_eit_decoder->p_building_eit = (dvbpsi_eit_t*)calloc(1, sizeof(dvbpsi_eit_t));
dvbpsi_InitEIT(p_eit_decoder->p_building_eit,
/* Initialize the structures if it's the first section received */
if(!p_eit_decoder->p_building_eit)
{
p_eit_decoder->p_building_eit =
(dvbpsi_eit_t*)malloc(sizeof(dvbpsi_eit_t));
dvbpsi_InitEIT(p_eit_decoder->p_building_eit,
p_section->i_extension, p_section->i_extension,
p_section->i_version, p_section->i_version,
p_section->b_current_next, p_section->b_current_next,
...@@ -394,108 +366,108 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -394,108 +366,108 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
| p_section->p_payload_start[3], | p_section->p_payload_start[3],
p_section->p_payload_start[4], p_section->p_payload_start[4],
p_section->p_payload_start[5]); p_section->p_payload_start[5]);
p_eit_decoder->i_last_section_number = p_section->i_last_number; p_eit_decoder->i_last_section_number = p_section->i_last_number;
p_eit_decoder->i_first_received_section_number = p_section->i_number; p_eit_decoder->i_first_received_section_number = p_section->i_number;
} }
/* Fill the section array */
if(p_eit_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(h_dvbpsi, "EIT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[p_section->i_number]);
}
p_eit_decoder->ap_sections[p_section->i_number] = p_section;
/* Check if we have all the sections */
b_complete = 0;
/* As there may be gaps in the section_number fields (see below), we
* have to wait until we have received a section_number twice or
* until we have a received a section_number which is
* first_received_section_number - 1;
* if the first_received_section_number is 0, it's enough to wait
* until the last_section_number has been received;
* this is the only way to be sure that a complete table has been
* sent! */
if((p_eit_decoder->i_first_received_section_number > 0 &&
(p_section->i_number ==
p_eit_decoder->i_first_received_section_number ||
p_section->i_number ==
p_eit_decoder->i_first_received_section_number - 1)) ||
(p_eit_decoder->i_first_received_section_number == 0 &&
p_section->i_number == p_eit_decoder->i_last_section_number))
{
for(unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
{
if(!p_eit_decoder->ap_sections[i])
break;
if(i == p_eit_decoder->i_last_section_number) /* Fill the section array */
if (p_eit_decoder->ap_sections[p_section->i_number] != NULL)
{ {
b_complete = 1; dvbpsi_debug(p_dvbpsi, "EIT decoder", "overwrite section number %d",
break; 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;
/* ETSI EN 300 468 V1.5.1 section 5.2.4 says that the EIT
* sections may be structured into a number of segments and /* Check if we have all the sections */
* that there may be a gap in the section_number between b_complete = 0;
* two segments (but not within a single segment); thus at
* the end of a segment (indicated by /* As there may be gaps in the section_number fields (see below), we
* section_number == segment_last_section_number) * have to wait until we have received a section_number twice or
* we have to search for the beginning of the next segment) */ * until we have a received a section_number which is
if(i == p_eit_decoder->ap_sections[i]->p_payload_start[4]) * first_received_section_number - 1;
* if the first_received_section_number is 0, it's enough to wait
* until the last_section_number has been received;
* this is the only way to be sure that a complete table has been
* sent! */
if ((p_eit_decoder->i_first_received_section_number > 0 &&
(p_section->i_number ==
p_eit_decoder->i_first_received_section_number ||
p_section->i_number ==
p_eit_decoder->i_first_received_section_number - 1)) ||
(p_eit_decoder->i_first_received_section_number == 0 &&
p_section->i_number == p_eit_decoder->i_last_section_number))
{ {
while(!p_eit_decoder->ap_sections[i + 1] && for (unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
(i + 1 < p_eit_decoder->i_last_section_number)) {
{ if (!p_eit_decoder->ap_sections[i])
i++; break;
}
if (i == p_eit_decoder->i_last_section_number)
{
b_complete = 1;
break;
}
/* ETSI EN 300 468 V1.5.1 section 5.2.4 says that the EIT
* sections may be structured into a number of segments and
* that there may be a gap in the section_number between
* two segments (but not within a single segment); thus at
* the end of a segment (indicated by
* section_number == segment_last_section_number)
* we have to search for the beginning of the next segment) */
if (i == p_eit_decoder->ap_sections[i]->p_payload_start[4])
{
while (!p_eit_decoder->ap_sections[i + 1] &&
(i + 1 < p_eit_decoder->i_last_section_number))
{
i++;
}
}
}
} }
}
}
if(b_complete) if (b_complete)
{
/* Save the current information */
p_eit_decoder->current_eit = *p_eit_decoder->p_building_eit;
p_eit_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_eit_decoder->i_last_section_number)
{
dvbpsi_psi_section_t * p_prev_section;
p_prev_section = p_eit_decoder->ap_sections[0];
for(unsigned int i = 1; i <= p_eit_decoder->i_last_section_number; i++)
{ {
if(p_eit_decoder->ap_sections[i] != NULL) /* Save the current information */
{ p_eit_decoder->current_eit = *p_eit_decoder->p_building_eit;
p_prev_section->p_next = p_eit_decoder->ap_sections[i]; p_eit_decoder->b_current_valid = 1;
p_prev_section = p_eit_decoder->ap_sections[i]; /* Chain the sections */
} if (p_eit_decoder->i_last_section_number)
{
dvbpsi_psi_section_t * p_prev_section;
p_prev_section = p_eit_decoder->ap_sections[0];
for (unsigned int i = 1; i <= p_eit_decoder->i_last_section_number; i++)
{
if (p_eit_decoder->ap_sections[i] != NULL)
{
p_prev_section->p_next = p_eit_decoder->ap_sections[i];
p_prev_section = p_eit_decoder->ap_sections[i];
}
}
}
/* Decode the sections */
dvbpsi_DecodeEITSections(p_eit_decoder->p_building_eit,
p_eit_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[0]);
/* signal the new EIT */
p_eit_decoder->pf_eit_callback(p_eit_decoder->p_cb_data,
p_eit_decoder->p_building_eit);
/* Reinitialize the structures */
p_eit_decoder->p_building_eit = NULL;
for (unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
p_eit_decoder->ap_sections[i] = NULL;
} }
}
/* Decode the sections */
dvbpsi_DecodeEITSections(p_eit_decoder->p_building_eit,
p_eit_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[0]);
/* signal the new EIT */
p_eit_decoder->pf_callback(p_eit_decoder->p_cb_data,
p_eit_decoder->p_building_eit);
/* Reinitialize the structures */
p_eit_decoder->p_building_eit = NULL;
for(unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
p_eit_decoder->ap_sections[i] = NULL;
} }
} else
else {
{ dvbpsi_DeletePSISections(p_section);
dvbpsi_DeletePSISections(p_section); }
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeEITSections * dvbpsi_DecodeEITSections
***************************************************************************** *****************************************************************************
...@@ -504,39 +476,38 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -504,39 +476,38 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
void dvbpsi_DecodeEITSections(dvbpsi_eit_t* p_eit, void dvbpsi_DecodeEITSections(dvbpsi_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;
while(p_section) while (p_section)
{
for(p_byte = p_section->p_payload_start + 6;
p_byte < p_section->p_payload_end - 12;)
{ {
uint16_t i_event_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1]; for (p_byte = p_section->p_payload_start + 6;
uint64_t i_start_time = ((uint64_t)(p_byte[2]) << 32) p_byte < p_section->p_payload_end - 12;)
| ((uint64_t)(p_byte[3]) << 24) {
| ((uint64_t)(p_byte[4]) << 16) uint16_t i_event_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1];
| ((uint64_t)(p_byte[5]) << 8) | p_byte[6]; uint64_t i_start_time = ((uint64_t)(p_byte[2]) << 32)
uint32_t i_duration = ((uint32_t)(p_byte[7]) << 16) | ((uint64_t)(p_byte[3]) << 24)
| ((uint32_t)(p_byte[8]) << 8) | p_byte[9]; | ((uint64_t)(p_byte[4]) << 16)
uint8_t i_running_status = (uint8_t)(p_byte[10]) >> 5; | ((uint64_t)(p_byte[5]) << 8) | p_byte[6];
int b_free_ca = (int)(p_byte[10] & 0x10) >> 4; uint32_t i_duration = ((uint32_t)(p_byte[7]) << 16)
uint16_t i_ev_length = ((uint16_t)(p_byte[10] & 0xf) << 8) | p_byte[11]; | ((uint32_t)(p_byte[8]) << 8) | p_byte[9];
dvbpsi_eit_event_t* p_event = dvbpsi_EITAddEvent(p_eit, uint8_t i_running_status = (uint8_t)(p_byte[10]) >> 5;
i_event_id, i_start_time, i_duration, int b_free_ca = (int)(p_byte[10] & 0x10) >> 4;
i_running_status, b_free_ca); uint16_t i_ev_length = ((uint16_t)(p_byte[10] & 0xf) << 8) | p_byte[11];
/* Event descriptors */ dvbpsi_eit_event_t* p_event = dvbpsi_EITAddEvent(p_eit,
p_byte += 12; i_event_id, i_start_time, i_duration,
p_end = p_byte + i_ev_length; i_running_status, b_free_ca);
while(p_byte + 2 <= p_end) /* Event descriptors */
{ p_byte += 12;
uint8_t i_tag = p_byte[0]; p_end = p_byte + i_ev_length;
uint8_t i_length = p_byte[1]; while (p_byte + 2 <= p_end)
if(i_length + 2 <= p_end - p_byte) {
dvbpsi_EITEventAddDescriptor(p_event, i_tag, i_length, p_byte + 2); uint8_t i_tag = p_byte[0];
p_byte += 2 + i_length; uint8_t i_length = p_byte[1];
} if (i_length + 2 <= p_end - p_byte)
dvbpsi_EITEventAddDescriptor(p_event, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
}
p_section = p_section->p_next;
} }
p_section = p_section->p_next;
}
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* $Id: eit.h 88 2004-02-24 14:31:18Z sam $ * $Id: eit.h 88 2004-02-24 14:31:18Z sam $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_eit_event_t * dvbpsi_eit_event_t
*****************************************************************************/ *****************************************************************************/
...@@ -70,7 +70,6 @@ typedef struct dvbpsi_eit_event_s ...@@ -70,7 +70,6 @@ typedef struct dvbpsi_eit_event_s
} dvbpsi_eit_event_t; } dvbpsi_eit_event_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_eit_t * dvbpsi_eit_t
*****************************************************************************/ *****************************************************************************/
...@@ -99,7 +98,6 @@ typedef struct dvbpsi_eit_s ...@@ -99,7 +98,6 @@ typedef struct dvbpsi_eit_s
} dvbpsi_eit_t; } dvbpsi_eit_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_eit_callback * dvbpsi_eit_callback
*****************************************************************************/ *****************************************************************************/
...@@ -110,27 +108,25 @@ typedef struct dvbpsi_eit_s ...@@ -110,27 +108,25 @@ typedef struct dvbpsi_eit_s
*/ */
typedef void (* dvbpsi_eit_callback)(void* p_cb_data, dvbpsi_eit_t* p_new_eit); typedef void (* dvbpsi_eit_callback)(void* p_cb_data, dvbpsi_eit_t* p_new_eit);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachEIT * dvbpsi_AttachEIT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_AttachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn dvbpsi_t *dvbpsi_AttachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_eit_callback pf_callback, uint16_t i_extension, dvbpsi_eit_callback pf_callback,
void* p_cb_data) 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 pointer to Subtable demultiplexor to which the EIT decoder is attached.
* \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F. * \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
* \param i_extension Table ID extension, here service ID. * \param i_extension Table ID extension, here service 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 p_dvbpsi or NULL on error
*/ */
int dvbpsi_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, dvbpsi_t *dvbpsi_AttachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_eit_callback pf_callback, uint16_t i_extension, dvbpsi_eit_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachEIT * dvbpsi_DetachEIT
*****************************************************************************/ *****************************************************************************/
...@@ -138,15 +134,15 @@ int dvbpsi_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, ...@@ -138,15 +134,15 @@ int dvbpsi_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
* \fn void dvbpsi_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn void dvbpsi_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
* \brief Destroy a EIT decoder. * \brief Destroy a EIT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached. * \param p_dvbpsi dvbpsi handle pointing to Subtable demultiplexor to which the
eit decoder is attached.
* \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F. * \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
* \param i_extension Table ID extension, here service ID. * \param i_extension Table ID extension, here service ID.
* \return nothing. * \return nothing.
*/ */
void dvbpsi_DetachEIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitEIT/dvbpsi_NewEIT * dvbpsi_InitEIT/dvbpsi_NewEIT
*****************************************************************************/ *****************************************************************************/
...@@ -188,7 +184,6 @@ do { \ ...@@ -188,7 +184,6 @@ do { \
dvbpsi_InitEIT(p_eit, i_service_id, i_version, b_current_next, i_ts_id, i_network_id, i_segment_last_section_number, i_last_table_id); \ dvbpsi_InitEIT(p_eit, i_service_id, i_version, b_current_next, i_ts_id, i_network_id, i_segment_last_section_number, i_last_table_id); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyEIT/dvbpsi_DeleteEIT * dvbpsi_EmptyEIT/dvbpsi_DeleteEIT
*****************************************************************************/ *****************************************************************************/
...@@ -212,7 +207,6 @@ do { \ ...@@ -212,7 +207,6 @@ do { \
free(p_eit); \ free(p_eit); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EITAddEvent * dvbpsi_EITAddEvent
*****************************************************************************/ *****************************************************************************/
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id: eit_private.h 88 2004-02-24 14:31:18Z sam $ * $Id: eit_private.h 88 2004-02-24 14:31:18Z sam $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -27,7 +28,6 @@ ...@@ -27,7 +28,6 @@
#ifndef _DVBPSI_EIT_PRIVATE_H_ #ifndef _DVBPSI_EIT_PRIVATE_H_
#define _DVBPSI_EIT_PRIVATE_H_ #define _DVBPSI_EIT_PRIVATE_H_
/***************************************************************************** /*****************************************************************************
* dvbpsi_eit_decoder_t * dvbpsi_eit_decoder_t
***************************************************************************** *****************************************************************************
...@@ -35,31 +35,31 @@ ...@@ -35,31 +35,31 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_eit_decoder_s typedef struct dvbpsi_eit_decoder_s
{ {
dvbpsi_eit_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
dvbpsi_eit_t current_eit; dvbpsi_eit_callback pf_eit_callback;
dvbpsi_eit_t * p_building_eit; void * p_cb_data;
int b_current_valid; dvbpsi_eit_t current_eit;
dvbpsi_eit_t * p_building_eit;
uint8_t i_last_section_number; int b_current_valid;
uint8_t i_first_received_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_eit_decoder_t; uint8_t i_last_section_number;
uint8_t i_first_received_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_eit_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherEITSections * dvbpsi_GatherEITSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherEITSections(dvbpsi_decoder_t* p_psi_decoder, void dvbpsi_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_DecodeEITSection * dvbpsi_DecodeEITSection
***************************************************************************** *****************************************************************************
...@@ -68,7 +68,6 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t* p_psi_decoder, ...@@ -68,7 +68,6 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t* p_psi_decoder,
void dvbpsi_DecodeEITSections(dvbpsi_eit_t* p_eit, void dvbpsi_DecodeEITSections(dvbpsi_eit_t* p_eit,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of eit_private.h" #error "Multiple inclusions of eit_private.h"
#endif #endif
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -26,7 +27,6 @@ ...@@ -26,7 +27,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -47,114 +47,104 @@ ...@@ -47,114 +47,104 @@
#include "nit.h" #include "nit.h"
#include "nit_private.h" #include "nit_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachNIT * dvbpsi_AttachNIT
***************************************************************************** *****************************************************************************
* Initialize a NIT subtable decoder. * Initialize a NIT subtable decoder.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_AttachNIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachNIT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_nit_callback pf_callback, uint16_t i_extension, dvbpsi_nit_callback pf_callback,
void* p_cb_data) void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_nit_decoder_t* p_nit_decoder;
dvbpsi_nit_decoder_t* p_nit_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) {
{ dvbpsi_error(p_dvbpsi, "NIT decoder",
dvbpsi_error(h_dvbpsi, "NIT decoder",
"Already a decoder for (table_id == 0x%02x," "Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return 1;
}
return 1; p_subdec = (dvbpsi_demux_subdec_t*)calloc(1, sizeof(dvbpsi_demux_subdec_t));
} if (p_subdec == NULL)
return 1;
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t)); p_nit_decoder = (dvbpsi_nit_decoder_t*)calloc(1, sizeof(dvbpsi_nit_decoder_t));
if(p_subdec == NULL) if (p_nit_decoder == NULL)
{ {
return 1; free(p_subdec);
} return 1;
}
p_nit_decoder = (dvbpsi_nit_decoder_t*)malloc(sizeof(dvbpsi_nit_decoder_t)); /* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherNITSections;
p_subdec->p_cb_data = p_nit_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachNIT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* NIT decoder information */
p_nit_decoder->i_network_id = i_extension;
p_nit_decoder->pf_nit_callback = pf_callback;
p_nit_decoder->p_cb_data = p_cb_data;
/* NIT decoder initial state */
p_nit_decoder->b_current_valid = 0;
p_nit_decoder->p_building_nit = NULL;
for (unsigned int i = 0; i <= 255; i++)
p_nit_decoder->ap_sections[i] = NULL;
if(p_nit_decoder == NULL) return 0;
{
free(p_subdec);
return 1;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherNITSections;
p_subdec->p_cb_data = p_nit_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachNIT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* NIT decoder information */
p_nit_decoder->i_network_id = i_extension;
p_nit_decoder->pf_callback = pf_callback;
p_nit_decoder->p_cb_data = p_cb_data;
/* NIT decoder initial state */
p_nit_decoder->b_current_valid = 0;
p_nit_decoder->p_building_nit = NULL;
for(unsigned int i = 0; i <= 255; i++)
p_nit_decoder->ap_sections[i] = NULL;
return 0;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachNIT * dvbpsi_DetachNIT
***************************************************************************** *****************************************************************************
* Close a NIT decoder. * Close a NIT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachNIT(dvbpsi_t * p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec; dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_nit_decoder_t* p_nit_decoder; dvbpsi_nit_decoder_t* p_nit_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_demux == NULL) p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
{ if(p_demux == NULL)
dvbpsi_error(h_dvbpsi, "NIT Decoder", {
dvbpsi_error(p_dvbpsi, "NIT Decoder",
"No such NIT decoder (table_id == 0x%02x," "No such NIT decoder (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return; return;
} }
p_nit_decoder = (dvbpsi_nit_decoder_t*)p_subdec->p_cb_data;
free(p_nit_decoder->p_building_nit);
for(unsigned int i = 0; i <= 255; i++) p_nit_decoder = (dvbpsi_nit_decoder_t*)p_subdec->p_cb_data;
{ free(p_nit_decoder->p_building_nit);
if(p_nit_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[i]);
}
free(p_subdec->p_cb_data); for (unsigned int i = 0; i <= 255; i++)
{
if (p_nit_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_nit_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);
p_subdec = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitNIT * dvbpsi_InitNIT
***************************************************************************** *****************************************************************************
...@@ -163,14 +153,13 @@ void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -163,14 +153,13 @@ void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id, void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id,
uint8_t i_version, int b_current_next) uint8_t i_version, int b_current_next)
{ {
p_nit->i_network_id = i_network_id; p_nit->i_network_id = i_network_id;
p_nit->i_version = i_version; p_nit->i_version = i_version;
p_nit->b_current_next = b_current_next; p_nit->b_current_next = b_current_next;
p_nit->p_first_descriptor = NULL; p_nit->p_first_descriptor = NULL;
p_nit->p_first_ts = NULL; p_nit->p_first_ts = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyNIT * dvbpsi_EmptyNIT
***************************************************************************** *****************************************************************************
...@@ -178,23 +167,22 @@ void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id, ...@@ -178,23 +167,22 @@ void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id,
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyNIT(dvbpsi_nit_t* p_nit) void dvbpsi_EmptyNIT(dvbpsi_nit_t* p_nit)
{ {
dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts; dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
dvbpsi_DeleteDescriptors(p_nit->p_first_descriptor); dvbpsi_DeleteDescriptors(p_nit->p_first_descriptor);
while(p_ts != NULL) while (p_ts != NULL)
{ {
dvbpsi_nit_ts_t* p_tmp = p_ts->p_next; dvbpsi_nit_ts_t* p_tmp = p_ts->p_next;
dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor); dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor);
free(p_ts); free(p_ts);
p_ts = p_tmp; p_ts = p_tmp;
} }
p_nit->p_first_descriptor = NULL; p_nit->p_first_descriptor = NULL;
p_nit->p_first_ts = NULL; p_nit->p_first_ts = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_NITAddDescriptor * dvbpsi_NITAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -204,28 +192,23 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit, ...@@ -204,28 +192,23 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
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 == NULL)
return NULL;
if(p_descriptor) if (p_nit->p_first_descriptor == NULL)
{ p_nit->p_first_descriptor = p_descriptor;
if(p_nit->p_first_descriptor == NULL)
{
p_nit->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_nit->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_nit->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_NITAddTS * dvbpsi_NITAddTS
***************************************************************************** *****************************************************************************
...@@ -234,32 +217,27 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit, ...@@ -234,32 +217,27 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit, dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit,
uint16_t i_ts_id, uint16_t i_orig_network_id) uint16_t i_ts_id, uint16_t i_orig_network_id)
{ {
dvbpsi_nit_ts_t* p_ts = (dvbpsi_nit_ts_t*)malloc(sizeof(dvbpsi_nit_ts_t)); dvbpsi_nit_ts_t* p_ts = (dvbpsi_nit_ts_t*)malloc(sizeof(dvbpsi_nit_ts_t));
if (p_ts == NULL)
return NULL;
if(p_ts)
{
p_ts->i_ts_id = i_ts_id; p_ts->i_ts_id = i_ts_id;
p_ts->i_orig_network_id = i_orig_network_id; p_ts->i_orig_network_id = i_orig_network_id;
p_ts->p_first_descriptor = NULL; p_ts->p_first_descriptor = NULL;
p_ts->p_next = NULL; p_ts->p_next = NULL;
if(p_nit->p_first_ts == NULL) if (p_nit->p_first_ts == NULL)
{ p_nit->p_first_ts = p_ts;
p_nit->p_first_ts = p_ts;
}
else else
{ {
dvbpsi_nit_ts_t* p_last_ts = p_nit->p_first_ts; dvbpsi_nit_ts_t* p_last_ts = p_nit->p_first_ts;
while(p_last_ts->p_next != NULL) while(p_last_ts->p_next != NULL)
p_last_ts = p_last_ts->p_next; p_last_ts = p_last_ts->p_next;
p_last_ts->p_next = p_ts; p_last_ts->p_next = p_ts;
} }
} return p_ts;
return p_ts;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_NITTSAddDescriptor * dvbpsi_NITTSAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -269,474 +247,461 @@ dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts, ...@@ -269,474 +247,461 @@ dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts,
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 == NULL)
return NULL;
if(p_descriptor) if (p_ts->p_first_descriptor == NULL)
{
if(p_ts->p_first_descriptor == NULL)
{
p_ts->p_first_descriptor = p_descriptor; p_ts->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_ts->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_ts->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherNITSections * dvbpsi_GatherNITSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherNITSections(dvbpsi_decoder_t * p_decoder, void dvbpsi_GatherNITSections(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_handle h_dvbpsi = (dvbpsi_handle) p_decoder; dvbpsi_nit_decoder_t* p_nit_decoder
dvbpsi_nit_decoder_t* p_nit_decoder
= (dvbpsi_nit_decoder_t*)p_private_decoder; = (dvbpsi_nit_decoder_t*)p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "NIT decoder", dvbpsi_debug(p_dvbpsi, "NIT decoder",
"Table version %2d, " "i_extension %5d, " "Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension, p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
if(p_section->i_table_id != 0x40 && p_section->i_table_id != 0x41) if (p_section->i_table_id != 0x40 && p_section->i_table_id != 0x41)
{ {
/* Invalid table_id value */ /* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "NIT decoder", dvbpsi_error(p_dvbpsi, "NIT decoder",
"invalid section (table_id == 0x%02x)", "invalid section (table_id == 0x%02x)",
p_section->i_table_id); p_section->i_table_id);
b_append = 0; b_append = 0;
} }
if(b_append && !p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "NIT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
/* Now if b_append is true then we have a valid NIT section */
if(b_append && (p_nit_decoder->i_network_id != p_section->i_extension))
{
/* Invalid program_number */
#if 0
dvbpsi_error(h_dvbpsi, "NIT decoder", "'network_id' don't match");
#endif
b_append = 0;
}
if(b_append) if (b_append && !p_section->b_syntax_indicator)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
{ {
b_reinit = 1; /* Invalid section_syntax_indicator */
p_decoder->b_discontinuity = 0; dvbpsi_error(p_dvbpsi, "NIT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
} }
else
/* Now if b_append is true then we have a valid NIT section */
if (b_append && (p_nit_decoder->i_network_id != p_section->i_extension))
{ {
/* Perform some few sanity checks */ /* Invalid program_number */
if(p_nit_decoder->p_building_nit) dvbpsi_error(p_dvbpsi, "NIT decoder", "'network_id' don't match");
{ b_append = 0;
if(p_nit_decoder->p_building_nit->i_version != p_section->i_version) }
if (b_append)
{
/* TS discontinuity check */
if (p_nit_decoder->b_discontinuity)
{ {
/* version_number */ b_reinit = 1;
dvbpsi_error(h_dvbpsi, "NIT decoder", p_nit_decoder->b_discontinuity = 0;
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
} }
else if(p_nit_decoder->i_last_section_number else
!= p_section->i_last_number)
{ {
/* last_section_number */ /* Perform some few sanity checks */
dvbpsi_error(h_dvbpsi, "NIT decoder", if (p_nit_decoder->p_building_nit)
"'last_section_number' differs" {
" whereas no discontinuity has occured"); if (p_nit_decoder->p_building_nit->i_version != p_section->i_version)
b_reinit = 1; {
} /* version_number */
} dvbpsi_error(p_dvbpsi, "NIT decoder",
else "'version_number' differs"
{ " whereas no discontinuity has occured");
if( (p_nit_decoder->b_current_valid) b_reinit = 1;
&& (p_nit_decoder->current_nit.i_version == p_section->i_version) }
&& (p_nit_decoder->current_nit.b_current_next == else if (p_nit_decoder->i_last_section_number
!= p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "NIT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
}
else
{
if ( (p_nit_decoder->b_current_valid)
&& (p_nit_decoder->current_nit.i_version == p_section->i_version)
&& (p_nit_decoder->current_nit.b_current_next ==
p_section->b_current_next)) p_section->b_current_next))
{ {
/* Don't decode since this version is already decoded */ /* Don't decode since this version is already decoded */
b_append = 0; b_append = 0;
}
}
} }
}
} }
}
/* Reinit the decoder if wanted */ /* Reinit the decoder if wanted */
if(b_reinit) if (b_reinit)
{
/* Force redecoding */
p_nit_decoder->b_current_valid = 0;
/* Free structures */
if(p_nit_decoder->p_building_nit)
{ {
free(p_nit_decoder->p_building_nit); /* Force redecoding */
p_nit_decoder->p_building_nit = NULL; p_nit_decoder->b_current_valid = 0;
} /* Free structures */
/* Clear the section array */ if(p_nit_decoder->p_building_nit)
for(unsigned int i = 0; i <= 255; i++) {
{ free(p_nit_decoder->p_building_nit);
if(p_nit_decoder->ap_sections[i] != NULL) p_nit_decoder->p_building_nit = NULL;
{ }
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[i]); /* Clear the section array */
p_nit_decoder->ap_sections[i] = NULL; for (unsigned int i = 0; i <= 255; i++)
} {
if (p_nit_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[i]);
p_nit_decoder->ap_sections[i] = NULL;
}
}
} }
}
/* Append the section to the list if wanted */ /* Append the section to the list if wanted */
if(b_append) if (b_append)
{
int b_complete;
/* Initialize the structures if it's the first section received */
if(!p_nit_decoder->p_building_nit)
{ {
p_nit_decoder->p_building_nit = int b_complete;
(dvbpsi_nit_t*)malloc(sizeof(dvbpsi_nit_t));
dvbpsi_InitNIT(p_nit_decoder->p_building_nit,
p_nit_decoder->i_network_id,
p_section->i_version,
p_section->b_current_next);
p_nit_decoder->i_last_section_number = p_section->i_last_number;
}
/* Fill the section array */ /* Initialize the structures if it's the first section received */
if(p_nit_decoder->ap_sections[p_section->i_number] != NULL) if (!p_nit_decoder->p_building_nit)
{ {
dvbpsi_debug(h_dvbpsi, "NIT decoder", "overwrite section number %d", p_nit_decoder->p_building_nit = (dvbpsi_nit_t*)malloc(sizeof(dvbpsi_nit_t));
p_section->i_number); dvbpsi_InitNIT(p_nit_decoder->p_building_nit,
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[p_section->i_number]); p_nit_decoder->i_network_id,
} p_section->i_version,
p_nit_decoder->ap_sections[p_section->i_number] = p_section; p_section->b_current_next);
p_nit_decoder->i_last_section_number = p_section->i_last_number;
}
/* Check if we have all the sections */ /* Fill the section array */
b_complete = 0; if (p_nit_decoder->ap_sections[p_section->i_number] != NULL)
for(unsigned int i = 0; i <= p_nit_decoder->i_last_section_number; i++) {
{ dvbpsi_debug(p_dvbpsi, "NIT decoder", "overwrite section number %d",
if(!p_nit_decoder->ap_sections[i]) p_section->i_number);
break; dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[p_section->i_number]);
}
p_nit_decoder->ap_sections[p_section->i_number] = p_section;
if(i == p_nit_decoder->i_last_section_number) /* Check if we have all the sections */
b_complete = 1; b_complete = 0;
} for (unsigned int i = 0; i <= p_nit_decoder->i_last_section_number; i++)
{
if (!p_nit_decoder->ap_sections[i])
break;
if (i == p_nit_decoder->i_last_section_number)
b_complete = 1;
}
if(b_complete) if (b_complete)
{ {
/* Save the current information */ /* Save the current information */
p_nit_decoder->current_nit = *p_nit_decoder->p_building_nit; p_nit_decoder->current_nit = *p_nit_decoder->p_building_nit;
p_nit_decoder->b_current_valid = 1; p_nit_decoder->b_current_valid = 1;
/* Chain the sections */ /* Chain the sections */
if(p_nit_decoder->i_last_section_number) if (p_nit_decoder->i_last_section_number)
{ {
for(unsigned int i = 0; (int)i <= p_nit_decoder->i_last_section_number - 1; i++) for (unsigned int i = 0; (int)i <= p_nit_decoder->i_last_section_number - 1; i++)
p_nit_decoder->ap_sections[i]->p_next = p_nit_decoder->ap_sections[i]->p_next =
p_nit_decoder->ap_sections[i + 1]; p_nit_decoder->ap_sections[i + 1];
} }
/* Decode the sections */ /* Decode the sections */
dvbpsi_DecodeNITSections(p_nit_decoder->p_building_nit, dvbpsi_DecodeNITSections(p_dvbpsi, p_nit_decoder->p_building_nit,
p_nit_decoder->ap_sections[0]); p_nit_decoder->ap_sections[0]);
/* Delete the sections */ /* Delete the sections */
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[0]); dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[0]);
/* signal the new NIT */ /* signal the new NIT */
p_nit_decoder->pf_callback(p_nit_decoder->p_cb_data, p_nit_decoder->pf_nit_callback(p_nit_decoder->p_cb_data,
p_nit_decoder->p_building_nit); p_nit_decoder->p_building_nit);
/* Reinitialize the structures */ /* Reinitialize the structures */
p_nit_decoder->p_building_nit = NULL; p_nit_decoder->p_building_nit = NULL;
for(unsigned int i = 0; i <= p_nit_decoder->i_last_section_number; i++) for (unsigned int i = 0; i <= p_nit_decoder->i_last_section_number; i++)
p_nit_decoder->ap_sections[i] = NULL; p_nit_decoder->ap_sections[i] = NULL;
}
}
else
{
dvbpsi_DeletePSISections(p_section);
} }
}
else
{
dvbpsi_DeletePSISections(p_section);
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeNITSections * dvbpsi_DecodeNITSections
***************************************************************************** *****************************************************************************
* NIT decoder. * NIT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeNITSections(dvbpsi_nit_t* p_nit, void dvbpsi_DecodeNITSections(dvbpsi_t *p_dvbpsi, dvbpsi_nit_t* p_nit,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t* p_byte, * p_end, * p_end2; uint8_t* p_byte, * p_end, * p_end2;
while(p_section) while (p_section)
{
/* - NIT descriptors */
p_byte = p_section->p_payload_start + 2;
p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[0] & 0x0f) << 8)
| p_section->p_payload_start[1]);
while(p_byte + 2 <= p_end)
{ {
uint8_t i_tag = p_byte[0]; /* - NIT descriptors */
uint8_t i_length = p_byte[1]; p_byte = p_section->p_payload_start + 2;
if(i_length + 2 <= p_end - p_byte) p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[0] & 0x0f) << 8)
dvbpsi_NITAddDescriptor(p_nit, i_tag, i_length, p_byte + 2); | p_section->p_payload_start[1]);
p_byte += 2 + i_length;
}
p_end = p_byte + ( ((uint16_t)(p_byte[0] & 0x0f) << 8) while (p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if (i_length + 2 <= p_end - p_byte)
dvbpsi_NITAddDescriptor(p_nit, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
p_end = p_byte + ( ((uint16_t)(p_byte[0] & 0x0f) << 8)
| p_byte[1]); | p_byte[1]);
if(p_end > p_section->p_payload_end) if (p_end > p_section->p_payload_end)
{ {
p_end = p_section->p_payload_end; p_end = p_section->p_payload_end;
} }
p_byte += 2; p_byte += 2;
/* - TSs */ /* - TSs */
for(; p_byte + 6 <= p_end;) for (; p_byte + 6 <= p_end;)
{ {
uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1]; uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1];
uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3]; uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3];
uint16_t i_ts_length = ((uint16_t)(p_byte[4] & 0x0f) << 8) | p_byte[5]; uint16_t i_ts_length = ((uint16_t)(p_byte[4] & 0x0f) << 8) | p_byte[5];
dvbpsi_nit_ts_t* p_ts = dvbpsi_NITAddTS(p_nit, i_ts_id, i_orig_network_id); dvbpsi_nit_ts_t* p_ts = dvbpsi_NITAddTS(p_nit, i_ts_id, i_orig_network_id);
/* - TS descriptors */ /* - TS descriptors */
p_byte += 6; p_byte += 6;
p_end2 = p_byte + i_ts_length; p_end2 = p_byte + i_ts_length;
if( p_end2 > p_section->p_payload_end ) if ( p_end2 > p_section->p_payload_end )
{ {
p_end2 = p_section->p_payload_end; p_end2 = p_section->p_payload_end;
} }
while(p_byte + 2 <= p_end2) while (p_byte + 2 <= p_end2)
{ {
uint8_t i_tag = p_byte[0]; uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1]; uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end2 - p_byte) if (i_length + 2 <= p_end2 - p_byte)
dvbpsi_NITTSAddDescriptor(p_ts, i_tag, i_length, p_byte + 2); dvbpsi_NITTSAddDescriptor(p_ts, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length; p_byte += 2 + i_length;
} }
}
p_section = p_section->p_next;
} }
p_section = p_section->p_next;
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GenNITSections * dvbpsi_GenNITSections
***************************************************************************** *****************************************************************************
* Generate NIT sections based on the dvbpsi_nit_t structure. * Generate NIT sections based on the dvbpsi_nit_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit, dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_t *p_dvbpsi,
uint8_t i_table_id) dvbpsi_nit_t* p_nit, uint8_t i_table_id)
{ {
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev; dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_nit->p_first_descriptor; dvbpsi_descriptor_t* p_descriptor = p_nit->p_first_descriptor;
dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts; dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
uint16_t i_network_descriptors_length, i_transport_stream_loop_length; uint16_t i_network_descriptors_length, i_transport_stream_loop_length;
uint8_t * p_transport_stream_loop_length; uint8_t * p_transport_stream_loop_length;
p_current->i_table_id = i_table_id; p_current->i_table_id = i_table_id;
p_current->b_syntax_indicator = 1; p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0; p_current->b_private_indicator = 0;
p_current->i_length = 13; /* including CRC_32 */ p_current->i_length = 13; /* including CRC_32 */
p_current->i_extension = p_nit->i_network_id; p_current->i_extension = p_nit->i_network_id;
p_current->i_version = p_nit->i_version; p_current->i_version = p_nit->i_version;
p_current->b_current_next = p_nit->b_current_next; p_current->b_current_next = p_nit->b_current_next;
p_current->i_number = 0; p_current->i_number = 0;
p_current->p_payload_end += 10; p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8; p_current->p_payload_start = p_current->p_data + 8;
/* NIT descriptors */ /* NIT descriptors */
while(p_descriptor != NULL) while (p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
{ {
/* network_descriptors_length */ /* New section if needed */
i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2; /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0; if ((p_current->p_payload_end - p_current->p_data)
p_current->p_data[9] = i_network_descriptors_length; + p_descriptor->i_length > 1018)
{
/* transport_stream_loop_length */ /* network_descriptors_length */
p_current->p_payload_end[0] = 0; i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_current->p_payload_end[1] = 0; p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0;
p_current->p_payload_end += 2; p_current->p_data[9] = i_network_descriptors_length;
p_prev = p_current; /* transport_stream_loop_length */
p_current = dvbpsi_NewPSISection(1024); p_current->p_payload_end[0] = 0;
p_prev->p_next = p_current; p_current->p_payload_end[1] = 0;
p_current->p_payload_end += 2;
p_current->i_table_id = i_table_id;
p_current->b_syntax_indicator = 1; p_prev = p_current;
p_current->b_private_indicator = 0; p_current = dvbpsi_NewPSISection(1024);
p_current->i_length = 13; /* including CRC_32 */ p_prev->p_next = p_current;
p_current->i_extension = p_nit->i_network_id;
p_current->i_version = p_nit->i_version; p_current->i_table_id = i_table_id;
p_current->b_current_next = p_nit->b_current_next; p_current->b_syntax_indicator = 1;
p_current->i_number = p_prev->i_number + 1; p_current->b_private_indicator = 0;
p_current->p_payload_end += 10; p_current->i_length = 13; /* including CRC_32 */
p_current->p_payload_start = p_current->p_data + 8; p_current->i_extension = p_nit->i_network_id;
} p_current->i_version = p_nit->i_version;
p_current->b_current_next = p_nit->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
}
/* p_payload_end is where the descriptor begins */ /* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length; p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2, memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data, p_descriptor->p_data,
p_descriptor->i_length); p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */ /* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2; p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next; p_descriptor = p_descriptor->p_next;
}
/* network_descriptors_length */
i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0;
p_current->p_data[9] = i_network_descriptors_length;
/* Store the position of the transport_stream_loop_length field
and reserve two bytes for it */
p_transport_stream_loop_length = p_current->p_payload_end;
p_current->p_payload_end += 2;
/* NIT TSs */
while(p_ts != NULL)
{
uint8_t* p_ts_start = p_current->p_payload_end;
uint16_t i_ts_length = 5;
/* Can the current section carry all the descriptors ? */
p_descriptor = p_ts->p_first_descriptor;
while( (p_descriptor != NULL)
&& ((p_ts_start - p_current->p_data) + i_ts_length <= 1020))
{
i_ts_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
} }
/* If _no_ and the current section isn't empty and an empty section /* network_descriptors_length */
may carry one more descriptor i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
then create a new section */ p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0;
if( (p_descriptor != NULL) p_current->p_data[9] = i_network_descriptors_length;
&& (p_ts_start - p_current->p_data != 12)
&& (i_ts_length <= 1008)) /* Store the position of the transport_stream_loop_length field
and reserve two bytes for it */
p_transport_stream_loop_length = p_current->p_payload_end;
p_current->p_payload_end += 2;
/* NIT TSs */
while (p_ts != NULL)
{ {
/* transport_stream_loop_length */ uint8_t* p_ts_start = p_current->p_payload_end;
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2; uint16_t i_ts_length = 5;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
#if 0 /* FIXME: */
/* will put more descriptors in an empty section */
dvbpsi_debug(h_dvbpsi, "NIT generator",
"create a new section to carry more TS descriptors");
#endif
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = i_table_id;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 13; /* including CRC_32 */
p_current->i_extension = p_nit->i_network_id;
p_current->i_version = p_nit->i_version;
p_current->b_current_next = p_nit->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* network_descriptors_length = 0 */
p_current->p_data[8] = 0xf0;
p_current->p_data[9] = 0x00;
/* Store the position of the transport_stream_loop_length field
and reserve two bytes for it */
p_transport_stream_loop_length = p_current->p_payload_end;
p_current->p_payload_end += 2;
p_ts_start = p_current->p_payload_end;
}
/* p_ts_start is where the TS begins */ /* Can the current section carry all the descriptors ? */
p_ts_start[0] = p_ts->i_ts_id >> 8; p_descriptor = p_ts->p_first_descriptor;
p_ts_start[1] = p_ts->i_ts_id & 0xff; while( (p_descriptor != NULL)
p_ts_start[2] = p_ts->i_orig_network_id >> 8; && ((p_ts_start - p_current->p_data) + i_ts_length <= 1020))
p_ts_start[3] = p_ts->i_orig_network_id & 0xff; {
i_ts_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* Increase the length by 6 */ /* If _no_ and the current section isn't empty and an empty section
p_current->p_payload_end += 6; may carry one more descriptor
p_current->i_length += 6; then create a new section */
if( (p_descriptor != NULL)
&& (p_ts_start - p_current->p_data != 12)
&& (i_ts_length <= 1008))
{
/* transport_stream_loop_length */
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
/* will put more descriptors in an empty section */
dvbpsi_debug(p_dvbpsi, "NIT generator",
"create a new section to carry more TS descriptors");
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = i_table_id;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 13; /* including CRC_32 */
p_current->i_extension = p_nit->i_network_id;
p_current->i_version = p_nit->i_version;
p_current->b_current_next = p_nit->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* network_descriptors_length = 0 */
p_current->p_data[8] = 0xf0;
p_current->p_data[9] = 0x00;
/* Store the position of the transport_stream_loop_length field
and reserve two bytes for it */
p_transport_stream_loop_length = p_current->p_payload_end;
p_current->p_payload_end += 2;
p_ts_start = p_current->p_payload_end;
}
/* p_ts_start is where the TS begins */
p_ts_start[0] = p_ts->i_ts_id >> 8;
p_ts_start[1] = p_ts->i_ts_id & 0xff;
p_ts_start[2] = p_ts->i_orig_network_id >> 8;
p_ts_start[3] = p_ts->i_orig_network_id & 0xff;
/* Increase the length by 6 */
p_current->p_payload_end += 6;
p_current->i_length += 6;
/* TS descriptors */ /* TS descriptors */
p_descriptor = p_ts->p_first_descriptor; p_descriptor = p_ts->p_first_descriptor;
while( (p_descriptor != NULL) while ( (p_descriptor != NULL)
&& ( (p_current->p_payload_end - p_current->p_data) && ( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length <= 1018)) + p_descriptor->i_length <= 1018))
{
/* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
if (p_descriptor != NULL)
dvbpsi_error(p_dvbpsi, "NIT generator", "unable to carry all the TS descriptors");
/* TS_info_length */
i_ts_length = p_current->p_payload_end - p_ts_start - 5;
p_ts_start[4] = (i_ts_length >> 8) | 0xf0;
p_ts_start[5] = i_ts_length;
p_ts = p_ts->p_next;
}
/* transport_stream_loop_length */
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
/* Finalization */
p_prev = p_result;
while (p_prev != NULL)
{ {
/* p_payload_end is where the descriptor begins */ p_prev->i_last_number = p_current->i_number;
p_current->p_payload_end[0] = p_descriptor->i_tag; dvbpsi_BuildPSISection(p_prev);
p_current->p_payload_end[1] = p_descriptor->i_length; p_prev = p_prev->p_next;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
} }
#if 0 /* FIXME: */
if(p_descriptor != NULL) return p_result;
dvbpsi_error(h_dvbpsi, "NIT generator", "unable to carry all the TS descriptors");
#endif
/* TS_info_length */
i_ts_length = p_current->p_payload_end - p_ts_start - 5;
p_ts_start[4] = (i_ts_length >> 8) | 0xf0;
p_ts_start[5] = i_ts_length;
p_ts = p_ts->p_next;
}
/* transport_stream_loop_length */
i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
/* Finalization */
p_prev = p_result;
while(p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
return p_result;
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -39,7 +40,6 @@ ...@@ -39,7 +40,6 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_nit_ts_t * dvbpsi_nit_ts_t
*****************************************************************************/ *****************************************************************************/
...@@ -66,7 +66,6 @@ typedef struct dvbpsi_nit_ts_s ...@@ -66,7 +66,6 @@ typedef struct dvbpsi_nit_ts_s
} dvbpsi_nit_ts_t; } dvbpsi_nit_ts_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_nit_t * dvbpsi_nit_t
*****************************************************************************/ *****************************************************************************/
...@@ -93,7 +92,6 @@ typedef struct dvbpsi_nit_s ...@@ -93,7 +92,6 @@ typedef struct dvbpsi_nit_s
} dvbpsi_nit_t; } dvbpsi_nit_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_nit_callback * dvbpsi_nit_callback
*****************************************************************************/ *****************************************************************************/
...@@ -104,27 +102,25 @@ typedef struct dvbpsi_nit_s ...@@ -104,27 +102,25 @@ typedef struct dvbpsi_nit_s
*/ */
typedef void (* dvbpsi_nit_callback)(void* p_cb_data, dvbpsi_nit_t* p_new_nit); typedef void (* dvbpsi_nit_callback)(void* p_cb_data, dvbpsi_nit_t* p_new_nit);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachNIT * dvbpsi_AttachNIT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_AttachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn int dvbpsi_AttachNIT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_nit_callback pf_callback, uint16_t i_extension, dvbpsi_nit_callback pf_callback,
void* p_cb_data) void* p_cb_data)
* \brief Creation and initialization of a NIT decoder. * \brief Creation and initialization of a NIT 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, 0x4E, 0x4F, or 0x50-0x6F. * \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
* \param i_extension Table ID extension, here service ID. * \param i_extension Table ID extension, here service ID.
* \param pf_callback function to call back on new NIT. * \param pf_callback function to call back on new NIT.
* \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 0 if everything went ok.
*/ */
int dvbpsi_AttachNIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachNIT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_nit_callback pf_callback, uint16_t i_extension, dvbpsi_nit_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachNIT * dvbpsi_DetachNIT
*****************************************************************************/ *****************************************************************************/
...@@ -132,15 +128,14 @@ int dvbpsi_AttachNIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, ...@@ -132,15 +128,14 @@ int dvbpsi_AttachNIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
* \fn void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
* \brief Destroy a NIT decoder. * \brief Destroy a NIT 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, 0x4E, 0x4F, or 0x50-0x6F. * \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
* \param i_extension Table ID extension, here service ID. * \param i_extension Table ID extension, here service ID.
* \return nothing. * \return nothing.
*/ */
void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachNIT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitNIT/dvbpsi_NewNIT * dvbpsi_InitNIT/dvbpsi_NewNIT
*****************************************************************************/ *****************************************************************************/
...@@ -176,7 +171,6 @@ do { \ ...@@ -176,7 +171,6 @@ do { \
dvbpsi_InitNIT(p_nit, i_network_id, i_version, b_current_next); \ dvbpsi_InitNIT(p_nit, i_network_id, i_version, b_current_next); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyNIT/dvbpsi_DeleteNIT * dvbpsi_EmptyNIT/dvbpsi_DeleteNIT
*****************************************************************************/ *****************************************************************************/
...@@ -200,7 +194,6 @@ do { \ ...@@ -200,7 +194,6 @@ do { \
free(p_nit); \ free(p_nit); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_NITAddDescriptor * dvbpsi_NITAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -220,7 +213,6 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit, ...@@ -220,7 +213,6 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
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_NITAddTS * dvbpsi_NITAddTS
*****************************************************************************/ *****************************************************************************/
...@@ -236,7 +228,6 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit, ...@@ -236,7 +228,6 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit, dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit,
uint16_t i_ts_id, uint16_t i_orig_network_id); uint16_t i_ts_id, uint16_t i_orig_network_id);
/***************************************************************************** /*****************************************************************************
* dvbpsi_NITTSAddDescriptor * dvbpsi_NITTSAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -256,7 +247,6 @@ dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts, ...@@ -256,7 +247,6 @@ dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts,
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_GenNITSections * dvbpsi_GenNITSections
*****************************************************************************/ *****************************************************************************/
...@@ -264,16 +254,16 @@ dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts, ...@@ -264,16 +254,16 @@ dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts,
* \fn dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit, * \fn dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit,
uint8_t i_table_id) uint8_t i_table_id)
* \brief NIT generator * \brief NIT generator
* \parma p_dvbpsi dvbpsi handle
* \param p_nit NIT structure * \param p_nit NIT structure
* \param i_table_id table id, 0x40 = actual network / 0x41 = other network * \param i_table_id table id, 0x40 = actual network / 0x41 = other network
* \return a pointer to the list of generated PSI sections. * \return a pointer to the list of generated PSI sections.
* *
* Generate NIT sections based on the dvbpsi_nit_t structure. * Generate NIT sections based on the dvbpsi_nit_t structure.
*/ */
dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit, dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_t* p_dvbpsi, dvbpsi_nit_t* p_nit,
uint8_t i_table_id); uint8_t i_table_id);
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -36,41 +37,40 @@ ...@@ -36,41 +37,40 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_nit_decoder_s typedef struct dvbpsi_nit_decoder_s
{ {
uint16_t i_network_id; DVBPSI_DECODER_COMMON
dvbpsi_nit_callback pf_callback; uint16_t i_network_id;
void * p_cb_data;
dvbpsi_nit_t current_nit; dvbpsi_nit_callback pf_nit_callback;
dvbpsi_nit_t * p_building_nit; void * p_cb_data;
int b_current_valid; dvbpsi_nit_t current_nit;
dvbpsi_nit_t * p_building_nit;
uint8_t i_last_section_number; int b_current_valid;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_nit_decoder_t; uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_nit_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherNITSections * dvbpsi_GatherNITSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherNITSections(dvbpsi_decoder_t* p_psi_decoder, void dvbpsi_GatherNITSections(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_DecodeNITSections * dvbpsi_DecodeNITSections
***************************************************************************** *****************************************************************************
* NIT decoder. * NIT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeNITSections(dvbpsi_nit_t* p_nit, void dvbpsi_DecodeNITSections(dvbpsi_t* p_dvbpsi, dvbpsi_nit_t* p_nit,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of nit_private.h" #error "Multiple inclusions of nit_private.h"
#endif #endif
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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,7 +25,6 @@ ...@@ -24,7 +25,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -36,54 +36,50 @@ ...@@ -36,54 +36,50 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
#include <assert.h>
#include "../dvbpsi.h" #include "../dvbpsi.h"
#include "../dvbpsi_private.h" #include "../dvbpsi_private.h"
#include "../psi.h" #include "../psi.h"
#include "pat.h" #include "pat.h"
#include "pat_private.h" #include "pat_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachPAT * dvbpsi_AttachPAT
***************************************************************************** *****************************************************************************
* Initialize a PAT decoder and return a handle on it. * Initialize a PAT decoder and return a handle on it.
*****************************************************************************/ *****************************************************************************/
dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback, dvbpsi_t *dvbpsi_AttachPAT(dvbpsi_t *p_dvbpsi, dvbpsi_pat_callback pf_callback,
void* p_cb_data) void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t)); assert(p_dvbpsi);
dvbpsi_pat_decoder_t* p_pat_decoder;
if(h_dvbpsi == NULL) dvbpsi_pat_decoder_t* p_pat_decoder = (dvbpsi_pat_decoder_t*) calloc(1, sizeof(dvbpsi_pat_decoder_t));
return NULL; if (p_pat_decoder == NULL)
return NULL;
p_pat_decoder = (dvbpsi_pat_decoder_t*)malloc(sizeof(dvbpsi_pat_decoder_t)); /* PSI decoder configuration */
p_pat_decoder->pf_callback = &dvbpsi_GatherPATSections;
p_pat_decoder->i_section_max_size = 1024;
if(p_pat_decoder == NULL) /* PSI decoder initial state */
{ p_pat_decoder->i_continuity_counter = 31;
free(h_dvbpsi); p_pat_decoder->b_discontinuity = 1;
return NULL; p_pat_decoder->p_current_section = NULL;
}
/* PAT decoder information */
p_pat_decoder->pf_pat_callback = pf_callback;
p_pat_decoder->p_cb_data = p_cb_data;
/* PAT decoder initial state */
p_pat_decoder->b_current_valid = 0;
p_pat_decoder->p_building_pat = NULL;
/* PSI decoder configuration */ for(unsigned int i = 0; i <= 255; i++)
h_dvbpsi->pf_callback = &dvbpsi_GatherPATSections; p_pat_decoder->ap_sections[i] = NULL;
h_dvbpsi->p_private_decoder = p_pat_decoder;
h_dvbpsi->i_section_max_size = 1024; p_dvbpsi->p_private = (void *)p_pat_decoder;
/* PSI decoder initial state */ return p_dvbpsi;
h_dvbpsi->i_continuity_counter = 31;
h_dvbpsi->b_discontinuity = 1;
h_dvbpsi->p_current_section = NULL;
/* PAT decoder information */
p_pat_decoder->pf_callback = pf_callback;
p_pat_decoder->p_cb_data = p_cb_data;
/* PAT decoder initial state */
p_pat_decoder->b_current_valid = 0;
p_pat_decoder->p_building_pat = NULL;
for(unsigned int i = 0; i <= 255; i++)
p_pat_decoder->ap_sections[i] = NULL;
return h_dvbpsi;
} }
...@@ -92,23 +88,21 @@ dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback, ...@@ -92,23 +88,21 @@ dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback,
***************************************************************************** *****************************************************************************
* Close a PAT decoder. The handle isn't valid any more. * Close a PAT decoder. The handle isn't valid any more.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachPAT(dvbpsi_handle h_dvbpsi) void dvbpsi_DetachPAT(dvbpsi_t *p_dvbpsi)
{ {
dvbpsi_pat_decoder_t* p_pat_decoder dvbpsi_pat_decoder_t* p_pat_decoder = (dvbpsi_pat_decoder_t*)p_dvbpsi->p_private;
= (dvbpsi_pat_decoder_t*)h_dvbpsi->p_private_decoder; free(p_pat_decoder->p_building_pat);
free(p_pat_decoder->p_building_pat); for (unsigned int i = 0; i <= 255; i++)
{
if (p_pat_decoder->ap_sections[i])
free(p_pat_decoder->ap_sections[i]);
}
for(unsigned int i = 0; i <= 255; i++) if (p_pat_decoder->p_current_section)
{ dvbpsi_DeletePSISections(p_pat_decoder->p_current_section);
if(p_pat_decoder->ap_sections[i]) free(p_pat_decoder);
free(p_pat_decoder->ap_sections[i]);
}
free(h_dvbpsi->p_private_decoder);
if(h_dvbpsi->p_current_section)
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section);
free(h_dvbpsi);
} }
...@@ -120,10 +114,10 @@ void dvbpsi_DetachPAT(dvbpsi_handle h_dvbpsi) ...@@ -120,10 +114,10 @@ void dvbpsi_DetachPAT(dvbpsi_handle h_dvbpsi)
void dvbpsi_InitPAT(dvbpsi_pat_t* p_pat, uint16_t i_ts_id, uint8_t i_version, void dvbpsi_InitPAT(dvbpsi_pat_t* p_pat, uint16_t i_ts_id, uint8_t i_version,
int b_current_next) int b_current_next)
{ {
p_pat->i_ts_id = i_ts_id; p_pat->i_ts_id = i_ts_id;
p_pat->i_version = i_version; p_pat->i_version = i_version;
p_pat->b_current_next = b_current_next; p_pat->b_current_next = b_current_next;
p_pat->p_first_program = NULL; p_pat->p_first_program = NULL;
} }
...@@ -134,16 +128,15 @@ void dvbpsi_InitPAT(dvbpsi_pat_t* p_pat, uint16_t i_ts_id, uint8_t i_version, ...@@ -134,16 +128,15 @@ void dvbpsi_InitPAT(dvbpsi_pat_t* p_pat, uint16_t i_ts_id, uint8_t i_version,
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyPAT(dvbpsi_pat_t* p_pat) void dvbpsi_EmptyPAT(dvbpsi_pat_t* p_pat)
{ {
dvbpsi_pat_program_t* p_program = p_pat->p_first_program; dvbpsi_pat_program_t* p_program = p_pat->p_first_program;
while(p_program != NULL) while(p_program != NULL)
{ {
dvbpsi_pat_program_t* p_tmp = p_program->p_next; dvbpsi_pat_program_t* p_tmp = p_program->p_next;
free(p_program); free(p_program);
p_program = p_tmp; p_program = p_tmp;
} }
p_pat->p_first_program = NULL;
p_pat->p_first_program = NULL;
} }
...@@ -155,29 +148,27 @@ void dvbpsi_EmptyPAT(dvbpsi_pat_t* p_pat) ...@@ -155,29 +148,27 @@ void dvbpsi_EmptyPAT(dvbpsi_pat_t* p_pat)
dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat, dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat,
uint16_t i_number, uint16_t i_pid) uint16_t i_number, uint16_t i_pid)
{ {
dvbpsi_pat_program_t* p_program dvbpsi_pat_program_t* p_program;
= (dvbpsi_pat_program_t*)malloc(sizeof(dvbpsi_pat_program_t));
p_program = (dvbpsi_pat_program_t*) malloc(sizeof(dvbpsi_pat_program_t));
if (p_program == NULL)
return NULL;
if(p_program)
{
p_program->i_number = i_number; p_program->i_number = i_number;
p_program->i_pid = i_pid; p_program->i_pid = i_pid;
p_program->p_next = NULL; p_program->p_next = NULL;
if(p_pat->p_first_program == NULL) if (p_pat->p_first_program == NULL)
{ p_pat->p_first_program = p_program;
p_pat->p_first_program = p_program;
}
else else
{ {
dvbpsi_pat_program_t* p_last_program = p_pat->p_first_program; dvbpsi_pat_program_t* p_last_program = p_pat->p_first_program;
while(p_last_program->p_next != NULL) while (p_last_program->p_next != NULL)
p_last_program = p_last_program->p_next; p_last_program = p_last_program->p_next;
p_last_program->p_next = p_program; p_last_program->p_next = p_program;
} }
}
return p_program; return p_program;
} }
...@@ -186,26 +177,27 @@ dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat, ...@@ -186,26 +177,27 @@ dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat,
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherPATSections(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section)
dvbpsi_psi_section_t* p_section)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_decoder; dvbpsi_pat_decoder_t* p_pat_decoder;
dvbpsi_pat_decoder_t* p_pat_decoder
= (dvbpsi_pat_decoder_t*)p_decoder->p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "PAT decoder", assert(p_dvbpsi->p_private);
dvbpsi_debug(p_dvbpsi, "PAT decoder",
"Table version %2d, " "i_extension %5d, " "Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension, p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
p_pat_decoder = (dvbpsi_pat_decoder_t *)p_dvbpsi->p_private;
if(p_section->i_table_id != 0x00) if(p_section->i_table_id != 0x00)
{ {
/* Invalid table_id value */ /* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "PAT decoder", dvbpsi_error(p_dvbpsi, "PAT decoder",
"invalid section (table_id == 0x%02x)", "invalid section (table_id == 0x%02x)",
p_section->i_table_id); p_section->i_table_id);
b_append = 0; b_append = 0;
...@@ -214,7 +206,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -214,7 +206,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
if(b_append && !p_section->b_syntax_indicator) if(b_append && !p_section->b_syntax_indicator)
{ {
/* Invalid section_syntax_indicator */ /* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "PAT decoder", dvbpsi_error(p_dvbpsi, "PAT decoder",
"invalid section (section_syntax_indicator == 0)"); "invalid section (section_syntax_indicator == 0)");
b_append = 0; b_append = 0;
} }
...@@ -223,10 +215,10 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -223,10 +215,10 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
if(b_append) if(b_append)
{ {
/* TS discontinuity check */ /* TS discontinuity check */
if(p_decoder->b_discontinuity) if(p_pat_decoder->b_discontinuity)
{ {
b_reinit = 1; b_reinit = 1;
p_decoder->b_discontinuity = 0; p_pat_decoder->b_discontinuity = 0;
} }
else else
{ {
...@@ -236,7 +228,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -236,7 +228,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
if(p_pat_decoder->p_building_pat->i_ts_id != p_section->i_extension) if(p_pat_decoder->p_building_pat->i_ts_id != p_section->i_extension)
{ {
/* transport_stream_id */ /* transport_stream_id */
dvbpsi_error(h_dvbpsi, "PAT decoder", dvbpsi_error(p_dvbpsi, "PAT decoder",
"'transport_stream_id' differs" "'transport_stream_id' differs"
" whereas no TS discontinuity has occured"); " whereas no TS discontinuity has occured");
b_reinit = 1; b_reinit = 1;
...@@ -245,7 +237,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -245,7 +237,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
!= p_section->i_version) != p_section->i_version)
{ {
/* version_number */ /* version_number */
dvbpsi_error(h_dvbpsi, "PAT decoder", dvbpsi_error(p_dvbpsi, "PAT decoder",
"'version_number' differs" "'version_number' differs"
" whereas no discontinuity has occured"); " whereas no discontinuity has occured");
b_reinit = 1; b_reinit = 1;
...@@ -254,7 +246,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -254,7 +246,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
p_section->i_last_number) p_section->i_last_number)
{ {
/* last_section_number */ /* last_section_number */
dvbpsi_error(h_dvbpsi, "PAT decoder", dvbpsi_error(p_dvbpsi, "PAT decoder",
"'last_section_number' differs" "'last_section_number' differs"
" whereas no discontinuity has occured"); " whereas no discontinuity has occured");
b_reinit = 1; b_reinit = 1;
...@@ -316,7 +308,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -316,7 +308,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
/* Fill the section array */ /* Fill the section array */
if(p_pat_decoder->ap_sections[p_section->i_number] != NULL) if(p_pat_decoder->ap_sections[p_section->i_number] != NULL)
{ {
dvbpsi_debug(h_dvbpsi, "PAT decoder", "overwrite section number %d", dvbpsi_debug(p_dvbpsi, "PAT decoder", "overwrite section number %d",
p_section->i_number); p_section->i_number);
dvbpsi_DeletePSISections(p_pat_decoder->ap_sections[p_section->i_number]); dvbpsi_DeletePSISections(p_pat_decoder->ap_sections[p_section->i_number]);
} }
...@@ -351,7 +343,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -351,7 +343,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
/* Delete the sections */ /* Delete the sections */
dvbpsi_DeletePSISections(p_pat_decoder->ap_sections[0]); dvbpsi_DeletePSISections(p_pat_decoder->ap_sections[0]);
/* signal the new PAT */ /* signal the new PAT */
p_pat_decoder->pf_callback(p_pat_decoder->p_cb_data, p_pat_decoder->pf_pat_callback(p_pat_decoder->p_cb_data,
p_pat_decoder->p_building_pat); p_pat_decoder->p_building_pat);
/* Reinitialize the structures */ /* Reinitialize the structures */
p_pat_decoder->p_building_pat = NULL; p_pat_decoder->p_building_pat = NULL;
...@@ -372,7 +364,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -372,7 +364,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
* PAT decoder. * PAT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat, void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
while(p_section) while(p_section)
{ {
...@@ -396,8 +388,8 @@ void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat, ...@@ -396,8 +388,8 @@ void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat,
* Generate PAT sections based on the dvbpsi_pat_t structure. The third * Generate PAT sections based on the dvbpsi_pat_t structure. The third
* argument is used to limit the number of program in each section (max: 253). * argument is used to limit the number of program in each section (max: 253).
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat, dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_t *p_dvbpsi,
int i_max_pps) dvbpsi_pat_t* p_pat, int i_max_pps)
{ {
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_current = p_result;
...@@ -467,4 +459,3 @@ dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat, ...@@ -467,4 +459,3 @@ dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
return p_result; return p_result;
} }
...@@ -103,29 +103,29 @@ typedef void (* dvbpsi_pat_callback)(void* p_cb_data, dvbpsi_pat_t* p_new_pat); ...@@ -103,29 +103,29 @@ typedef void (* dvbpsi_pat_callback)(void* p_cb_data, dvbpsi_pat_t* p_new_pat);
* dvbpsi_AttachPAT * dvbpsi_AttachPAT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback, * \fn dvbpsi_t *dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback, void* p_cb_data)
void* p_cb_data)
* \brief Creation and initialization of a PAT decoder. * \brief Creation and initialization of a PAT decoder.
* \param p_dvbpsi pointer to dvbpsi_t handle
* \param pf_callback function to call back on new PAT * \param pf_callback function to call back on new PAT
* \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 a pointer to the decoder for future calls. * \return a pointer to the decoder for future calls.
*/ */
dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback, dvbpsi_t *dvbpsi_AttachPAT(dvbpsi_t *p_dvbpsi, dvbpsi_pat_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachPAT * dvbpsi_DetachPAT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_DetachPAT(dvbpsi_handle h_dvbpsi) * \fn void dvbpsi_DetachPAT(dvbpsi_t *p_dvbpsi)
* \brief Destroy a PAT decoder. * \brief Destroy a PAT decoder.
* \param h_dvbpsi handle to the decoder * \param p_dvbpsi pointer to dvbpsi_t handle
* \return nothing. * \return nothing.
* *
* The handle isn't valid any more. * The handle isn't valid any more.
*/ */
void dvbpsi_DetachPAT(dvbpsi_handle h_dvbpsi); void dvbpsi_DetachPAT(dvbpsi_t *p_dvbpsi);
/***************************************************************************** /*****************************************************************************
...@@ -208,6 +208,7 @@ dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat, ...@@ -208,6 +208,7 @@ dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat,
* \fn dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat, * \fn dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
int i_max_pps); int i_max_pps);
* \brief PAT generator. * \brief PAT generator.
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_pat pointer to the PAT structure * \param p_pat pointer to the PAT structure
* \param i_max_pps limitation of the number of program in each section * \param i_max_pps limitation of the number of program in each section
* (max: 253). * (max: 253).
...@@ -215,9 +216,8 @@ dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat, ...@@ -215,9 +216,8 @@ dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat,
* *
* Generate PAT sections based on the dvbpsi_pat_t structure. * Generate PAT sections based on the dvbpsi_pat_t structure.
*/ */
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat, dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_t *p_dvbpsi,
int i_max_pps); dvbpsi_pat_t* p_pat, int i_max_pps);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -35,16 +35,18 @@ ...@@ -35,16 +35,18 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_pat_decoder_s typedef struct dvbpsi_pat_decoder_s
{ {
dvbpsi_pat_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
dvbpsi_pat_t current_pat; dvbpsi_pat_callback pf_pat_callback;
dvbpsi_pat_t * p_building_pat; void * p_cb_data;
int b_current_valid; dvbpsi_pat_t current_pat;
dvbpsi_pat_t * p_building_pat;
uint8_t i_last_section_number; int b_current_valid;
dvbpsi_psi_section_t * ap_sections [256];
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_pat_decoder_t; } dvbpsi_pat_decoder_t;
...@@ -54,9 +56,7 @@ typedef struct dvbpsi_pat_decoder_s ...@@ -54,9 +56,7 @@ typedef struct dvbpsi_pat_decoder_s
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherPATSections(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section);
dvbpsi_psi_section_t* p_section);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodePATSection * dvbpsi_DecodePATSection
...@@ -66,7 +66,6 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder, ...@@ -66,7 +66,6 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat, void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of pat_private.h" #error "Multiple inclusions of pat_private.h"
#endif #endif
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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,7 +25,6 @@ ...@@ -24,7 +25,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
#include <assert.h>
#include "../dvbpsi.h" #include "../dvbpsi.h"
#include "../dvbpsi_private.h" #include "../dvbpsi_private.h"
#include "../psi.h" #include "../psi.h"
...@@ -44,78 +46,69 @@ ...@@ -44,78 +46,69 @@
#include "pmt.h" #include "pmt.h"
#include "pmt_private.h" #include "pmt_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachPMT * dvbpsi_AttachPMT
***************************************************************************** *****************************************************************************
* Initialize a PMT decoder and return a handle on it. * Initialize a PMT decoder and return a handle on it.
*****************************************************************************/ *****************************************************************************/
dvbpsi_handle dvbpsi_AttachPMT(uint16_t i_program_number, dvbpsi_t *dvbpsi_AttachPMT(dvbpsi_t *p_dvbpsi, uint16_t i_program_number,
dvbpsi_pmt_callback pf_callback, dvbpsi_pmt_callback pf_callback,
void* p_cb_data) void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t)); dvbpsi_pmt_decoder_t* p_pmt_decoder;
dvbpsi_pmt_decoder_t* p_pmt_decoder; p_pmt_decoder = (dvbpsi_pmt_decoder_t*)malloc(sizeof(dvbpsi_pmt_decoder_t));
if(h_dvbpsi == NULL) if (p_pmt_decoder == NULL)
return NULL; return NULL;
p_pmt_decoder = (dvbpsi_pmt_decoder_t*)malloc(sizeof(dvbpsi_pmt_decoder_t)); p_dvbpsi->p_private = (void *)p_pmt_decoder;
if(p_pmt_decoder == NULL) /* PSI decoder configuration */
{ p_pmt_decoder->pf_callback = &dvbpsi_GatherPMTSections;
free(h_dvbpsi); p_pmt_decoder->i_section_max_size = 1024;
return NULL;
}
/* PSI decoder configuration */
h_dvbpsi->pf_callback = &dvbpsi_GatherPMTSections;
h_dvbpsi->p_private_decoder = p_pmt_decoder;
h_dvbpsi->i_section_max_size = 1024;
/* PSI decoder initial state */
h_dvbpsi->i_continuity_counter = 31;
h_dvbpsi->b_discontinuity = 1;
h_dvbpsi->p_current_section = NULL;
/* PMT decoder configuration */
p_pmt_decoder->i_program_number = i_program_number;
p_pmt_decoder->pf_callback = pf_callback;
p_pmt_decoder->p_cb_data = p_cb_data;
/* PMT decoder initial state */
p_pmt_decoder->b_current_valid = 0;
p_pmt_decoder->p_building_pmt = NULL;
for(unsigned int i = 0; i <= 255; i++)
p_pmt_decoder->ap_sections[i] = NULL;
return h_dvbpsi;
}
/* PSI decoder initial state */
p_pmt_decoder->i_continuity_counter = 31;
p_pmt_decoder->b_discontinuity = 1;
p_pmt_decoder->p_current_section = NULL;
/* PMT decoder configuration */
p_pmt_decoder->i_program_number = i_program_number;
p_pmt_decoder->pf_pmt_callback = pf_callback;
p_pmt_decoder->p_cb_data = p_cb_data;
/* PMT decoder initial state */
p_pmt_decoder->b_current_valid = 0;
p_pmt_decoder->p_building_pmt = NULL;
for (unsigned int i = 0; i <= 255; i++)
p_pmt_decoder->ap_sections[i] = NULL;
return p_dvbpsi;
}
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachPMT * dvbpsi_DetachPMT
***************************************************************************** *****************************************************************************
* Close a PMT decoder. The handle isn't valid any more. * Close a PMT decoder. The handle isn't valid any more.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi) void dvbpsi_DetachPMT(dvbpsi_t *p_dvbpsi)
{ {
dvbpsi_pmt_decoder_t* p_pmt_decoder dvbpsi_pmt_decoder_t* p_pmt_decoder
= (dvbpsi_pmt_decoder_t*)h_dvbpsi->p_private_decoder; = (dvbpsi_pmt_decoder_t*)p_dvbpsi->p_private;
free(p_pmt_decoder->p_building_pmt);
free(p_pmt_decoder->p_building_pmt);
for(unsigned int i = 0; i <= 255; i++) for (unsigned int i = 0; i <= 255; i++)
{ {
if(p_pmt_decoder->ap_sections[i]) if (p_pmt_decoder->ap_sections[i])
free(p_pmt_decoder->ap_sections[i]); free(p_pmt_decoder->ap_sections[i]);
} }
free(h_dvbpsi->p_private_decoder); if (p_pmt_decoder->p_current_section)
if(h_dvbpsi->p_current_section) dvbpsi_DeletePSISections(p_pmt_decoder->p_current_section);
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); free(p_pmt_decoder);
free(h_dvbpsi); p_dvbpsi->p_private = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitPMT * dvbpsi_InitPMT
***************************************************************************** *****************************************************************************
...@@ -124,15 +117,14 @@ void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi) ...@@ -124,15 +117,14 @@ void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi)
void dvbpsi_InitPMT(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number, void dvbpsi_InitPMT(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number,
uint8_t i_version, int b_current_next, uint16_t i_pcr_pid) uint8_t i_version, int b_current_next, uint16_t i_pcr_pid)
{ {
p_pmt->i_program_number = i_program_number; p_pmt->i_program_number = i_program_number;
p_pmt->i_version = i_version; p_pmt->i_version = i_version;
p_pmt->b_current_next = b_current_next; p_pmt->b_current_next = b_current_next;
p_pmt->i_pcr_pid = i_pcr_pid; p_pmt->i_pcr_pid = i_pcr_pid;
p_pmt->p_first_descriptor = NULL; p_pmt->p_first_descriptor = NULL;
p_pmt->p_first_es = NULL; p_pmt->p_first_es = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyPMT * dvbpsi_EmptyPMT
***************************************************************************** *****************************************************************************
...@@ -140,23 +132,22 @@ void dvbpsi_InitPMT(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number, ...@@ -140,23 +132,22 @@ void dvbpsi_InitPMT(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number,
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyPMT(dvbpsi_pmt_t* p_pmt) void dvbpsi_EmptyPMT(dvbpsi_pmt_t* p_pmt)
{ {
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es;
dvbpsi_DeleteDescriptors(p_pmt->p_first_descriptor); dvbpsi_DeleteDescriptors(p_pmt->p_first_descriptor);
while(p_es != NULL) while(p_es != NULL)
{ {
dvbpsi_pmt_es_t* p_tmp = p_es->p_next; dvbpsi_pmt_es_t* p_tmp = p_es->p_next;
dvbpsi_DeleteDescriptors(p_es->p_first_descriptor); dvbpsi_DeleteDescriptors(p_es->p_first_descriptor);
free(p_es); free(p_es);
p_es = p_tmp; p_es = p_tmp;
} }
p_pmt->p_first_descriptor = NULL; p_pmt->p_first_descriptor = NULL;
p_pmt->p_first_es = NULL; p_pmt->p_first_es = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_PMTAddDescriptor * dvbpsi_PMTAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -166,28 +157,23 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt, ...@@ -166,28 +157,23 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt,
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); p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if (p_descriptor == NULL)
return NULL;
if(p_descriptor) if (p_pmt->p_first_descriptor == NULL)
{ p_pmt->p_first_descriptor = p_descriptor;
if(p_pmt->p_first_descriptor == NULL)
{
p_pmt->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_pmt->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_pmt->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_PMTAddES * dvbpsi_PMTAddES
***************************************************************************** *****************************************************************************
...@@ -196,32 +182,27 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt, ...@@ -196,32 +182,27 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt,
dvbpsi_pmt_es_t* dvbpsi_PMTAddES(dvbpsi_pmt_t* p_pmt, dvbpsi_pmt_es_t* dvbpsi_PMTAddES(dvbpsi_pmt_t* p_pmt,
uint8_t i_type, uint16_t i_pid) uint8_t i_type, uint16_t i_pid)
{ {
dvbpsi_pmt_es_t* p_es = (dvbpsi_pmt_es_t*)malloc(sizeof(dvbpsi_pmt_es_t)); dvbpsi_pmt_es_t* p_es = (dvbpsi_pmt_es_t*)malloc(sizeof(dvbpsi_pmt_es_t));
if (p_es == NULL)
return NULL;
if(p_es)
{
p_es->i_type = i_type; p_es->i_type = i_type;
p_es->i_pid = i_pid; p_es->i_pid = i_pid;
p_es->p_first_descriptor = NULL; p_es->p_first_descriptor = NULL;
p_es->p_next = NULL; p_es->p_next = NULL;
if(p_pmt->p_first_es == NULL) if (p_pmt->p_first_es == NULL)
{ p_pmt->p_first_es = p_es;
p_pmt->p_first_es = p_es;
}
else else
{ {
dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es; dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es;
while(p_last_es->p_next != NULL) while (p_last_es->p_next != NULL)
p_last_es = p_last_es->p_next; p_last_es = p_last_es->p_next;
p_last_es->p_next = p_es; p_last_es->p_next = p_es;
} }
} return p_es;
return p_es;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_PMTESAddDescriptor * dvbpsi_PMTESAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -231,216 +212,208 @@ dvbpsi_descriptor_t* dvbpsi_PMTESAddDescriptor(dvbpsi_pmt_es_t* p_es, ...@@ -231,216 +212,208 @@ dvbpsi_descriptor_t* dvbpsi_PMTESAddDescriptor(dvbpsi_pmt_es_t* p_es,
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); p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if (p_descriptor == NULL)
return NULL;
if(p_descriptor) if (p_es->p_first_descriptor == NULL)
{ p_es->p_first_descriptor = p_descriptor;
if(p_es->p_first_descriptor == NULL)
{
p_es->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_es->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_es->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherPMTSections * dvbpsi_GatherPMTSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherPMTSections(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t* p_section)
dvbpsi_psi_section_t* p_section)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_decoder; dvbpsi_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t*)p_dvbpsi->p_private;
dvbpsi_pmt_decoder_t* p_pmt_decoder assert(p_pmt_decoder);
= (dvbpsi_pmt_decoder_t*)p_decoder->p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "PMT decoder", dvbpsi_debug(p_dvbpsi, "PMT decoder",
"Table version %2d, " "i_extension %5d, " "Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension, p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
if(p_section->i_table_id != 0x02) if (p_section->i_table_id != 0x02)
{ {
/* Invalid table_id value */ /* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "PMT decoder", dvbpsi_error(p_dvbpsi, "PMT decoder",
"invalid section (table_id == 0x%02x)", "invalid section (table_id == 0x%02x)",
p_section->i_table_id); p_section->i_table_id);
b_append = 0; b_append = 0;
} }
if(b_append && !p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "PMT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
/* Now if b_append is true then we have a valid PMT section */
if(b_append && (p_pmt_decoder->i_program_number != p_section->i_extension))
{
/* Invalid program_number */
#if 0
dvbpsi_error(h_dvbpsi, "PMT decoder", \
"'program_number' don't match");
#endif
b_append = 0;
}
if(b_append) if (b_append && !p_section->b_syntax_indicator)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
{ {
b_reinit = 1; /* Invalid section_syntax_indicator */
p_decoder->b_discontinuity = 0; dvbpsi_error(p_dvbpsi, "PMT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
} }
else
/* Now if b_append is true then we have a valid PMT section */
if (b_append && (p_pmt_decoder->i_program_number != p_section->i_extension))
{
/* Invalid program_number */
dvbpsi_error(p_dvbpsi, "PMT decoder", "'program_number' don't match");
b_append = 0;
}
if (b_append)
{ {
/* Perform some few sanity checks */ /* TS discontinuity check */
if(p_pmt_decoder->p_building_pmt) if (p_pmt_decoder->b_discontinuity)
{
if(p_pmt_decoder->p_building_pmt->i_version != p_section->i_version)
{ {
/* version_number */ b_reinit = 1;
dvbpsi_error(h_dvbpsi, "PMT decoder", p_pmt_decoder->b_discontinuity = 0;
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
} }
else if(p_pmt_decoder->i_last_section_number else
!= p_section->i_last_number)
{ {
/* last_section_number */ /* Perform some few sanity checks */
dvbpsi_error(h_dvbpsi, "PMT decoder", if (p_pmt_decoder->p_building_pmt)
{
if (p_pmt_decoder->p_building_pmt->i_version != p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "PMT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
else if (p_pmt_decoder->i_last_section_number
!= p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "PMT decoder",
"'last_section_number' differs" "'last_section_number' differs"
" whereas no discontinuity has occured"); " whereas no discontinuity has occured");
b_reinit = 1; b_reinit = 1;
}
}
else
{
if( (p_pmt_decoder->b_current_valid)
&& (p_pmt_decoder->current_pmt.i_version == p_section->i_version)
&& (p_pmt_decoder->current_pmt.b_current_next ==
p_section->b_current_next))
{
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
} }
}
else
{
if( (p_pmt_decoder->b_current_valid)
&& (p_pmt_decoder->current_pmt.i_version == p_section->i_version)
&& (p_pmt_decoder->current_pmt.b_current_next ==
p_section->b_current_next))
{
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
} }
}
/* Reinit the decoder if wanted */ /* Reinit the decoder if wanted */
if(b_reinit) if (b_reinit)
{
/* Force redecoding */
p_pmt_decoder->b_current_valid = 0;
/* Free structures */
if(p_pmt_decoder->p_building_pmt)
{ {
free(p_pmt_decoder->p_building_pmt); /* Force redecoding */
p_pmt_decoder->p_building_pmt = NULL; p_pmt_decoder->b_current_valid = 0;
}
/* Clear the section array */ /* Free structures */
for(unsigned int i = 0; i <= 255; i++) if (p_pmt_decoder->p_building_pmt)
{ {
if(p_pmt_decoder->ap_sections[i] != NULL) free(p_pmt_decoder->p_building_pmt);
{ p_pmt_decoder->p_building_pmt = NULL;
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[i]); }
p_pmt_decoder->ap_sections[i] = NULL;
}
}
}
/* Append the section to the list if wanted */ /* Clear the section array */
if(b_append) for (unsigned int i = 0; i <= 255; i++)
{ {
int b_complete; if (p_pmt_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[i]);
p_pmt_decoder->ap_sections[i] = NULL;
}
}
}
/* Initialize the structures if it's the first section received */ /* Append the section to the list if wanted */
if(!p_pmt_decoder->p_building_pmt) if (b_append)
{ {
p_pmt_decoder->p_building_pmt = int b_complete;
/* Initialize the structures if it's the first section received */
if (!p_pmt_decoder->p_building_pmt)
{
p_pmt_decoder->p_building_pmt =
(dvbpsi_pmt_t*)malloc(sizeof(dvbpsi_pmt_t)); (dvbpsi_pmt_t*)malloc(sizeof(dvbpsi_pmt_t));
dvbpsi_InitPMT(p_pmt_decoder->p_building_pmt, dvbpsi_InitPMT(p_pmt_decoder->p_building_pmt,
p_pmt_decoder->i_program_number, p_pmt_decoder->i_program_number,
p_section->i_version, p_section->i_version,
p_section->b_current_next, p_section->b_current_next,
((uint16_t)(p_section->p_payload_start[0] & 0x1f) << 8) ((uint16_t)(p_section->p_payload_start[0] & 0x1f) << 8)
| p_section->p_payload_start[1]); | p_section->p_payload_start[1]);
p_pmt_decoder->i_last_section_number = p_section->i_last_number; p_pmt_decoder->i_last_section_number = p_section->i_last_number;
} }
/* Fill the section array */ /* Fill the section array */
if(p_pmt_decoder->ap_sections[p_section->i_number] != NULL) if (p_pmt_decoder->ap_sections[p_section->i_number] != NULL)
{ {
dvbpsi_debug(h_dvbpsi, "PMT decoder", "overwrite section number %d", dvbpsi_debug(p_dvbpsi, "PMT decoder", "overwrite section number %d",
p_section->i_number); p_section->i_number);
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[p_section->i_number]); dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[p_section->i_number]);
} }
p_pmt_decoder->ap_sections[p_section->i_number] = p_section; p_pmt_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 = 0;
for(unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++) for (unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++)
{ {
if(!p_pmt_decoder->ap_sections[i]) if (!p_pmt_decoder->ap_sections[i])
break; break;
if(i == p_pmt_decoder->i_last_section_number) if (i == p_pmt_decoder->i_last_section_number)
b_complete = 1; b_complete = 1;
} }
if(b_complete) if (b_complete)
{ {
/* Save the current information */ /* Save the current information */
p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt; p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt;
p_pmt_decoder->b_current_valid = 1; p_pmt_decoder->b_current_valid = 1;
/* Chain the sections */ /* Chain the sections */
if(p_pmt_decoder->i_last_section_number) if (p_pmt_decoder->i_last_section_number)
{ {
for(unsigned int i = 0; (int)i <= p_pmt_decoder->i_last_section_number - 1; i++) for (unsigned int i = 0; (int)i <= p_pmt_decoder->i_last_section_number - 1; i++)
p_pmt_decoder->ap_sections[i]->p_next = p_pmt_decoder->ap_sections[i]->p_next =
p_pmt_decoder->ap_sections[i + 1]; p_pmt_decoder->ap_sections[i + 1];
} }
/* Decode the sections */ /* Decode the sections */
dvbpsi_DecodePMTSections(p_pmt_decoder->p_building_pmt, dvbpsi_DecodePMTSections(p_pmt_decoder->p_building_pmt,
p_pmt_decoder->ap_sections[0]); p_pmt_decoder->ap_sections[0]);
/* Delete the sections */ /* Delete the sections */
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[0]); dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[0]);
/* signal the new PMT */ /* signal the new PMT */
p_pmt_decoder->pf_callback(p_pmt_decoder->p_cb_data, p_pmt_decoder->pf_pmt_callback(p_pmt_decoder->p_cb_data,
p_pmt_decoder->p_building_pmt); p_pmt_decoder->p_building_pmt);
/* Reinitialize the structures */ /* Reinitialize the structures */
p_pmt_decoder->p_building_pmt = NULL; p_pmt_decoder->p_building_pmt = NULL;
for(unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++) for (unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++)
p_pmt_decoder->ap_sections[i] = NULL; p_pmt_decoder->ap_sections[i] = NULL;
}
}
else
{
dvbpsi_DeletePSISections(p_section);
} }
}
else
{
dvbpsi_DeletePSISections(p_section);
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodePMTSections * dvbpsi_DecodePMTSections
***************************************************************************** *****************************************************************************
...@@ -449,49 +422,48 @@ void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, ...@@ -449,49 +422,48 @@ void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt, void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t* p_byte, * p_end; uint8_t* p_byte, * p_end;
while(p_section)
{
/* - PMT descriptors */
p_byte = p_section->p_payload_start + 4;
p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[2] & 0x0f) << 8)
| p_section->p_payload_start[3]);
while(p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end - p_byte)
dvbpsi_PMTAddDescriptor(p_pmt, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
/* - ESs */ while (p_section)
for(p_byte = p_end; p_byte + 5 <= p_section->p_payload_end;)
{ {
uint8_t i_type = p_byte[0]; /* - PMT descriptors */
uint16_t i_pid = ((uint16_t)(p_byte[1] & 0x1f) << 8) | p_byte[2]; p_byte = p_section->p_payload_start + 4;
uint16_t i_es_length = ((uint16_t)(p_byte[3] & 0x0f) << 8) | p_byte[4]; p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[2] & 0x0f) << 8)
dvbpsi_pmt_es_t* p_es = dvbpsi_PMTAddES(p_pmt, i_type, i_pid); | p_section->p_payload_start[3]);
/* - ES descriptors */ while (p_byte + 2 <= p_end)
p_byte += 5; {
p_end = p_byte + i_es_length; uint8_t i_tag = p_byte[0];
if( p_end > p_section->p_payload_end ) uint8_t i_length = p_byte[1];
{ if (i_length + 2 <= p_end - p_byte)
p_end = p_section->p_payload_end; dvbpsi_PMTAddDescriptor(p_pmt, i_tag, i_length, p_byte + 2);
} p_byte += 2 + i_length;
while(p_byte + 2 <= p_end) }
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end - p_byte)
dvbpsi_PMTESAddDescriptor(p_es, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
}
p_section = p_section->p_next; /* - ESs */
} for (p_byte = p_end; p_byte + 5 <= p_section->p_payload_end;)
{
uint8_t i_type = p_byte[0];
uint16_t i_pid = ((uint16_t)(p_byte[1] & 0x1f) << 8) | p_byte[2];
uint16_t i_es_length = ((uint16_t)(p_byte[3] & 0x0f) << 8) | p_byte[4];
dvbpsi_pmt_es_t* p_es = dvbpsi_PMTAddES(p_pmt, i_type, i_pid);
/* - ES descriptors */
p_byte += 5;
p_end = p_byte + i_es_length;
if (p_end > p_section->p_payload_end)
{
p_end = p_section->p_payload_end;
}
while (p_byte + 2 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if (i_length + 2 <= p_end - p_byte)
dvbpsi_PMTESAddDescriptor(p_es, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
}
p_section = p_section->p_next;
}
} }
...@@ -500,185 +472,183 @@ void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt, ...@@ -500,185 +472,183 @@ void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt,
***************************************************************************** *****************************************************************************
* Generate PMT sections based on the dvbpsi_pmt_t structure. * Generate PMT sections based on the dvbpsi_pmt_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt) dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_t *p_dvbpsi, dvbpsi_pmt_t* p_pmt)
{ {
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result; dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev; dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_pmt->p_first_descriptor; dvbpsi_descriptor_t* p_descriptor = p_pmt->p_first_descriptor;
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es;
uint16_t i_info_length; uint16_t i_info_length;
p_current->i_table_id = 0x02; p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1; p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0; p_current->b_private_indicator = 0;
p_current->i_length = 13; /* header + CRC_32 */ p_current->i_length = 13; /* header + CRC_32 */
p_current->i_extension = p_pmt->i_program_number; p_current->i_extension = p_pmt->i_program_number;
p_current->i_version = p_pmt->i_version; p_current->i_version = p_pmt->i_version;
p_current->b_current_next = p_pmt->b_current_next; p_current->b_current_next = p_pmt->b_current_next;
p_current->i_number = 0; p_current->i_number = 0;
p_current->p_payload_end += 12; /* just after the header */ p_current->p_payload_end += 12; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8; p_current->p_payload_start = p_current->p_data + 8;
/* PCR_PID */ /* PCR_PID */
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0;
p_current->p_data[9] = p_pmt->i_pcr_pid; p_current->p_data[9] = p_pmt->i_pcr_pid;
/* PMT descriptors */ /* PMT descriptors */
while(p_descriptor != NULL) while (p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
{ {
/* program_info_length */ /* New section if needed */
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12; /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
p_current->p_data[10] = (i_info_length >> 8) | 0xf0; if ((p_current->p_payload_end - p_current->p_data)
p_current->p_data[11] = i_info_length; + p_descriptor->i_length > 1018)
{
p_prev = p_current; /* program_info_length */
p_current = dvbpsi_NewPSISection(1024); i_info_length = (p_current->p_payload_end - p_current->p_data) - 12;
p_prev->p_next = p_current; p_current->p_data[10] = (i_info_length >> 8) | 0xf0;
p_current->p_data[11] = i_info_length;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1; p_prev = p_current;
p_current->b_private_indicator = 0; p_current = dvbpsi_NewPSISection(1024);
p_current->i_length = 13; /* header + CRC_32 */ p_prev->p_next = p_current;
p_current->i_extension = p_pmt->i_program_number;
p_current->i_version = p_pmt->i_version; p_current->i_table_id = 0x02;
p_current->b_current_next = p_pmt->b_current_next; p_current->b_syntax_indicator = 1;
p_current->i_number = p_prev->i_number + 1; p_current->b_private_indicator = 0;
p_current->p_payload_end += 12; /* just after the header */ p_current->i_length = 13; /* header + CRC_32 */
p_current->p_payload_start = p_current->p_data + 8; p_current->i_extension = p_pmt->i_program_number;
p_current->i_version = p_pmt->i_version;
/* PCR_PID */ p_current->b_current_next = p_pmt->b_current_next;
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; p_current->i_number = p_prev->i_number + 1;
p_current->p_data[9] = p_pmt->i_pcr_pid; p_current->p_payload_end += 12; /* just after the header */
} p_current->p_payload_start = p_current->p_data + 8;
/* PCR_PID */
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0;
p_current->p_data[9] = p_pmt->i_pcr_pid;
}
/* p_payload_end is where the descriptor begins */ /* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag; p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length; p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2, memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data, p_descriptor->p_data,
p_descriptor->i_length); p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */ /* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2; p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2; p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next; p_descriptor = p_descriptor->p_next;
}
/* program_info_length */
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12;
p_current->p_data[10] = (i_info_length >> 8) | 0xf0;
p_current->p_data[11] = i_info_length;
/* PMT ESs */
while(p_es != NULL)
{
uint8_t* p_es_start = p_current->p_payload_end;
uint16_t i_es_length = 5;
/* Can the current section carry all the descriptors ? */
p_descriptor = p_es->p_first_descriptor;
while( (p_descriptor != NULL)
&& ((p_es_start - p_current->p_data) + i_es_length <= 1020))
{
i_es_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
} }
/* If _no_ and the current section isn't empty and an empty section /* program_info_length */
may carry one more descriptor i_info_length = (p_current->p_payload_end - p_current->p_data) - 12;
then create a new section */ p_current->p_data[10] = (i_info_length >> 8) | 0xf0;
if( (p_descriptor != NULL) p_current->p_data[11] = i_info_length;
&& (p_es_start - p_current->p_data != 12)
&& (i_es_length <= 1008)) /* PMT ESs */
while (p_es != NULL)
{ {
/* will put more descriptors in an empty section */ uint8_t* p_es_start = p_current->p_payload_end;
#if 0 uint16_t i_es_length = 5;
dvbpsi_debug(h_dvbpsi, "PMT generator",
"create a new section to carry more ES descriptors"); /* Can the current section carry all the descriptors ? */
#endif p_descriptor = p_es->p_first_descriptor;
p_prev = p_current; while( (p_descriptor != NULL)
p_current = dvbpsi_NewPSISection(1024); && ((p_es_start - p_current->p_data) + i_es_length <= 1020))
p_prev->p_next = p_current; {
i_es_length += p_descriptor->i_length + 2;
p_current->i_table_id = 0x02; p_descriptor = p_descriptor->p_next;
p_current->b_syntax_indicator = 1; }
p_current->b_private_indicator = 0;
p_current->i_length = 13; /* header + CRC_32 */ /* If _no_ and the current section isn't empty and an empty section
p_current->i_extension = p_pmt->i_program_number; may carry one more descriptor
p_current->i_version = p_pmt->i_version; then create a new section */
p_current->b_current_next = p_pmt->b_current_next; if( (p_descriptor != NULL)
p_current->i_number = p_prev->i_number + 1; && (p_es_start - p_current->p_data != 12)
p_current->p_payload_end += 12; /* just after the header */ && (i_es_length <= 1008))
p_current->p_payload_start = p_current->p_data + 8; {
/* will put more descriptors in an empty section */
/* PCR_PID */ dvbpsi_debug(p_dvbpsi, "PMT generator",
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; "create a new section to carry more ES descriptors");
p_current->p_data[9] = p_pmt->i_pcr_pid;
p_prev = p_current;
/* program_info_length */ p_current = dvbpsi_NewPSISection(1024);
i_info_length = 0; p_prev->p_next = p_current;
p_current->p_data[10] = 0xf0;
p_current->p_data[11] = 0x00; p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
p_es_start = p_current->p_payload_end; p_current->b_private_indicator = 0;
} p_current->i_length = 13; /* header + CRC_32 */
p_current->i_extension = p_pmt->i_program_number;
p_current->i_version = p_pmt->i_version;
p_current->b_current_next = p_pmt->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 12; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* PCR_PID */
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0;
p_current->p_data[9] = p_pmt->i_pcr_pid;
/* program_info_length */
i_info_length = 0;
p_current->p_data[10] = 0xf0;
p_current->p_data[11] = 0x00;
p_es_start = p_current->p_payload_end;
}
/* p_es_start is where the ES begins */
p_es_start[0] = p_es->i_type;
p_es_start[1] = (p_es->i_pid >> 8) | 0xe0;
p_es_start[2] = p_es->i_pid;
/* Increase the length by 5 */
p_current->p_payload_end += 5;
p_current->i_length += 5;
/* ES descriptors */
p_descriptor = p_es->p_first_descriptor;
while( (p_descriptor != NULL)
&& ( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length <= 1018))
{
/* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* p_es_start is where the ES begins */ if (p_descriptor != NULL)
p_es_start[0] = p_es->i_type; dvbpsi_error(p_dvbpsi, "PMT generator", "unable to carry all the ES descriptors");
p_es_start[1] = (p_es->i_pid >> 8) | 0xe0;
p_es_start[2] = p_es->i_pid;
/* Increase the length by 5 */ /* ES_info_length */
p_current->p_payload_end += 5; i_es_length = p_current->p_payload_end - p_es_start - 5;
p_current->i_length += 5; p_es_start[3] = (i_es_length >> 8) | 0xf0;
p_es_start[4] = i_es_length;
p_es = p_es->p_next;
}
/* ES descriptors */ /* Finalization */
p_descriptor = p_es->p_first_descriptor; p_prev = p_result;
while( (p_descriptor != NULL) while (p_prev != NULL)
&& ( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length <= 1018))
{ {
/* p_payload_end is where the descriptor begins */ p_prev->i_last_number = p_current->i_number;
p_current->p_payload_end[0] = p_descriptor->i_tag; dvbpsi_BuildPSISection(p_prev);
p_current->p_payload_end[1] = p_descriptor->i_length; p_prev = p_prev->p_next;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
} }
#if 0
if(p_descriptor != NULL)
dvbpsi_error(h_dvbpsi, "PMT generator", "unable to carry all the ES descriptors");
#endif
/* ES_info_length */
i_es_length = p_current->p_payload_end - p_es_start - 5;
p_es_start[3] = (i_es_length >> 8) | 0xf0;
p_es_start[4] = i_es_length;
p_es = p_es->p_next;
}
/* Finalization */
p_prev = p_result;
while(p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
return p_result;
}
return p_result;
}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* $Id$ * $Id$
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_pmt_es_t * dvbpsi_pmt_es_t
*****************************************************************************/ *****************************************************************************/
...@@ -64,7 +64,6 @@ typedef struct dvbpsi_pmt_es_s ...@@ -64,7 +64,6 @@ typedef struct dvbpsi_pmt_es_s
} dvbpsi_pmt_es_t; } dvbpsi_pmt_es_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_pmt_t * dvbpsi_pmt_t
*****************************************************************************/ *****************************************************************************/
...@@ -93,7 +92,6 @@ typedef struct dvbpsi_pmt_s ...@@ -93,7 +92,6 @@ typedef struct dvbpsi_pmt_s
} dvbpsi_pmt_t; } dvbpsi_pmt_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_pmt_callback * dvbpsi_pmt_callback
*****************************************************************************/ *****************************************************************************/
...@@ -104,38 +102,37 @@ typedef struct dvbpsi_pmt_s ...@@ -104,38 +102,37 @@ typedef struct dvbpsi_pmt_s
*/ */
typedef void (* dvbpsi_pmt_callback)(void* p_cb_data, dvbpsi_pmt_t* p_new_pmt); typedef void (* dvbpsi_pmt_callback)(void* p_cb_data, dvbpsi_pmt_t* p_new_pmt);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachPMT * dvbpsi_AttachPMT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_handle dvbpsi_AttachPMT(uint16_t i_program_number, * \fn dvbpsi_t *dvbpsi_AttachPMT(dvbpsi_t *p_dvbpsi,
uint16_t i_program_number,
dvbpsi_pmt_callback pf_callback, dvbpsi_pmt_callback pf_callback,
void* p_cb_data) void* p_cb_data)
* \brief Creation and initialization of a PMT decoder. * \brief Creates and initialization of a PMT decoder and attaches it to dvbpsi_t
* handle
* \param i_program_number program number * \param i_program_number program number
* \param pf_callback function to call back on new PMT * \param pf_callback function to call back on new PMT
* \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 a pointer to the decoder for future calls. * \return a pointer to the decoder for future calls.
*/ */
dvbpsi_handle dvbpsi_AttachPMT(uint16_t i_program_number, dvbpsi_t *dvbpsi_AttachPMT(dvbpsi_t *p_dvbpsi, uint16_t i_program_number,
dvbpsi_pmt_callback pf_callback, dvbpsi_pmt_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachPMT * dvbpsi_DetachPMT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi) * \fn void dvbpsi_DetachPMT(dvbpsi_t *p_dvbpsi)
* \brief Destroy a PMT decoder. * \brief Destroy a PMT decoder.
* \param h_dvbpsi handle to the decoder * \param p_dvbpsi handle
* \return nothing. * \return nothing.
* *
* The handle isn't valid any more. * The handle isn't valid any more.
*/ */
void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi); void dvbpsi_DetachPMT(dvbpsi_t *p_dvbpsi);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitPMT/dvbpsi_NewPMT * dvbpsi_InitPMT/dvbpsi_NewPMT
...@@ -175,7 +172,6 @@ do { \ ...@@ -175,7 +172,6 @@ do { \
i_pcr_pid); \ i_pcr_pid); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyPMT/dvbpsi_DeletePMT * dvbpsi_EmptyPMT/dvbpsi_DeletePMT
*****************************************************************************/ *****************************************************************************/
...@@ -199,7 +195,6 @@ do { \ ...@@ -199,7 +195,6 @@ do { \
free(p_pmt); \ free(p_pmt); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_PMTAddDescriptor * dvbpsi_PMTAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -219,7 +214,6 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt, ...@@ -219,7 +214,6 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt,
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_PMTAddES * dvbpsi_PMTAddES
*****************************************************************************/ *****************************************************************************/
...@@ -235,7 +229,6 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt, ...@@ -235,7 +229,6 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt,
dvbpsi_pmt_es_t* dvbpsi_PMTAddES(dvbpsi_pmt_t* p_pmt, dvbpsi_pmt_es_t* dvbpsi_PMTAddES(dvbpsi_pmt_t* p_pmt,
uint8_t i_type, uint16_t i_pid); uint8_t i_type, uint16_t i_pid);
/***************************************************************************** /*****************************************************************************
* dvbpsi_PMTESAddDescriptor * dvbpsi_PMTESAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -255,20 +248,20 @@ dvbpsi_descriptor_t* dvbpsi_PMTESAddDescriptor(dvbpsi_pmt_es_t* p_es, ...@@ -255,20 +248,20 @@ dvbpsi_descriptor_t* dvbpsi_PMTESAddDescriptor(dvbpsi_pmt_es_t* p_es,
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_GenPMTSections * dvbpsi_GenPMTSections
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt) * \fn dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_t *p_dvbpsi,
dvbpsi_pmt_t* p_pmt)
* \brief PMT generator * \brief PMT generator
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_pmt PMT structure * \param p_pmt PMT structure
* \return a pointer to the list of generated PSI sections. * \return a pointer to the list of generated PSI sections.
* *
* Generate PMT sections based on the dvbpsi_pmt_t structure. * Generate PMT sections based on the dvbpsi_pmt_t structure.
*/ */
dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt); dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_t *p_dvbpsi, dvbpsi_pmt_t* p_pmt);
#ifdef __cplusplus #ifdef __cplusplus
}; };
...@@ -277,4 +270,3 @@ dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt); ...@@ -277,4 +270,3 @@ dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt);
#else #else
#error "Multiple inclusions of pmt.h" #error "Multiple inclusions of pmt.h"
#endif #endif
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id: pmt_private.h,v 1.1 2002/01/22 20:30:16 bozo Exp $ * $Id: pmt_private.h,v 1.1 2002/01/22 20:30:16 bozo Exp $
* *
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -34,31 +35,31 @@ ...@@ -34,31 +35,31 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_pmt_decoder_s typedef struct dvbpsi_pmt_decoder_s
{ {
uint16_t i_program_number; DVBPSI_DECODER_COMMON
dvbpsi_pmt_callback pf_callback; uint16_t i_program_number;
void * p_cb_data;
dvbpsi_pmt_t current_pmt; dvbpsi_pmt_callback pf_pmt_callback;
dvbpsi_pmt_t * p_building_pmt; void * p_cb_data;
int b_current_valid; dvbpsi_pmt_t current_pmt;
dvbpsi_pmt_t * p_building_pmt;
uint8_t i_last_section_number; int b_current_valid;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_pmt_decoder_t; uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_pmt_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherPMTSections * dvbpsi_GatherPMTSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherPMTSections(dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodePMTSections * dvbpsi_DecodePMTSections
***************************************************************************** *****************************************************************************
...@@ -67,7 +68,6 @@ void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, ...@@ -67,7 +68,6 @@ void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt, void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of pmt_private.h" #error "Multiple inclusions of pmt_private.h"
#endif #endif
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
* Copyright (C) 2001-2010 VideoLAN * Copyright (C) 2001-2010 VideoLAN
* $Id$ * $Id$
* *
* Authors: Johan Bilien <jobi@via.ecp.fr> * Authors: Johan Bilien <jobi@via.ecp.fr>\
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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,7 +25,6 @@ ...@@ -24,7 +25,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -45,113 +45,103 @@ ...@@ -45,113 +45,103 @@
#include "sdt.h" #include "sdt.h"
#include "sdt_private.h" #include "sdt_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachSDT * dvbpsi_AttachSDT
***************************************************************************** *****************************************************************************
* Initialize a SDT subtable decoder. * Initialize a SDT subtable decoder.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_AttachSDT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, dvbpsi_t *dvbpsi_AttachSDT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_sdt_callback pf_callback, uint16_t i_extension, dvbpsi_sdt_callback pf_callback,
void* p_cb_data) void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_sdt_decoder_t* p_sdt_decoder;
dvbpsi_sdt_decoder_t* p_sdt_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) {
{ dvbpsi_error(p_dvbpsi, "SDT decoder",
dvbpsi_error(h_dvbpsi, "SDT decoder",
"Already a decoder for (table_id == 0x%02x," "Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return NULL;
}
p_subdec = (dvbpsi_demux_subdec_t*)calloc(1, sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
return NULL;
return 1; p_sdt_decoder = (dvbpsi_sdt_decoder_t*)calloc(1, sizeof(dvbpsi_sdt_decoder_t));
} if (p_sdt_decoder == NULL)
{
free(p_subdec);
return NULL;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t)); /* subtable decoder configuration */
if(p_subdec == NULL) p_subdec->pf_callback = &dvbpsi_GatherSDTSections;
{ p_subdec->p_cb_data = p_sdt_decoder;
return 1; p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
} p_subdec->pf_detach = &dvbpsi_DetachSDT;
p_sdt_decoder = (dvbpsi_sdt_decoder_t*)malloc(sizeof(dvbpsi_sdt_decoder_t)); /* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
if(p_sdt_decoder == NULL) /* SDT decoder information */
{ p_sdt_decoder->pf_sdt_callback = pf_callback;
free(p_subdec); p_sdt_decoder->p_cb_data = p_cb_data;
return 1;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherSDTSections;
p_subdec->p_cb_data = p_sdt_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachSDT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* SDT decoder information */
p_sdt_decoder->pf_callback = pf_callback;
p_sdt_decoder->p_cb_data = p_cb_data;
/* SDT decoder initial state */
p_sdt_decoder->b_current_valid = 0;
p_sdt_decoder->p_building_sdt = NULL;
for(unsigned int i = 0; i <= 255; i++)
p_sdt_decoder->ap_sections[i] = NULL;
return 0;
}
/* SDT decoder initial state */
p_sdt_decoder->b_current_valid = 0;
p_sdt_decoder->p_building_sdt = NULL;
for (unsigned int i = 0; i <= 255; i++)
p_sdt_decoder->ap_sections[i] = NULL;
return p_dvbpsi;
}
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachSDT * dvbpsi_DetachSDT
***************************************************************************** *****************************************************************************
* Close a SDT decoder. * Close a SDT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachSDT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
uint16_t i_extension)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec; dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_sdt_decoder_t* p_sdt_decoder; dvbpsi_sdt_decoder_t* p_sdt_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_demux == NULL) p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
{ if (p_subdec == NULL)
dvbpsi_error(h_dvbpsi, "SDT Decoder", {
dvbpsi_error(p_dvbpsi, "SDT Decoder",
"No such SDT decoder (table_id == 0x%02x," "No such SDT decoder (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return; return;
} }
p_sdt_decoder = (dvbpsi_sdt_decoder_t*)p_subdec->p_cb_data;
free(p_sdt_decoder->p_building_sdt);
for(unsigned int i = 0; i <= 255; i++) p_sdt_decoder = (dvbpsi_sdt_decoder_t*)p_subdec->p_cb_data;
{ free(p_sdt_decoder->p_building_sdt);
if(p_sdt_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[i]);
}
free(p_subdec->p_cb_data); for (unsigned int i = 0; i <= 255; i++)
{
if (p_sdt_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_sdt_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);
p_subdec = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitSDT * dvbpsi_InitSDT
***************************************************************************** *****************************************************************************
...@@ -160,14 +150,13 @@ void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -160,14 +150,13 @@ void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
void dvbpsi_InitSDT(dvbpsi_sdt_t* p_sdt, uint16_t i_ts_id, uint8_t i_version, void dvbpsi_InitSDT(dvbpsi_sdt_t* p_sdt, uint16_t i_ts_id, uint8_t i_version,
int b_current_next, uint16_t i_network_id) int b_current_next, uint16_t i_network_id)
{ {
p_sdt->i_ts_id = i_ts_id; p_sdt->i_ts_id = i_ts_id;
p_sdt->i_version = i_version; p_sdt->i_version = i_version;
p_sdt->b_current_next = b_current_next; p_sdt->b_current_next = b_current_next;
p_sdt->i_network_id = i_network_id; p_sdt->i_network_id = i_network_id;
p_sdt->p_first_service = NULL; p_sdt->p_first_service = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptySDT * dvbpsi_EmptySDT
***************************************************************************** *****************************************************************************
...@@ -175,20 +164,18 @@ void dvbpsi_InitSDT(dvbpsi_sdt_t* p_sdt, uint16_t i_ts_id, uint8_t i_version, ...@@ -175,20 +164,18 @@ void dvbpsi_InitSDT(dvbpsi_sdt_t* p_sdt, uint16_t i_ts_id, uint8_t i_version,
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptySDT(dvbpsi_sdt_t* p_sdt) void dvbpsi_EmptySDT(dvbpsi_sdt_t* p_sdt)
{ {
dvbpsi_sdt_service_t* p_service = p_sdt->p_first_service; dvbpsi_sdt_service_t* p_service = p_sdt->p_first_service;
while(p_service != NULL)
{
dvbpsi_sdt_service_t* p_tmp = p_service->p_next;
dvbpsi_DeleteDescriptors(p_service->p_first_descriptor);
free(p_service);
p_service = p_tmp;
}
p_sdt->p_first_service = NULL; while (p_service != NULL)
{
dvbpsi_sdt_service_t* p_tmp = p_service->p_next;
dvbpsi_DeleteDescriptors(p_service->p_first_descriptor);
free(p_service);
p_service = p_tmp;
}
p_sdt->p_first_service = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_SDTAddService * dvbpsi_SDTAddService
***************************************************************************** *****************************************************************************
...@@ -201,11 +188,11 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt, ...@@ -201,11 +188,11 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt,
uint8_t i_running_status, uint8_t i_running_status,
int b_free_ca) int b_free_ca)
{ {
dvbpsi_sdt_service_t * p_service dvbpsi_sdt_service_t * p_service;
= (dvbpsi_sdt_service_t*)malloc(sizeof(dvbpsi_sdt_service_t)); p_service = (dvbpsi_sdt_service_t*)malloc(sizeof(dvbpsi_sdt_service_t));
if (p_service == NULL)
return NULL;
if(p_service)
{
p_service->i_service_id = i_service_id; p_service->i_service_id = i_service_id;
p_service->b_eit_schedule = b_eit_schedule; p_service->b_eit_schedule = b_eit_schedule;
p_service->b_eit_present = b_eit_present; p_service->b_eit_present = b_eit_present;
...@@ -214,23 +201,19 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt, ...@@ -214,23 +201,19 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt,
p_service->p_next = NULL; p_service->p_next = NULL;
p_service->p_first_descriptor = NULL; p_service->p_first_descriptor = NULL;
if(p_sdt->p_first_service == NULL) if (p_sdt->p_first_service == NULL)
{ p_sdt->p_first_service = p_service;
p_sdt->p_first_service = p_service;
}
else else
{ {
dvbpsi_sdt_service_t * p_last_service = p_sdt->p_first_service; dvbpsi_sdt_service_t * p_last_service = p_sdt->p_first_service;
while(p_last_service->p_next != NULL) while(p_last_service->p_next != NULL)
p_last_service = p_last_service->p_next; p_last_service = p_last_service->p_next;
p_last_service->p_next = p_service; p_last_service->p_next = p_service;
} }
}
return p_service; return p_service;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_SDTServiceAddDescriptor * dvbpsi_SDTServiceAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -241,44 +224,40 @@ dvbpsi_descriptor_t *dvbpsi_SDTServiceAddDescriptor( ...@@ -241,44 +224,40 @@ dvbpsi_descriptor_t *dvbpsi_SDTServiceAddDescriptor(
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); p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if (p_descriptor == NULL)
return NULL;
if(p_descriptor) if (p_service->p_first_descriptor == NULL)
{ p_service->p_first_descriptor = p_descriptor;
if(p_service->p_first_descriptor == NULL)
{
p_service->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t * p_last_descriptor = p_service->p_first_descriptor; dvbpsi_descriptor_t * p_last_descriptor = p_service->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherSDTSections * dvbpsi_GatherSDTSections
***************************************************************************** *****************************************************************************
* Callback for the subtable demultiplexor. * Callback for the subtable demultiplexor.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder, void dvbpsi_GatherSDTSections(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_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_sdt_decoder_t * p_sdt_decoder dvbpsi_sdt_decoder_t *p_sdt_decoder
= (dvbpsi_sdt_decoder_t*)p_private_decoder; = (dvbpsi_sdt_decoder_t*)p_private_decoder;
int b_append = 1;
int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "SDT decoder", int b_append = 1;
int b_reinit = 0;
dvbpsi_debug(p_dvbpsi, "SDT decoder",
"Table version %2d, " "i_table_id %2d, " "i_extension %5d, " "Table version %2d, " "i_table_id %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id, p_section->i_version, p_section->i_table_id,
...@@ -286,163 +265,158 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -286,163 +265,158 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder,
p_section->i_number, p_section->i_last_number, p_section->i_number, p_section->i_last_number,
p_section->b_current_next); p_section->b_current_next);
if(!p_section->b_syntax_indicator) if (!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "SDT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
/* Now if b_append is true then we have a valid SDT section */
if(b_append)
{
/* TS discontinuity check */
if(p_psi_decoder->b_discontinuity)
{ {
b_reinit = 1; /* Invalid section_syntax_indicator */
p_psi_decoder->b_discontinuity = 0; dvbpsi_error(p_dvbpsi, "SDT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
} }
else
/* Now if b_append is true then we have a valid SDT section */
if (b_append)
{ {
/* Perform a few sanity checks */ /* TS discontinuity check */
if(p_sdt_decoder->p_building_sdt) if (p_demux->b_discontinuity)
{
if(p_sdt_decoder->p_building_sdt->i_ts_id != p_section->i_extension)
{ {
/* transport_stream_id */ b_reinit = 1;
dvbpsi_error(h_dvbpsi, "SDT decoder", p_demux->b_discontinuity = 0;
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
} }
else if(p_sdt_decoder->p_building_sdt->i_version else
!= p_section->i_version)
{ {
/* version_number */ /* Perform a few sanity checks */
dvbpsi_error(h_dvbpsi, "SDT decoder", if (p_sdt_decoder->p_building_sdt)
"'version_number' differs" {
" whereas no discontinuity has occured"); if (p_sdt_decoder->p_building_sdt->i_ts_id != p_section->i_extension)
b_reinit = 1; {
/* transport_stream_id */
dvbpsi_error(p_dvbpsi, "SDT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
}
else if (p_sdt_decoder->p_building_sdt->i_version != p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "SDT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
else if (p_sdt_decoder->i_last_section_number != p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(p_dvbpsi, "SDT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
}
else
{
if( (p_sdt_decoder->b_current_valid)
&& (p_sdt_decoder->current_sdt.i_version == p_section->i_version)
&& (p_sdt_decoder->current_sdt.b_current_next == p_section->b_current_next))
{
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
} }
else if(p_sdt_decoder->i_last_section_number != }
p_section->i_last_number)
/* Reinit the decoder if wanted */
if (b_reinit)
{
/* Force redecoding */
p_sdt_decoder->b_current_valid = 0;
/* Free structures */
if (p_sdt_decoder->p_building_sdt)
{ {
/* last_section_number */ free(p_sdt_decoder->p_building_sdt);
dvbpsi_error(h_dvbpsi, "SDT decoder", p_sdt_decoder->p_building_sdt = 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_sdt_decoder->b_current_valid)
&& (p_sdt_decoder->current_sdt.i_version == p_section->i_version)
&& (p_sdt_decoder->current_sdt.b_current_next ==
p_section->b_current_next))
{ {
/* Don't decode since this version is already decoded */ if (p_sdt_decoder->ap_sections[i] != NULL)
b_append = 0; {
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[i]);
p_sdt_decoder->ap_sections[i] = NULL;
}
} }
}
} }
}
/* Reinit the decoder if wanted */ /* Append the section to the list if wanted */
if(b_reinit) if (b_append)
{
/* Force redecoding */
p_sdt_decoder->b_current_valid = 0;
/* Free structures */
if(p_sdt_decoder->p_building_sdt)
{ {
free(p_sdt_decoder->p_building_sdt); int b_complete;
p_sdt_decoder->p_building_sdt = NULL;
}
/* Clear the section array */
for(unsigned int i = 0; i <= 255; i++)
{
if(p_sdt_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[i]);
p_sdt_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_sdt_decoder->p_building_sdt) if (!p_sdt_decoder->p_building_sdt)
{ {
p_sdt_decoder->p_building_sdt = p_sdt_decoder->p_building_sdt =
(dvbpsi_sdt_t*)malloc(sizeof(dvbpsi_sdt_t)); (dvbpsi_sdt_t*)calloc(1, sizeof(dvbpsi_sdt_t));
dvbpsi_InitSDT(p_sdt_decoder->p_building_sdt, dvbpsi_InitSDT(p_sdt_decoder->p_building_sdt,
p_section->i_extension, p_section->i_extension,
p_section->i_version, p_section->i_version,
p_section->b_current_next, p_section->b_current_next,
((uint16_t)(p_section->p_payload_start[0]) << 8) ((uint16_t)(p_section->p_payload_start[0]) << 8)
| p_section->p_payload_start[1]); | p_section->p_payload_start[1]);
p_sdt_decoder->i_last_section_number = p_section->i_last_number; p_sdt_decoder->i_last_section_number = p_section->i_last_number;
} }
/* Fill the section array */ /* Fill the section array */
if(p_sdt_decoder->ap_sections[p_section->i_number] != NULL) if (p_sdt_decoder->ap_sections[p_section->i_number] != NULL)
{ {
dvbpsi_debug(h_dvbpsi, "SDT decoder", "overwrite section number %d", dvbpsi_debug(p_dvbpsi, "SDT decoder", "overwrite section number %d",
p_section->i_number); p_section->i_number);
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[p_section->i_number]); dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[p_section->i_number]);
} }
p_sdt_decoder->ap_sections[p_section->i_number] = p_section; p_sdt_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 = 0;
for(unsigned int i = 0; i <= p_sdt_decoder->i_last_section_number; i++) for (unsigned int i = 0; i <= p_sdt_decoder->i_last_section_number; i++)
{ {
if(!p_sdt_decoder->ap_sections[i]) if (!p_sdt_decoder->ap_sections[i])
break; break;
if(i == p_sdt_decoder->i_last_section_number) if (i == p_sdt_decoder->i_last_section_number)
b_complete = 1; b_complete = 1;
} }
if(b_complete) if (b_complete)
{
/* Save the current information */
p_sdt_decoder->current_sdt = *p_sdt_decoder->p_building_sdt;
p_sdt_decoder->b_current_valid = 1;
/* Chain the sections */
if (p_sdt_decoder->i_last_section_number)
{
for (unsigned int i = 0; (int)i <= p_sdt_decoder->i_last_section_number - 1; i++)
p_sdt_decoder->ap_sections[i]->p_next = p_sdt_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_DecodeSDTSections(p_sdt_decoder->p_building_sdt,
p_sdt_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[0]);
/* signal the new SDT */
p_sdt_decoder->pf_sdt_callback(p_sdt_decoder->p_cb_data,
p_sdt_decoder->p_building_sdt);
/* Reinitialize the structures */
p_sdt_decoder->p_building_sdt = NULL;
for (unsigned int i = 0; i <= p_sdt_decoder->i_last_section_number; i++)
p_sdt_decoder->ap_sections[i] = NULL;
}
}
else
{ {
/* Save the current information */ dvbpsi_DeletePSISections(p_section);
p_sdt_decoder->current_sdt = *p_sdt_decoder->p_building_sdt;
p_sdt_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_sdt_decoder->i_last_section_number)
{
for(unsigned int i = 0; (int)i <= p_sdt_decoder->i_last_section_number - 1; i++)
p_sdt_decoder->ap_sections[i]->p_next =
p_sdt_decoder->ap_sections[i + 1];
}
/* Decode the sections */
dvbpsi_DecodeSDTSections(p_sdt_decoder->p_building_sdt,
p_sdt_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[0]);
/* signal the new SDT */
p_sdt_decoder->pf_callback(p_sdt_decoder->p_cb_data,
p_sdt_decoder->p_building_sdt);
/* Reinitialize the structures */
p_sdt_decoder->p_building_sdt = NULL;
for(unsigned int i = 0; i <= p_sdt_decoder->i_last_section_number; i++)
p_sdt_decoder->ap_sections[i] = NULL;
} }
}
else
{
dvbpsi_DeletePSISections(p_section);
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeSDTSection * dvbpsi_DecodeSDTSection
***************************************************************************** *****************************************************************************
...@@ -451,161 +425,153 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -451,161 +425,153 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder,
void dvbpsi_DecodeSDTSections(dvbpsi_sdt_t* p_sdt, void dvbpsi_DecodeSDTSections(dvbpsi_sdt_t* p_sdt,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t *p_byte, *p_end; uint8_t *p_byte, *p_end;
while(p_section) while (p_section)
{
for(p_byte = p_section->p_payload_start + 3;
p_byte + 4 < p_section->p_payload_end;)
{ {
uint16_t i_service_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1]; for (p_byte = p_section->p_payload_start + 3;
int b_eit_schedule = (int)((p_byte[2] & 0x2) >> 1); p_byte + 4 < p_section->p_payload_end;)
int b_eit_present = (int)((p_byte[2]) & 0x1); {
uint8_t i_running_status = (uint8_t)(p_byte[3]) >> 5; uint16_t i_service_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1];
int b_free_ca = (int)((p_byte[3] & 0x10) >> 4); int b_eit_schedule = (int)((p_byte[2] & 0x2) >> 1);
uint16_t i_srv_length = ((uint16_t)(p_byte[3] & 0xf) <<8) | p_byte[4]; int b_eit_present = (int)((p_byte[2]) & 0x1);
dvbpsi_sdt_service_t* p_service = dvbpsi_SDTAddService(p_sdt, uint8_t i_running_status = (uint8_t)(p_byte[3]) >> 5;
i_service_id, b_eit_schedule, b_eit_present, int b_free_ca = (int)((p_byte[3] & 0x10) >> 4);
i_running_status, b_free_ca); uint16_t i_srv_length = ((uint16_t)(p_byte[3] & 0xf) <<8) | p_byte[4];
dvbpsi_sdt_service_t* p_service = dvbpsi_SDTAddService(p_sdt,
/* Service descriptors */ i_service_id, b_eit_schedule, b_eit_present,
p_byte += 5; i_running_status, b_free_ca);
p_end = p_byte + i_srv_length;
if( p_end > p_section->p_payload_end ) break; /* Service descriptors */
p_byte += 5;
while(p_byte + 2 <= p_end) p_end = p_byte + i_srv_length;
{ if( p_end > p_section->p_payload_end ) break;
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1]; while(p_byte + 2 <= p_end)
if(i_length + 2 <= p_end - p_byte) {
dvbpsi_SDTServiceAddDescriptor(p_service, i_tag, i_length, p_byte + 2); uint8_t i_tag = p_byte[0];
p_byte += 2 + i_length; uint8_t i_length = p_byte[1];
} if (i_length + 2 <= p_end - p_byte)
dvbpsi_SDTServiceAddDescriptor(p_service, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
}
p_section = p_section->p_next;
} }
p_section = p_section->p_next;
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GenSDTSections * dvbpsi_GenSDTSections
***************************************************************************** *****************************************************************************
* Generate SDT sections based on the dvbpsi_sdt_t structure. * Generate SDT sections based on the dvbpsi_sdt_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_GenSDTSections(dvbpsi_sdt_t* p_sdt) dvbpsi_psi_section_t *dvbpsi_GenSDTSections(dvbpsi_t *p_dvbpsi, dvbpsi_sdt_t* p_sdt)
{ {
dvbpsi_psi_section_t * p_result = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t *p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t * p_current = p_result; dvbpsi_psi_section_t *p_current = p_result;
dvbpsi_psi_section_t * p_prev; dvbpsi_psi_section_t *p_prev;
dvbpsi_sdt_service_t * p_service = p_sdt->p_first_service; dvbpsi_sdt_service_t *p_service = p_sdt->p_first_service;
p_current->i_table_id = 0x42; p_current->i_table_id = 0x42;
p_current->b_syntax_indicator = 1; p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 1; p_current->b_private_indicator = 1;
p_current->i_length = 12; /* header + CRC_32 */ p_current->i_length = 12; /* header + CRC_32 */
p_current->i_extension = p_sdt->i_ts_id; p_current->i_extension = p_sdt->i_ts_id;
p_current->i_version = p_sdt->i_version; p_current->i_version = p_sdt->i_version;
p_current->b_current_next = p_sdt->b_current_next; p_current->b_current_next = p_sdt->b_current_next;
p_current->i_number = 0; p_current->i_number = 0;
p_current->p_payload_end += 11; /* just after the header */ p_current->p_payload_end += 11; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8; p_current->p_payload_start = p_current->p_data + 8;
/* Original Network ID */ /* Original Network ID */
p_current->p_data[8] = (p_sdt->i_network_id >> 8) ; p_current->p_data[8] = (p_sdt->i_network_id >> 8) ;
p_current->p_data[9] = p_sdt->i_network_id; p_current->p_data[9] = p_sdt->i_network_id;
p_current->p_data[10] = 0xff; p_current->p_data[10] = 0xff;
/* SDT service */ /* SDT service */
while(p_service != NULL) while (p_service != NULL)
{
uint8_t * p_service_start = p_current->p_payload_end;
uint16_t i_service_length = 5;
dvbpsi_descriptor_t * p_descriptor = p_service->p_first_descriptor;
while ( (p_descriptor != NULL)&& ((p_service_start - p_current->p_data) + i_service_length <= 1020) )
{ {
i_service_length += p_descriptor->i_length + 2; uint8_t * p_service_start = p_current->p_payload_end;
p_descriptor = p_descriptor->p_next; uint16_t i_service_length = 5;
}
if ( (p_descriptor != NULL) && (p_service_start - p_current->p_data != 11) && (i_service_length <= 1009) ) dvbpsi_descriptor_t * p_descriptor = p_service->p_first_descriptor;
{
/* will put more descriptors in an empty section */
#if 0
dvbpsi_debug(h_dvbpsi, "SDT generator","create a new section to carry more Service descriptors");
#endif
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x42;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 1;
p_current->i_length = 12; /* header + CRC_32 */
p_current->i_extension = p_sdt->i_ts_id;;
p_current->i_version = p_sdt->i_version;
p_current->b_current_next = p_sdt->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 11; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* Original Network ID */
p_current->p_data[8] = (p_sdt->i_network_id >> 8) ;
p_current->p_data[9] = p_sdt->i_network_id;
p_current->p_data[10] = 0xff;
p_service_start = p_current->p_payload_end;
}
p_service_start[0] = (p_service->i_service_id >>8); while ((p_descriptor != NULL)&& ((p_service_start - p_current->p_data) + i_service_length <= 1020))
p_service_start[1] = (p_service->i_service_id ); {
p_service_start[2] = 0xfc | (p_service-> b_eit_schedule ? 0x2 : 0x0) | (p_service->b_eit_present ? 0x01 : 0x00); i_service_length += p_descriptor->i_length + 2;
p_service_start[3] = ((p_service->i_running_status & 0x07) << 5 ) | ((p_service->b_free_ca & 0x1) << 4); p_descriptor = p_descriptor->p_next;
}
/* Increase the length by 5 */ if ((p_descriptor != NULL) && (p_service_start - p_current->p_data != 11) && (i_service_length <= 1009))
p_current->p_payload_end += 5; {
p_current->i_length += 5; /* will put more descriptors in an empty section */
dvbpsi_debug(p_dvbpsi, "SDT generator","create a new section to carry more Service descriptors");
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x42;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 1;
p_current->i_length = 12; /* header + CRC_32 */
p_current->i_extension = p_sdt->i_ts_id;;
p_current->i_version = p_sdt->i_version;
p_current->b_current_next = p_sdt->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 11; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* Original Network ID */
p_current->p_data[8] = (p_sdt->i_network_id >> 8) ;
p_current->p_data[9] = p_sdt->i_network_id;
p_current->p_data[10] = 0xff;
p_service_start = p_current->p_payload_end;
}
/* ES descriptors */ p_service_start[0] = (p_service->i_service_id >>8);
p_descriptor = p_service->p_first_descriptor; p_service_start[1] = (p_service->i_service_id );
while ( (p_descriptor != NULL) && ( (p_current->p_payload_end - p_current->p_data) + p_descriptor->i_length <= 1018) ) p_service_start[2] = 0xfc | (p_service-> b_eit_schedule ? 0x2 : 0x0) | (p_service->b_eit_present ? 0x01 : 0x00);
{ p_service_start[3] = ((p_service->i_running_status & 0x07) << 5 ) | ((p_service->b_free_ca & 0x1) << 4);
/* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
#if 0 /* Increase the length by 5 */
if(p_descriptor != NULL) p_current->p_payload_end += 5;
dvbpsi_error(h_dvbpsi, "SDT generator", "unable to carry all the descriptors"); p_current->i_length += 5;
#endif
/* ES_info_length */ /* ES descriptors */
i_service_length = p_current->p_payload_end - p_service_start - 5; p_descriptor = p_service->p_first_descriptor;
p_service_start[3] |= ((i_service_length >> 8) & 0x0f); while ((p_descriptor != NULL) && ( (p_current->p_payload_end - p_current->p_data) + p_descriptor->i_length <= 1018))
p_service_start[4] = i_service_length; {
/* p_payload_end is where the descriptor begins */
p_service = p_service->p_next; p_current->p_payload_end[0] = p_descriptor->i_tag;
} p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length);
/* Finalization */ /* Increase length by descriptor_length + 2 */
p_prev = p_result; p_current->p_payload_end += p_descriptor->i_length + 2;
while(p_prev != NULL) p_current->i_length += p_descriptor->i_length + 2;
{ p_descriptor = p_descriptor->p_next;
p_prev->i_last_number = p_current->i_number; }
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next; if (p_descriptor != NULL)
} dvbpsi_error(p_dvbpsi, "SDT generator", "unable to carry all the descriptors");
return p_result;
} /* ES_info_length */
i_service_length = p_current->p_payload_end - p_service_start - 5;
p_service_start[3] |= ((i_service_length >> 8) & 0x0f);
p_service_start[4] = i_service_length;
p_service = p_service->p_next;
}
/* Finalization */
p_prev = p_result;
while (p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
return p_result;
}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* $Id$ * $Id$
* *
* Authors: Johan Bilien <jobi@via.ecp.fr> * Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_sdt_service_t * dvbpsi_sdt_service_t
*****************************************************************************/ *****************************************************************************/
...@@ -65,13 +65,11 @@ typedef struct dvbpsi_sdt_service_s ...@@ -65,13 +65,11 @@ typedef struct dvbpsi_sdt_service_s
dvbpsi_descriptor_t * p_first_descriptor; /*!< First of the following dvbpsi_descriptor_t * p_first_descriptor; /*!< First of the following
DVB descriptors */ DVB descriptors */
struct dvbpsi_sdt_service_s * p_next; /*!< next element of struct dvbpsi_sdt_service_s * p_next; /*!< next element of
the list */ the list */
} dvbpsi_sdt_service_t; } dvbpsi_sdt_service_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_sdt_t * dvbpsi_sdt_t
*****************************************************************************/ *****************************************************************************/
...@@ -98,7 +96,6 @@ typedef struct dvbpsi_sdt_s ...@@ -98,7 +96,6 @@ typedef struct dvbpsi_sdt_s
} dvbpsi_sdt_t; } dvbpsi_sdt_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_sdt_callback * dvbpsi_sdt_callback
*****************************************************************************/ *****************************************************************************/
...@@ -109,42 +106,38 @@ typedef struct dvbpsi_sdt_s ...@@ -109,42 +106,38 @@ typedef struct dvbpsi_sdt_s
*/ */
typedef void (* dvbpsi_sdt_callback)(void* p_cb_data, dvbpsi_sdt_t* p_new_sdt); typedef void (* dvbpsi_sdt_callback)(void* p_cb_data, dvbpsi_sdt_t* p_new_sdt);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachSDT * dvbpsi_AttachSDT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_AttachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn int dvbpsi_AttachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_sdt_callback pf_callback, uint16_t i_extension, dvbpsi_sdt_callback pf_callback,
void* p_cb_data) void* p_cb_data)
* \brief Creation and initialization of a SDT decoder. * \brief Creation and initialization of a SDT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached. * \param p_dvbpsi pointer to dvbpsi to hold decoder/demuxer structure
* \param i_table_id Table ID, 0x42 or 0x46. * \param i_table_id Table ID, 0x42 or 0x46.
* \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 SDT. * \param pf_callback function to call back on new SDT.
* \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 pointer to dvbpsi handle or NULL on error
*/ */
int dvbpsi_AttachSDT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, dvbpsi_t *dvbpsi_AttachSDT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_sdt_callback pf_callback, uint16_t i_extension, dvbpsi_sdt_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachSDT * dvbpsi_DetachSDT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn void dvbpsi_DetachSDT(dvbpsi_demux_t *p_demux, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
* \brief Destroy a SDT decoder. * \brief Destroy a SDT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached. * \param p_dvbpsi pointer holding decoder/demuxer structure
* \param i_table_id Table ID, 0x42 or 0x46. * \param i_table_id Table ID, 0x42 or 0x46.
* \param i_extension Table ID extension, here TS ID. * \param i_extension Table ID extension, here TS ID.
* \return nothing. * \return nothing.
*/ */
void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachSDT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension);
uint16_t i_extension);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitSDT/dvbpsi_NewSDT * dvbpsi_InitSDT/dvbpsi_NewSDT
...@@ -180,7 +173,6 @@ do { \ ...@@ -180,7 +173,6 @@ do { \
dvbpsi_InitSDT(p_sdt, i_ts_id, i_version, b_current_next, i_network_id); \ dvbpsi_InitSDT(p_sdt, i_ts_id, i_version, b_current_next, i_network_id); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptySDT/dvbpsi_DeleteSDT * dvbpsi_EmptySDT/dvbpsi_DeleteSDT
*****************************************************************************/ *****************************************************************************/
...@@ -204,7 +196,6 @@ do { \ ...@@ -204,7 +196,6 @@ do { \
free(p_sdt); \ free(p_sdt); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_SDTAddService * dvbpsi_SDTAddService
*****************************************************************************/ *****************************************************************************/
...@@ -228,7 +219,6 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt, ...@@ -228,7 +219,6 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt,
uint16_t i_service_id, int b_eit_schedule, int b_eit_present, uint16_t i_service_id, int b_eit_schedule, int b_eit_present,
uint8_t i_running_status,int b_free_ca); uint8_t i_running_status,int b_free_ca);
/***************************************************************************** /*****************************************************************************
* dvbpsi_SDTServiceAddDescriptor * dvbpsi_SDTServiceAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -249,13 +239,22 @@ dvbpsi_descriptor_t *dvbpsi_SDTServiceAddDescriptor( ...@@ -249,13 +239,22 @@ dvbpsi_descriptor_t *dvbpsi_SDTServiceAddDescriptor(
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_GenSDTSections * dvbpsi_GenSDTSections
***************************************************************************** *****************************************************************************
* Generate SDT sections based on the dvbpsi_sdt_t structure. * Generate SDT sections based on the dvbpsi_sdt_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_GenSDTSections(dvbpsi_sdt_t * p_sdt); /*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenSDTSections(dvbpsi_t *p_dvbpsi,
dvbpsi_sdt_t * p_sdt)
* \brief SDT generator
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_sdt SDT structure
* \return a pointer to the list of generated PSI sections.
*
* Generate PMT sections based on the dvbpsi_pmt_t structure.
*/
dvbpsi_psi_section_t *dvbpsi_GenSDTSections(dvbpsi_t *p_dvbpsi, dvbpsi_sdt_t * p_sdt);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id: sdt_private.h,v 1.1 2002/12/11 13:04:57 jobi Exp $ * $Id: sdt_private.h,v 1.1 2002/12/11 13:04:57 jobi Exp $
* *
* Authors: Johan Bilien <jobi@via.ecp.fr> * Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -27,7 +28,6 @@ ...@@ -27,7 +28,6 @@
#ifndef _DVBPSI_SDT_PRIVATE_H_ #ifndef _DVBPSI_SDT_PRIVATE_H_
#define _DVBPSI_SDT_PRIVATE_H_ #define _DVBPSI_SDT_PRIVATE_H_
/***************************************************************************** /*****************************************************************************
* dvbpsi_sdt_decoder_t * dvbpsi_sdt_decoder_t
***************************************************************************** *****************************************************************************
...@@ -35,30 +35,30 @@ ...@@ -35,30 +35,30 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_sdt_decoder_s typedef struct dvbpsi_sdt_decoder_s
{ {
dvbpsi_sdt_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
dvbpsi_sdt_t current_sdt; dvbpsi_sdt_callback pf_sdt_callback;
dvbpsi_sdt_t * p_building_sdt; void * p_cb_data;
int b_current_valid; dvbpsi_sdt_t current_sdt;
dvbpsi_sdt_t * p_building_sdt;
uint8_t i_last_section_number; int b_current_valid;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_sdt_decoder_t; uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_sdt_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherSDTSections * dvbpsi_GatherSDTSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherSDTSections(dvbpsi_decoder_t* p_psi_decoder, void dvbpsi_GatherSDTSections(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_DecodeSDTSection * dvbpsi_DecodeSDTSection
***************************************************************************** *****************************************************************************
...@@ -67,7 +67,6 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t* p_psi_decoder, ...@@ -67,7 +67,6 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t* p_psi_decoder,
void dvbpsi_DecodeSDTSections(dvbpsi_sdt_t* p_sdt, void dvbpsi_DecodeSDTSections(dvbpsi_sdt_t* p_sdt,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of sdt_private.h" #error "Multiple inclusions of sdt_private.h"
#endif #endif
......
...@@ -52,12 +52,11 @@ ...@@ -52,12 +52,11 @@
***************************************************************************** *****************************************************************************
* Initialize a SIS subtable decoder. * Initialize a SIS subtable decoder.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachSIS(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_sis_callback pf_callback, uint16_t i_extension, dvbpsi_sis_callback pf_callback,
void* p_cb_data) void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_sis_decoder_t* p_sis_decoder; dvbpsi_sis_decoder_t* p_sis_decoder;
...@@ -65,11 +64,10 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id, ...@@ -65,11 +64,10 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id,
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{ {
dvbpsi_error(h_dvbpsi, "SIS decoder", dvbpsi_error(p_dvbpsi, "SIS decoder",
"Already a decoder for (table_id == 0x%02x," "Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
return 1; return 1;
} }
...@@ -97,7 +95,7 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id, ...@@ -97,7 +95,7 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id,
p_demux->p_first_subdec = p_subdec; p_demux->p_first_subdec = p_subdec;
/* SIS decoder information */ /* SIS decoder information */
p_sis_decoder->pf_callback = pf_callback; p_sis_decoder->pf_sis_callback = pf_callback;
p_sis_decoder->p_cb_data = p_cb_data; p_sis_decoder->p_cb_data = p_cb_data;
return 0; return 0;
...@@ -108,10 +106,10 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id, ...@@ -108,10 +106,10 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id,
***************************************************************************** *****************************************************************************
* Close a SIS decoder. * Close a SIS decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachSIS(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec; dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_sis_decoder_t* p_sis_decoder; dvbpsi_sis_decoder_t* p_sis_decoder;
...@@ -121,7 +119,7 @@ void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -121,7 +119,7 @@ void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension); p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if (p_demux == NULL) if (p_demux == NULL)
{ {
dvbpsi_error(h_dvbpsi, "SIS Decoder", dvbpsi_error(p_dvbpsi, "SIS Decoder",
"No such SIS decoder (table_id == 0x%02x," "No such SIS decoder (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, i_extension); i_table_id, i_extension);
...@@ -129,7 +127,6 @@ void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -129,7 +127,6 @@ void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
} }
p_sis_decoder = (dvbpsi_sis_decoder_t*)p_subdec->p_cb_data; p_sis_decoder = (dvbpsi_sis_decoder_t*)p_subdec->p_cb_data;
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;
...@@ -138,6 +135,7 @@ void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -138,6 +135,7 @@ void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
*pp_prev_subdec = p_subdec->p_next; *pp_prev_subdec = p_subdec->p_next;
free(p_subdec); free(p_subdec);
p_subdec = NULL;
} }
/***************************************************************************** /*****************************************************************************
...@@ -197,23 +195,19 @@ dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis, ...@@ -197,23 +195,19 @@ dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis,
uint8_t *p_data) uint8_t *p_data)
{ {
dvbpsi_descriptor_t * p_descriptor; dvbpsi_descriptor_t * p_descriptor;
p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
if (p_descriptor) if (p_descriptor == NULL)
return NULL;
if (p_sis->p_first_descriptor == NULL)
p_sis->p_first_descriptor = p_descriptor;
else
{ {
if (p_sis->p_first_descriptor == NULL) dvbpsi_descriptor_t *p_last_descriptor = p_sis->p_first_descriptor;
{ while (p_last_descriptor->p_next != NULL)
p_sis->p_first_descriptor = p_descriptor; p_last_descriptor = p_last_descriptor->p_next;
} p_last_descriptor->p_next = p_descriptor;
else
{
dvbpsi_descriptor_t * p_last_descriptor = p_sis->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;
} }
...@@ -222,17 +216,17 @@ dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis, ...@@ -222,17 +216,17 @@ dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis,
***************************************************************************** *****************************************************************************
* Callback for the subtable demultiplexor. * Callback for the subtable demultiplexor.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, void dvbpsi_GatherSISSections(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_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_sis_decoder_t * p_sis_decoder dvbpsi_sis_decoder_t * p_sis_decoder
= (dvbpsi_sis_decoder_t*)p_private_decoder; = (dvbpsi_sis_decoder_t*)p_private_decoder;
int b_append = 1; int b_append = 1;
int b_reinit = 0; int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "SIS decoder", dvbpsi_debug(p_dvbpsi, "SIS decoder",
"Table version %2d, " "i_table_id %2d, " "i_extension %5d, " "Table version %2d, " "i_table_id %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d", "section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id, p_section->i_version, p_section->i_table_id,
...@@ -243,7 +237,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -243,7 +237,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_section->i_table_id != 0xFC) if (p_section->i_table_id != 0xFC)
{ {
/* Invalid table_id value */ /* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "SIS decoder", dvbpsi_error(p_dvbpsi, "SIS decoder",
"invalid section (table_id == 0x%02x)", "invalid section (table_id == 0x%02x)",
p_section->i_table_id); p_section->i_table_id);
b_append = 0; b_append = 0;
...@@ -252,7 +246,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -252,7 +246,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_section->b_syntax_indicator != 0) if (p_section->b_syntax_indicator != 0)
{ {
/* Invalid section_syntax_indicator */ /* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "SIS decoder", dvbpsi_error(p_dvbpsi, "SIS decoder",
"invalid section (section_syntax_indicator != 0)"); "invalid section (section_syntax_indicator != 0)");
b_append = 0; b_append = 0;
} }
...@@ -260,7 +254,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -260,7 +254,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_section->b_private_indicator != 0) if (p_section->b_private_indicator != 0)
{ {
/* Invalid private_syntax_indicator */ /* Invalid private_syntax_indicator */
dvbpsi_error(h_dvbpsi, "SIS decoder", dvbpsi_error(p_dvbpsi, "SIS decoder",
"invalid private section (private_syntax_indicator != 0)"); "invalid private section (private_syntax_indicator != 0)");
b_append = 0; b_append = 0;
} }
...@@ -269,10 +263,10 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -269,10 +263,10 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (b_append) if (b_append)
{ {
/* TS discontinuity check */ /* TS discontinuity check */
if (p_psi_decoder->b_discontinuity) if (p_demux->b_discontinuity)
{ {
b_reinit = 1; b_reinit = 1;
p_psi_decoder->b_discontinuity = 0; p_demux->b_discontinuity = 0;
} }
else else
{ {
...@@ -282,8 +276,8 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -282,8 +276,8 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_sis_decoder->p_building_sis->i_protocol_version != 0) if (p_sis_decoder->p_building_sis->i_protocol_version != 0)
{ {
/* transport_stream_id */ /* transport_stream_id */
dvbpsi_error(h_dvbpsi, "SIS decoder", dvbpsi_error(p_dvbpsi, "SIS decoder",
"'protocol_version' differs");\ "'protocol_version' differs");
b_reinit = 1; b_reinit = 1;
} }
} }
...@@ -335,7 +329,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, ...@@ -335,7 +329,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
***************************************************************************** *****************************************************************************
* SIS decoder. * SIS decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeSISSections(dvbpsi_sis_t* p_sis, void dvbpsi_DecodeSISSections(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t *p_byte, *p_end; uint8_t *p_byte, *p_end;
...@@ -409,7 +403,7 @@ void dvbpsi_DecodeSISSections(dvbpsi_sis_t* p_sis, ...@@ -409,7 +403,7 @@ void dvbpsi_DecodeSISSections(dvbpsi_sis_t* p_sis,
***************************************************************************** *****************************************************************************
* Generate SIS sections based on the dvbpsi_sis_t structure. * Generate SIS sections based on the dvbpsi_sis_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_sis_t* p_sis) dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_t *p_dvbpsi, dvbpsi_sis_t* p_sis)
{ {
dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024); dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024);
...@@ -479,4 +473,3 @@ dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_sis_t* p_sis) ...@@ -479,4 +473,3 @@ dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_sis_t* p_sis)
dvbpsi_BuildPSISection(p_current); dvbpsi_BuildPSISection(p_current);
return p_current; return p_current;
} }
...@@ -90,7 +90,6 @@ typedef struct dvbpsi_sis_s ...@@ -90,7 +90,6 @@ typedef struct dvbpsi_sis_s
DVB descriptors */ DVB descriptors */
/* FIXME: alignment stuffing */ /* FIXME: alignment stuffing */
uint32_t i_ecrc; /*!< CRC 32 of decrypted splice_info_section */ uint32_t i_ecrc; /*!< CRC 32 of decrypted splice_info_section */
} dvbpsi_sis_t; } dvbpsi_sis_t;
...@@ -105,7 +104,6 @@ typedef struct dvbpsi_sis_s ...@@ -105,7 +104,6 @@ typedef struct dvbpsi_sis_s
*/ */
typedef void (* dvbpsi_sis_callback)(void* p_cb_data, dvbpsi_sis_t* p_new_sis); typedef void (* dvbpsi_sis_callback)(void* p_cb_data, dvbpsi_sis_t* p_new_sis);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachSIS * dvbpsi_AttachSIS
*****************************************************************************/ *****************************************************************************/
...@@ -114,18 +112,17 @@ typedef void (* dvbpsi_sis_callback)(void* p_cb_data, dvbpsi_sis_t* p_new_sis); ...@@ -114,18 +112,17 @@ typedef void (* dvbpsi_sis_callback)(void* p_cb_data, dvbpsi_sis_t* p_new_sis);
uint16_t i_extension, dvbpsi_sis_callback pf_callback, uint16_t i_extension, dvbpsi_sis_callback pf_callback,
void* p_cb_data) void* p_cb_data)
* \brief Creation and initialization of a SIS decoder. * \brief Creation and initialization of a SIS decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached. * \param p_dvbpsi pointer to dvbpsi to hold decoder/demuxer structure
* \param i_table_id Table ID, 0xFC. * \param i_table_id Table ID, 0xFC.
* \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 SIS. * \param pf_callback function to call back on new SIS.
* \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 0 if everything went ok.
*/ */
int dvbpsi_AttachSIS(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachSIS(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_sis_callback pf_callback, uint16_t i_extension, dvbpsi_sis_callback pf_callback,
void* p_cb_data); void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachSIS * dvbpsi_DetachSIS
*****************************************************************************/ *****************************************************************************/
...@@ -133,15 +130,14 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, ...@@ -133,15 +130,14 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
* \fn void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
* \brief Destroy a SIS decoder. * \brief Destroy a SIS decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached. * \param p_dvbpsi pointer to dvbpsi to hold decoder/demuxer structure
* \param i_table_id Table ID, 0xFC. * \param i_table_id Table ID, 0xFC.
* \param i_extension Table ID extension, here TS ID. * \param i_extension Table ID extension, here TS ID.
* \return nothing. * \return nothing.
*/ */
void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachSIS(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitSIS/dvbpsi_NewSIS * dvbpsi_InitSIS/dvbpsi_NewSIS
*****************************************************************************/ *****************************************************************************/
...@@ -206,16 +202,16 @@ do { \ ...@@ -206,16 +202,16 @@ do { \
* \param p_data descriptor's data * \param p_data descriptor's data
* \return a pointer to the added descriptor. * \return a pointer to the added descriptor.
*/ */
dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis, dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor(dvbpsi_sis_t *p_sis,
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_GenSISSections * dvbpsi_GenSISSections
***************************************************************************** *****************************************************************************
* Generate SIS sections based on the dvbpsi_sis_t structure. * Generate SIS sections based on the dvbpsi_sis_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_sis_t * p_sis); dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_t *p_dvbpsi, dvbpsi_sis_t * p_sis);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -34,37 +34,36 @@ ...@@ -34,37 +34,36 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_sis_decoder_s typedef struct dvbpsi_sis_decoder_s
{ {
dvbpsi_sis_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
/* */ dvbpsi_sis_callback pf_sis_callback;
dvbpsi_sis_t *current_sis; void * p_cb_data;
dvbpsi_sis_t *p_building_sis;
int b_current_valid; /* */
dvbpsi_sis_t *current_sis;
dvbpsi_sis_t *p_building_sis;
} dvbpsi_sis_decoder_t; int b_current_valid;
} dvbpsi_sis_decoder_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherSISSections * dvbpsi_GatherSISSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherSISSections(dvbpsi_decoder_t* p_psi_decoder, void dvbpsi_GatherSISSections(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_DecodeSISSection * dvbpsi_DecodeSISSection
***************************************************************************** *****************************************************************************
* SIS decoder. * SIS decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeSISSections(dvbpsi_sis_t* p_sis, void dvbpsi_DecodeSISSections(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of sis_private.h" #error "Multiple inclusions of sis_private.h"
#endif #endif
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -26,7 +27,6 @@ ...@@ -26,7 +27,6 @@
* *
*****************************************************************************/ *****************************************************************************/
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
...@@ -47,60 +47,53 @@ ...@@ -47,60 +47,53 @@
#include "tot.h" #include "tot.h"
#include "tot_private.h" #include "tot_private.h"
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachTOT * dvbpsi_AttachTOT
***************************************************************************** *****************************************************************************
* Initialize a TDT/TOT subtable decoder. * Initialize a TDT/TOT subtable decoder.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachTOT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
uint16_t i_extension,
dvbpsi_tot_callback pf_callback, void* p_cb_data) dvbpsi_tot_callback pf_callback, void* p_cb_data)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder; dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_tot_decoder_t* p_tot_decoder;
dvbpsi_tot_decoder_t* p_tot_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0))
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0)) {
{ dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder",
"Already a decoder for (table_id == 0x%02x," "Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, 0); i_table_id, 0);
return 1;
}
return 1; p_subdec = (dvbpsi_demux_subdec_t*)calloc(1, sizeof(dvbpsi_demux_subdec_t));
} if(p_subdec == NULL)
return 1;
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
{
return 1;
}
p_tot_decoder = (dvbpsi_tot_decoder_t*)malloc(sizeof(dvbpsi_tot_decoder_t));
if(p_tot_decoder == NULL) p_tot_decoder = (dvbpsi_tot_decoder_t*)calloc(1, sizeof(dvbpsi_tot_decoder_t));
{ if (p_tot_decoder == NULL)
free(p_subdec); {
return 1; free(p_subdec);
} return 1;
}
/* subtable decoder configuration */ /* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherTOTSections; p_subdec->pf_callback = &dvbpsi_GatherTOTSections;
p_subdec->p_cb_data = p_tot_decoder; p_subdec->p_cb_data = p_tot_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)0; p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)0;
p_subdec->pf_detach = dvbpsi_DetachTOT; p_subdec->pf_detach = dvbpsi_DetachTOT;
/* 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;
/* TDT/TOT decoder information */ /* TDT/TOT decoder information */
p_tot_decoder->pf_callback = pf_callback; p_tot_decoder->pf_tot_callback = pf_callback;
p_tot_decoder->p_cb_data = p_cb_data; p_tot_decoder->p_cb_data = p_cb_data;
return 0; return 0;
} }
/***************************************************************************** /*****************************************************************************
...@@ -108,35 +101,34 @@ int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, ...@@ -108,35 +101,34 @@ int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
***************************************************************************** *****************************************************************************
* Close a TDT/TOT decoder. * Close a TDT/TOT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DetachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachTOT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension) uint16_t i_extension)
{ {
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder; dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec; dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec; dvbpsi_demux_subdec_t** pp_prev_subdec;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0); p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0);
if (p_demux == NULL)
if(p_demux == NULL) {
{ dvbpsi_error(p_dvbpsi, "TDT/TOT Decoder",
dvbpsi_error(h_dvbpsi, "TDT/TOT Decoder",
"No such TDT/TOT decoder (table_id == 0x%02x," "No such TDT/TOT decoder (table_id == 0x%02x,"
"extension == 0x%02x)", "extension == 0x%02x)",
i_table_id, 0); i_table_id, 0);
return; return;
} }
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);
p_subdec = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitTOT * dvbpsi_InitTOT
***************************************************************************** *****************************************************************************
...@@ -144,11 +136,10 @@ void dvbpsi_DetachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, ...@@ -144,11 +136,10 @@ void dvbpsi_DetachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
*****************************************************************************/ *****************************************************************************/
void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot, uint64_t i_utc_time) void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot, uint64_t i_utc_time)
{ {
p_tot->i_utc_time = i_utc_time; p_tot->i_utc_time = i_utc_time;
p_tot->p_first_descriptor = NULL; p_tot->p_first_descriptor = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyTOT * dvbpsi_EmptyTOT
***************************************************************************** *****************************************************************************
...@@ -156,12 +147,10 @@ void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot, uint64_t i_utc_time) ...@@ -156,12 +147,10 @@ void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot, uint64_t i_utc_time)
*****************************************************************************/ *****************************************************************************/
void dvbpsi_EmptyTOT(dvbpsi_tot_t* p_tot) void dvbpsi_EmptyTOT(dvbpsi_tot_t* p_tot)
{ {
dvbpsi_DeleteDescriptors(p_tot->p_first_descriptor); dvbpsi_DeleteDescriptors(p_tot->p_first_descriptor);
p_tot->p_first_descriptor = NULL;
p_tot->p_first_descriptor = NULL;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_TOTAddDescriptor * dvbpsi_TOTAddDescriptor
***************************************************************************** *****************************************************************************
...@@ -171,300 +160,275 @@ dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot, ...@@ -171,300 +160,275 @@ dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
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 == NULL)
return NULL;
if(p_descriptor) if (p_tot->p_first_descriptor == NULL)
{ p_tot->p_first_descriptor = p_descriptor;
if(p_tot->p_first_descriptor == NULL)
{
p_tot->p_first_descriptor = p_descriptor;
}
else else
{ {
dvbpsi_descriptor_t* p_last_descriptor = p_tot->p_first_descriptor; dvbpsi_descriptor_t* p_last_descriptor = p_tot->p_first_descriptor;
while(p_last_descriptor->p_next != NULL) while(p_last_descriptor->p_next != NULL)
p_last_descriptor = p_last_descriptor->p_next; p_last_descriptor = p_last_descriptor->p_next;
p_last_descriptor->p_next = p_descriptor; p_last_descriptor->p_next = p_descriptor;
} }
} return p_descriptor;
return p_descriptor;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GatherTOTSections * dvbpsi_GatherTOTSections
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherTOTSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherTOTSections(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_handle h_dvbpsi = (dvbpsi_handle) p_decoder; dvbpsi_tot_decoder_t* p_tot_decoder
dvbpsi_tot_decoder_t* p_tot_decoder
= (dvbpsi_tot_decoder_t*)p_private_decoder; = (dvbpsi_tot_decoder_t*)p_private_decoder;
int b_append = 1; int b_append = 1;
dvbpsi_tot_t* p_building_tot; dvbpsi_tot_t* p_building_tot;
dvbpsi_debug(h_dvbpsi, "TDT/TOT decoder", "got a section"); dvbpsi_debug(p_dvbpsi, "TDT/TOT decoder", "got a section");
if(p_section->i_table_id != 0x70 && p_section->i_table_id != 0x73) if (p_section->i_table_id != 0x70 && p_section->i_table_id != 0x73)
{ {
/* Invalid table_id value */ /* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder", dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
"invalid section (table_id == 0x%02x)", "invalid section (table_id == 0x%02x)",
p_section->i_table_id); p_section->i_table_id);
b_append = 0; b_append = 0;
} }
if(b_append && p_section->b_syntax_indicator != 0) if (b_append && p_section->b_syntax_indicator != 0)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder",
"invalid section (section_syntax_indicator != 0)");
b_append = 0;
}
/* Now if b_append is true then we have a valid TDT/TOT section */
if(b_append)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
{ {
/* We don't care about discontinuities with the TDT/TOT as it /* Invalid section_syntax_indicator */
only consists of one section anyway */ dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
p_decoder->b_discontinuity = 0; "invalid section (section_syntax_indicator != 0)");
b_append = 0;
} }
p_building_tot = (dvbpsi_tot_t*)malloc(sizeof(dvbpsi_tot_t)); /* Now if b_append is true then we have a valid TDT/TOT section */
dvbpsi_InitTOT(p_building_tot, ((uint64_t)p_section->p_payload_start[0] << 32) if (b_append)
{
/* TS discontinuity check */
if (p_tot_decoder->b_discontinuity)
{
/* We don't care about discontinuities with the TDT/TOT as it
only consists of one section anyway */
p_tot_decoder->b_discontinuity = 0;
}
p_building_tot = (dvbpsi_tot_t*)malloc(sizeof(dvbpsi_tot_t));
dvbpsi_InitTOT(p_building_tot, ((uint64_t)p_section->p_payload_start[0] << 32)
| ((uint64_t)p_section->p_payload_start[1] << 24) | ((uint64_t)p_section->p_payload_start[1] << 24)
| ((uint64_t)p_section->p_payload_start[2] << 16) | ((uint64_t)p_section->p_payload_start[2] << 16)
| ((uint64_t)p_section->p_payload_start[3] << 8) | ((uint64_t)p_section->p_payload_start[3] << 8)
| (uint64_t)p_section->p_payload_start[4]); | (uint64_t)p_section->p_payload_start[4]);
/* Decode the section */ /* Decode the section */
dvbpsi_DecodeTOTSections(p_building_tot, p_section); dvbpsi_DecodeTOTSections(p_dvbpsi, p_building_tot, p_section);
/* Delete the section */ /* Delete the section */
dvbpsi_DeletePSISections(p_section); dvbpsi_DeletePSISections(p_section);
/* signal the new TDT/TOT */ /* signal the new TDT/TOT */
p_tot_decoder->pf_callback(p_tot_decoder->p_cb_data, p_building_tot); p_tot_decoder->pf_tot_callback(p_tot_decoder->p_cb_data, p_building_tot);
} }
else else
{ {
dvbpsi_DeletePSISections(p_section); dvbpsi_DeletePSISections(p_section);
} }
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_ValidTOTSection * dvbpsi_ValidTOTSection
***************************************************************************** *****************************************************************************
* Check the CRC_32 if the section has b_syntax_indicator set. * Check the CRC_32 if the section has b_syntax_indicator set.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_ValidTOTSection(dvbpsi_psi_section_t* p_section) int dvbpsi_ValidTOTSection(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t* p_section)
{ {
if(p_section->i_table_id == 0x73) if (p_section->i_table_id != 0x73)
{ {
/* A TDT always has a length of 5 bytes (which is only the UTC time) */
if (p_section->i_length != 5)
{
dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
"TDT has an invalid payload size (%d bytes) !!!",
p_section->i_length);
return 0;
}
return 1;
}
/* Check the CRC_32 if it's a TOT */ /* Check the CRC_32 if it's a TOT */
uint32_t i_crc = 0xffffffff; uint32_t i_crc = 0xffffffff;
uint8_t* p_byte = p_section->p_data; uint8_t* p_byte = p_section->p_data;
while(p_byte < p_section->p_payload_end) while (p_byte < p_section->p_payload_end)
{ {
i_crc = (i_crc << 8) ^ dvbpsi_crc32_table[(i_crc >> 24) ^ (*p_byte)]; i_crc = (i_crc << 8) ^ dvbpsi_crc32_table[(i_crc >> 24) ^ (*p_byte)];
p_byte++; p_byte++;
} }
if(i_crc == 0) if (i_crc == 0)
{ return 1;
return 1;
}
else else
{ {
#if 0 /* FIXME */ dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder", "Bad CRC_32 (0x%08x) !!!", i_crc);
"Bad CRC_32 (0x%08x) !!!", i_crc); return 0;
#endif
return 0;
} }
}
else
{
/* A TDT always has a length of 5 bytes (which is only the UTC time) */
if(p_section->i_length != 5) {
#if 0 /* FIXME */
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder",
"TDT has an invalid payload size (%d bytes) !!!",
p_section->i_length);
#endif
return 0;
}
}
return 1; return 1;
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeTOTSections * dvbpsi_DecodeTOTSections
***************************************************************************** *****************************************************************************
* TDT/TOT decoder. * TDT/TOT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeTOTSections(dvbpsi_tot_t* p_tot, void dvbpsi_DecodeTOTSections(dvbpsi_t* p_dvbpsi, dvbpsi_tot_t* p_tot,
dvbpsi_psi_section_t* p_section) dvbpsi_psi_section_t* p_section)
{ {
uint8_t* p_byte; if (p_section)
if(p_section)
{
if (!dvbpsi_ValidTOTSection(p_section)) {
return;
}
p_byte = p_section->p_payload_start;
if(p_byte + 5 <= p_section->p_payload_end)
{ {
p_tot->i_utc_time = ((uint64_t)p_byte[0] << 32) | uint8_t* p_byte;
((uint64_t)p_byte[1] << 24) |
((uint64_t)p_byte[2] << 16) | if (!dvbpsi_ValidTOTSection(p_dvbpsi, p_section))
((uint64_t)p_byte[3] << 8) | return;
(uint64_t)p_byte[4];
p_byte = p_section->p_payload_start;
if (p_byte + 5 <= p_section->p_payload_end)
{
p_tot->i_utc_time = ((uint64_t)p_byte[0] << 32) |
((uint64_t)p_byte[1] << 24) |
((uint64_t)p_byte[2] << 16) |
((uint64_t)p_byte[3] << 8) |
(uint64_t)p_byte[4];
}
/* If we have a TOT, extract the descriptors */
if (p_section->i_table_id == 0x73)
{
uint8_t* p_end;
p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[5] & 0x0f) << 8)
| p_section->p_payload_start[6]);
p_byte += 7;
while (p_byte + 5 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if (i_length + 2 <= p_section->p_payload_end - p_byte)
dvbpsi_TOTAddDescriptor(p_tot, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
}
} }
/* If we have a TOT, extract the descriptors */
if (p_section->i_table_id == 0x73)
{
uint8_t* p_end;
p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[5] & 0x0f) << 8)
| p_section->p_payload_start[6]);
p_byte += 7;
while(p_byte + 5 <= p_end)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_section->p_payload_end - p_byte)
dvbpsi_TOTAddDescriptor(p_tot, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
}
}
} }
/***************************************************************************** /*****************************************************************************
* dvbpsi_GenTOTSections * dvbpsi_GenTOTSections
***************************************************************************** *****************************************************************************
* Generate TDT/TOT sections based on the dvbpsi_tot_t structure. * Generate TDT/TOT sections based on the dvbpsi_tot_t structure.
*****************************************************************************/ *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_tot_t* p_tot) dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_t *p_dvbpsi, dvbpsi_tot_t* p_tot)
{ {
dvbpsi_psi_section_t* p_result; dvbpsi_psi_section_t* p_result;
dvbpsi_descriptor_t* p_descriptor = p_tot->p_first_descriptor;
dvbpsi_descriptor_t* p_descriptor = p_tot->p_first_descriptor;
/* If it has descriptors, it must be a TOT, otherwise a TDT */
/* If it has descriptors, it must be a TOT, otherwise a TDT */ p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8);
p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8);
p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70;
p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70; p_result->b_syntax_indicator = 0;
p_result->b_syntax_indicator = 0; p_result->b_private_indicator = 0;
p_result->b_private_indicator = 0; p_result->i_length = 5;
p_result->i_length = 5; p_result->p_payload_start = p_result->p_data + 3;
p_result->p_payload_start = p_result->p_data + 3; p_result->p_payload_end = p_result->p_data + 8;
p_result->p_payload_end = p_result->p_data + 8;
p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff;
p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff; p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff;
p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff; p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff;
p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff; p_result->p_data[6] = (p_tot->i_utc_time >> 8) & 0xff;
p_result->p_data[6] = (p_tot->i_utc_time >> 8) & 0xff; p_result->p_data[7] = p_tot->i_utc_time & 0xff;
p_result->p_data[7] = p_tot->i_utc_time & 0xff;
if (p_result->i_table_id == 0x73)
if(p_result->i_table_id == 0x73) {
/* Special handling for TOT only (A TDT doesn't have descriptors!) */
/* Reserve two bytes for descriptors_loop_length */
p_result->p_payload_end += 2;
p_result->i_length += 2;
/* TOT descriptors */
while(p_descriptor != NULL)
{ {
/* A TOT cannot have multiple sections! */ /* Special handling for TOT only (A TDT doesn't have descriptors!) */
if( (p_result->p_payload_end - p_result->p_data) /* Reserve two bytes for descriptors_loop_length */
+ p_descriptor->i_length > 4090) p_result->p_payload_end += 2;
{ p_result->i_length += 2;
#if 0 /* FIXME: */
dvbpsi_error(h_dvbpsi, "TDT/TOT generator", /* TOT descriptors */
"TOT does not fit into one section as it ought to be !!!"); while (p_descriptor != NULL)
#endif {
break; /* A TOT cannot have multiple sections! */
} if( (p_result->p_payload_end - p_result->p_data)
+ p_descriptor->i_length > 4090)
/* p_payload_end is where the descriptor begins */ {
p_result->p_payload_end[0] = p_descriptor->i_tag; dvbpsi_error(p_dvbpsi, "TDT/TOT generator",
p_result->p_payload_end[1] = p_descriptor->i_length; "TOT does not fit into one section as it ought to be !!!");
memcpy(p_result->p_payload_end + 2, break;
p_descriptor->p_data, }
p_descriptor->i_length);
/* p_payload_end is where the descriptor begins */
/* Increase length by descriptor_length + 2 */ p_result->p_payload_end[0] = p_descriptor->i_tag;
p_result->p_payload_end += p_descriptor->i_length + 2; p_result->p_payload_end[1] = p_descriptor->i_length;
p_result->i_length += p_descriptor->i_length + 2; memcpy(p_result->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor = p_descriptor->p_next; p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_result->p_payload_end += p_descriptor->i_length + 2;
p_result->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* descriptors_loop_length */
p_result->p_payload_start[5] = ((p_result->i_length - 7) << 8) | 0xf0;
p_result->p_payload_start[6] = (p_result->i_length - 7) & 0xff;
} }
/* descriptors_loop_length */ if (p_result->i_table_id == 0x73)
p_result->p_payload_start[5] = ((p_result->i_length - 7) << 8) | 0xf0; {
p_result->p_payload_start[6] = (p_result->i_length - 7) & 0xff; /* A TOT has a CRC_32 although it's a private section,
} but the CRC_32 is part of the payload! */
p_result->p_payload_end += 4;
if (p_result->i_table_id == 0x73) { p_result->i_length += 4;
/* A TOT has a CRC_32 although it's a private section, }
but the CRC_32 is part of the payload! */
p_result->p_payload_end += 4;
p_result->i_length += 4;
}
dvbpsi_BuildPSISection(p_result);
if (p_result->i_table_id == 0x73) {
uint8_t* p_byte = p_result->p_data;
p_tot->i_crc = 0xffffffff; dvbpsi_BuildPSISection(p_result);
while(p_byte < p_result->p_payload_end - 4) if (p_result->i_table_id == 0x73)
{ {
p_tot->i_crc = (p_tot->i_crc << 8) uint8_t* p_byte = p_result->p_data;
^ dvbpsi_crc32_table[(p_tot->i_crc >> 24) ^ (*p_byte)]; p_tot->i_crc = 0xffffffff;
p_byte++;
while (p_byte < p_result->p_payload_end - 4)
{
p_tot->i_crc = (p_tot->i_crc << 8)
^ dvbpsi_crc32_table[(p_tot->i_crc >> 24) ^ (*p_byte)];
p_byte++;
}
p_byte[0] = (p_tot->i_crc >> 24) & 0xff;
p_byte[1] = (p_tot->i_crc >> 16) & 0xff;
p_byte[2] = (p_tot->i_crc >> 8) & 0xff;
p_byte[3] = p_tot->i_crc & 0xff;
} }
p_byte[0] = (p_tot->i_crc >> 24) & 0xff; if (!dvbpsi_ValidTOTSection(p_dvbpsi, p_result))
p_byte[1] = (p_tot->i_crc >> 16) & 0xff; {
p_byte[2] = (p_tot->i_crc >> 8) & 0xff; dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************");
p_byte[3] = p_tot->i_crc & 0xff; dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* Generated TDT/TOT section is invalid. *");
} dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* --- libdvbpsi-devel@videolan.org --- *");
#ifdef DEBUG dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************");
if(!dvbpsi_ValidTOTSection(p_result)) }
{
dvbpsi_error(h_dvbpsi, "TDT/TOT generator", "********************************************");
dvbpsi_error(h_dvbpsi, "TDT/TOT generator", "* Generated TDT/TOT section is invalid. *");
dvbpsi_error(h_dvbpsi, "TDT/TOT generator", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
dvbpsi_error(h_dvbpsi, "TDT/TOT generator", "* --- libdvbpsi-devel@videolan.org --- *");
dvbpsi_error(h_dvbpsi, "TDT/TOT generator", "********************************************");
}
#endif
return p_result; return p_result;
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -39,7 +40,6 @@ ...@@ -39,7 +40,6 @@
extern "C" { extern "C" {
#endif #endif
/***************************************************************************** /*****************************************************************************
* dvbpsi_tot_t * dvbpsi_tot_t
*****************************************************************************/ *****************************************************************************/
...@@ -64,7 +64,6 @@ typedef struct dvbpsi_tot_s ...@@ -64,7 +64,6 @@ typedef struct dvbpsi_tot_s
} dvbpsi_tot_t; } dvbpsi_tot_t;
/***************************************************************************** /*****************************************************************************
* dvbpsi_tot_callback * dvbpsi_tot_callback
*****************************************************************************/ *****************************************************************************/
...@@ -75,26 +74,24 @@ typedef struct dvbpsi_tot_s ...@@ -75,26 +74,24 @@ typedef struct dvbpsi_tot_s
*/ */
typedef void (* dvbpsi_tot_callback)(void* p_cb_data, dvbpsi_tot_t* p_new_tot); typedef void (* dvbpsi_tot_callback)(void* p_cb_data, dvbpsi_tot_t* p_new_tot);
/***************************************************************************** /*****************************************************************************
* dvbpsi_AttachTOT * dvbpsi_AttachTOT
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn int dvbpsi_AttachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, * \fn int dvbpsi_AttachTOT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
dvbpsi_tot_callback pf_callback, void* p_cb_data) dvbpsi_tot_callback pf_callback, void* p_cb_data)
* \brief Creation and initialization of a TDT/TOT decoder. * \brief Creation and initialization of a TDT/TOT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached. * \param p_dvbpsi dvbpsi handle pointing to Subtable demultiplexor to which the decoder is attached.
* \param i_table_id Table ID, usually 0x70 * \param i_table_id Table ID, usually 0x70
* \param i_extension Table ID extension, unused in the TDT/TOT * \param i_extension Table ID extension, unused in the TDT/TOT
* \param pf_callback function to call back on new TDT/TOT. * \param pf_callback function to call back on new TDT/TOT.
* \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 0 if everything went ok.
*/ */
int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, int dvbpsi_AttachTOT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension, uint16_t i_extension,
dvbpsi_tot_callback pf_callback, void* p_cb_data); dvbpsi_tot_callback pf_callback, void* p_cb_data);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DetachTOT * dvbpsi_DetachTOT
*****************************************************************************/ *****************************************************************************/
...@@ -106,10 +103,9 @@ int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id, ...@@ -106,10 +103,9 @@ int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
* \param i_extension Table ID extension, unused in the TDT/TOT * \param i_extension Table ID extension, unused in the TDT/TOT
* \return nothing. * \return nothing.
*/ */
void dvbpsi_DetachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id, void dvbpsi_DetachTOT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id,
uint16_t i_extension); uint16_t i_extension);
/***************************************************************************** /*****************************************************************************
* dvbpsi_InitTOT/dvbpsi_NewTOT * dvbpsi_InitTOT/dvbpsi_NewTOT
*****************************************************************************/ *****************************************************************************/
...@@ -136,7 +132,6 @@ do { \ ...@@ -136,7 +132,6 @@ do { \
dvbpsi_InitTOT(p_tot, i_utc_time); \ dvbpsi_InitTOT(p_tot, i_utc_time); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_EmptyTOT/dvbpsi_DeleteTOT * dvbpsi_EmptyTOT/dvbpsi_DeleteTOT
*****************************************************************************/ *****************************************************************************/
...@@ -160,7 +155,6 @@ do { \ ...@@ -160,7 +155,6 @@ do { \
free(p_tot); \ free(p_tot); \
} while(0); } while(0);
/***************************************************************************** /*****************************************************************************
* dvbpsi_TOTAddDescriptor * dvbpsi_TOTAddDescriptor
*****************************************************************************/ *****************************************************************************/
...@@ -180,20 +174,19 @@ dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot, ...@@ -180,20 +174,19 @@ dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
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_GenTOTSections * dvbpsi_GenTOTSections
*****************************************************************************/ *****************************************************************************/
/*! /*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_Ttot_t* p_tot) * \fn dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_Ttot_t* p_tot)
* \brief TDT/TOT generator * \brief TDT/TOT generator
* \param p_dvbpsi dvbpsi handle
* \param p_tot TDT/TOT structure * \param p_tot TDT/TOT structure
* \return a pointer to the list of generated PSI sections. * \return a pointer to the list of generated PSI sections.
* *
* Generate TDT/TOT sections based on the dvbpsi_tot_t structure. * Generate TDT/TOT sections based on the dvbpsi_tot_t structure.
*/ */
dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_tot_t* p_tot); dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_t* p_dvbpsi, dvbpsi_tot_t* p_tot);
#ifdef __cplusplus #ifdef __cplusplus
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Authors: Johann Hanne * Authors: Johann Hanne
* heavily based on pmt.c which was written by * heavily based on pmt.c which was written by
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
* *
* 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
...@@ -36,8 +37,10 @@ ...@@ -36,8 +37,10 @@
*****************************************************************************/ *****************************************************************************/
typedef struct dvbpsi_tot_decoder_s typedef struct dvbpsi_tot_decoder_s
{ {
dvbpsi_tot_callback pf_callback; DVBPSI_DECODER_COMMON
void * p_cb_data;
dvbpsi_tot_callback pf_tot_callback;
void * p_cb_data;
} dvbpsi_tot_decoder_t; } dvbpsi_tot_decoder_t;
...@@ -47,27 +50,25 @@ typedef struct dvbpsi_tot_decoder_s ...@@ -47,27 +50,25 @@ typedef struct dvbpsi_tot_decoder_s
***************************************************************************** *****************************************************************************
* Callback for the PSI decoder. * Callback for the PSI decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_GatherTOTSections(dvbpsi_decoder_t* p_decoder, void dvbpsi_GatherTOTSections(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_ValidTOTSection * dvbpsi_ValidTOTSection
***************************************************************************** *****************************************************************************
* Check the CRC_32 if the section has b_syntax_indicator set. * Check the CRC_32 if the section has b_syntax_indicator set.
*****************************************************************************/ *****************************************************************************/
int dvbpsi_ValidTOTSection(dvbpsi_psi_section_t* p_section); int dvbpsi_ValidTOTSection(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section);
/***************************************************************************** /*****************************************************************************
* dvbpsi_DecodeTOTSections * dvbpsi_DecodeTOTSections
***************************************************************************** *****************************************************************************
* TDT/TOT decoder. * TDT/TOT decoder.
*****************************************************************************/ *****************************************************************************/
void dvbpsi_DecodeTOTSections(dvbpsi_tot_t* p_tot, void dvbpsi_DecodeTOTSections(dvbpsi_t* p_dvbpsi, dvbpsi_tot_t* p_tot,
dvbpsi_psi_section_t* p_section); dvbpsi_psi_section_t* p_section);
#else #else
#error "Multiple inclusions of tot_private.h" #error "Multiple inclusions of tot_private.h"
#endif #endif
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