Commit e2393869 authored by Zlu Zu's avatar Zlu Zu Committed by Jean-Paul Saman

BAT decoder and generator

Original patch was modified by Jean-Paul Saman <jpsaman@videolan.org>
- changed license to LGPLv2.1
- general cleanup
- fixed memleaks
- add missing prototypes to bat_private.h
- add static to functions in example/decode_bat.c
parent 897aa49f
...@@ -60,3 +60,7 @@ E: jpsaman@videolan.org ...@@ -60,3 +60,7 @@ E: jpsaman@videolan.org
D: VBI Data Descriptor (0x45) D: VBI Data Descriptor (0x45)
D: CUE Identifier Descriptor (0x8a) D: CUE Identifier Descriptor (0x8a)
D: Splice Information Table D: Splice Information Table
N: Zlu Zu
E: zluzu@gmail.com
D: BAT decoder and generator
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
noinst_PROGRAMS = decode_pat decode_pmt get_pcr_pid decode_sdt decode_mpeg noinst_PROGRAMS = decode_pat decode_pmt get_pcr_pid decode_sdt decode_mpeg decode_bat
decode_pat_SOURCES = decode_pat.c decode_pat_SOURCES = decode_pat.c
decode_pat_LDFLAGS = -L../src -ldvbpsi decode_pat_LDFLAGS = -L../src -ldvbpsi
...@@ -20,3 +20,5 @@ decode_mpeg_SOURCES += connect.c connect.h ...@@ -20,3 +20,5 @@ decode_mpeg_SOURCES += connect.c connect.h
endif endif
decode_mpeg_LDFLAGS = -L../src -ldvbpsi -lm decode_mpeg_LDFLAGS = -L../src -ldvbpsi -lm
decode_bat_SOURCES = decode_bat.c
decode_bat_LDFLAGS = -L../src -ldvbpsi
/*****************************************************************************
* decode_bat.c: BAT decoder example
*----------------------------------------------------------------------------
* Copyright (C) 2001-2010 VideoLAN
* $Id: decode_bat.c 01 2010-04-01 17:55:18 zhuzlu $
*
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*----------------------------------------------------------------------------
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#endif
/* The libdvbpsi distribution defines DVBPSI_DIST */
#ifdef DVBPSI_DIST
#include "../src/dvbpsi.h"
#include "../src/psi.h"
#include "../src/demux.h"
#include "../src/descriptor.h"
#include "../src/tables/bat.h"
#else
#include <dvbpsi/dvbpsi.h>
#include <dvbpsi/psi.h>
#include <dvbpsi/demux.h>
#include <dvbpsi/descriptor.h>
#include <dvbpsi/bat.h>
#endif
/*****************************************************************************
* ReadPacket
*****************************************************************************/
static int ReadPacket(int i_fd, uint8_t* p_dst)
{
int i = 187;
int i_rc = 1;
p_dst[0] = 0;
while((p_dst[0] != 0x47) && (i_rc > 0))
{
i_rc = read(i_fd, p_dst, 1);
}
while((i != 0) && (i_rc > 0))
{
i_rc = read(i_fd, p_dst + 188 - i, i);
if(i_rc >= 0)
i -= i_rc;
}
return (i == 0) ? 1 : 0;
}
/*****************************************************************************
* DumpDescriptors
*****************************************************************************/
static void DumpDescriptors(const char* str, dvbpsi_descriptor_t* p_descriptor)
{
while(p_descriptor)
{
int i;
printf("%s 0x%02x : \"", str, p_descriptor->i_tag);
for(i = 0; i < p_descriptor->i_length; i++)
printf("%.2x", p_descriptor->p_data[i]);
printf("\"\n");
p_descriptor = p_descriptor->p_next;
}
};
/*****************************************************************************
* Print_0xb1
*****************************************************************************/
static void Print_DescTag_0xb1(uint16_t i_ts_id, dvbpsi_descriptor_t* p_descriptor)
{
int i;
uint8_t *pdata;
unsigned int sub_bouquet_id;
int num;
unsigned int formater;
pdata = p_descriptor->p_data;
num=(p_descriptor->i_length-2)/9;
sub_bouquet_id= (((unsigned int)pdata[0]&0xff)<<8)|pdata[1];
if(sub_bouquet_id!=0xffff)
{
printf("sub_bouquet_id!=0xffff\n");
return;
}
if(num*9!=p_descriptor->i_length-2)
{
printf("num of private_services error\n");
return;
}
pdata+=2;
printf("\nts_id: %d, service_num: %d, service_id list: \n",i_ts_id,num);
formater=0;
for(i = 0; i < num; i++)
{
uint16_t service_id=(((uint16_t)pdata[0]&0xff)<<8)|pdata[1];
printf("%.4x ", service_id);
formater++;
if(0 == formater%16)
{
printf("\n");
}
pdata+=9;
}
printf("\r\n");
}
/*****************************************************************************
* DumpDescriptors_verbose
*****************************************************************************/
static void DumpDescriptors_verbose(uint16_t i_ts_id, dvbpsi_descriptor_t* p_descriptor)
{
while(p_descriptor)
{
if(0xb1 == p_descriptor->i_tag)
{
Print_DescTag_0xb1(i_ts_id,p_descriptor);
}
p_descriptor = p_descriptor->p_next;
}
};
/*****************************************************************************
* DumpBAT_verbose
*****************************************************************************/
static void DumpBAT_verbose(void* p_zero, dvbpsi_bat_t* p_bat)
{
dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
while(p_ts)
{
DumpDescriptors_verbose(p_ts->i_ts_id, p_ts->p_first_descriptor);
p_ts = p_ts->p_next;
}
}
/*****************************************************************************
* DumpBAT
*****************************************************************************/
static void DumpBAT(void* p_zero, dvbpsi_bat_t* p_bat)
{
dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
{
printf( "\n");
printf( "New active BAT(binary dumped)\n");
printf( " bouquet_id : %d\n",
p_bat->i_bouquet_id);
printf( " version_number : %d\n",
p_bat->i_version);
printf( " | ts_id \n");
while(p_ts)
{
printf(" | 0x%02x \n",
p_ts->i_ts_id);
DumpDescriptors(" | ]", p_ts->p_first_descriptor);
p_ts = p_ts->p_next;
}
printf( "\n");
printf( "New active BAT(string dumped)\n");
DumpBAT_verbose(p_zero,p_bat);
printf("\n");
}
dvbpsi_DeleteBAT(p_bat);
}
/*****************************************************************************
* NewSubtable
*****************************************************************************/
static void NewSubtableBAT(void * p_zero, dvbpsi_handle h_dvbpsi,
uint8_t i_table_id, uint16_t i_extension)
{
if(i_table_id == 0x4a)
{
dvbpsi_AttachBAT(h_dvbpsi, i_table_id, i_extension, DumpBAT, NULL);
}
}
/*****************************************************************************
* main
*****************************************************************************/
int main(int i_argc, char* pa_argv[])
{
int i_fd;
uint8_t data[188];
dvbpsi_handle h_dvbpsi;
int b_ok;
if(i_argc != 2)
return 1;
i_fd = open(pa_argv[1], 0);
h_dvbpsi = dvbpsi_AttachDemux(NewSubtableBAT, NULL);
b_ok = ReadPacket(i_fd, data);
while(b_ok)
{
uint16_t i_pid = ((uint16_t)(data[1] & 0x1f) << 8) + data[2];
if(i_pid == 0x11)
dvbpsi_PushPacket(h_dvbpsi, data);
b_ok = ReadPacket(i_fd, data);
}
dvbpsi_DetachDemux(h_dvbpsi);
return 0;
}
...@@ -16,6 +16,7 @@ libdvbpsi_la_LDFLAGS = -version-info 7:0:0 ...@@ -16,6 +16,7 @@ libdvbpsi_la_LDFLAGS = -version-info 7:0:0
pkginclude_HEADERS = dvbpsi.h psi.h descriptor.h demux.h \ pkginclude_HEADERS = dvbpsi.h psi.h descriptor.h demux.h \
tables/pat.h tables/pmt.h tables/sdt.h tables/eit.h \ tables/pat.h tables/pmt.h tables/sdt.h tables/eit.h \
tables/cat.h tables/nit.h tables/tot.h tables/sis.h \ tables/cat.h tables/nit.h tables/tot.h tables/sis.h \
tables/bat.h \
descriptors/dr_02.h \ descriptors/dr_02.h \
descriptors/dr_03.h \ descriptors/dr_03.h \
descriptors/dr_04.h \ descriptors/dr_04.h \
...@@ -84,5 +85,6 @@ tables_src = tables/pat.c tables/pat_private.h \ ...@@ -84,5 +85,6 @@ tables_src = tables/pat.c tables/pat_private.h \
tables/cat.c tables/cat_private.h \ tables/cat.c tables/cat_private.h \
tables/nit.c tables/nit_private.h \ tables/nit.c tables/nit_private.h \
tables/tot.c tables/tot_private.h \ tables/tot.c tables/tot_private.h \
tables/sis.c tables/sis_private.h tables/sis.c tables/sis_private.h \
tables/bat.c tables/bat_private.h
This diff is collapsed.
/*****************************************************************************
* bat.h
* Copyright (C) 2001-2010 VideoLAN
* $Id: bat.h $
*
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
* heavily based on nit.h which was written by
* Johann Hanne
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
*****************************************************************************/
/*!
* \file bat.h
* \author Zhu zhenglu <zhuzlu@gmail.com>
* \brief Application interface for the BAT decoder.
*
* Application interface for the BAT decoder. New
* decoded BAT are sent by callback to the application. If a table
* wasn't active (b_current_next == 0) and the next is the same but active
* (b_current_next == 1) then the service description list is empty and should
* be caught from the previous structure.
* This is a simulation to sdt.h
*/
#ifndef _DVBPSI_BAT_H_
#define _DVBPSI_BAT_H_
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************************
* dvbpsi_bat_ts_t
*****************************************************************************/
/*!
* \struct dvbpsi_bat_ts_s
* \brief BAT transport stream description structure.
*
* This structure is used to store a decoded BAT service description.
* (ETSI EN 300 468 V1.5.1 section 5.2.2).
*/
/*!
* \typedef struct dvbpsi_bat_ts_s dvbpsi_bat_ts_t
* \brief dvbpsi_bat_ts_t type definition.
*/
typedef struct dvbpsi_bat_ts_s
{
uint16_t i_ts_id; /*!< transport stream id */
uint16_t i_orig_network_id; /*!< original network id */
dvbpsi_descriptor_t * p_first_descriptor; /*!< descriptor list */
struct dvbpsi_bat_ts_s * p_next; /*!< next element of
the list */
} dvbpsi_bat_ts_t;
/*****************************************************************************
* dvbpsi_bat_t
*****************************************************************************/
/*!
* \struct dvbpsi_bat_s
* \brief BAT structure.
*
* This structure is used to store a decoded BAT.
* (ETSI EN 300 468 V1.5.1 section 5.2.2).
*/
/*!
* \typedef struct dvbpsi_bat_s dvbpsi_bat_t
* \brief dvbpsi_bat_t type definition.
*/
typedef struct dvbpsi_bat_s
{
uint16_t i_bouquet_id; /*!< bouquet_id */
uint8_t i_version; /*!< version_number */
int b_current_next; /*!< current_next_indicator */
dvbpsi_descriptor_t * p_first_descriptor; /*!< descriptor list */
dvbpsi_bat_ts_t * p_first_ts; /*!< transport stream description
list */
} dvbpsi_bat_t;
/*****************************************************************************
* dvbpsi_bat_callback
*****************************************************************************/
/*!
* \typedef void (* dvbpsi_bat_callback)(void* p_cb_data,
dvbpsi_bat_t* p_new_bat)
* \brief Callback type definition.
*/
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,
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 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,
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,
uint16_t i_extension)
* \brief Destroy a BAT decoder.
* \param p_demux 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,
uint16_t i_extension);
/*****************************************************************************
* dvbpsi_InitBAT/dvbpsi_NewBAT
*****************************************************************************/
/*!
* \fn void dvbpsi_InitBAT(dvbpsi_bat_t *p_bat, uint16_t i_bouquet_id, uint8_t i_version,
int b_current_next)
* \brief Initialize a user-allocated dvbpsi_bat_t structure.
* \param p_bat pointer to the BAT structure
* \param i_bouquet_id bouquet ID
* \param i_version BAT version
* \param b_current_next current next indicator
* \param i_network_id original network id
* \return nothing.
*/
void dvbpsi_InitBAT(dvbpsi_bat_t *p_bat, uint16_t i_bouquet_id, uint8_t i_version,
int b_current_next);
/*!
* \def dvbpsi_NewBAT(p_bat, i_bouquet_id, i_version, b_current_next)
* \brief Allocate and initialize a new dvbpsi_bat_t structure.
* \param p_bat pointer to the BAT structure
* \param i_bouquet_id bouquet ID
* \param i_version BAT version
* \param b_current_next current next indicator
* \param i_network_id original network id
* \return nothing.
*/
#define dvbpsi_NewBAT(p_bat, i_bouquet_id, i_version, b_current_next) \
do { \
p_bat = (dvbpsi_bat_t*)malloc(sizeof(dvbpsi_bat_t)); \
if(p_bat != NULL) \
dvbpsi_InitBAT(p_bat, i_bouquet_id, i_version, b_current_next); \
} while(0);
/*****************************************************************************
* dvbpsi_EmptyBAT/dvbpsi_DeleteBAT
*****************************************************************************/
/*!
* \fn void dvbpsi_EmptyBAT(dvbpsi_bat_t* p_bat)
* \brief Clean a dvbpsi_bat_t structure.
* \param p_bat pointer to the BAT structure
* \return nothing.
*/
void dvbpsi_EmptyBAT(dvbpsi_bat_t *p_bat);
/*!
* \def dvbpsi_DeleteBAT(p_bat)
* \brief Clean and free a dvbpsi_bat_t structure.
* \param p_bat pointer to the BAT structure
* \return nothing.
*/
#define dvbpsi_DeleteBAT(p_bat) \
do { \
dvbpsi_EmptyBAT(p_bat); \
free(p_bat); \
} while(0);
/*****************************************************************************
* dvbpsi_GenBATSections
*****************************************************************************
*!
* \fn dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_bat_t* p_bat)
* \brief BAT generator
* \param p_bat BAT structure
* \return a pointer to the list of generated PSI sections.
*
* Generate BAT sections based on the dvbpsi_bat_t structure.
*****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_GenBATSections(dvbpsi_bat_t * p_bat);
#ifdef __cplusplus
};
#endif
#else
#error "Multiple inclusions of bat.h"
#endif
/*****************************************************************************
* bat_private.h: private BAT structures
*----------------------------------------------------------------------------
* Copyright (C) 2001-2010 VideoLAN
* $Id: bat_private.h 88 2004-02-24 14:31:18Z sam $
*
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
*----------------------------------------------------------------------------
*
*****************************************************************************/
#ifndef _DVBPSI_BAT_PRIVATE_H_
#define _DVBPSI_BAT_PRIVATE_H_
/*****************************************************************************
* dvbpsi_bat_decoder_t
*****************************************************************************
* BAT decoder.
*****************************************************************************/
typedef struct dvbpsi_bat_decoder_s
{
dvbpsi_bat_callback pf_callback;
void * p_cb_data;
dvbpsi_bat_t current_bat;
dvbpsi_bat_t * p_building_bat;
int b_current_valid;
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);
/*****************************************************************************
* dvbpsi_DecodeBATSections
*****************************************************************************
* BAT decoder.
*****************************************************************************/
void dvbpsi_DecodeBATSections(dvbpsi_bat_t* p_bat,
dvbpsi_psi_section_t* p_section);
/*****************************************************************************
* dvbpsi_BATAddTS
*****************************************************************************
* Add a TS description at the end of the BAT.
*****************************************************************************/
dvbpsi_bat_ts_t *dvbpsi_BATAddTS(dvbpsi_bat_t* p_bat,
uint16_t i_ts_id, uint16_t i_orig_network_id);
/*****************************************************************************
* dvbpsi_BATBouquetAddDescriptor
*****************************************************************************
* Add a descriptor in the BAT Bouquet descriptors (the first loop description),
* which is in the first loop of BAT.
*****************************************************************************/
dvbpsi_descriptor_t *dvbpsi_BATBouquetAddDescriptor(
dvbpsi_bat_t *p_bat,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
/*****************************************************************************
* dvbpsi_BATTSAddDescriptor
*****************************************************************************
* Add a descriptor in the BAT TS descriptors, which is in the second loop of BAT.
*****************************************************************************/
dvbpsi_descriptor_t *dvbpsi_BATTSAddDescriptor(
dvbpsi_bat_ts_t *p_ts,
uint8_t i_tag, uint8_t i_length,
uint8_t *p_data);
#else
#error "Multiple inclusions of bat_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