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 @@
* $Id$
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -24,7 +25,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -36,6 +36,8 @@
#include <stdint.h>
#endif
#include <assert.h>
#include "dvbpsi.h"
#include "dvbpsi_private.h"
#include "psi.h"
......@@ -46,39 +48,33 @@
*****************************************************************************
* Creation of the demux structure
*****************************************************************************/
dvbpsi_handle dvbpsi_AttachDemux(dvbpsi_demux_new_cb_t pf_new_cb,
void * p_new_cb_data)
dvbpsi_t *dvbpsi_AttachDemux(dvbpsi_t * p_dvbpsi,
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));
dvbpsi_demux_t * p_demux;
if(h_dvbpsi == NULL)
return NULL;
p_demux = (dvbpsi_demux_t*)malloc(sizeof(dvbpsi_demux_t));
if(p_demux == NULL)
{
free(h_dvbpsi);
return NULL;
}
/* PSI decoder configuration */
h_dvbpsi->pf_callback = &dvbpsi_Demux;
h_dvbpsi->p_private_decoder = p_demux;
h_dvbpsi->i_section_max_size = 4096;
/* PSI decoder initial state */
h_dvbpsi->i_continuity_counter = 31;
h_dvbpsi->b_discontinuity = 1;
h_dvbpsi->p_current_section = NULL;
/* 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;
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t*)malloc(sizeof(dvbpsi_demux_t));
if (p_demux == NULL)
return NULL;
/* PSI decoder configuration */
p_demux->pf_callback = &dvbpsi_Demux;
p_demux->i_section_max_size = 4096;
/* PSI decoder initial state */
p_demux->i_continuity_counter = 31;
p_demux->b_discontinuity = 1;
p_demux->p_current_section = NULL;
/* Subtables demux configuration */
p_demux->p_first_subdec = NULL;
p_demux->pf_new_callback = pf_new_cb;
p_demux->p_new_cb_data = p_new_cb_data;
p_dvbpsi->p_private = (void *)p_demux;
return p_dvbpsi;
}
/*****************************************************************************
......@@ -90,18 +86,18 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_demux,
uint8_t i_table_id,
uint16_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;
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;
while(p_subdec)
{
if(p_subdec->i_id == i_id)
break;
while (p_subdec)
{
if (p_subdec->i_id == i_id)
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,
*****************************************************************************
* 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;
dvbpsi_demux_subdec_t * p_subdec;
p_demux = (dvbpsi_demux_t *)p_decoder->p_private_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
p_section->i_extension);
if(p_subdec == NULL)
{
/* Tell the application we found a new subtable, so that it may attach a
* subtable decoder */
p_demux->pf_new_callback(p_demux->p_new_cb_data, p_decoder,
p_section->i_table_id,
p_section->i_extension);
/* Check if a new subtable decoder is available */
p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
p_section->i_extension);
}
if(p_subdec)
{
p_subdec->pf_callback(p_demux->p_decoder, p_subdec->p_cb_data, p_section);
}
else
{
dvbpsi_DeletePSISections(p_section);
}
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
dvbpsi_demux_t * p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t * p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
p_section->i_extension);
if (p_subdec == NULL)
{
/* Tell the application we found a new subtable, so that it may attach a
* subtable decoder */
p_demux->pf_new_callback(p_demux->p_new_cb_data, (dvbpsi_decoder_t *)p_demux,
p_section->i_table_id, p_section->i_extension);
/* Check if a new subtable decoder is available */
p_subdec = dvbpsi_demuxGetSubDec(p_demux, p_section->i_table_id,
p_section->i_extension);
}
if (p_subdec)
{
p_subdec->pf_callback(p_dvbpsi, p_subdec->p_cb_data, p_section);
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
......@@ -147,26 +141,28 @@ void dvbpsi_Demux(dvbpsi_handle p_decoder, dvbpsi_psi_section_t * p_section)
*****************************************************************************
* Destroys a demux structure
*****************************************************************************/
void dvbpsi_DetachDemux(dvbpsi_handle h_dvbpsi)
void dvbpsi_DetachDemux(dvbpsi_t *p_dvbpsi)
{
dvbpsi_demux_t* p_demux
= (dvbpsi_demux_t*)h_dvbpsi->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec
= p_demux->p_first_subdec;
dvbpsi_demux_subdec_t* p_subdec_temp;
while(p_subdec)
{
p_subdec_temp = p_subdec;
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,
p_subdec_temp->i_id & 0xFFFF);
else free(p_subdec_temp);
}
free(p_demux);
if(h_dvbpsi->p_current_section)
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section);
free(h_dvbpsi);
assert(p_dvbpsi);
assert(p_dvbpsi->p_private);
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec = p_demux->p_first_subdec;
while (p_subdec)
{
dvbpsi_demux_subdec_t* p_subdec_temp = p_subdec;
p_subdec = p_subdec->p_next;
if (p_subdec_temp->pf_detach)
p_subdec_temp->pf_detach(p_dvbpsi, (p_subdec_temp->i_id >> 16) & 0xFFFF,
p_subdec_temp->i_id & 0xFFFF);
else free(p_subdec_temp);
}
if (p_demux->p_current_section)
dvbpsi_DeletePSISections(p_demux->p_current_section);
p_dvbpsi->p_private = NULL;
free(p_demux);
}
......@@ -5,6 +5,7 @@
* $Id$
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -37,19 +38,18 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_demux_new_cb_t
*****************************************************************************/
/*!
* \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,
uint16_t i_extension);
* \brief Callback used in case of a new subtable detected.
*/
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,
uint16_t i_extension);
......@@ -58,15 +58,15 @@ typedef void (*dvbpsi_demux_new_cb_t) (void * p_cb_data,
*****************************************************************************/
/*!
* \typedef void (*dvbpsi_demux_subdec_cb_t)
(dvbpsi_decoder_t* p_psi_decoder,
void* p_private_decoder,
dvbpsi_psi_section_t* p_section);
(dvbpsi_t *p_dvbpsi,
void *p_private_decoder,
dvbpsi_psi_section_t *p_section);
* \brief Subtable specific decoder.
*/
typedef void (*dvbpsi_demux_subdec_cb_t)
(dvbpsi_decoder_t* p_psi_decoder,
void* p_private_decoder,
dvbpsi_psi_section_t* p_section);
(dvbpsi_t *p_dvbpsi,
void *p_private_decoder,
dvbpsi_psi_section_t *p_section);
/*****************************************************************************
* dvbpsi_demux_subdec_t
......@@ -90,12 +90,12 @@ typedef struct dvbpsi_demux_subdec_s
void * p_cb_data;
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_t
* dvbpsi_demux_s
*****************************************************************************/
/*!
* \struct dvbpsi_demux_s
......@@ -108,41 +108,44 @@ typedef struct dvbpsi_demux_subdec_s
* \typedef struct dvbpsi_demux_s dvbpsi_demux_t
* \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_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_DECODER_COMMON
} 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
*****************************************************************************/
/*!
* \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.
* \param p_dvbpsi pointer to dvbpsi_t handle
* \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.
* \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,
void * p_new_cb_data);
dvbpsi_t *dvbpsi_AttachDemux(dvbpsi_t * p_dvbpsi,
dvbpsi_demux_new_cb_t pf_new_cb,
void * p_new_cb_data);
/*****************************************************************************
* dvbpsi_DetachDemux
*****************************************************************************/
/*!
* \fn void dvbpsi_DetachDemux(dvbpsi_handle h_dvbpsi)
* \fn void dvbpsi_DetachDemux(dvbpsi_decoder_t *p_decoder)
* \brief Destroys a demux structure.
* \param h_dvbpsi The handle of the demux to be destroyed.
*/
void dvbpsi_DetachDemux(dvbpsi_handle h_dvbpsi);
void dvbpsi_DetachDemux(dvbpsi_t *p_dvbpsi);
/*****************************************************************************
* dvbpsi_demuxGetSubDec
......@@ -163,14 +166,13 @@ dvbpsi_demux_subdec_t * dvbpsi_demuxGetSubDec(dvbpsi_demux_t * p_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)
* \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.
*/
void dvbpsi_Demux(dvbpsi_handle h_dvbpsi,
dvbpsi_psi_section_t * p_section);
void dvbpsi_Demux(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section);
#ifdef __cplusplus
};
......
......@@ -5,6 +5,7 @@
* $Id$
*
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -30,6 +31,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdbool.h>
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
......@@ -37,6 +39,8 @@
#include <stdint.h>
#endif
#include <assert.h>
#include "dvbpsi.h"
#include "dvbpsi_private.h"
#include "psi.h"
......@@ -137,13 +141,66 @@ uint32_t dvbpsi_crc32_table[256] =
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
*****************************************************************************
* 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 */
dvbpsi_psi_section_t* p_section; /* Current section */
......@@ -154,38 +211,41 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
int i_available; /* Byte count available in the
packet */
dvbpsi_decoder_t *p_decoder = (dvbpsi_decoder_t *)handle->p_private;
assert(p_decoder);
/* TS start code */
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;
}
/* Continuity check */
i_expected_counter = (h_dvbpsi->i_continuity_counter + 1) & 0xf;
h_dvbpsi->i_continuity_counter = p_data[3] & 0xf;
i_expected_counter = (p_decoder->i_continuity_counter + 1) & 0xf;
p_decoder->i_continuity_counter = p_data[3] & 0xf;
if(i_expected_counter == ((h_dvbpsi->i_continuity_counter + 1) & 0xf)
&& !h_dvbpsi->b_discontinuity)
if(i_expected_counter == ((p_decoder->i_continuity_counter + 1) & 0xf)
&& !p_decoder->b_discontinuity)
{
dvbpsi_error(h_dvbpsi, "PSI decoder",
dvbpsi_error(handle, "PSI decoder",
"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]);
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",
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]);
h_dvbpsi->b_discontinuity = 1;
if(h_dvbpsi->p_current_section)
p_decoder->b_discontinuity = 1;
if(p_decoder->p_current_section)
{
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section);
h_dvbpsi->p_current_section = NULL;
dvbpsi_DeletePSISections(p_decoder->p_current_section);
p_decoder->p_current_section = NULL;
}
}
......@@ -208,7 +268,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
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
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)
if(p_new_pos)
{
/* Allocation of the structure */
h_dvbpsi->p_current_section
p_decoder->p_current_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 */
p_payload_pos = p_new_pos;
/* New section is being handled */
p_new_pos = NULL;
/* Just need the header to know how long is the section */
h_dvbpsi->i_need = 3;
h_dvbpsi->b_complete_header = 0;
p_decoder->i_need = 3;
p_decoder->b_complete_header = 0;
}
else
{
......@@ -240,40 +300,40 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
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
header/section */
memcpy(p_section->p_payload_end, p_payload_pos, h_dvbpsi->i_need);
p_payload_pos += h_dvbpsi->i_need;
p_section->p_payload_end += h_dvbpsi->i_need;
i_available -= h_dvbpsi->i_need;
memcpy(p_section->p_payload_end, p_payload_pos, p_decoder->i_need);
p_payload_pos += p_decoder->i_need;
p_section->p_payload_end += p_decoder->i_need;
i_available -= p_decoder->i_need;
if(!h_dvbpsi->b_complete_header)
if(!p_decoder->b_complete_header)
{
/* Header is complete */
h_dvbpsi->b_complete_header = 1;
/* Compute p_section->i_length and update h_dvbpsi->i_need */
h_dvbpsi->i_need = p_section->i_length
p_decoder->b_complete_header = 1;
/* Compute p_section->i_length and update p_decoder->i_need */
p_decoder->i_need = p_section->i_length
= ((uint16_t)(p_section->p_data[1] & 0xf)) << 8
| p_section->p_data[2];
/* Check that the section isn't too long */
if(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);
h_dvbpsi->p_current_section = NULL;
p_decoder->p_current_section = NULL;
/* If there is a new section not being handled then go forward
in the packet */
if(p_new_pos)
{
h_dvbpsi->p_current_section
p_decoder->p_current_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_new_pos = NULL;
h_dvbpsi->i_need = 3;
h_dvbpsi->b_complete_header = 0;
p_decoder->i_need = 3;
p_decoder->b_complete_header = 0;
i_available = 188 + p_data - p_payload_pos;
}
else
......@@ -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;
}
h_dvbpsi->pf_callback(h_dvbpsi, p_section);
h_dvbpsi->p_current_section = NULL;
p_decoder->pf_callback(handle, p_section);
p_decoder->p_current_section = NULL;
}
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 */
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
......@@ -337,13 +397,13 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
in the packet */
if(p_new_pos)
{
h_dvbpsi->p_current_section
p_decoder->p_current_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_new_pos = NULL;
h_dvbpsi->i_need = 3;
h_dvbpsi->b_complete_header = 0;
p_decoder->i_need = 3;
p_decoder->b_complete_header = 0;
i_available = 188 + p_data - p_payload_pos;
}
else
......@@ -358,7 +418,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
header/section */
memcpy(p_section->p_payload_end, p_payload_pos, i_available);
p_section->p_payload_end += i_available;
h_dvbpsi->i_need -= i_available;
p_decoder->i_need -= i_available;
i_available = 0;
}
}
......@@ -375,7 +435,7 @@ void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
#define DVBPSI_MSG_FORMAT "libdvbpsi (%s): "
#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) &&
(level <= dvbpsi->i_msg_level))
......@@ -400,7 +460,7 @@ void message(dvbpsi_handle dvbpsi, const int level, const char *fmt, ...)
}
}
#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)
{
......@@ -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)
{
......@@ -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)
{
......
......@@ -4,6 +4,7 @@
* $Id$
*
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -40,16 +41,82 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_handle
*****************************************************************************/
/*!
* \typedef struct dvbpsi_decoder_s * dvbpsi_handle
* \brief Decoder abstration.
* \typedef struct dvbpsi_s dvbpsi_t
* \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
......@@ -63,8 +130,7 @@ typedef struct dvbpsi_decoder_s * dvbpsi_handle;
*
* 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
......@@ -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_decoder_s dvbpsi_decoder_t
* \brief dvbpsi_decoder_t type definition.
*/
typedef struct dvbpsi_decoder_s dvbpsi_decoder_t;
/*****************************************************************************
* dvbpsi_callback
*****************************************************************************/
/*!
* \typedef void (* dvbpsi_callback)(dvbpsi_handle p_decoder,
* \typedef void (* dvbpsi_callback)(dvbpsi_t *p_dvbpsi,
dvbpsi_psi_section_t* p_section)
* \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_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
*****************************************************************************/
......@@ -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
* decoder.
*/
/*!
* \typedef struct dvbpsi_decoder_s dvbpsi_decoder_t
* \brief dvbpsi_decoder_t type definition.
*/
typedef struct dvbpsi_decoder_s
#define DVBPSI_DECODER_COMMON \
dvbpsi_callback pf_callback; /*!< PSI decoder's callback */ \
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 */
struct dvbpsi_decoder_s
{
dvbpsi_callback pf_callback; /*!< PSI decoder's
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 */
DVBPSI_DECODER_COMMON
};
/* 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_decoder_t;
/*****************************************************************************
* dvbpsi_NewDecoder
*****************************************************************************/
/*!
* \fn dvbpsi_decoder_t *dvbpsi_NewDecoder(dvbpsi_t *handle, dvbpsi_callback *callback)
* \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
};
......
......@@ -5,6 +5,7 @@
* $Id$
*
* 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
* 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, ...);
# define dvbpsi_debug(hnd, str, x...) \
message(hnd, DVBPSI_MSG_DEBUG, "libdvbpsi debug ("src"): " str, x)
#else
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_debug(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_t *dvbpsi, const char *src, const char *fmt, ...);
void dvbpsi_debug(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...);
#endif
#else
......
......@@ -114,18 +114,14 @@ int dvbpsi_ValidPSISection(dvbpsi_psi_section_t* p_section)
}
if(i_crc == 0)
{
return 1;
}
else
{
return 0;
}
}
else
{
/* 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)
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[3] = p_section->i_crc & 0xff;
#if 0
if(!dvbpsi_ValidPSISection(p_section))
{
dvbpsi_error(h_dvbpsi,"misc PSI", "********************************************");
dvbpsi_error(h_dvbpsi,"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(h_dvbpsi,"misc PSI", "* --- libdvbpsi-devel@videolan.org --- *");
dvbpsi_error(h_dvbpsi,"misc PSI", "********************************************");
dvbpsi_error(handle,"misc PSI", "********************************************");
dvbpsi_error(handle,"misc PSI", "* Generated PSI section has a bad CRC_32. *");
dvbpsi_error(handle,"misc PSI", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
dvbpsi_error(handle,"misc PSI", "* --- libdvbpsi-devel@videolan.org --- *");
dvbpsi_error(handle,"misc PSI", "********************************************");
}
#endif
}
......
......@@ -130,7 +130,7 @@ void dvbpsi_DeletePSISections(dvbpsi_psi_section_t * p_section);
* \fn int dvbpsi_ValidPSISection(dvbpsi_psi_section_t* p_section)
* \brief Validity check of a PSI section.
* \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.
*/
......
......@@ -7,6 +7,7 @@
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
* heavily based on nit.c which was written by
* Johann Hanne
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -46,64 +47,61 @@
#include "bat.h"
#include "bat_private.h"
/*****************************************************************************
* dvbpsi_AttachBAT
*****************************************************************************
* 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)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_bat_decoder_t* p_bat_decoder;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_bat_decoder_t* p_bat_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(h_dvbpsi, "BAT decoder",
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(p_dvbpsi, "BAT decoder",
"Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)",
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)
{
return 1;
}
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
if (p_subdec == NULL)
{
return 1;
}
p_bat_decoder = (dvbpsi_bat_decoder_t*)malloc(sizeof(dvbpsi_bat_decoder_t));
if(p_bat_decoder == NULL)
{
free(p_subdec);
return 1;
}
p_bat_decoder = (dvbpsi_bat_decoder_t*)malloc(sizeof(dvbpsi_bat_decoder_t));
if (p_bat_decoder == NULL)
{
free(p_subdec);
return 1;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherBATSections;
p_subdec->p_cb_data = p_bat_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachBAT;
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherBATSections;
p_subdec->p_cb_data = p_bat_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
p_subdec->pf_detach = dvbpsi_DetachBAT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* BAT decoder information */
p_bat_decoder->pf_callback = pf_callback;
p_bat_decoder->p_cb_data = p_cb_data;
/* BAT decoder initial state */
p_bat_decoder->b_current_valid = 0;
p_bat_decoder->p_building_bat = NULL;
/* BAT decoder information */
p_bat_decoder->pf_bat_callback = pf_callback;
p_bat_decoder->p_cb_data = p_cb_data;
/* BAT decoder initial state */
p_bat_decoder->b_current_valid = 0;
p_bat_decoder->p_building_bat = NULL;
for(unsigned int i = 0; i < 256; i++)
p_bat_decoder->ap_sections[i] = NULL;
for (unsigned int i = 0; i < 256; i++)
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,
*****************************************************************************
* Close a BAT decoder.
*****************************************************************************/
void dvbpsi_DetachBAT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension)
void dvbpsi_DetachBAT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_bat_decoder_t* p_bat_decoder;
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_bat_decoder_t* p_bat_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_subdec == NULL)
{
dvbpsi_error(h_dvbpsi, "BAT Decoder",
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if (p_subdec == NULL)
{
dvbpsi_error(p_dvbpsi, "BAT Decoder",
"No such BAT decoder (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, i_extension);
return;
}
p_bat_decoder = (dvbpsi_bat_decoder_t*)p_subdec->p_cb_data;
free(p_bat_decoder->p_building_bat);
return;
}
for(unsigned int i = 0; i < 256; i++)
{
if(p_bat_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]);
}
p_bat_decoder = (dvbpsi_bat_decoder_t*)p_subdec->p_cb_data;
free(p_bat_decoder->p_building_bat);
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;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
pp_prev_subdec = &p_demux->p_first_subdec;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
p_subdec = NULL;
}
/*****************************************************************************
......@@ -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,
int b_current_next)
{
p_bat->i_bouquet_id = i_bouquet_id;
p_bat->i_version = i_version;
p_bat->b_current_next = b_current_next;
p_bat->p_first_ts = NULL;
p_bat->p_first_descriptor = NULL;
p_bat->i_bouquet_id = i_bouquet_id;
p_bat->i_version = i_version;
p_bat->b_current_next = b_current_next;
p_bat->p_first_ts = 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
*****************************************************************************/
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);
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;
}
dvbpsi_DeleteDescriptors(p_bat->p_first_descriptor);
p_bat->p_first_descriptor = NULL;
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)
dvbpsi_bat_ts_t *dvbpsi_BATAddTS(dvbpsi_bat_t* p_bat,
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));
if(p_ts)
{
if (p_ts == NULL)
return NULL;
p_ts->i_ts_id = i_ts_id;
p_ts->i_orig_network_id = i_orig_network_id;
p_ts->p_next = NULL;
p_ts->p_first_descriptor = NULL;
if(p_bat->p_first_ts == NULL)
{
p_bat->p_first_ts = p_ts;
}
if (p_bat->p_first_ts == NULL)
p_bat->p_first_ts = p_ts;
else
{
dvbpsi_bat_ts_t * p_last_ts = p_bat->p_first_ts;
while(p_last_ts->p_next != NULL)
p_last_ts = p_last_ts->p_next;
p_last_ts->p_next = p_ts;
dvbpsi_bat_ts_t * p_last_ts = p_bat->p_first_ts;
while(p_last_ts->p_next != NULL)
p_last_ts = p_last_ts->p_next;
p_last_ts->p_next = p_ts;
}
}
return p_ts;
return p_ts;
}
/*****************************************************************************
......@@ -230,24 +224,21 @@ dvbpsi_descriptor_t *dvbpsi_BATBouquetAddDescriptor(
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);
if(p_descriptor)
{
if(p_bat->p_first_descriptor == NULL)
{
if (p_descriptor == NULL)
return NULL;
if (p_bat->p_first_descriptor == NULL)
p_bat->p_first_descriptor = p_descriptor;
}
else
{
dvbpsi_descriptor_t * p_last_descriptor = p_bat->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;
dvbpsi_descriptor_t * p_last_descriptor = p_bat->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;
}
/*****************************************************************************
......@@ -260,24 +251,21 @@ dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor(
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);
if(p_descriptor)
{
if(p_ts->p_first_descriptor == NULL)
{
p_ts->p_first_descriptor = p_descriptor;
}
if (p_descriptor == NULL)
return NULL;
if (p_ts->p_first_descriptor == NULL)
p_ts->p_first_descriptor = p_descriptor;
else
{
dvbpsi_descriptor_t *p_last_descriptor = p_ts->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;
dvbpsi_descriptor_t *p_last_descriptor = p_ts->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;
}
/*****************************************************************************
......@@ -285,17 +273,17 @@ dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor(
*****************************************************************************
* 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,
dvbpsi_psi_section_t * p_section)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_bat_decoder_t * p_bat_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_private_decoder;
int b_append = 1;
int b_reinit = 0;
int b_append = 1;
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, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id,
......@@ -303,166 +291,164 @@ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if(!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(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)
if (!p_section->b_syntax_indicator)
{
b_reinit = 1;
p_psi_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
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 */
if(p_bat_decoder->p_building_bat)
{
if(p_bat_decoder->p_building_bat->i_bouquet_id != p_section->i_extension)
/* TS discontinuity check */
if (p_demux->b_discontinuity)
{
/* bouquet_id */
dvbpsi_error(h_dvbpsi, "BAT decoder",
"'bouquet_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
b_reinit = 1;
p_demux->b_discontinuity = 0;
}
else if(p_bat_decoder->p_building_bat->i_version
!= p_section->i_version)
else
{
/* version_number */
dvbpsi_error(h_dvbpsi, "BAT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
else if(p_bat_decoder->i_last_section_number !=
/* Perform a few sanity checks */
if (p_bat_decoder->p_building_bat)
{
if (p_bat_decoder->p_building_bat->i_bouquet_id != p_section->i_extension)
{
/* bouquet_id */
dvbpsi_error(p_dvbpsi, "BAT decoder",
"'bouquet_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 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)
{
/* 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 */
dvbpsi_error(h_dvbpsi, "BAT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
free(p_bat_decoder->p_building_bat);
p_bat_decoder->p_building_bat = NULL;
}
}
else
{
if( (p_bat_decoder->b_current_valid)
&& (p_bat_decoder->current_bat.i_version == p_section->i_version))
/* Clear the section array */
for (unsigned int i = 0; i < 256; i++)
{
/* 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_callback(p_bat_decoder->p_cb_data, p_bat);
}
/* Don't decode since this version is already decoded */
b_append = 0;
if (p_bat_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]);
p_bat_decoder->ap_sections[i] = NULL;
}
}
}
}
}
/* 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)
{
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++)
/* Append the section to the list if wanted */
if (b_append)
{
if(p_bat_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[i]);
p_bat_decoder->ap_sections[i] = NULL;
}
}
}
/* Append the section to the list if wanted */
if(b_append)
{
int b_complete;
int b_complete = 0;
/* Initialize the structures if it's the first section received */
if(!p_bat_decoder->p_building_bat)
{
p_bat_decoder->p_building_bat =
/* Initialize the structures if it's the first section received */
if (!p_bat_decoder->p_building_bat)
{
p_bat_decoder->p_building_bat =
(dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t));
dvbpsi_InitBAT(p_bat_decoder->p_building_bat,
dvbpsi_InitBAT(p_bat_decoder->p_building_bat,
p_section->i_extension,
p_section->i_version,
p_section->b_current_next);
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 */
if(p_bat_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(h_dvbpsi, "BAT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[p_section->i_number]);
}
p_bat_decoder->ap_sections[p_section->i_number] = p_section;
/* Fill the section array */
if (p_bat_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(p_dvbpsi, "BAT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_bat_decoder->ap_sections[p_section->i_number]);
}
p_bat_decoder->ap_sections[p_section->i_number] = p_section;
/* Check if we have all the sections */
b_complete = 0;
for(unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++)
{
if(!p_bat_decoder->ap_sections[i])
break;
/* Check if we have all the sections */
for (unsigned int i = 0; i <= p_bat_decoder->i_last_section_number; i++)
{
if (!p_bat_decoder->ap_sections[i])
break;
if (i == p_bat_decoder->i_last_section_number)
b_complete = 1;
}
if(i == p_bat_decoder->i_last_section_number)
b_complete = 1;
if (b_complete)
{
/* 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;
}
}
if(b_complete)
else
{
/* 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_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;
dvbpsi_DeletePSISections(p_section);
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
......@@ -473,7 +459,7 @@ void dvbpsi_GatherBATSections(dvbpsi_decoder_t * p_psi_decoder,
* p_section as the input parameter
* 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)
{
uint8_t* p_byte, * p_end, * p_end2;
......@@ -536,197 +522,196 @@ void dvbpsi_DecodeBATSections(dvbpsi_bat_t* p_bat,
* Generate BAT sections based on the dvbpsi_bat_t structure.
* 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_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_bat->p_first_descriptor;
dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
uint16_t i_bouquet_descriptors_length, i_transport_stream_loop_length;
uint8_t * p_transport_stream_loop_length;
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 = 0;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* first loop descriptors */
while(p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_bat->p_first_descriptor;
dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
uint16_t i_bouquet_descriptors_length, i_transport_stream_loop_length;
uint8_t * p_transport_stream_loop_length;
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 = 0;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* first loop descriptors */
while (p_descriptor != NULL)
{
/* bouquet_descriptors_length */
i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0;
p_current->p_data[9] = i_bouquet_descriptors_length;
/* transport_stream_loop_length */
p_current->p_payload_end[0] = 0;
p_current->p_payload_end[1] = 0;
p_current->p_payload_end += 2;
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
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;
}
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
{
/* bouquet_descriptors_length */
i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0;
p_current->p_data[9] = i_bouquet_descriptors_length;
/* transport_stream_loop_length */
p_current->p_payload_end[0] = 0;
p_current->p_payload_end[1] = 0;
p_current->p_payload_end += 2;
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
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;
}
/* 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);
/* 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;
/* 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;
}
/* 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;
p_descriptor = p_descriptor->p_next;
}
/* 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;
/* 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;
/* second loop: BAT TSs */
while(p_ts != NULL)
{
uint8_t* p_ts_start = p_current->p_payload_end;
uint16_t i_transport_descriptors_length = 5;
/* 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;
/* 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_transport_descriptors_length <= 1020))
/* second loop: BAT TSs */
while (p_ts != NULL)
{
i_transport_descriptors_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
uint8_t* p_ts_start = p_current->p_payload_end;
uint16_t i_transport_descriptors_length = 5;
/* If _no_ and the current section isn't empty and an empty section
may carry one more descriptor
then create a new section */
if( (p_descriptor != NULL)
&& (p_ts_start - p_current->p_data != 12)
&& (i_transport_descriptors_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;
#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;
}
/* 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_transport_descriptors_length <= 1020))
{
i_transport_descriptors_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->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;
}
#if 0 /* FIXME: */
if(p_descriptor != NULL)
dvbpsi_error(h_dvbpsi, "BAT generator", "unable to carry all the TS descriptors");
#endif
/* transport_descriptors_length */
i_transport_descriptors_length = p_current->p_payload_end - p_ts_start - 5;
p_ts_start[4] = (i_transport_descriptors_length >> 8) | 0xf0;
p_ts_start[5] = i_transport_descriptors_length;
/* If _no_ and the current section isn't empty and an empty section
may carry one more descriptor
then create a new section */
if( (p_descriptor != NULL)
&& (p_ts_start - p_current->p_data != 12)
&& (i_transport_descriptors_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, "BAT 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 = 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 = 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 */
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 (p_descriptor != NULL)
dvbpsi_error(p_dvbpsi, "BAT generator", "unable to carry all the TS descriptors");
/* 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;
}
/* transport_descriptors_length */
i_transport_descriptors_length = p_current->p_payload_end - p_ts_start - 5;
p_ts_start[4] = (i_transport_descriptors_length >> 8) | 0xf0;
p_ts_start[5] = i_transport_descriptors_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;
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 @@
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
* heavily based on nit.h which was written by
* Johann Hanne
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -110,43 +111,40 @@ typedef struct dvbpsi_bat_s
*/
typedef void (* dvbpsi_bat_callback)(void* p_cb_data, dvbpsi_bat_t* p_new_bat);
/*****************************************************************************
* 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,
void* p_cb_data)
* \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_extension Table ID extension, here bouquet ID.
* \param pf_callback function to call back on new BAT.
* \param p_cb_data private data given in argument to the callback.
* \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,
void* p_cb_data);
/*****************************************************************************
* 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)
* \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_extension Table ID extension, here bouquet ID.
* \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);
/*****************************************************************************
* dvbpsi_InitBAT/dvbpsi_NewBAT
*****************************************************************************/
......@@ -181,7 +179,6 @@ do { \
dvbpsi_InitBAT(p_bat, i_bouquet_id, i_version, b_current_next); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyBAT/dvbpsi_DeleteBAT
*****************************************************************************/
......@@ -207,8 +204,8 @@ do { \
/*****************************************************************************
* dvbpsi_GenBATSections
*****************************************************************************
*!
*****************************************************************************/
/*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_bat_t* p_bat)
* \brief BAT generator
* \param p_bat BAT structure
......@@ -216,8 +213,7 @@ do { \
*
* 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
};
......
......@@ -5,6 +5,7 @@
* $Id: bat_private.h 88 2004-02-24 14:31:18Z sam $
*
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -28,7 +29,6 @@
#ifndef _DVBPSI_BAT_PRIVATE_H_
#define _DVBPSI_BAT_PRIVATE_H_
/*****************************************************************************
* dvbpsi_bat_decoder_t
*****************************************************************************
......@@ -36,39 +36,37 @@
*****************************************************************************/
typedef struct dvbpsi_bat_decoder_s
{
dvbpsi_bat_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_bat_t current_bat;
dvbpsi_bat_t * p_building_bat;
dvbpsi_bat_callback pf_bat_callback;
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;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
} dvbpsi_bat_decoder_t;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_bat_decoder_t;
/*****************************************************************************
* dvbpsi_GatherBATSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherBATSections(dvbpsi_decoder_t* p_psi_decoder,
void* p_private_decoder,
dvbpsi_psi_section_t* p_section);
void dvbpsi_GatherBATSections(dvbpsi_t* p_dvbpsi,
void* p_private_decoder, dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodeBATSections
*****************************************************************************
* 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_BATAddTS
*****************************************************************************
......
......@@ -7,6 +7,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -26,7 +27,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -39,6 +39,8 @@
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
......@@ -46,76 +48,65 @@
#include "cat.h"
#include "cat_private.h"
/*****************************************************************************
* dvbpsi_AttachCAT
*****************************************************************************
* 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)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t));
dvbpsi_cat_decoder_t* p_cat_decoder;
if(h_dvbpsi == NULL)
return NULL;
p_cat_decoder = (dvbpsi_cat_decoder_t*)malloc(sizeof(dvbpsi_cat_decoder_t));
if(p_cat_decoder == NULL)
{
free(h_dvbpsi);
return NULL;
}
/* PSI decoder configuration */
h_dvbpsi->pf_callback = &dvbpsi_GatherCATSections;
h_dvbpsi->p_private_decoder = p_cat_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;
/* CAT decoder configuration */
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;
}
assert(p_dvbpsi);
dvbpsi_cat_decoder_t* p_cat_decoder;
p_cat_decoder = (dvbpsi_cat_decoder_t*)calloc(1, sizeof(dvbpsi_cat_decoder_t));
if (p_cat_decoder == NULL)
return NULL;
/* PSI decoder configuration */
p_cat_decoder->pf_callback = &dvbpsi_GatherCATSections;
p_dvbpsi->p_private = p_cat_decoder;
p_cat_decoder->i_section_max_size = 1024;
/* PSI decoder initial state */
p_cat_decoder->i_continuity_counter = 31;
p_cat_decoder->b_discontinuity = 1;
p_cat_decoder->p_current_section = NULL;
/* CAT decoder configuration */
p_cat_decoder->pf_cat_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 p_dvbpsi;
}
/*****************************************************************************
* dvbpsi_DetachCAT
*****************************************************************************
* 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*)h_dvbpsi->p_private_decoder;
dvbpsi_cat_decoder_t* p_cat_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++)
{
if(p_cat_decoder->ap_sections[i])
free(p_cat_decoder->ap_sections[i]);
}
for (unsigned int i = 0; i <= 255; i++)
{
if (p_cat_decoder->ap_sections[i])
free(p_cat_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);
if (p_cat_decoder->p_current_section)
dvbpsi_DeletePSISections(p_cat_decoder->p_current_section);
free(p_cat_decoder);
p_dvbpsi->p_private = NULL;
}
/*****************************************************************************
* dvbpsi_InitCAT
*****************************************************************************
......@@ -124,12 +115,11 @@ void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi)
void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
uint8_t i_version, int b_current_next)
{
p_cat->i_version = i_version;
p_cat->b_current_next = b_current_next;
p_cat->p_first_descriptor = NULL;
p_cat->i_version = i_version;
p_cat->b_current_next = b_current_next;
p_cat->p_first_descriptor = NULL;
}
/*****************************************************************************
* dvbpsi_EmptyCAT
*****************************************************************************
......@@ -137,12 +127,10 @@ void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
*****************************************************************************/
void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat)
{
dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor);
p_cat->p_first_descriptor = NULL;
dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor);
p_cat->p_first_descriptor = NULL;
}
/*****************************************************************************
* dvbpsi_CATAddDescriptor
*****************************************************************************
......@@ -152,202 +140,194 @@ dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat,
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);
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;
}
else
{
dvbpsi_descriptor_t* p_last_descriptor = p_cat->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;
dvbpsi_descriptor_t* p_last_descriptor = p_cat->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;
}
/*****************************************************************************
* dvbpsi_GatherCATSections
*****************************************************************************
* 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_handle h_dvbpsi = (dvbpsi_handle) p_decoder;
dvbpsi_cat_decoder_t* p_cat_decoder
= (dvbpsi_cat_decoder_t*)p_decoder->p_private_decoder;
int b_append = 1;
int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "CAT decoder",
"Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if(p_section->i_table_id != 0x01)
{
/* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "CAT decoder",
dvbpsi_cat_decoder_t* p_cat_decoder
= (dvbpsi_cat_decoder_t*)p_dvbpsi->p_private;
int b_append = 1;
int b_reinit = 0;
dvbpsi_debug(p_dvbpsi, "CAT decoder",
"Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if (p_section->i_table_id != 0x01)
{
/* Invalid table_id value */
dvbpsi_error(p_dvbpsi, "CAT decoder",
"invalid section (table_id == 0x%02x)",
p_section->i_table_id);
b_append = 0;
}
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_append = 0;
}
if (b_append && !p_section->b_syntax_indicator)
{
b_reinit = 1;
p_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "CAT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
else
if (b_append)
{
/* Perform some few sanity checks */
if(p_cat_decoder->p_building_cat)
{
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)
/* TS discontinuity check */
if (p_cat_decoder->b_discontinuity)
{
/* last_section_number */
dvbpsi_error(h_dvbpsi, "CAT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
b_reinit = 1;
p_cat_decoder->b_discontinuity = 0;
}
}
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))
else
{
/* Don't decode since this version is already decoded */
b_append = 0;
/* Perform some few sanity checks */
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 */
if(b_reinit)
{
/* Force redecoding */
p_cat_decoder->b_current_valid = 0;
/* Free structures */
if(p_cat_decoder->p_building_cat)
/* Reinit the decoder if wanted */
if (b_reinit)
{
free(p_cat_decoder->p_building_cat);
p_cat_decoder->p_building_cat = NULL;
}
/* Clear the section array */
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;
}
/* 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);
p_cat_decoder->p_building_cat = NULL;
}
/* Clear the section array */
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 */
if(b_append)
{
int b_complete;
/* Initialize the structures if it's the first section received */
if(!p_cat_decoder->p_building_cat)
/* Append the section to the list if wanted */
if (b_append)
{
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_InitCAT(p_cat_decoder->p_building_cat,
dvbpsi_InitCAT(p_cat_decoder->p_building_cat,
p_section->i_version,
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 */
if(p_cat_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(h_dvbpsi, "CAT decoder", "overwrite section number %d",
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;
/* Fill the section array */
if (p_cat_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(p_dvbpsi, "CAT decoder", "overwrite section number %d",
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;
/* Check if we have all the sections */
b_complete = 0;
for(unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++)
{
if(!p_cat_decoder->ap_sections[i])
break;
/* Check if we have all the sections */
for (unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++)
{
if (!p_cat_decoder->ap_sections[i])
break;
if(i == p_cat_decoder->i_last_section_number)
b_complete = 1;
}
if (i == p_cat_decoder->i_last_section_number)
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 */
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;
dvbpsi_DeletePSISections(p_section);
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_DecodeCATSections
*****************************************************************************
......@@ -356,96 +336,91 @@ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat,
dvbpsi_psi_section_t* p_section)
{
uint8_t* p_byte;
uint8_t* p_byte;
while(p_section)
{
/* CAT descriptors */
p_byte = p_section->p_payload_start;
while(p_byte + 5 <= p_section->p_payload_end)
while (p_section)
{
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;
/* 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];
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
*****************************************************************************
* 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_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor;
p_current->i_table_id = 0x01;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */
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 = 0;
p_current->p_payload_end += 8; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* CAT descriptors */
while(p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor;
p_current->i_table_id = 0x01;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */
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 = 0;
p_current->p_payload_end += 8; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* CAT descriptors */
while (p_descriptor != NULL)
{
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x01;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */
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;
/* 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;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x01;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */
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 */
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;
}
/* 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;
/* 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 @@
* Authors: Johann Hanne
* heavily based on pmt.h which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -39,7 +40,6 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_cat_t
*****************************************************************************/
......@@ -63,7 +63,6 @@ typedef struct dvbpsi_cat_s
} dvbpsi_cat_t;
/*****************************************************************************
* dvbpsi_cat_callback
*****************************************************************************/
......@@ -74,21 +73,20 @@ typedef struct dvbpsi_cat_s
*/
typedef void (* dvbpsi_cat_callback)(void* p_cb_data, dvbpsi_cat_t* p_new_cat);
/*****************************************************************************
* dvbpsi_AttachCAT
*****************************************************************************/
/*!
* \fn dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback,
void* p_cb_data)
* \fn dvbpsi_t *dvbpsi_AttachCAT(dvbpsi_t *p_dvbpsi,
dvbpsi_cat_callback pf_callback, void* p_cb_data)
* \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 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,
void* p_cb_data);
dvbpsi_t *dvbpsi_AttachCAT(dvbpsi_t *p_dvbpsi, dvbpsi_cat_callback pf_callback,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachCAT
......@@ -96,13 +94,12 @@ dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback,
/*!
* \fn void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi)
* \brief Destroy a CAT decoder.
* \param h_dvbpsi handle to the decoder
* \param p_dvbpsi handle holds the decoder pointer
* \return nothing.
*
* 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
......@@ -136,7 +133,6 @@ do { \
dvbpsi_InitCAT(p_cat, i_version, b_current_next); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyCAT/dvbpsi_DeleteCAT
*****************************************************************************/
......@@ -160,7 +156,6 @@ do { \
free(p_cat); \
} while(0);
/*****************************************************************************
* dvbpsi_CATAddDescriptor
*****************************************************************************/
......@@ -180,20 +175,19 @@ dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat,
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data);
/*****************************************************************************
* dvbpsi_GenCATSections
*****************************************************************************/
/*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat)
* \brief CAT generator
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_cat CAT structure
* \return a pointer to the list of generated PSI sections.
*
* 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
};
......
......@@ -7,6 +7,7 @@
* Authors: Johann Hanne
* heavily based on pmt_private.h which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -36,28 +37,27 @@
*****************************************************************************/
typedef struct dvbpsi_cat_decoder_s
{
dvbpsi_cat_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_cat_t current_cat;
dvbpsi_cat_t * p_building_cat;
dvbpsi_cat_callback pf_cat_callback;
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;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
} dvbpsi_cat_decoder_t;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_cat_decoder_t;
/*****************************************************************************
* dvbpsi_GatherCATSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
dvbpsi_psi_section_t* p_section);
void dvbpsi_GatherCATSections(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodeCATSections
......@@ -67,7 +67,6 @@ void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat,
dvbpsi_psi_section_t* p_section);
#else
#error "Multiple inclusions of cat_private.h"
#endif
......
......@@ -6,6 +6,7 @@
*
* Authors: Christophe Massiot <massiot@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
* modify it under the terms of the GNU Lesser General Public
......@@ -25,7 +26,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -46,113 +46,102 @@
#include "eit.h"
#include "eit_private.h"
/*****************************************************************************
* dvbpsi_AttachEIT
*****************************************************************************
* Initialize a EIT subtable decoder.
*****************************************************************************/
int dvbpsi_AttachEIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
uint16_t i_extension, dvbpsi_eit_callback pf_callback,
void* p_cb_data)
dvbpsi_t *dvbpsi_AttachEIT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
dvbpsi_eit_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_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_eit_decoder_t* p_eit_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(h_dvbpsi, "EIT decoder",
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_eit_decoder_t* p_eit_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension) != NULL)
{
dvbpsi_error(p_dvbpsi, "EIT decoder",
"Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)",
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));
if(p_subdec == NULL)
{
return 1;
}
p_eit_decoder = (dvbpsi_eit_decoder_t*)calloc(1, sizeof(dvbpsi_eit_decoder_t));
if (p_eit_decoder == NULL)
{
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)
{
free(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;
}
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* EIT decoder information */
p_eit_decoder->pf_eit_callback = pf_callback;
p_eit_decoder->p_cb_data = p_cb_data;
/* EIT decoder initial state */
p_eit_decoder->b_current_valid = 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
*****************************************************************************
* 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)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_eit_decoder_t* p_eit_decoder;
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_eit_decoder_t* p_eit_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_demux == NULL)
{
dvbpsi_error(h_dvbpsi, "EIT Decoder",
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if (p_subdec == NULL)
{
dvbpsi_error(p_dvbpsi, "EIT Decoder",
"No such EIT decoder (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, i_extension);
return;
}
p_eit_decoder = (dvbpsi_eit_decoder_t*)p_subdec->p_cb_data;
free(p_eit_decoder->p_building_eit);
return;
}
for(unsigned int i = 0; i <= 255; i++)
{
if(p_eit_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
}
p_eit_decoder = (dvbpsi_eit_decoder_t*)p_subdec->p_cb_data;
free(p_eit_decoder->p_building_eit);
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;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
pp_prev_subdec = &p_demux->p_first_subdec;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
p_subdec = NULL;
}
/*****************************************************************************
* dvbpsi_InitEIT
*****************************************************************************
......@@ -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_last_table_id)
{
p_eit->i_service_id = i_service_id;
p_eit->i_version = i_version;
p_eit->b_current_next = b_current_next;
p_eit->i_ts_id = i_ts_id;
p_eit->i_network_id = i_network_id;
p_eit->i_segment_last_section_number = i_segment_last_section_number;
p_eit->i_last_table_id = i_last_table_id;
p_eit->p_first_event = NULL;
p_eit->i_service_id = i_service_id;
p_eit->i_version = i_version;
p_eit->b_current_next = b_current_next;
p_eit->i_ts_id = i_ts_id;
p_eit->i_network_id = i_network_id;
p_eit->i_segment_last_section_number = i_segment_last_section_number;
p_eit->i_last_table_id = i_last_table_id;
p_eit->p_first_event = NULL;
}
/*****************************************************************************
* dvbpsi_EmptyEIT
*****************************************************************************
......@@ -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)
{
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)
{
dvbpsi_eit_event_t* p_tmp = p_event->p_next;
dvbpsi_DeleteDescriptors(p_event->p_first_descriptor);
free(p_event);
p_event = p_tmp;
}
p_eit->p_first_event = NULL;
while(p_event != NULL)
{
dvbpsi_eit_event_t* p_tmp = p_event->p_next;
dvbpsi_DeleteDescriptors(p_event->p_first_descriptor);
free(p_event);
p_event = p_tmp;
}
p_eit->p_first_event = NULL;
}
/*****************************************************************************
* dvbpsi_EITAddEvent
*****************************************************************************
......@@ -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,
uint8_t i_running_status,int b_free_ca)
{
dvbpsi_eit_event_t* p_event
= (dvbpsi_eit_event_t*)malloc(sizeof(dvbpsi_eit_event_t));
dvbpsi_eit_event_t* p_event;
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_start_time = i_start_time;
p_event->i_duration = i_duration;
......@@ -217,71 +203,58 @@ dvbpsi_eit_event_t* dvbpsi_EITAddEvent(dvbpsi_eit_t* p_eit,
p_event->p_next = NULL;
p_event->p_first_descriptor = NULL;
if(p_eit->p_first_event == NULL)
{
p_eit->p_first_event = p_event;
}
if (p_eit->p_first_event == NULL)
p_eit->p_first_event = p_event;
else
{
dvbpsi_eit_event_t* p_last_event = p_eit->p_first_event;
while(p_last_event->p_next != NULL)
p_last_event = p_last_event->p_next;
p_last_event->p_next = p_event;
dvbpsi_eit_event_t* p_last_event = p_eit->p_first_event;
while(p_last_event->p_next != NULL)
p_last_event = p_last_event->p_next;
p_last_event->p_next = p_event;
}
}
return p_event;
return p_event;
}
/*****************************************************************************
* dvbpsi_EITEventAddDescriptor
*****************************************************************************
* Add a descriptor in the EIT event description.
*****************************************************************************/
dvbpsi_descriptor_t* dvbpsi_EITEventAddDescriptor(
dvbpsi_eit_event_t* p_event,
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data)
dvbpsi_descriptor_t* dvbpsi_EITEventAddDescriptor( dvbpsi_eit_event_t* p_event,
uint8_t i_tag, uint8_t i_length, uint8_t* p_data)
{
dvbpsi_descriptor_t* p_descriptor
= dvbpsi_NewDescriptor(i_tag, i_length, p_data);
dvbpsi_descriptor_t* p_descriptor;
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;
}
else
{
dvbpsi_descriptor_t* p_last_descriptor = p_event->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;
dvbpsi_descriptor_t* p_last_descriptor = p_event->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;
}
/*****************************************************************************
* dvbpsi_GatherEITSections
*****************************************************************************
* Callback for the subtable demultiplexor.
*****************************************************************************/
void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
void * p_private_decoder,
dvbpsi_psi_section_t * p_section)
void dvbpsi_GatherEITSections(dvbpsi_t *p_dvbpsi, void *p_private_decoder,
dvbpsi_psi_section_t *p_section)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_eit_decoder_t* p_eit_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_private_decoder;
int b_append = 1;
int b_reinit = 0;
int b_append = 1;
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, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id,
......@@ -289,102 +262,101 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if(!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(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)
if (!p_section->b_syntax_indicator)
{
b_reinit = 1;
p_psi_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
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 */
if(p_eit_decoder->p_building_eit)
{
if(p_eit_decoder->p_building_eit->i_service_id != p_section->i_extension)
/* TS discontinuity check */
if (p_demux->b_discontinuity)
{
/* service_id */
dvbpsi_error(h_dvbpsi, "EIT decoder",
"'service_id' differs"
" whereas no TS discontinuity has occurred");
b_reinit = 1;
b_reinit = 1;
p_demux->b_discontinuity = 0;
}
else if(p_eit_decoder->p_building_eit->i_version
!= p_section->i_version)
else
{
/* version_number */
dvbpsi_error(h_dvbpsi, "EIT decoder",
"'version_number' differs"
" whereas no discontinuity has occurred");
b_reinit = 1;
/* Perform a few sanity checks */
if (p_eit_decoder->p_building_eit)
{
if (p_eit_decoder->p_building_eit->i_service_id
!= 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 */
dvbpsi_error(h_dvbpsi, "EIT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
free(p_eit_decoder->p_building_eit);
p_eit_decoder->p_building_eit = NULL;
}
}
else
{
if( (p_eit_decoder->b_current_valid)
&& (p_eit_decoder->current_eit.i_version == p_section->i_version)
&& (p_eit_decoder->current_eit.b_current_next ==
p_section->b_current_next))
/* Clear the section array */
for (unsigned int i = 0; i <= 255; i++)
{
/* Don't decode since this version is already decoded */
b_append = 0;
if(p_eit_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[i]);
p_eit_decoder->ap_sections[i] = NULL;
}
}
}
}
}
/* Reinit the decoder if wanted */
if(b_reinit)
{
/* Force redecoding */
p_eit_decoder->b_current_valid = 0;
/* Free structures */
if(p_eit_decoder->p_building_eit)
/* Append the section to the list if wanted */
if (b_append)
{
free(p_eit_decoder->p_building_eit);
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;
}
}
}
int b_complete;
/* Append the section to the list if wanted */
if(b_append)
{
int b_complete;
/* 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,
/* 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*)calloc(1, sizeof(dvbpsi_eit_t));
dvbpsi_InitEIT(p_eit_decoder->p_building_eit,
p_section->i_extension,
p_section->i_version,
p_section->b_current_next,
......@@ -394,108 +366,108 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
| p_section->p_payload_start[3],
p_section->p_payload_start[4],
p_section->p_payload_start[5]);
p_eit_decoder->i_last_section_number = p_section->i_last_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;
p_eit_decoder->i_last_section_number = p_section->i_last_number;
p_eit_decoder->i_first_received_section_number = p_section->i_number;
}
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;
break;
dvbpsi_debug(p_dvbpsi, "EIT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_eit_decoder->ap_sections[p_section->i_number]);
}
/* 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])
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))
{
while(!p_eit_decoder->ap_sections[i + 1] &&
(i + 1 < p_eit_decoder->i_last_section_number))
{
i++;
}
for (unsigned int i = 0; i <= p_eit_decoder->i_last_section_number; i++)
{
if (!p_eit_decoder->ap_sections[i])
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)
{
/* 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 (b_complete)
{
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];
}
/* 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)
{
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
{
dvbpsi_DeletePSISections(p_section);
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_DecodeEITSections
*****************************************************************************
......@@ -504,39 +476,38 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t * p_psi_decoder,
void dvbpsi_DecodeEITSections(dvbpsi_eit_t* p_eit,
dvbpsi_psi_section_t* p_section)
{
uint8_t* p_byte, * p_end;
uint8_t* p_byte, * p_end;
while(p_section)
{
for(p_byte = p_section->p_payload_start + 6;
p_byte < p_section->p_payload_end - 12;)
while (p_section)
{
uint16_t i_event_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1];
uint64_t i_start_time = ((uint64_t)(p_byte[2]) << 32)
| ((uint64_t)(p_byte[3]) << 24)
| ((uint64_t)(p_byte[4]) << 16)
| ((uint64_t)(p_byte[5]) << 8) | p_byte[6];
uint32_t i_duration = ((uint32_t)(p_byte[7]) << 16)
| ((uint32_t)(p_byte[8]) << 8) | p_byte[9];
uint8_t i_running_status = (uint8_t)(p_byte[10]) >> 5;
int b_free_ca = (int)(p_byte[10] & 0x10) >> 4;
uint16_t i_ev_length = ((uint16_t)(p_byte[10] & 0xf) << 8) | p_byte[11];
dvbpsi_eit_event_t* p_event = dvbpsi_EITAddEvent(p_eit,
i_event_id, i_start_time, i_duration,
i_running_status, b_free_ca);
/* Event descriptors */
p_byte += 12;
p_end = p_byte + i_ev_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_EITEventAddDescriptor(p_event, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
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];
uint64_t i_start_time = ((uint64_t)(p_byte[2]) << 32)
| ((uint64_t)(p_byte[3]) << 24)
| ((uint64_t)(p_byte[4]) << 16)
| ((uint64_t)(p_byte[5]) << 8) | p_byte[6];
uint32_t i_duration = ((uint32_t)(p_byte[7]) << 16)
| ((uint32_t)(p_byte[8]) << 8) | p_byte[9];
uint8_t i_running_status = (uint8_t)(p_byte[10]) >> 5;
int b_free_ca = (int)(p_byte[10] & 0x10) >> 4;
uint16_t i_ev_length = ((uint16_t)(p_byte[10] & 0xf) << 8) | p_byte[11];
dvbpsi_eit_event_t* p_event = dvbpsi_EITAddEvent(p_eit,
i_event_id, i_start_time, i_duration,
i_running_status, b_free_ca);
/* Event descriptors */
p_byte += 12;
p_end = p_byte + i_ev_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_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 @@
* $Id: eit.h 88 2004-02-24 14:31:18Z sam $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -37,7 +38,6 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_eit_event_t
*****************************************************************************/
......@@ -70,7 +70,6 @@ typedef struct dvbpsi_eit_event_s
} dvbpsi_eit_event_t;
/*****************************************************************************
* dvbpsi_eit_t
*****************************************************************************/
......@@ -99,7 +98,6 @@ typedef struct dvbpsi_eit_s
} dvbpsi_eit_t;
/*****************************************************************************
* dvbpsi_eit_callback
*****************************************************************************/
......@@ -110,27 +108,25 @@ typedef struct dvbpsi_eit_s
*/
typedef void (* dvbpsi_eit_callback)(void* p_cb_data, dvbpsi_eit_t* p_new_eit);
/*****************************************************************************
* 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,
void* p_cb_data)
* \brief Creation and initialization of a EIT decoder.
* \param p_demux Subtable demultiplexor to which the decoder is attached.
* \param p_dvbpsi pointer to Subtable demultiplexor to which the EIT decoder is attached.
* \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
* \param i_extension Table ID extension, here service ID.
* \param pf_callback function to call back on new EIT.
* \param p_cb_data private data given in argument to the callback.
* \return 0 if everything went ok.
* \return 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,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachEIT
*****************************************************************************/
......@@ -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,
uint16_t i_extension)
* \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_extension Table ID extension, here service ID.
* \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);
/*****************************************************************************
* dvbpsi_InitEIT/dvbpsi_NewEIT
*****************************************************************************/
......@@ -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); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyEIT/dvbpsi_DeleteEIT
*****************************************************************************/
......@@ -212,7 +207,6 @@ do { \
free(p_eit); \
} while(0);
/*****************************************************************************
* dvbpsi_EITAddEvent
*****************************************************************************/
......
......@@ -5,6 +5,7 @@
* $Id: eit_private.h 88 2004-02-24 14:31:18Z sam $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -27,7 +28,6 @@
#ifndef _DVBPSI_EIT_PRIVATE_H_
#define _DVBPSI_EIT_PRIVATE_H_
/*****************************************************************************
* dvbpsi_eit_decoder_t
*****************************************************************************
......@@ -35,31 +35,31 @@
*****************************************************************************/
typedef struct dvbpsi_eit_decoder_s
{
dvbpsi_eit_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_eit_t current_eit;
dvbpsi_eit_t * p_building_eit;
dvbpsi_eit_callback pf_eit_callback;
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;
uint8_t i_first_received_section_number;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
} 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
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherEITSections(dvbpsi_decoder_t* p_psi_decoder,
void* p_private_decoder,
void dvbpsi_GatherEITSections(dvbpsi_t* p_dvbpsi,
void* p_private_decoder,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodeEITSection
*****************************************************************************
......@@ -68,7 +68,6 @@ void dvbpsi_GatherEITSections(dvbpsi_decoder_t* p_psi_decoder,
void dvbpsi_DecodeEITSections(dvbpsi_eit_t* p_eit,
dvbpsi_psi_section_t* p_section);
#else
#error "Multiple inclusions of eit_private.h"
#endif
......
......@@ -7,6 +7,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -26,7 +27,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -47,114 +47,104 @@
#include "nit.h"
#include "nit_private.h"
/*****************************************************************************
* dvbpsi_AttachNIT
*****************************************************************************
* 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,
void* p_cb_data)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_nit_decoder_t* p_nit_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(h_dvbpsi, "NIT decoder",
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_nit_decoder_t* p_nit_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(p_dvbpsi, "NIT decoder",
"Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, i_extension);
return 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_nit_decoder = (dvbpsi_nit_decoder_t*)calloc(1, sizeof(dvbpsi_nit_decoder_t));
if (p_nit_decoder == NULL)
{
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)
{
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;
return 0;
}
/*****************************************************************************
* dvbpsi_DetachNIT
*****************************************************************************
* 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)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_nit_decoder_t* p_nit_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_nit_decoder_t* p_nit_decoder;
if(p_demux == NULL)
{
dvbpsi_error(h_dvbpsi, "NIT Decoder",
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if(p_demux == NULL)
{
dvbpsi_error(p_dvbpsi, "NIT Decoder",
"No such NIT decoder (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, i_extension);
return;
}
p_nit_decoder = (dvbpsi_nit_decoder_t*)p_subdec->p_cb_data;
free(p_nit_decoder->p_building_nit);
return;
}
for(unsigned int i = 0; i <= 255; i++)
{
if(p_nit_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[i]);
}
p_nit_decoder = (dvbpsi_nit_decoder_t*)p_subdec->p_cb_data;
free(p_nit_decoder->p_building_nit);
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;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
pp_prev_subdec = &p_demux->p_first_subdec;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
p_subdec = NULL;
}
/*****************************************************************************
* dvbpsi_InitNIT
*****************************************************************************
......@@ -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,
uint8_t i_version, int b_current_next)
{
p_nit->i_network_id = i_network_id;
p_nit->i_version = i_version;
p_nit->b_current_next = b_current_next;
p_nit->p_first_descriptor = NULL;
p_nit->p_first_ts = NULL;
p_nit->i_network_id = i_network_id;
p_nit->i_version = i_version;
p_nit->b_current_next = b_current_next;
p_nit->p_first_descriptor = NULL;
p_nit->p_first_ts = NULL;
}
/*****************************************************************************
* dvbpsi_EmptyNIT
*****************************************************************************
......@@ -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)
{
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)
{
dvbpsi_nit_ts_t* p_tmp = p_ts->p_next;
dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor);
free(p_ts);
p_ts = p_tmp;
}
while (p_ts != NULL)
{
dvbpsi_nit_ts_t* p_tmp = p_ts->p_next;
dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor);
free(p_ts);
p_ts = p_tmp;
}
p_nit->p_first_descriptor = NULL;
p_nit->p_first_ts = NULL;
p_nit->p_first_descriptor = NULL;
p_nit->p_first_ts = NULL;
}
/*****************************************************************************
* dvbpsi_NITAddDescriptor
*****************************************************************************
......@@ -204,28 +192,23 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
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);
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
{
dvbpsi_descriptor_t* p_last_descriptor = p_nit->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;
dvbpsi_descriptor_t* p_last_descriptor = p_nit->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;
}
/*****************************************************************************
* dvbpsi_NITAddTS
*****************************************************************************
......@@ -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,
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_orig_network_id = i_orig_network_id;
p_ts->p_first_descriptor = NULL;
p_ts->p_next = NULL;
if(p_nit->p_first_ts == NULL)
{
p_nit->p_first_ts = p_ts;
}
if (p_nit->p_first_ts == NULL)
p_nit->p_first_ts = p_ts;
else
{
dvbpsi_nit_ts_t* p_last_ts = p_nit->p_first_ts;
while(p_last_ts->p_next != NULL)
p_last_ts = p_last_ts->p_next;
p_last_ts->p_next = p_ts;
dvbpsi_nit_ts_t* p_last_ts = p_nit->p_first_ts;
while(p_last_ts->p_next != NULL)
p_last_ts = p_last_ts->p_next;
p_last_ts->p_next = p_ts;
}
}
return p_ts;
return p_ts;
}
/*****************************************************************************
* dvbpsi_NITTSAddDescriptor
*****************************************************************************
......@@ -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* p_data)
{
dvbpsi_descriptor_t* p_descriptor
dvbpsi_descriptor_t* p_descriptor
= 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;
}
else
{
dvbpsi_descriptor_t* p_last_descriptor = p_ts->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;
dvbpsi_descriptor_t* p_last_descriptor = p_ts->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;
}
/*****************************************************************************
* dvbpsi_GatherNITSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherNITSections(dvbpsi_decoder_t * p_decoder,
void dvbpsi_GatherNITSections(dvbpsi_t *p_dvbpsi,
void * p_private_decoder,
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;
int b_append = 1;
int b_reinit = 0;
int b_append = 1;
int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "NIT decoder",
dvbpsi_debug(p_dvbpsi, "NIT decoder",
"Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if(p_section->i_table_id != 0x40 && p_section->i_table_id != 0x41)
{
/* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "NIT decoder",
if (p_section->i_table_id != 0x40 && p_section->i_table_id != 0x41)
{
/* Invalid table_id value */
dvbpsi_error(p_dvbpsi, "NIT decoder",
"invalid section (table_id == 0x%02x)",
p_section->i_table_id);
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;
}
b_append = 0;
}
if(b_append)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
if (b_append && !p_section->b_syntax_indicator)
{
b_reinit = 1;
p_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
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 */
if(p_nit_decoder->p_building_nit)
{
if(p_nit_decoder->p_building_nit->i_version != p_section->i_version)
/* Invalid program_number */
dvbpsi_error(p_dvbpsi, "NIT decoder", "'network_id' don't match");
b_append = 0;
}
if (b_append)
{
/* TS discontinuity check */
if (p_nit_decoder->b_discontinuity)
{
/* version_number */
dvbpsi_error(h_dvbpsi, "NIT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
b_reinit = 1;
p_nit_decoder->b_discontinuity = 0;
}
else if(p_nit_decoder->i_last_section_number
!= p_section->i_last_number)
else
{
/* last_section_number */
dvbpsi_error(h_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 ==
/* Perform some few sanity checks */
if (p_nit_decoder->p_building_nit)
{
if (p_nit_decoder->p_building_nit->i_version != p_section->i_version)
{
/* version_number */
dvbpsi_error(p_dvbpsi, "NIT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
}
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))
{
/* Don't decode since this version is already decoded */
b_append = 0;
{
/* Don't decode since this version is already decoded */
b_append = 0;
}
}
}
}
}
}
/* Reinit the decoder if wanted */
if(b_reinit)
{
/* Force redecoding */
p_nit_decoder->b_current_valid = 0;
/* Free structures */
if(p_nit_decoder->p_building_nit)
/* Reinit the decoder if wanted */
if (b_reinit)
{
free(p_nit_decoder->p_building_nit);
p_nit_decoder->p_building_nit = NULL;
}
/* Clear the section array */
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;
}
/* 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);
p_nit_decoder->p_building_nit = NULL;
}
/* Clear the section array */
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 */
if(b_append)
{
int b_complete;
/* Initialize the structures if it's the first section received */
if(!p_nit_decoder->p_building_nit)
/* Append the section to the list if wanted */
if (b_append)
{
p_nit_decoder->p_building_nit =
(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;
}
int b_complete;
/* Fill the section array */
if(p_nit_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(h_dvbpsi, "NIT decoder", "overwrite section number %d",
p_section->i_number);
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[p_section->i_number]);
}
p_nit_decoder->ap_sections[p_section->i_number] = p_section;
/* Initialize the structures if it's the first section received */
if (!p_nit_decoder->p_building_nit)
{
p_nit_decoder->p_building_nit = (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;
}
/* Check if we have all the sections */
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;
/* Fill the section array */
if (p_nit_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(p_dvbpsi, "NIT decoder", "overwrite section number %d",
p_section->i_number);
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)
b_complete = 1;
}
/* Check if we have all the sections */
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)
{
/* Save the current information */
p_nit_decoder->current_nit = *p_nit_decoder->p_building_nit;
p_nit_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_nit_decoder->i_last_section_number)
{
for(unsigned int i = 0; (int)i <= p_nit_decoder->i_last_section_number - 1; i++)
p_nit_decoder->ap_sections[i]->p_next =
if (b_complete)
{
/* Save the current information */
p_nit_decoder->current_nit = *p_nit_decoder->p_building_nit;
p_nit_decoder->b_current_valid = 1;
/* Chain the sections */
if (p_nit_decoder->i_last_section_number)
{
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 + 1];
}
/* Decode the sections */
dvbpsi_DecodeNITSections(p_nit_decoder->p_building_nit,
p_nit_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[0]);
/* signal the new NIT */
p_nit_decoder->pf_callback(p_nit_decoder->p_cb_data,
p_nit_decoder->p_building_nit);
/* Reinitialize the structures */
p_nit_decoder->p_building_nit = NULL;
for(unsigned int i = 0; i <= p_nit_decoder->i_last_section_number; i++)
p_nit_decoder->ap_sections[i] = NULL;
}
/* Decode the sections */
dvbpsi_DecodeNITSections(p_dvbpsi, p_nit_decoder->p_building_nit,
p_nit_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[0]);
/* signal the new NIT */
p_nit_decoder->pf_nit_callback(p_nit_decoder->p_cb_data,
p_nit_decoder->p_building_nit);
/* Reinitialize the structures */
p_nit_decoder->p_building_nit = NULL;
for (unsigned int i = 0; i <= p_nit_decoder->i_last_section_number; i++)
p_nit_decoder->ap_sections[i] = NULL;
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_DecodeNITSections
*****************************************************************************
* 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)
{
uint8_t* p_byte, * p_end, * p_end2;
uint8_t* p_byte, * p_end, * p_end2;
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)
while (p_section)
{
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;
}
/* - 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]);
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]);
if(p_end > p_section->p_payload_end)
{
p_end = p_section->p_payload_end;
}
p_byte += 2;
if (p_end > p_section->p_payload_end)
{
p_end = p_section->p_payload_end;
}
p_byte += 2;
/* - TSs */
for(; p_byte + 6 <= p_end;)
{
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_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);
/* - TS descriptors */
p_byte += 6;
p_end2 = p_byte + i_ts_length;
if( p_end2 > p_section->p_payload_end )
{
p_end2 = p_section->p_payload_end;
}
while(p_byte + 2 <= p_end2)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if(i_length + 2 <= p_end2 - p_byte)
dvbpsi_NITTSAddDescriptor(p_ts, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
/* - TSs */
for (; p_byte + 6 <= p_end;)
{
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_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);
/* - TS descriptors */
p_byte += 6;
p_end2 = p_byte + i_ts_length;
if ( p_end2 > p_section->p_payload_end )
{
p_end2 = p_section->p_payload_end;
}
while (p_byte + 2 <= p_end2)
{
uint8_t i_tag = p_byte[0];
uint8_t i_length = p_byte[1];
if (i_length + 2 <= p_end2 - p_byte)
dvbpsi_NITTSAddDescriptor(p_ts, 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_GenNITSections
*****************************************************************************
* Generate NIT sections based on the dvbpsi_nit_t structure.
*****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit,
uint8_t i_table_id)
dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_t *p_dvbpsi,
dvbpsi_nit_t* p_nit, uint8_t i_table_id)
{
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_nit->p_first_descriptor;
dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
uint16_t i_network_descriptors_length, i_transport_stream_loop_length;
uint8_t * p_transport_stream_loop_length;
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 = 0;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* NIT descriptors */
while(p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_nit->p_first_descriptor;
dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
uint16_t i_network_descriptors_length, i_transport_stream_loop_length;
uint8_t * p_transport_stream_loop_length;
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 = 0;
p_current->p_payload_end += 10;
p_current->p_payload_start = p_current->p_data + 8;
/* NIT descriptors */
while (p_descriptor != NULL)
{
/* 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;
/* transport_stream_loop_length */
p_current->p_payload_end[0] = 0;
p_current->p_payload_end[1] = 0;
p_current->p_payload_end += 2;
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
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;
}
/* 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 */
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;
/* transport_stream_loop_length */
p_current->p_payload_end[0] = 0;
p_current->p_payload_end[1] = 0;
p_current->p_payload_end += 2;
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
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;
}
/* 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;
}
/* 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;
/* 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 _no_ and the current section isn't empty and an empty section
may carry one more descriptor
then create a new section */
if( (p_descriptor != NULL)
&& (p_ts_start - p_current->p_data != 12)
&& (i_ts_length <= 1008))
/* 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)
{
/* 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, "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;
}
uint8_t* p_ts_start = p_current->p_payload_end;
uint16_t i_ts_length = 5;
/* 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;
/* 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;
}
/* Increase the length by 6 */
p_current->p_payload_end += 6;
p_current->i_length += 6;
/* If _no_ and the current section isn't empty and an empty section
may carry one more descriptor
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 */
p_descriptor = p_ts->p_first_descriptor;
while( (p_descriptor != NULL)
/* 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;
}
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_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_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
#if 0 /* FIXME: */
if(p_descriptor != NULL)
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;
return p_result;
}
......@@ -6,6 +6,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -39,7 +40,6 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_nit_ts_t
*****************************************************************************/
......@@ -66,7 +66,6 @@ typedef struct dvbpsi_nit_ts_s
} dvbpsi_nit_ts_t;
/*****************************************************************************
* dvbpsi_nit_t
*****************************************************************************/
......@@ -93,7 +92,6 @@ typedef struct dvbpsi_nit_s
} dvbpsi_nit_t;
/*****************************************************************************
* dvbpsi_nit_callback
*****************************************************************************/
......@@ -104,27 +102,25 @@ typedef struct dvbpsi_nit_s
*/
typedef void (* dvbpsi_nit_callback)(void* p_cb_data, dvbpsi_nit_t* p_new_nit);
/*****************************************************************************
* 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,
void* p_cb_data)
* \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_extension Table ID extension, here service ID.
* \param pf_callback function to call back on new NIT.
* \param p_cb_data private data given in argument to the callback.
* \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,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachNIT
*****************************************************************************/
......@@ -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,
uint16_t i_extension)
* \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_extension Table ID extension, here service ID.
* \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);
/*****************************************************************************
* dvbpsi_InitNIT/dvbpsi_NewNIT
*****************************************************************************/
......@@ -176,7 +171,6 @@ do { \
dvbpsi_InitNIT(p_nit, i_network_id, i_version, b_current_next); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyNIT/dvbpsi_DeleteNIT
*****************************************************************************/
......@@ -200,7 +194,6 @@ do { \
free(p_nit); \
} while(0);
/*****************************************************************************
* dvbpsi_NITAddDescriptor
*****************************************************************************/
......@@ -220,7 +213,6 @@ dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data);
/*****************************************************************************
* dvbpsi_NITAddTS
*****************************************************************************/
......@@ -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,
uint16_t i_ts_id, uint16_t i_orig_network_id);
/*****************************************************************************
* dvbpsi_NITTSAddDescriptor
*****************************************************************************/
......@@ -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* p_data);
/*****************************************************************************
* dvbpsi_GenNITSections
*****************************************************************************/
......@@ -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,
uint8_t i_table_id)
* \brief NIT generator
* \parma p_dvbpsi dvbpsi handle
* \param p_nit NIT structure
* \param i_table_id table id, 0x40 = actual network / 0x41 = other network
* \return a pointer to the list of generated PSI sections.
*
* 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);
#ifdef __cplusplus
};
#endif
......
......@@ -7,6 +7,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -36,41 +37,40 @@
*****************************************************************************/
typedef struct dvbpsi_nit_decoder_s
{
uint16_t i_network_id;
DVBPSI_DECODER_COMMON
dvbpsi_nit_callback pf_callback;
void * p_cb_data;
uint16_t i_network_id;
dvbpsi_nit_t current_nit;
dvbpsi_nit_t * p_building_nit;
dvbpsi_nit_callback pf_nit_callback;
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;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
} dvbpsi_nit_decoder_t;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_nit_decoder_t;
/*****************************************************************************
* dvbpsi_GatherNITSections
*****************************************************************************
* 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,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodeNITSections
*****************************************************************************
* 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);
#else
#error "Multiple inclusions of nit_private.h"
#endif
......
......@@ -5,6 +5,7 @@
* $Id$
*
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -24,7 +25,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -36,54 +36,50 @@
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
#include "pat.h"
#include "pat_private.h"
/*****************************************************************************
* dvbpsi_AttachPAT
*****************************************************************************
* Initialize a PAT decoder and return a handle on it.
*****************************************************************************/
dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback,
void* p_cb_data)
dvbpsi_t *dvbpsi_AttachPAT(dvbpsi_t *p_dvbpsi, dvbpsi_pat_callback pf_callback,
void* p_cb_data)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t));
dvbpsi_pat_decoder_t* p_pat_decoder;
assert(p_dvbpsi);
if(h_dvbpsi == NULL)
return NULL;
dvbpsi_pat_decoder_t* p_pat_decoder = (dvbpsi_pat_decoder_t*) calloc(1, sizeof(dvbpsi_pat_decoder_t));
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)
{
free(h_dvbpsi);
return NULL;
}
/* PSI decoder initial state */
p_pat_decoder->i_continuity_counter = 31;
p_pat_decoder->b_discontinuity = 1;
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 */
h_dvbpsi->pf_callback = &dvbpsi_GatherPATSections;
h_dvbpsi->p_private_decoder = p_pat_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;
/* 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;
for(unsigned int i = 0; i <= 255; i++)
p_pat_decoder->ap_sections[i] = NULL;
p_dvbpsi->p_private = (void *)p_pat_decoder;
return p_dvbpsi;
}
......@@ -92,23 +88,21 @@ dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback,
*****************************************************************************
* 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*)h_dvbpsi->p_private_decoder;
dvbpsi_pat_decoder_t* p_pat_decoder = (dvbpsi_pat_decoder_t*)p_dvbpsi->p_private;
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->ap_sections[i])
free(p_pat_decoder->ap_sections[i]);
}
if (p_pat_decoder->p_current_section)
dvbpsi_DeletePSISections(p_pat_decoder->p_current_section);
free(p_pat_decoder);
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)
void dvbpsi_InitPAT(dvbpsi_pat_t* p_pat, uint16_t i_ts_id, uint8_t i_version,
int b_current_next)
{
p_pat->i_ts_id = i_ts_id;
p_pat->i_version = i_version;
p_pat->b_current_next = b_current_next;
p_pat->p_first_program = NULL;
p_pat->i_ts_id = i_ts_id;
p_pat->i_version = i_version;
p_pat->b_current_next = b_current_next;
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,
*****************************************************************************/
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)
{
dvbpsi_pat_program_t* p_tmp = p_program->p_next;
free(p_program);
p_program = p_tmp;
}
p_pat->p_first_program = NULL;
while(p_program != NULL)
{
dvbpsi_pat_program_t* p_tmp = p_program->p_next;
free(p_program);
p_program = p_tmp;
}
p_pat->p_first_program = NULL;
}
......@@ -155,29 +148,27 @@ void dvbpsi_EmptyPAT(dvbpsi_pat_t* p_pat)
dvbpsi_pat_program_t* dvbpsi_PATAddProgram(dvbpsi_pat_t* p_pat,
uint16_t i_number, uint16_t i_pid)
{
dvbpsi_pat_program_t* p_program
= (dvbpsi_pat_program_t*)malloc(sizeof(dvbpsi_pat_program_t));
dvbpsi_pat_program_t* p_program;
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_pid = i_pid;
p_program->p_next = NULL;
if(p_pat->p_first_program == NULL)
{
p_pat->p_first_program = p_program;
}
if (p_pat->p_first_program == NULL)
p_pat->p_first_program = p_program;
else
{
dvbpsi_pat_program_t* p_last_program = p_pat->p_first_program;
while(p_last_program->p_next != NULL)
p_last_program = p_last_program->p_next;
p_last_program->p_next = p_program;
dvbpsi_pat_program_t* p_last_program = p_pat->p_first_program;
while (p_last_program->p_next != NULL)
p_last_program = p_last_program->p_next;
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,
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
dvbpsi_psi_section_t* p_section)
void dvbpsi_GatherPATSections(dvbpsi_t* p_dvbpsi, 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_decoder->p_private_decoder;
dvbpsi_pat_decoder_t* p_pat_decoder;
int b_append = 1;
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, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
p_pat_decoder = (dvbpsi_pat_decoder_t *)p_dvbpsi->p_private;
if(p_section->i_table_id != 0x00)
{
/* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "PAT decoder",
dvbpsi_error(p_dvbpsi, "PAT decoder",
"invalid section (table_id == 0x%02x)",
p_section->i_table_id);
b_append = 0;
......@@ -214,7 +206,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
if(b_append && !p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "PAT decoder",
dvbpsi_error(p_dvbpsi, "PAT decoder",
"invalid section (section_syntax_indicator == 0)");
b_append = 0;
}
......@@ -223,10 +215,10 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
if(b_append)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
if(p_pat_decoder->b_discontinuity)
{
b_reinit = 1;
p_decoder->b_discontinuity = 0;
p_pat_decoder->b_discontinuity = 0;
}
else
{
......@@ -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)
{
/* transport_stream_id */
dvbpsi_error(h_dvbpsi, "PAT decoder",
dvbpsi_error(p_dvbpsi, "PAT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
......@@ -245,7 +237,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
!= p_section->i_version)
{
/* version_number */
dvbpsi_error(h_dvbpsi, "PAT decoder",
dvbpsi_error(p_dvbpsi, "PAT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
......@@ -254,7 +246,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
p_section->i_last_number)
{
/* last_section_number */
dvbpsi_error(h_dvbpsi, "PAT decoder",
dvbpsi_error(p_dvbpsi, "PAT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
......@@ -316,7 +308,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
/* Fill the section array */
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);
dvbpsi_DeletePSISections(p_pat_decoder->ap_sections[p_section->i_number]);
}
......@@ -351,7 +343,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
/* Delete the sections */
dvbpsi_DeletePSISections(p_pat_decoder->ap_sections[0]);
/* 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);
/* Reinitialize the structures */
p_pat_decoder->p_building_pat = NULL;
......@@ -372,7 +364,7 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
* PAT decoder.
*****************************************************************************/
void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat,
dvbpsi_psi_section_t* p_section)
dvbpsi_psi_section_t* p_section)
{
while(p_section)
{
......@@ -396,8 +388,8 @@ void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat,
* Generate PAT sections based on the dvbpsi_pat_t structure. The third
* argument is used to limit the number of program in each section (max: 253).
*****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
int i_max_pps)
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_t *p_dvbpsi,
dvbpsi_pat_t* p_pat, int i_max_pps)
{
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result;
......@@ -467,4 +459,3 @@ dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
return p_result;
}
......@@ -103,29 +103,29 @@ typedef void (* dvbpsi_pat_callback)(void* p_cb_data, dvbpsi_pat_t* p_new_pat);
* dvbpsi_AttachPAT
*****************************************************************************/
/*!
* \fn dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback,
void* p_cb_data)
* \fn dvbpsi_t *dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback, void* p_cb_data)
* \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 p_cb_data private data given in argument to the callback
* \return a pointer to the decoder for future calls.
*/
dvbpsi_handle dvbpsi_AttachPAT(dvbpsi_pat_callback pf_callback,
void* p_cb_data);
dvbpsi_t *dvbpsi_AttachPAT(dvbpsi_t *p_dvbpsi, dvbpsi_pat_callback pf_callback,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachPAT
*****************************************************************************/
/*!
* \fn void dvbpsi_DetachPAT(dvbpsi_handle h_dvbpsi)
* \fn void dvbpsi_DetachPAT(dvbpsi_t *p_dvbpsi)
* \brief Destroy a PAT decoder.
* \param h_dvbpsi handle to the decoder
* \param p_dvbpsi pointer to dvbpsi_t handle
* \return nothing.
*
* 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,
* \fn dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
int i_max_pps);
* \brief PAT generator.
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_pat pointer to the PAT structure
* \param i_max_pps limitation of the number of program in each section
* (max: 253).
......@@ -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.
*/
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
int i_max_pps);
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_t *p_dvbpsi,
dvbpsi_pat_t* p_pat, int i_max_pps);
#ifdef __cplusplus
};
......
......@@ -35,16 +35,18 @@
*****************************************************************************/
typedef struct dvbpsi_pat_decoder_s
{
dvbpsi_pat_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_pat_t current_pat;
dvbpsi_pat_t * p_building_pat;
dvbpsi_pat_callback pf_pat_callback;
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;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_pat_decoder_t;
......@@ -54,9 +56,7 @@ typedef struct dvbpsi_pat_decoder_s
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
dvbpsi_psi_section_t* p_section);
void dvbpsi_GatherPATSections(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodePATSection
......@@ -66,7 +66,6 @@ void dvbpsi_GatherPATSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodePATSections(dvbpsi_pat_t* p_pat,
dvbpsi_psi_section_t* p_section);
#else
#error "Multiple inclusions of pat_private.h"
#endif
......
......@@ -5,6 +5,7 @@
* $Id$
*
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -24,7 +25,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -37,6 +37,8 @@
#include <stdint.h>
#endif
#include <assert.h>
#include "../dvbpsi.h"
#include "../dvbpsi_private.h"
#include "../psi.h"
......@@ -44,78 +46,69 @@
#include "pmt.h"
#include "pmt_private.h"
/*****************************************************************************
* dvbpsi_AttachPMT
*****************************************************************************
* 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,
void* p_cb_data)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t));
dvbpsi_pmt_decoder_t* p_pmt_decoder;
if(h_dvbpsi == NULL)
return NULL;
p_pmt_decoder = (dvbpsi_pmt_decoder_t*)malloc(sizeof(dvbpsi_pmt_decoder_t));
if(p_pmt_decoder == NULL)
{
free(h_dvbpsi);
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;
}
dvbpsi_pmt_decoder_t* p_pmt_decoder;
p_pmt_decoder = (dvbpsi_pmt_decoder_t*)malloc(sizeof(dvbpsi_pmt_decoder_t));
if (p_pmt_decoder == NULL)
return NULL;
p_dvbpsi->p_private = (void *)p_pmt_decoder;
/* PSI decoder configuration */
p_pmt_decoder->pf_callback = &dvbpsi_GatherPMTSections;
p_pmt_decoder->i_section_max_size = 1024;
/* 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
*****************************************************************************
* 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*)h_dvbpsi->p_private_decoder;
free(p_pmt_decoder->p_building_pmt);
dvbpsi_pmt_decoder_t* p_pmt_decoder
= (dvbpsi_pmt_decoder_t*)p_dvbpsi->p_private;
free(p_pmt_decoder->p_building_pmt);
for(unsigned int i = 0; i <= 255; i++)
{
if(p_pmt_decoder->ap_sections[i])
free(p_pmt_decoder->ap_sections[i]);
}
for (unsigned int i = 0; i <= 255; i++)
{
if (p_pmt_decoder->ap_sections[i])
free(p_pmt_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);
if (p_pmt_decoder->p_current_section)
dvbpsi_DeletePSISections(p_pmt_decoder->p_current_section);
free(p_pmt_decoder);
p_dvbpsi->p_private = NULL;
}
/*****************************************************************************
* dvbpsi_InitPMT
*****************************************************************************
......@@ -124,15 +117,14 @@ void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi)
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)
{
p_pmt->i_program_number = i_program_number;
p_pmt->i_version = i_version;
p_pmt->b_current_next = b_current_next;
p_pmt->i_pcr_pid = i_pcr_pid;
p_pmt->p_first_descriptor = NULL;
p_pmt->p_first_es = NULL;
p_pmt->i_program_number = i_program_number;
p_pmt->i_version = i_version;
p_pmt->b_current_next = b_current_next;
p_pmt->i_pcr_pid = i_pcr_pid;
p_pmt->p_first_descriptor = NULL;
p_pmt->p_first_es = NULL;
}
/*****************************************************************************
* dvbpsi_EmptyPMT
*****************************************************************************
......@@ -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)
{
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)
{
dvbpsi_pmt_es_t* p_tmp = p_es->p_next;
dvbpsi_DeleteDescriptors(p_es->p_first_descriptor);
free(p_es);
p_es = p_tmp;
}
while(p_es != NULL)
{
dvbpsi_pmt_es_t* p_tmp = p_es->p_next;
dvbpsi_DeleteDescriptors(p_es->p_first_descriptor);
free(p_es);
p_es = p_tmp;
}
p_pmt->p_first_descriptor = NULL;
p_pmt->p_first_es = NULL;
p_pmt->p_first_descriptor = NULL;
p_pmt->p_first_es = NULL;
}
/*****************************************************************************
* dvbpsi_PMTAddDescriptor
*****************************************************************************
......@@ -166,28 +157,23 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt,
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data)
{
dvbpsi_descriptor_t* p_descriptor
= dvbpsi_NewDescriptor(i_tag, i_length, p_data);
dvbpsi_descriptor_t* p_descriptor;
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
{
dvbpsi_descriptor_t* p_last_descriptor = p_pmt->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;
dvbpsi_descriptor_t* p_last_descriptor = p_pmt->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;
}
/*****************************************************************************
* dvbpsi_PMTAddES
*****************************************************************************
......@@ -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,
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_pid = i_pid;
p_es->p_first_descriptor = NULL;
p_es->p_next = NULL;
if(p_pmt->p_first_es == NULL)
{
p_pmt->p_first_es = p_es;
}
if (p_pmt->p_first_es == NULL)
p_pmt->p_first_es = p_es;
else
{
dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es;
while(p_last_es->p_next != NULL)
p_last_es = p_last_es->p_next;
p_last_es->p_next = p_es;
dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es;
while (p_last_es->p_next != NULL)
p_last_es = p_last_es->p_next;
p_last_es->p_next = p_es;
}
}
return p_es;
return p_es;
}
/*****************************************************************************
* dvbpsi_PMTESAddDescriptor
*****************************************************************************
......@@ -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* p_data)
{
dvbpsi_descriptor_t* p_descriptor
= dvbpsi_NewDescriptor(i_tag, i_length, p_data);
dvbpsi_descriptor_t* p_descriptor;
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
{
dvbpsi_descriptor_t* p_last_descriptor = p_es->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;
dvbpsi_descriptor_t* p_last_descriptor = p_es->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;
}
/*****************************************************************************
* dvbpsi_GatherPMTSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder,
dvbpsi_psi_section_t* p_section)
void dvbpsi_GatherPMTSections(dvbpsi_t *p_dvbpsi, 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_decoder->p_private_decoder;
int b_append = 1;
int b_reinit = 0;
dvbpsi_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t*)p_dvbpsi->p_private;
assert(p_pmt_decoder);
int b_append = 1;
int b_reinit = 0;
dvbpsi_debug(h_dvbpsi, "PMT decoder",
dvbpsi_debug(p_dvbpsi, "PMT decoder",
"Table version %2d, " "i_extension %5d, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_extension,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if(p_section->i_table_id != 0x02)
{
/* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "PMT decoder",
if (p_section->i_table_id != 0x02)
{
/* Invalid table_id value */
dvbpsi_error(p_dvbpsi, "PMT decoder",
"invalid section (table_id == 0x%02x)",
p_section->i_table_id);
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;
}
b_append = 0;
}
if(b_append)
{
/* TS discontinuity check */
if(p_decoder->b_discontinuity)
if (b_append && !p_section->b_syntax_indicator)
{
b_reinit = 1;
p_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
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 */
if(p_pmt_decoder->p_building_pmt)
{
if(p_pmt_decoder->p_building_pmt->i_version != p_section->i_version)
/* TS discontinuity check */
if (p_pmt_decoder->b_discontinuity)
{
/* version_number */
dvbpsi_error(h_dvbpsi, "PMT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
b_reinit = 1;
p_pmt_decoder->b_discontinuity = 0;
}
else if(p_pmt_decoder->i_last_section_number
!= p_section->i_last_number)
else
{
/* last_section_number */
dvbpsi_error(h_dvbpsi, "PMT decoder",
/* Perform some few sanity checks */
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"
" 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 */
if(b_reinit)
{
/* Force redecoding */
p_pmt_decoder->b_current_valid = 0;
/* Free structures */
if(p_pmt_decoder->p_building_pmt)
/* Reinit the decoder if wanted */
if (b_reinit)
{
free(p_pmt_decoder->p_building_pmt);
p_pmt_decoder->p_building_pmt = NULL;
}
/* Clear the section array */
for(unsigned int i = 0; i <= 255; i++)
{
if(p_pmt_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[i]);
p_pmt_decoder->ap_sections[i] = NULL;
}
}
}
/* 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);
p_pmt_decoder->p_building_pmt = NULL;
}
/* Append the section to the list if wanted */
if(b_append)
{
int b_complete;
/* Clear the section array */
for (unsigned int i = 0; i <= 255; i++)
{
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 */
if(!p_pmt_decoder->p_building_pmt)
/* Append the section to the list if wanted */
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_InitPMT(p_pmt_decoder->p_building_pmt,
dvbpsi_InitPMT(p_pmt_decoder->p_building_pmt,
p_pmt_decoder->i_program_number,
p_section->i_version,
p_section->b_current_next,
((uint16_t)(p_section->p_payload_start[0] & 0x1f) << 8)
| 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 */
if(p_pmt_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(h_dvbpsi, "PMT decoder", "overwrite section number %d",
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;
/* Fill the section array */
if (p_pmt_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(p_dvbpsi, "PMT decoder", "overwrite section number %d",
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;
/* Check if we have all the sections */
b_complete = 0;
for(unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++)
{
if(!p_pmt_decoder->ap_sections[i])
break;
/* Check if we have all the sections */
b_complete = 0;
for (unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++)
{
if (!p_pmt_decoder->ap_sections[i])
break;
if(i == p_pmt_decoder->i_last_section_number)
b_complete = 1;
}
if (i == p_pmt_decoder->i_last_section_number)
b_complete = 1;
}
if(b_complete)
{
/* Save the current information */
p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt;
p_pmt_decoder->b_current_valid = 1;
/* Chain the sections */
if(p_pmt_decoder->i_last_section_number)
{
for(unsigned int i = 0; (int)i <= p_pmt_decoder->i_last_section_number - 1; i++)
p_pmt_decoder->ap_sections[i]->p_next =
if (b_complete)
{
/* Save the current information */
p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt;
p_pmt_decoder->b_current_valid = 1;
/* Chain the sections */
if (p_pmt_decoder->i_last_section_number)
{
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 + 1];
}
/* Decode the sections */
dvbpsi_DecodePMTSections(p_pmt_decoder->p_building_pmt,
p_pmt_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[0]);
/* signal the new PMT */
p_pmt_decoder->pf_callback(p_pmt_decoder->p_cb_data,
p_pmt_decoder->p_building_pmt);
/* Reinitialize the structures */
p_pmt_decoder->p_building_pmt = NULL;
for(unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++)
p_pmt_decoder->ap_sections[i] = NULL;
}
/* Decode the sections */
dvbpsi_DecodePMTSections(p_pmt_decoder->p_building_pmt,
p_pmt_decoder->ap_sections[0]);
/* Delete the sections */
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[0]);
/* signal the new PMT */
p_pmt_decoder->pf_pmt_callback(p_pmt_decoder->p_cb_data,
p_pmt_decoder->p_building_pmt);
/* Reinitialize the structures */
p_pmt_decoder->p_building_pmt = NULL;
for (unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++)
p_pmt_decoder->ap_sections[i] = NULL;
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_DecodePMTSections
*****************************************************************************
......@@ -449,49 +422,48 @@ void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt,
dvbpsi_psi_section_t* p_section)
{
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;
}
uint8_t* p_byte, * p_end;
/* - ESs */
for(p_byte = p_end; p_byte + 5 <= p_section->p_payload_end;)
while (p_section)
{
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;
}
}
/* - 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;
}
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,
*****************************************************************************
* 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_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_pmt->p_first_descriptor;
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es;
uint16_t i_info_length;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
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 = 0;
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;
/* PMT descriptors */
while(p_descriptor != NULL)
{
/* New section if needed */
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_pmt->p_first_descriptor;
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es;
uint16_t i_info_length;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
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 = 0;
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;
/* PMT descriptors */
while (p_descriptor != NULL)
{
/* 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;
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
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;
}
/* 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 */
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;
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
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;
}
/* 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;
}
/* 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;
/* 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 _no_ and the current section isn't empty and an empty section
may carry one more descriptor
then create a new section */
if( (p_descriptor != NULL)
&& (p_es_start - p_current->p_data != 12)
&& (i_es_length <= 1008))
/* 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)
{
/* will put more descriptors in an empty section */
#if 0
dvbpsi_debug(h_dvbpsi, "PMT generator",
"create a new section to carry more ES descriptors");
#endif
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
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;
}
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
may carry one more descriptor
then create a new section */
if( (p_descriptor != NULL)
&& (p_es_start - p_current->p_data != 12)
&& (i_es_length <= 1008))
{
/* will put more descriptors in an empty section */
dvbpsi_debug(p_dvbpsi, "PMT generator",
"create a new section to carry more ES descriptors");
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
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 */
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;
if (p_descriptor != NULL)
dvbpsi_error(p_dvbpsi, "PMT generator", "unable to carry all the ES descriptors");
/* Increase the length by 5 */
p_current->p_payload_end += 5;
p_current->i_length += 5;
/* 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;
}
/* 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))
/* Finalization */
p_prev = p_result;
while (p_prev != NULL)
{
/* 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_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->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 @@
* $Id$
*
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -37,7 +38,6 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_pmt_es_t
*****************************************************************************/
......@@ -64,7 +64,6 @@ typedef struct dvbpsi_pmt_es_s
} dvbpsi_pmt_es_t;
/*****************************************************************************
* dvbpsi_pmt_t
*****************************************************************************/
......@@ -93,7 +92,6 @@ typedef struct dvbpsi_pmt_s
} dvbpsi_pmt_t;
/*****************************************************************************
* dvbpsi_pmt_callback
*****************************************************************************/
......@@ -104,38 +102,37 @@ typedef struct dvbpsi_pmt_s
*/
typedef void (* dvbpsi_pmt_callback)(void* p_cb_data, dvbpsi_pmt_t* p_new_pmt);
/*****************************************************************************
* 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,
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 pf_callback function to call back on new PMT
* \param p_cb_data private data given in argument to the callback
* \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,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachPMT
*****************************************************************************/
/*!
* \fn void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi)
* \fn void dvbpsi_DetachPMT(dvbpsi_t *p_dvbpsi)
* \brief Destroy a PMT decoder.
* \param h_dvbpsi handle to the decoder
* \param p_dvbpsi handle
* \return nothing.
*
* 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
......@@ -175,7 +172,6 @@ do { \
i_pcr_pid); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyPMT/dvbpsi_DeletePMT
*****************************************************************************/
......@@ -199,7 +195,6 @@ do { \
free(p_pmt); \
} while(0);
/*****************************************************************************
* dvbpsi_PMTAddDescriptor
*****************************************************************************/
......@@ -219,7 +214,6 @@ dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt,
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data);
/*****************************************************************************
* dvbpsi_PMTAddES
*****************************************************************************/
......@@ -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,
uint8_t i_type, uint16_t i_pid);
/*****************************************************************************
* dvbpsi_PMTESAddDescriptor
*****************************************************************************/
......@@ -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* p_data);
/*****************************************************************************
* 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
* \param p_dvbpsi is a pointer to dvbpsi_t
* \param p_pmt PMT 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_GenPMTSections(dvbpsi_pmt_t* p_pmt);
dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_t *p_dvbpsi, dvbpsi_pmt_t* p_pmt);
#ifdef __cplusplus
};
......@@ -277,4 +270,3 @@ dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt);
#else
#error "Multiple inclusions of pmt.h"
#endif
......@@ -5,6 +5,7 @@
* $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>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -34,31 +35,31 @@
*****************************************************************************/
typedef struct dvbpsi_pmt_decoder_s
{
uint16_t i_program_number;
DVBPSI_DECODER_COMMON
dvbpsi_pmt_callback pf_callback;
void * p_cb_data;
uint16_t i_program_number;
dvbpsi_pmt_t current_pmt;
dvbpsi_pmt_t * p_building_pmt;
dvbpsi_pmt_callback pf_pmt_callback;
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;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
} dvbpsi_pmt_decoder_t;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_pmt_decoder_t;
/*****************************************************************************
* dvbpsi_GatherPMTSections
*****************************************************************************
* 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_DecodePMTSections
*****************************************************************************
......@@ -67,7 +68,6 @@ void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt,
dvbpsi_psi_section_t* p_section);
#else
#error "Multiple inclusions of pmt_private.h"
#endif
......
......@@ -4,7 +4,8 @@
* Copyright (C) 2001-2010 VideoLAN
* $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
* modify it under the terms of the GNU Lesser General Public
......@@ -24,7 +25,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -45,113 +45,103 @@
#include "sdt.h"
#include "sdt_private.h"
/*****************************************************************************
* dvbpsi_AttachSDT
*****************************************************************************
* 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,
void* p_cb_data)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_sdt_decoder_t* p_sdt_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(h_dvbpsi, "SDT decoder",
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_sdt_decoder_t* p_sdt_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
{
dvbpsi_error(p_dvbpsi, "SDT decoder",
"Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)",
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));
if(p_subdec == NULL)
{
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;
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)
{
free(p_subdec);
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 information */
p_sdt_decoder->pf_sdt_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 p_dvbpsi;
}
/*****************************************************************************
* dvbpsi_DetachSDT
*****************************************************************************
* Close a SDT decoder.
*****************************************************************************/
void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension)
void dvbpsi_DetachSDT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_sdt_decoder_t* p_sdt_decoder;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_sdt_decoder_t* p_sdt_decoder;
if(p_demux == NULL)
{
dvbpsi_error(h_dvbpsi, "SDT Decoder",
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
if (p_subdec == NULL)
{
dvbpsi_error(p_dvbpsi, "SDT Decoder",
"No such SDT decoder (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, i_extension);
return;
}
p_sdt_decoder = (dvbpsi_sdt_decoder_t*)p_subdec->p_cb_data;
free(p_sdt_decoder->p_building_sdt);
return;
}
for(unsigned int i = 0; i <= 255; i++)
{
if(p_sdt_decoder->ap_sections[i])
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[i]);
}
p_sdt_decoder = (dvbpsi_sdt_decoder_t*)p_subdec->p_cb_data;
free(p_sdt_decoder->p_building_sdt);
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;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
pp_prev_subdec = &p_demux->p_first_subdec;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
p_subdec = NULL;
}
/*****************************************************************************
* dvbpsi_InitSDT
*****************************************************************************
......@@ -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,
int b_current_next, uint16_t i_network_id)
{
p_sdt->i_ts_id = i_ts_id;
p_sdt->i_version = i_version;
p_sdt->b_current_next = b_current_next;
p_sdt->i_network_id = i_network_id;
p_sdt->p_first_service = NULL;
p_sdt->i_ts_id = i_ts_id;
p_sdt->i_version = i_version;
p_sdt->b_current_next = b_current_next;
p_sdt->i_network_id = i_network_id;
p_sdt->p_first_service = NULL;
}
/*****************************************************************************
* dvbpsi_EmptySDT
*****************************************************************************
......@@ -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)
{
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;
}
dvbpsi_sdt_service_t* p_service = p_sdt->p_first_service;
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
*****************************************************************************
......@@ -201,11 +188,11 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt,
uint8_t i_running_status,
int b_free_ca)
{
dvbpsi_sdt_service_t * p_service
= (dvbpsi_sdt_service_t*)malloc(sizeof(dvbpsi_sdt_service_t));
dvbpsi_sdt_service_t * p_service;
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->b_eit_schedule = b_eit_schedule;
p_service->b_eit_present = b_eit_present;
......@@ -214,23 +201,19 @@ dvbpsi_sdt_service_t *dvbpsi_SDTAddService(dvbpsi_sdt_t* p_sdt,
p_service->p_next = NULL;
p_service->p_first_descriptor = NULL;
if(p_sdt->p_first_service == NULL)
{
p_sdt->p_first_service = p_service;
}
if (p_sdt->p_first_service == NULL)
p_sdt->p_first_service = p_service;
else
{
dvbpsi_sdt_service_t * p_last_service = p_sdt->p_first_service;
while(p_last_service->p_next != NULL)
p_last_service = p_last_service->p_next;
p_last_service->p_next = p_service;
dvbpsi_sdt_service_t * p_last_service = p_sdt->p_first_service;
while(p_last_service->p_next != NULL)
p_last_service = p_last_service->p_next;
p_last_service->p_next = p_service;
}
}
return p_service;
return p_service;
}
/*****************************************************************************
* dvbpsi_SDTServiceAddDescriptor
*****************************************************************************
......@@ -241,44 +224,40 @@ dvbpsi_descriptor_t *dvbpsi_SDTServiceAddDescriptor(
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data)
{
dvbpsi_descriptor_t * p_descriptor
= dvbpsi_NewDescriptor(i_tag, i_length, p_data);
dvbpsi_descriptor_t * p_descriptor;
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
{
dvbpsi_descriptor_t * p_last_descriptor = p_service->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;
dvbpsi_descriptor_t * p_last_descriptor = p_service->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;
}
/*****************************************************************************
* dvbpsi_GatherSDTSections
*****************************************************************************
* 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,
dvbpsi_psi_section_t * p_section)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_sdt_decoder_t * p_sdt_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_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, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id,
......@@ -286,163 +265,158 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder,
p_section->i_number, p_section->i_last_number,
p_section->b_current_next);
if(!p_section->b_syntax_indicator)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(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)
if (!p_section->b_syntax_indicator)
{
b_reinit = 1;
p_psi_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
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 */
if(p_sdt_decoder->p_building_sdt)
{
if(p_sdt_decoder->p_building_sdt->i_ts_id != p_section->i_extension)
/* TS discontinuity check */
if (p_demux->b_discontinuity)
{
/* transport_stream_id */
dvbpsi_error(h_dvbpsi, "SDT decoder",
"'transport_stream_id' differs"
" whereas no TS discontinuity has occured");
b_reinit = 1;
b_reinit = 1;
p_demux->b_discontinuity = 0;
}
else if(p_sdt_decoder->p_building_sdt->i_version
!= p_section->i_version)
else
{
/* version_number */
dvbpsi_error(h_dvbpsi, "SDT decoder",
"'version_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
/* Perform a few sanity checks */
if (p_sdt_decoder->p_building_sdt)
{
if (p_sdt_decoder->p_building_sdt->i_ts_id != p_section->i_extension)
{
/* 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 */
dvbpsi_error(h_dvbpsi, "SDT decoder",
"'last_section_number' differs"
" whereas no discontinuity has occured");
b_reinit = 1;
free(p_sdt_decoder->p_building_sdt);
p_sdt_decoder->p_building_sdt = NULL;
}
}
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))
/* Clear the section array */
for (unsigned int i = 0; i <= 255; i++)
{
/* Don't decode since this version is already decoded */
b_append = 0;
if (p_sdt_decoder->ap_sections[i] != NULL)
{
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[i]);
p_sdt_decoder->ap_sections[i] = NULL;
}
}
}
}
}
/* 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)
/* Append the section to the list if wanted */
if (b_append)
{
free(p_sdt_decoder->p_building_sdt);
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;
int b_complete;
/* Initialize the structures if it's the first section received */
if(!p_sdt_decoder->p_building_sdt)
{
p_sdt_decoder->p_building_sdt =
(dvbpsi_sdt_t*)malloc(sizeof(dvbpsi_sdt_t));
dvbpsi_InitSDT(p_sdt_decoder->p_building_sdt,
p_section->i_extension,
p_section->i_version,
p_section->b_current_next,
((uint16_t)(p_section->p_payload_start[0]) << 8)
| p_section->p_payload_start[1]);
p_sdt_decoder->i_last_section_number = p_section->i_last_number;
}
/* Initialize the structures if it's the first section received */
if (!p_sdt_decoder->p_building_sdt)
{
p_sdt_decoder->p_building_sdt =
(dvbpsi_sdt_t*)calloc(1, sizeof(dvbpsi_sdt_t));
dvbpsi_InitSDT(p_sdt_decoder->p_building_sdt,
p_section->i_extension,
p_section->i_version,
p_section->b_current_next,
((uint16_t)(p_section->p_payload_start[0]) << 8)
| p_section->p_payload_start[1]);
p_sdt_decoder->i_last_section_number = p_section->i_last_number;
}
/* Fill the section array */
if(p_sdt_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(h_dvbpsi, "SDT decoder", "overwrite section number %d",
/* Fill the section array */
if (p_sdt_decoder->ap_sections[p_section->i_number] != NULL)
{
dvbpsi_debug(p_dvbpsi, "SDT decoder", "overwrite section number %d",
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;
dvbpsi_DeletePSISections(p_sdt_decoder->ap_sections[p_section->i_number]);
}
p_sdt_decoder->ap_sections[p_section->i_number] = p_section;
/* Check if we have all the sections */
b_complete = 0;
for(unsigned int i = 0; i <= p_sdt_decoder->i_last_section_number; i++)
{
if(!p_sdt_decoder->ap_sections[i])
break;
/* Check if we have all the sections */
b_complete = 0;
for (unsigned int i = 0; i <= p_sdt_decoder->i_last_section_number; i++)
{
if (!p_sdt_decoder->ap_sections[i])
break;
if(i == p_sdt_decoder->i_last_section_number)
b_complete = 1;
}
if (i == p_sdt_decoder->i_last_section_number)
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 */
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;
dvbpsi_DeletePSISections(p_section);
}
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_DecodeSDTSection
*****************************************************************************
......@@ -451,161 +425,153 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t * p_psi_decoder,
void dvbpsi_DecodeSDTSections(dvbpsi_sdt_t* p_sdt,
dvbpsi_psi_section_t* p_section)
{
uint8_t *p_byte, *p_end;
uint8_t *p_byte, *p_end;
while(p_section)
{
for(p_byte = p_section->p_payload_start + 3;
p_byte + 4 < p_section->p_payload_end;)
while (p_section)
{
uint16_t i_service_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1];
int b_eit_schedule = (int)((p_byte[2] & 0x2) >> 1);
int b_eit_present = (int)((p_byte[2]) & 0x1);
uint8_t i_running_status = (uint8_t)(p_byte[3]) >> 5;
int b_free_ca = (int)((p_byte[3] & 0x10) >> 4);
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,
i_service_id, b_eit_schedule, b_eit_present,
i_running_status, b_free_ca);
/* Service descriptors */
p_byte += 5;
p_end = p_byte + i_srv_length;
if( p_end > p_section->p_payload_end ) break;
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_SDTServiceAddDescriptor(p_service, i_tag, i_length, p_byte + 2);
p_byte += 2 + i_length;
}
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];
int b_eit_schedule = (int)((p_byte[2] & 0x2) >> 1);
int b_eit_present = (int)((p_byte[2]) & 0x1);
uint8_t i_running_status = (uint8_t)(p_byte[3]) >> 5;
int b_free_ca = (int)((p_byte[3] & 0x10) >> 4);
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,
i_service_id, b_eit_schedule, b_eit_present,
i_running_status, b_free_ca);
/* Service descriptors */
p_byte += 5;
p_end = p_byte + i_srv_length;
if( p_end > p_section->p_payload_end ) break;
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_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
*****************************************************************************
* 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_current = p_result;
dvbpsi_psi_section_t * p_prev;
dvbpsi_sdt_service_t * p_service = p_sdt->p_first_service;
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 = 0;
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;
/* SDT service */
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) )
dvbpsi_psi_section_t *p_result = dvbpsi_NewPSISection(1024);
dvbpsi_psi_section_t *p_current = p_result;
dvbpsi_psi_section_t *p_prev;
dvbpsi_sdt_service_t *p_service = p_sdt->p_first_service;
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 = 0;
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;
/* SDT service */
while (p_service != NULL)
{
i_service_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
uint8_t * p_service_start = p_current->p_payload_end;
uint16_t i_service_length = 5;
if ( (p_descriptor != NULL) && (p_service_start - p_current->p_data != 11) && (i_service_length <= 1009) )
{
/* 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;
}
dvbpsi_descriptor_t * p_descriptor = p_service->p_first_descriptor;
p_service_start[0] = (p_service->i_service_id >>8);
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);
p_service_start[3] = ((p_service->i_running_status & 0x07) << 5 ) | ((p_service->b_free_ca & 0x1) << 4);
while ((p_descriptor != NULL)&& ((p_service_start - p_current->p_data) + i_service_length <= 1020))
{
i_service_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* Increase the length by 5 */
p_current->p_payload_end += 5;
p_current->i_length += 5;
if ((p_descriptor != NULL) && (p_service_start - p_current->p_data != 11) && (i_service_length <= 1009))
{
/* 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_descriptor = p_service->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_service_start[0] = (p_service->i_service_id >>8);
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);
p_service_start[3] = ((p_service->i_running_status & 0x07) << 5 ) | ((p_service->b_free_ca & 0x1) << 4);
#if 0
if(p_descriptor != NULL)
dvbpsi_error(h_dvbpsi, "SDT generator", "unable to carry all the descriptors");
#endif
/* Increase the length by 5 */
p_current->p_payload_end += 5;
p_current->i_length += 5;
/* 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;
}
/* ES descriptors */
p_descriptor = p_service->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;
}
if (p_descriptor != NULL)
dvbpsi_error(p_dvbpsi, "SDT generator", "unable to carry all the descriptors");
/* 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 @@
* $Id$
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -37,7 +38,6 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_sdt_service_t
*****************************************************************************/
......@@ -65,13 +65,11 @@ typedef struct dvbpsi_sdt_service_s
dvbpsi_descriptor_t * p_first_descriptor; /*!< First of the following
DVB descriptors */
struct dvbpsi_sdt_service_s * p_next; /*!< next element of
the list */
} dvbpsi_sdt_service_t;
/*****************************************************************************
* dvbpsi_sdt_t
*****************************************************************************/
......@@ -98,7 +96,6 @@ typedef struct dvbpsi_sdt_s
} dvbpsi_sdt_t;
/*****************************************************************************
* dvbpsi_sdt_callback
*****************************************************************************/
......@@ -109,42 +106,38 @@ typedef struct dvbpsi_sdt_s
*/
typedef void (* dvbpsi_sdt_callback)(void* p_cb_data, dvbpsi_sdt_t* p_new_sdt);
/*****************************************************************************
* 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,
void* p_cb_data)
* \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_extension Table ID extension, here TS ID.
* \param pf_callback function to call back on new SDT.
* \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,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachSDT
*****************************************************************************/
/*!
* \fn void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension)
* \fn void dvbpsi_DetachSDT(dvbpsi_demux_t *p_demux, uint8_t i_table_id,
uint16_t i_extension)
* \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_extension Table ID extension, here TS ID.
* \return nothing.
*/
void dvbpsi_DetachSDT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
uint16_t i_extension);
void dvbpsi_DetachSDT(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension);
/*****************************************************************************
* dvbpsi_InitSDT/dvbpsi_NewSDT
......@@ -180,7 +173,6 @@ do { \
dvbpsi_InitSDT(p_sdt, i_ts_id, i_version, b_current_next, i_network_id); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptySDT/dvbpsi_DeleteSDT
*****************************************************************************/
......@@ -204,7 +196,6 @@ do { \
free(p_sdt); \
} while(0);
/*****************************************************************************
* dvbpsi_SDTAddService
*****************************************************************************/
......@@ -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,
uint8_t i_running_status,int b_free_ca);
/*****************************************************************************
* dvbpsi_SDTServiceAddDescriptor
*****************************************************************************/
......@@ -249,13 +239,22 @@ dvbpsi_descriptor_t *dvbpsi_SDTServiceAddDescriptor(
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
/*****************************************************************************
* dvbpsi_GenSDTSections
*****************************************************************************
* 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
};
......
......@@ -5,6 +5,7 @@
* $Id: sdt_private.h,v 1.1 2002/12/11 13:04:57 jobi Exp $
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman@videolan.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -27,7 +28,6 @@
#ifndef _DVBPSI_SDT_PRIVATE_H_
#define _DVBPSI_SDT_PRIVATE_H_
/*****************************************************************************
* dvbpsi_sdt_decoder_t
*****************************************************************************
......@@ -35,30 +35,30 @@
*****************************************************************************/
typedef struct dvbpsi_sdt_decoder_s
{
dvbpsi_sdt_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_sdt_t current_sdt;
dvbpsi_sdt_t * p_building_sdt;
dvbpsi_sdt_callback pf_sdt_callback;
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;
dvbpsi_psi_section_t * ap_sections [256];
int b_current_valid;
} dvbpsi_sdt_decoder_t;
uint8_t i_last_section_number;
dvbpsi_psi_section_t * ap_sections [256];
} dvbpsi_sdt_decoder_t;
/*****************************************************************************
* dvbpsi_GatherSDTSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherSDTSections(dvbpsi_decoder_t* p_psi_decoder,
void* p_private_decoder,
void dvbpsi_GatherSDTSections(dvbpsi_t *p_dvbpsi,
void* p_private_decoder,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodeSDTSection
*****************************************************************************
......@@ -67,7 +67,6 @@ void dvbpsi_GatherSDTSections(dvbpsi_decoder_t* p_psi_decoder,
void dvbpsi_DecodeSDTSections(dvbpsi_sdt_t* p_sdt,
dvbpsi_psi_section_t* p_section);
#else
#error "Multiple inclusions of sdt_private.h"
#endif
......
......@@ -52,12 +52,11 @@
*****************************************************************************
* 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,
void* p_cb_data)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_psi_decoder;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
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,
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,"
"extension == 0x%02x)",
i_table_id, i_extension);
return 1;
}
......@@ -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;
/* 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;
return 0;
......@@ -108,10 +106,10 @@ int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id,
*****************************************************************************
* 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)
{
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** pp_prev_subdec;
dvbpsi_sis_decoder_t* p_sis_decoder;
......@@ -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);
if (p_demux == NULL)
{
dvbpsi_error(h_dvbpsi, "SIS Decoder",
dvbpsi_error(p_dvbpsi, "SIS Decoder",
"No such SIS decoder (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, i_extension);
......@@ -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;
free(p_subdec->p_cb_data);
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,
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
p_subdec = NULL;
}
/*****************************************************************************
......@@ -197,23 +195,19 @@ dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis,
uint8_t *p_data)
{
dvbpsi_descriptor_t * p_descriptor;
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)
{
p_sis->p_first_descriptor = 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;
}
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;
}
......@@ -222,17 +216,17 @@ dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis,
*****************************************************************************
* 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,
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_private_decoder;
int b_append = 1;
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, "
"section %3d up to %3d, " "current %1d",
p_section->i_version, p_section->i_table_id,
......@@ -243,7 +237,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_section->i_table_id != 0xFC)
{
/* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "SIS decoder",
dvbpsi_error(p_dvbpsi, "SIS decoder",
"invalid section (table_id == 0x%02x)",
p_section->i_table_id);
b_append = 0;
......@@ -252,7 +246,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_section->b_syntax_indicator != 0)
{
/* Invalid section_syntax_indicator */
dvbpsi_error(h_dvbpsi, "SIS decoder",
dvbpsi_error(p_dvbpsi, "SIS decoder",
"invalid section (section_syntax_indicator != 0)");
b_append = 0;
}
......@@ -260,7 +254,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_section->b_private_indicator != 0)
{
/* Invalid private_syntax_indicator */
dvbpsi_error(h_dvbpsi, "SIS decoder",
dvbpsi_error(p_dvbpsi, "SIS decoder",
"invalid private section (private_syntax_indicator != 0)");
b_append = 0;
}
......@@ -269,10 +263,10 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (b_append)
{
/* TS discontinuity check */
if (p_psi_decoder->b_discontinuity)
if (p_demux->b_discontinuity)
{
b_reinit = 1;
p_psi_decoder->b_discontinuity = 0;
p_demux->b_discontinuity = 0;
}
else
{
......@@ -282,8 +276,8 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder,
if (p_sis_decoder->p_building_sis->i_protocol_version != 0)
{
/* transport_stream_id */
dvbpsi_error(h_dvbpsi, "SIS decoder",
"'protocol_version' differs");\
dvbpsi_error(p_dvbpsi, "SIS decoder",
"'protocol_version' differs");
b_reinit = 1;
}
}
......@@ -335,7 +329,7 @@ void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_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)
{
uint8_t *p_byte, *p_end;
......@@ -409,7 +403,7 @@ void dvbpsi_DecodeSISSections(dvbpsi_sis_t* p_sis,
*****************************************************************************
* 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);
......@@ -479,4 +473,3 @@ dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_sis_t* p_sis)
dvbpsi_BuildPSISection(p_current);
return p_current;
}
......@@ -90,7 +90,6 @@ typedef struct dvbpsi_sis_s
DVB descriptors */
/* FIXME: alignment stuffing */
uint32_t i_ecrc; /*!< CRC 32 of decrypted splice_info_section */
} dvbpsi_sis_t;
......@@ -105,7 +104,6 @@ typedef struct dvbpsi_sis_s
*/
typedef void (* dvbpsi_sis_callback)(void* p_cb_data, dvbpsi_sis_t* p_new_sis);
/*****************************************************************************
* dvbpsi_AttachSIS
*****************************************************************************/
......@@ -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,
void* p_cb_data)
* \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_extension Table ID extension, here TS ID.
* \param pf_callback function to call back on new SIS.
* \param p_cb_data private data given in argument to the callback.
* \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,
void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachSIS
*****************************************************************************/
......@@ -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,
uint16_t i_extension)
* \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_extension Table ID extension, here TS ID.
* \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);
/*****************************************************************************
* dvbpsi_InitSIS/dvbpsi_NewSIS
*****************************************************************************/
......@@ -206,16 +202,16 @@ do { \
* \param p_data descriptor's data
* \return a pointer to the added descriptor.
*/
dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor(dvbpsi_sis_t *p_sis,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
/*****************************************************************************
* dvbpsi_GenSISSections
*****************************************************************************
* 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
};
......
......@@ -34,37 +34,36 @@
*****************************************************************************/
typedef struct dvbpsi_sis_decoder_s
{
dvbpsi_sis_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
/* */
dvbpsi_sis_t *current_sis;
dvbpsi_sis_t *p_building_sis;
dvbpsi_sis_callback pf_sis_callback;
void * p_cb_data;
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
*****************************************************************************
* 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,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_DecodeSISSection
*****************************************************************************
* 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);
#else
#error "Multiple inclusions of sis_private.h"
#endif
......
......@@ -7,6 +7,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -26,7 +27,6 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
......@@ -47,60 +47,53 @@
#include "tot.h"
#include "tot_private.h"
/*****************************************************************************
* dvbpsi_AttachTOT
*****************************************************************************
* Initialize a TDT/TOT subtable decoder.
*****************************************************************************/
int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
uint16_t i_extension,
int dvbpsi_AttachTOT(dvbpsi_t* p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
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_psi_decoder->p_private_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_tot_decoder_t* p_tot_decoder;
if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0))
{
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder",
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_tot_decoder_t* p_tot_decoder;
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0))
{
dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
"Already a decoder for (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, 0);
return 1;
}
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));
p_subdec = (dvbpsi_demux_subdec_t*)calloc(1, sizeof(dvbpsi_demux_subdec_t));
if(p_subdec == NULL)
return 1;
if(p_tot_decoder == NULL)
{
free(p_subdec);
return 1;
}
p_tot_decoder = (dvbpsi_tot_decoder_t*)calloc(1, sizeof(dvbpsi_tot_decoder_t));
if (p_tot_decoder == NULL)
{
free(p_subdec);
return 1;
}
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherTOTSections;
p_subdec->p_cb_data = p_tot_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)0;
p_subdec->pf_detach = dvbpsi_DetachTOT;
/* subtable decoder configuration */
p_subdec->pf_callback = &dvbpsi_GatherTOTSections;
p_subdec->p_cb_data = p_tot_decoder;
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)0;
p_subdec->pf_detach = dvbpsi_DetachTOT;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* Attach the subtable decoder to the demux */
p_subdec->p_next = p_demux->p_first_subdec;
p_demux->p_first_subdec = p_subdec;
/* TDT/TOT decoder information */
p_tot_decoder->pf_callback = pf_callback;
p_tot_decoder->p_cb_data = p_cb_data;
/* TDT/TOT decoder information */
p_tot_decoder->pf_tot_callback = pf_callback;
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,
*****************************************************************************
* 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)
{
dvbpsi_handle h_dvbpsi = (dvbpsi_handle) p_demux->p_decoder;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *)p_dvbpsi->p_private;
dvbpsi_demux_subdec_t* p_subdec;
dvbpsi_demux_subdec_t** pp_prev_subdec;
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0);
if(p_demux == NULL)
{
dvbpsi_error(h_dvbpsi, "TDT/TOT Decoder",
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0);
if (p_demux == NULL)
{
dvbpsi_error(p_dvbpsi, "TDT/TOT Decoder",
"No such TDT/TOT decoder (table_id == 0x%02x,"
"extension == 0x%02x)",
i_table_id, 0);
return;
}
return;
}
free(p_subdec->p_cb_data);
free(p_subdec->p_cb_data);
pp_prev_subdec = &p_demux->p_first_subdec;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
pp_prev_subdec = &p_demux->p_first_subdec;
while(*pp_prev_subdec != p_subdec)
pp_prev_subdec = &(*pp_prev_subdec)->p_next;
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
*pp_prev_subdec = p_subdec->p_next;
free(p_subdec);
p_subdec = NULL;
}
/*****************************************************************************
* dvbpsi_InitTOT
*****************************************************************************
......@@ -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)
{
p_tot->i_utc_time = i_utc_time;
p_tot->p_first_descriptor = NULL;
p_tot->i_utc_time = i_utc_time;
p_tot->p_first_descriptor = NULL;
}
/*****************************************************************************
* dvbpsi_EmptyTOT
*****************************************************************************
......@@ -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)
{
dvbpsi_DeleteDescriptors(p_tot->p_first_descriptor);
p_tot->p_first_descriptor = NULL;
dvbpsi_DeleteDescriptors(p_tot->p_first_descriptor);
p_tot->p_first_descriptor = NULL;
}
/*****************************************************************************
* dvbpsi_TOTAddDescriptor
*****************************************************************************
......@@ -171,300 +160,275 @@ dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
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);
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
{
dvbpsi_descriptor_t* p_last_descriptor = p_tot->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;
dvbpsi_descriptor_t* p_last_descriptor = p_tot->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;
}
/*****************************************************************************
* dvbpsi_GatherTOTSections
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherTOTSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_GatherTOTSections(dvbpsi_t* p_dvbpsi,
void * p_private_decoder,
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;
int b_append = 1;
dvbpsi_tot_t* p_building_tot;
int b_append = 1;
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)
{
/* Invalid table_id value */
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder",
if (p_section->i_table_id != 0x70 && p_section->i_table_id != 0x73)
{
/* Invalid table_id value */
dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
"invalid section (table_id == 0x%02x)",
p_section->i_table_id);
b_append = 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)
b_append = 0;
}
if (b_append && p_section->b_syntax_indicator != 0)
{
/* We don't care about discontinuities with the TDT/TOT as it
only consists of one section anyway */
p_decoder->b_discontinuity = 0;
/* Invalid section_syntax_indicator */
dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
"invalid section (section_syntax_indicator != 0)");
b_append = 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)
/* Now if b_append is true then we have a valid TDT/TOT section */
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[2] << 16)
| ((uint64_t)p_section->p_payload_start[3] << 8)
| (uint64_t)p_section->p_payload_start[4]);
/* Decode the section */
dvbpsi_DecodeTOTSections(p_building_tot, p_section);
/* Delete the section */
dvbpsi_DeletePSISections(p_section);
/* signal the new TDT/TOT */
p_tot_decoder->pf_callback(p_tot_decoder->p_cb_data, p_building_tot);
}
else
{
dvbpsi_DeletePSISections(p_section);
}
/* Decode the section */
dvbpsi_DecodeTOTSections(p_dvbpsi, p_building_tot, p_section);
/* Delete the section */
dvbpsi_DeletePSISections(p_section);
/* signal the new TDT/TOT */
p_tot_decoder->pf_tot_callback(p_tot_decoder->p_cb_data, p_building_tot);
}
else
{
dvbpsi_DeletePSISections(p_section);
}
}
/*****************************************************************************
* dvbpsi_ValidTOTSection
*****************************************************************************
* 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 */
uint32_t i_crc = 0xffffffff;
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)];
p_byte++;
i_crc = (i_crc << 8) ^ dvbpsi_crc32_table[(i_crc >> 24) ^ (*p_byte)];
p_byte++;
}
if(i_crc == 0)
{
return 1;
}
if (i_crc == 0)
return 1;
else
{
#if 0 /* FIXME */
dvbpsi_error(h_dvbpsi, "TDT/TOT decoder",
"Bad CRC_32 (0x%08x) !!!", i_crc);
#endif
return 0;
dvbpsi_error(p_dvbpsi, "TDT/TOT decoder",
"Bad CRC_32 (0x%08x) !!!", i_crc);
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
*****************************************************************************
* 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)
{
uint8_t* p_byte;
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)
if (p_section)
{
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];
uint8_t* p_byte;
if (!dvbpsi_ValidTOTSection(p_dvbpsi, 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) |
((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
*****************************************************************************
* 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_descriptor_t* p_descriptor = p_tot->p_first_descriptor;
/* If it has descriptors, it must be a TOT, otherwise a TDT */
p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8);
p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70;
p_result->b_syntax_indicator = 0;
p_result->b_private_indicator = 0;
p_result->i_length = 5;
p_result->p_payload_start = p_result->p_data + 3;
p_result->p_payload_end = p_result->p_data + 8;
p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff;
p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff;
p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff;
p_result->p_data[6] = (p_tot->i_utc_time >> 8) & 0xff;
p_result->p_data[7] = p_tot->i_utc_time & 0xff;
if(p_result->i_table_id == 0x73) {
/* Special handling for TOT only (A TDT doesn't have descriptors!) */
/* Reserve two bytes for descriptors_loop_length */
p_result->p_payload_end += 2;
p_result->i_length += 2;
/* TOT descriptors */
while(p_descriptor != NULL)
dvbpsi_psi_section_t* p_result;
dvbpsi_descriptor_t* p_descriptor = p_tot->p_first_descriptor;
/* If it has descriptors, it must be a TOT, otherwise a TDT */
p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8);
p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70;
p_result->b_syntax_indicator = 0;
p_result->b_private_indicator = 0;
p_result->i_length = 5;
p_result->p_payload_start = p_result->p_data + 3;
p_result->p_payload_end = p_result->p_data + 8;
p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff;
p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff;
p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff;
p_result->p_data[6] = (p_tot->i_utc_time >> 8) & 0xff;
p_result->p_data[7] = p_tot->i_utc_time & 0xff;
if (p_result->i_table_id == 0x73)
{
/* A TOT cannot have multiple sections! */
if( (p_result->p_payload_end - p_result->p_data)
+ p_descriptor->i_length > 4090)
{
#if 0 /* FIXME: */
dvbpsi_error(h_dvbpsi, "TDT/TOT generator",
"TOT does not fit into one section as it ought to be !!!");
#endif
break;
}
/* p_payload_end is where the descriptor begins */
p_result->p_payload_end[0] = p_descriptor->i_tag;
p_result->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_result->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_result->p_payload_end += p_descriptor->i_length + 2;
p_result->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
/* Special handling for TOT only (A TDT doesn't have descriptors!) */
/* Reserve two bytes for descriptors_loop_length */
p_result->p_payload_end += 2;
p_result->i_length += 2;
/* TOT descriptors */
while (p_descriptor != NULL)
{
/* A TOT cannot have multiple sections! */
if( (p_result->p_payload_end - p_result->p_data)
+ p_descriptor->i_length > 4090)
{
dvbpsi_error(p_dvbpsi, "TDT/TOT generator",
"TOT does not fit into one section as it ought to be !!!");
break;
}
/* p_payload_end is where the descriptor begins */
p_result->p_payload_end[0] = p_descriptor->i_tag;
p_result->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_result->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* Increase length by descriptor_length + 2 */
p_result->p_payload_end += p_descriptor->i_length + 2;
p_result->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* descriptors_loop_length */
p_result->p_payload_start[5] = ((p_result->i_length - 7) << 8) | 0xf0;
p_result->p_payload_start[6] = (p_result->i_length - 7) & 0xff;
}
/* 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;
}
if (p_result->i_table_id == 0x73) {
/* A TOT has a CRC_32 although it's a private section,
but the CRC_32 is part of the payload! */
p_result->p_payload_end += 4;
p_result->i_length += 4;
}
dvbpsi_BuildPSISection(p_result);
if (p_result->i_table_id == 0x73) {
uint8_t* p_byte = p_result->p_data;
if (p_result->i_table_id == 0x73)
{
/* A TOT has a CRC_32 although it's a private section,
but the CRC_32 is part of the payload! */
p_result->p_payload_end += 4;
p_result->i_length += 4;
}
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)
^ dvbpsi_crc32_table[(p_tot->i_crc >> 24) ^ (*p_byte)];
p_byte++;
uint8_t* p_byte = p_result->p_data;
p_tot->i_crc = 0xffffffff;
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;
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;
}
#ifdef DEBUG
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
if (!dvbpsi_ValidTOTSection(p_dvbpsi, p_result))
{
dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************");
dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* Generated TDT/TOT section is invalid. *");
dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* --- libdvbpsi-devel@videolan.org --- *");
dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************");
}
return p_result;
return p_result;
}
......@@ -6,6 +6,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -39,7 +40,6 @@
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_tot_t
*****************************************************************************/
......@@ -64,7 +64,6 @@ typedef struct dvbpsi_tot_s
} dvbpsi_tot_t;
/*****************************************************************************
* dvbpsi_tot_callback
*****************************************************************************/
......@@ -75,26 +74,24 @@ typedef struct dvbpsi_tot_s
*/
typedef void (* dvbpsi_tot_callback)(void* p_cb_data, dvbpsi_tot_t* p_new_tot);
/*****************************************************************************
* 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)
* \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_extension Table ID extension, unused in the 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.
* \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,
dvbpsi_tot_callback pf_callback, void* p_cb_data);
/*****************************************************************************
* dvbpsi_DetachTOT
*****************************************************************************/
......@@ -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
* \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);
/*****************************************************************************
* dvbpsi_InitTOT/dvbpsi_NewTOT
*****************************************************************************/
......@@ -136,7 +132,6 @@ do { \
dvbpsi_InitTOT(p_tot, i_utc_time); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyTOT/dvbpsi_DeleteTOT
*****************************************************************************/
......@@ -160,7 +155,6 @@ do { \
free(p_tot); \
} while(0);
/*****************************************************************************
* dvbpsi_TOTAddDescriptor
*****************************************************************************/
......@@ -180,20 +174,19 @@ dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
uint8_t i_tag, uint8_t i_length,
uint8_t* p_data);
/*****************************************************************************
* dvbpsi_GenTOTSections
*****************************************************************************/
/*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_Ttot_t* p_tot)
* \brief TDT/TOT generator
* \param p_dvbpsi dvbpsi handle
* \param p_tot TDT/TOT structure
* \return a pointer to the list of generated PSI sections.
*
* 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
};
......
......@@ -7,6 +7,7 @@
* Authors: Johann Hanne
* heavily based on pmt.c which was written by
* 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
* modify it under the terms of the GNU Lesser General Public
......@@ -36,8 +37,10 @@
*****************************************************************************/
typedef struct dvbpsi_tot_decoder_s
{
dvbpsi_tot_callback pf_callback;
void * p_cb_data;
DVBPSI_DECODER_COMMON
dvbpsi_tot_callback pf_tot_callback;
void * p_cb_data;
} dvbpsi_tot_decoder_t;
......@@ -47,27 +50,25 @@ typedef struct dvbpsi_tot_decoder_s
*****************************************************************************
* Callback for the PSI decoder.
*****************************************************************************/
void dvbpsi_GatherTOTSections(dvbpsi_decoder_t* p_decoder,
void dvbpsi_GatherTOTSections(dvbpsi_t* p_dvbpsi,
void * p_private_decoder,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_ValidTOTSection
*****************************************************************************
* 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
*****************************************************************************
* 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);
#else
#error "Multiple inclusions of tot_private.h"
#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