Commit 29256049 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Merge branch 'branch/libdvbpsi-ng' of git.m2x.eu:libdvbpsi

Conflicts:
	configure.ac
	examples/decode_mpeg.c
	examples/get_pcr_pid.c
	src/Makefile.am
	src/demux.h
	src/dvbpsi.h
	src/dvbpsi_private.h
	src/psi.h
	src/tables/bat.h
	src/tables/bat_private.h
	src/tables/cat.h
	src/tables/cat_private.h
	src/tables/eit.h
	src/tables/eit_private.h
	src/tables/nit.h
	src/tables/nit_private.h
	src/tables/pat.h
	src/tables/pat_private.h
	src/tables/pmt.h
	src/tables/pmt_private.h
	src/tables/sdt.h
	src/tables/sdt_private.h
	src/tables/sis.h
	src/tables/sis_private.h
	src/tables/tot.h
	src/tables/tot_private.h
parents 08e3266c 2fede7bd
......@@ -21,12 +21,14 @@ configure
libtool
stamp-*
*-stamp
doc/doxygen
examples/decode_mpeg
examples/decode_pat
examples/decode_pmt
examples/decode_sdt
examples/decode_bat
examples/get_pcr_pid
examples/dvbinfo/dvbinfo
misc/gen_crc
misc/gen_pat
misc/gen_pmt
......
INSTALL file for "libdvbpsi".
* Developers
* Configuring "libdvbpsi"
* Building "libdvbpsi"
* Installing and using "libdvbpsi"
* Building documentation
* Building packages
Developers
==========
Before starting to enhance libdvbpsi as you downloaded it from the git repository
at git.videolan.org make sure you have autotools (autoconf, automake, m4, libtool)
installed.
Clone the repository:
git clone git://git.videolan.org/libdvbpsi.git
In contrast to other autotools enabled programs libdvbpsi uses a script named
'bootstrap' to generate the configure script. Others use a program 'autogen.sh'
for that. For libdvbpsi you need to run:
./bootstrap
Run the configure script for development:
./configure --prefix=/usr --enable-debug --disable-release
Now you can start enhancing libdvbpsi.
Configuring "libdvbpsi"
=======================
......@@ -26,7 +55,6 @@ Building "libdvbpsi"
Once configured, run 'make' to build the library and the programs
located in the 'examples' and 'misc' directories.
Installing and using "libdvbpsi"
================================
......@@ -54,5 +82,10 @@ doxygen tool (http://www.doxygen.org/) and the graphviz tool
Building packages
=================
Further writing.
Once configure, run 'make dist', this will generate a libdvbpsi-${VERSION}.tar.gz
and libdvbpsi-${VERSION}.tar.bz2. If you intend to build a package for RPM based
linux distributions, then you can run 'rpmbuild -ta libdvbpsi-${VERSION}.tar.gz'
or 'rpmbuild -ta libdvbpsi-${VERSION}.tar.bz2'.
For distributions that use another package management system look at their documentation
on howto create a installable package for it.
$Id$
Changes between 0.2.2 and 1.0.0:
--------------------------------
* new example application dvbinfo
* updated documentation (new api howto)
* add log callback (remove fprintf's)
* make API more consistent
- introduces dvbpsi_t typedef
- removed dvbpis_handle
Changes between 0.2.1 and 0.2.2:
--------------------------------
......
AC_INIT(libdvbpsi, 0.2.2)
AC_INIT(libdvbpsi, 1.0.0)
AC_PREREQ(2.50)
AC_CONFIG_AUX_DIR(.auto)
......@@ -7,7 +7,7 @@ AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
#AC_CANONICAL_HOST
dnl AC_CANONICAL_HOST
AC_PROG_CC
AC_STDC_HEADERS
AC_C_INLINE
......@@ -15,9 +15,8 @@ AC_C_INLINE
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
dnl default CFLAGS
CFLAGS="${CFLAGS} -Wall -DDVBPSI_DIST --std=gnu99"
CFLAGS="${CFLAGS} -Wall -Werror --std=gnu99 -D_GNU_SOURCE"
CFLAGS="${CFLAGS} -Wpointer-arith -Wcast-align -Wcast-qual -Wstrict-prototypes -Wshadow -Waggregate-return -Wmissing-prototypes -Wnested-externs -Wsign-compare"
dnl check the operating system
......@@ -37,7 +36,7 @@ AC_ARG_ENABLE(debug,
esac],[debug=false])
if test "$debug" = "true"
then
CFLAGS="${CFLAGS} -DDEBUG -g"
CFLAGS="${CFLAGS} -g -ggdb3"
fi
......@@ -53,12 +52,12 @@ if test "$release" = "true"
then
CFLAGS="${CFLAGS} -O6"
else
CFLAGS="${CFLAGS} -O2"
CFLAGS="${CFLAGS} -O2 -DDVBPSI_DIST"
fi
dnl Check for headers
AC_CHECK_HEADERS(stdint.h inttypes.h)
AC_CHECK_FUNCS(gettimeofday)
AC_CHECK_HEADERS(stdbool.h stdint.h inttypes.h getopt.h strings.h sys/time.h)
dnl AC_CHECK_FUNCS([gettimeofday])
AC_CHECK_HEADERS(sys/socket.h, [ac_have_sys_socket_h=yes])
AM_CONDITIONAL(HAVE_SYS_SOCKET_H, test "${ac_have_sys_socket_h}" = "yes")
......@@ -79,6 +78,7 @@ fi
AC_OUTPUT([Makefile
src/Makefile
examples/Makefile
examples/dvbinfo/Makefile
misc/Makefile
doc/Makefile
wince/Makefile
......
## Process this file with automake to produce Makefile.in
EXTRA_DIST=index.doxygen structure.doxygen usage.doxygen newdec.doxygen \
howto-new-api.doxygen \
decoder.dot doxygen.cfg
MOSTLYCLEANFILES=decoder.png
......
......@@ -31,7 +31,7 @@ PROJECT_NAME = libdvbpsi
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 0.2.2
PROJECT_NUMBER = 1.0.0
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
......@@ -585,6 +585,7 @@ INPUT = index.doxygen \
structure.doxygen \
usage.doxygen \
newdec.doxygen \
howto-new-api.doxygen \
../src \
../src/tables \
../src/descriptors
......
/*! \page Howto port dvbpsi API (upto version 0.2.0) to version 1.0.0
<p>An update to libdvbpsi API was long overdue. In time the API grew to be inconsistent and
needed some cleanup. The following issue are addressed in this version:</p>
<ul>
<li>explicit library handle allocation with <em>dvbpsi_NewHandle()</em> (delete with <em>dvbpsi_DeleteHandle()</em>)</li>
<li>consistent API for table and descriptor decoder/encoders</li>
<li>message callback function for easier intergrating libdvbpsi logging in applications</li>
</ul>
<p>The biggest change is the addition off an explicit dvbpsi_t pointer to
ALL table decoder and encoder API's. This dvbpsi_t pointer is a dvbpsi handle
which must be allocated using <em>dvbpsi_NewHandle()</em> and takes a callback function
for logging.
</p>
<code>dvbpsi_t *dvbpsi_NewHandle(dvbpsi_message_cb callback, enum dvbpsi_msg_level level);</code>
<p>The dvbpsi_t pointer must be released by calling <em>dvbpsi_DeleteHandle()</em></p>
<code>void dvbpsi_DeleteHandle(dvbpsi_t *handle);</code>
<h2>Example</h2>
<p>
The following examples shows howto translate existing applications. In these examples only
source code snippits are used and can thus not be compiled standalone. The examples are taken
from existing applications using libdvbpsi.
</p>
<p>In many existing applications the following scheme is used to attaching a PAT decoder to a dvbpsi handle:</p>
<code>
dvbpsi_handle handle;
dvbpsi_AttachPAT(handle, handle_PAT, data);
</code>
<p>The same scheme is used for other PSI tables too, this translate to the following code sequence:</p>
<code>
dvbpsi_t *handle = dvbpsi_NewHandle(&dvbpsi_message, DVBPSI_MSG_DEBUG);
if (handle == NULL)
goto error;
if (!dvbpsi_AttachPAT(handle, handle_PAT, data))
{
dvbpsi_DeleteHandle(handle);
handle = NULL;
goto error;
}
return 0;
error:
if (dvbpsi_HasDecoder(handle))
dvbpsi_DetachPAT(andle);
if (handle)
dvbpsi_DeleteHandle(handle);
return -1;
</code>
<p>The <em>message callback function</em> <b>dvbpsi_message</b> is defined as follows below. In this case
the output goes directly to the console. Applications however can call into their messaging API and pass
along libdvbpsi messages if wanted.
</p>
<code>
static void dvbpsi_message(dvbpsi_t *p_dvbpsi, const dvbpsi_msg_level_t level, const char* msg)
{
switch(level)
{
case DVBPSI_MSG_ERROR: fprintf(stderr, "Error: "); break;
case DVBPSI_MSG_WARN: fprintf(stderr, "Warning: "); break;
case DVBPSI_MSG_DEBUG: fprintf(stderr, "Debug: "); break;
default:
return;
}
fprintf(stderr, "%s\n", msg);
}
</code>
*/
......@@ -15,7 +15,9 @@ describes how to use it and the "C" API.</p>
<h2>What is libdvbpsi ?</h2>
<p><em>libdvbpsi</em> is a set of tools which allows to decode and generate all the Program specific Information (<em>PSI</em>) present in a MPEG2 TS or a DVB stream.</p>
<p><em>libdvbpsi</em> is a library that provides API's to decode and generate all the Program specific Information (<em>PSI</em>) and descriptors present in a MPEG2 TS or a DVB stream.</p>
<p><b><em>libdvbpsi</em> version 1.0.0 breaks API compatibility with earlier versions</b>. The benefits are a more consistent API and the library no longer makes calls to printf which improves its use in threaded applications.</p>
<p>The two keywords are <em>portability</em> and <em>simplicity</em>.</p>
......@@ -44,6 +46,7 @@ describes how to use it and the "C" API.</p>
<li>\ref structure</li>
<li>\ref usage</li>
<li>\ref newdec</li>
<li>\ref howto-new-api</li>
</ul>
*/
......@@ -29,4 +29,6 @@ tables.</p>
\ref usage
\ref howto-new-api
*/
/*! \page usage API usage
<p>When the application needs a new decoder it just has to call the
<p>Each application requires a handle to the dvbpsi library. The function
dvbpsi_NewHandle(&message_cb, DVBPSI_MSG_DEBUG) will return a handle. All
error, warning or debug messages will trigger the <em>message_cb</em> function.
Unless DVBPSI_MSG_NONE is passed to dvbpsi_NewHandle(). For each <em>
dvbpsi_AttachXXX()</em> function a unique dvbpsi handle must be used.</p>
<p>A dvbpsi handle must be passed to an <em>dvbpsi_AttachXXX()</em> function
which attaches a decoder to the (dvbpsi_t*)->p_private pointer. The
<em>dvbpsi_AttachXXX()</em> function where XXX is the name of the table
(ex: dvbpsi_AttachPAT()). The function returns a handle on the new
decoder.</p>
(ex: dvbpsi_AttachPAT()). The function returns the dvbpsi handle with the
new decoder attached decoder.</p>
<p>Then the application has to send the TS packets needed by the decoder
by calling the dvbpsi_PushPacket() function. If a new table is complete
......@@ -12,10 +19,9 @@ called <em>dvbpsi_AttachXXX()</em>.</p>
<p>When the application don't need the decoder anymore it just has to
call the <em>dvbpsi_DetachXXX()</em> function (ex:
dvbpsi_DetachPAT()).</p>
<p>In this version of <em>libdvbpsi</em> the descriptors aren't decoded.
These decoders will come in the next release.</p>
dvbpsi_DetachPAT()). The dvbpsi handle must be released by calling
dvbpsi_DeleteHandle(). At the time of calling the decoder must already
have been detached.</p>
<p>For specific tools, the best to do is to have a look at the include
file:</p>
......@@ -35,4 +41,6 @@ file:</p>
\ref structure
\ref howto-new-api
*/
## Process this file with automake to produce Makefile.in
SUBDIRS = dvbinfo
DIST_SUBDIRS = $(SUBDIRS)
noinst_PROGRAMS = decode_pat decode_pmt get_pcr_pid decode_sdt decode_mpeg decode_bat
decode_pat_SOURCES = decode_pat.c
decode_pat_CPPFLAGS = -DDVBPSI_DIST
decode_pat_LDFLAGS = -L../src -ldvbpsi
decode_pmt_SOURCES = decode_pmt.c
decode_pmt_CPPFLAGS = -DDVBPSI_DIST
decode_pmt_LDFLAGS = -L../src -ldvbpsi -lm
get_pcr_pid_SOURCES = get_pcr_pid.c
get_pcr_pid_CPPFLAGS = -DDVBPSI_DIST
get_pcr_pid_LDFLAGS = -L../src -ldvbpsi -lm
decode_sdt_SOURCES = decode_sdt.c
decode_sdt_CPPFLAGS = -DDVBPSI_DIST
decode_sdt_LDFLAGS = -L../src -ldvbpsi
decode_mpeg_SOURCES = decode_mpeg.c
if HAVE_SYS_SOCKET_H
decode_mpeg_SOURCES += connect.c connect.h
endif
decode_mpeg_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -DDVBPSI_DIST
decode_mpeg_LDFLAGS = -L../src -ldvbpsi -lm
decode_bat_SOURCES = decode_bat.c
decode_bat_CPPFLAGS = -DDVBPSI_DIST
decode_bat_LDFLAGS = -L../src -ldvbpsi
/*****************************************************************************
* decode_bat.c: BAT decoder example
*----------------------------------------------------------------------------
* Copyright (C) 2001-2010 VideoLAN
* Copyright (C) 2001-2011 VideoLAN
* $Id: decode_bat.c 01 2010-04-01 17:55:18 zhuzlu $
*
* Authors: Zhu zhenglu <zhuzlu@gmail.com>
......@@ -24,11 +24,11 @@
*
*****************************************************************************/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
......@@ -56,7 +56,7 @@
/*****************************************************************************
* ReadPacket
*****************************************************************************/
static int ReadPacket(int i_fd, uint8_t* p_dst)
static bool ReadPacket(int i_fd, uint8_t* p_dst)
{
int i = 187;
int i_rc = 1;
......@@ -75,7 +75,7 @@ static int ReadPacket(int i_fd, uint8_t* p_dst)
i -= i_rc;
}
return (i == 0) ? 1 : 0;
return (i == 0) ? true : false;
}
......@@ -198,15 +198,28 @@ static void DumpBAT(void* p_zero, dvbpsi_bat_t* p_bat)
/*****************************************************************************
* NewSubtable
*****************************************************************************/
static void NewSubtableBAT(void * p_zero, dvbpsi_handle h_dvbpsi,
static void NewSubtableBAT(void * p_zero, dvbpsi_t *p_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);
if (!dvbpsi_AttachBAT(p_dvbpsi, i_table_id, i_extension, DumpBAT, NULL))
fprintf(stderr, "failed to attach BAT subdecoder\n");
}
}
static void message(dvbpsi_t *handle, const dvbpsi_msg_level_t level, const char* msg)
{
switch(level)
{
case DVBPSI_MSG_ERROR: fprintf(stderr, "Error: "); break;
case DVBPSI_MSG_WARN: fprintf(stderr, "Warning: "); break;
case DVBPSI_MSG_DEBUG: fprintf(stderr, "Debug: "); break;
default: /* do nothing */
return;
}
fprintf(stderr, "%s\n", msg);
}
/*****************************************************************************
* main
......@@ -215,15 +228,21 @@ int main(int i_argc, char* pa_argv[])
{
int i_fd;
uint8_t data[188];
dvbpsi_handle h_dvbpsi;
int b_ok;
dvbpsi_t *p_dvbpsi;
bool b_ok;
if(i_argc != 2)
return 1;
i_fd = open(pa_argv[1], 0);
if (i_fd < 0)
return 1;
h_dvbpsi = dvbpsi_AttachDemux(NewSubtableBAT, NULL);
p_dvbpsi = dvbpsi_NewHandle(&message, DVBPSI_MSG_DEBUG);
if (p_dvbpsi == NULL)
goto out;
if (!dvbpsi_AttachDemux(p_dvbpsi, NewSubtableBAT, NULL))
goto out;
b_ok = ReadPacket(i_fd, data);
......@@ -231,11 +250,16 @@ int main(int i_argc, char* pa_argv[])
{
uint16_t i_pid = ((uint16_t)(data[1] & 0x1f) << 8) + data[2];
if(i_pid == 0x11)
dvbpsi_PushPacket(h_dvbpsi, data);
dvbpsi_PushPacket(p_dvbpsi, data);
b_ok = ReadPacket(i_fd, data);
}
dvbpsi_DetachDemux(h_dvbpsi);
out:
if (p_dvbpsi)
{
dvbpsi_DetachDemux(p_dvbpsi);
dvbpsi_DeleteHandle(p_dvbpsi);
}
close(i_fd);
return 0;
}
/*****************************************************************************
* decode_mpeg.c: MPEG decoder example
*----------------------------------------------------------------------------
* Copyright (C) 2001-2010 VideoLAN
* Copyright (C) 2001-2011 VideoLAN
* $Id: decode_mpeg.c 104 2005-03-21 13:38:56Z massiot $
*
* Authors: Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
......@@ -29,10 +29,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
#define HAVE_GETTIMEOFDAY 1
#include <sys/time.h>
#endif
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
......@@ -100,7 +104,7 @@ typedef int64_t mtime_t;
typedef struct
{
dvbpsi_handle handle;
dvbpsi_t * handle;
int i_pat_version;
int i_ts_id;
......@@ -119,7 +123,7 @@ typedef struct ts_pid_s
typedef struct ts_pmt_s
{
dvbpsi_handle handle;
dvbpsi_t * handle;
int i_number; /* i_number = 0 is actually a NIT */
int i_pmt_version;
......@@ -183,6 +187,10 @@ static int ReadPacketFromSocket( int i_socket, uint8_t* p_dst, size_t i_size)
*****************************************************************************/
static void report_Header( int i_report )
{
#ifndef HAVE_GETTIMEOFDAY
printf("*** WARNING: !!! no gettimeofday support found !!! timing information will not be given !!! ***\n");
#endif
switch(i_report)
{
case REPORT_PCR:
......@@ -200,11 +208,7 @@ static void report_Header( int i_report )
*****************************************************************************/
#ifdef HAVE_GETTIMEOFDAY
static mtime_t report_UDPPacketTiming( int32_t i_seqno, int32_t bytes, mtime_t time_prev, mtime_t *time_base )
#else
static void report_UDPPacketTiming( int32_t i_seqno, int32_t bytes )
#endif
{
#ifdef HAVE_GETTIMEOFDAY
mtime_t time_current;
mtime_t tv_delta;
struct timeval tv;
......@@ -226,10 +230,14 @@ static void report_UDPPacketTiming( int32_t i_seqno, int32_t bytes )
time_prev = time_current;
printf( "%d\n", bytes );
return time_prev;
}
#else
printf( "\n" );
#endif
static void report_UDPPacketTiming( int32_t i_seqno, int32_t bytes )
{
printf( "%.2d %"PRId64" %"PRId64" ", i_seqno, 0UL, 0UL );
printf( "%d\n", bytes );
}
#endif
#ifdef HAVE_GETTIMEOFDAY
static mtime_t report_PCRPacketTiming( int i_cc, ts_pid_t *ts_pid,
......@@ -285,6 +293,19 @@ static void report_PCRPacketTiming( int i_cc, ts_pid_t *ts_pid,
#endif
}
static void message(dvbpsi_t *handle, const dvbpsi_msg_level_t level, const char* msg)
{
switch(level)
{
case DVBPSI_MSG_ERROR: fprintf(stderr, "Error: "); break;
case DVBPSI_MSG_WARN: fprintf(stderr, "Warning: "); break;
case DVBPSI_MSG_DEBUG: fprintf(stderr, "Debug: "); break;
default: /* do nothing */
return;
}
fprintf(stderr, "%s\n", msg);
}
/*****************************************************************************
* DumpPAT
*****************************************************************************/
......@@ -293,6 +314,14 @@ static void DumpPAT(void* p_data, dvbpsi_pat_t* p_pat)
dvbpsi_pat_program_t* p_program = p_pat->p_first_program;
ts_stream_t* p_stream = (ts_stream_t*) p_data;
if (p_stream->pmt.handle)
{
fprintf(stderr, "freeing old PMT\n");
dvbpsi_DetachPMT(p_stream->pmt.handle);
dvbpsi_DeleteHandle(p_stream->pmt.handle);
p_stream->pmt.handle = NULL;
}
p_stream->pat.i_pat_version = p_pat->i_version;
p_stream->pat.i_ts_id = p_pat->i_ts_id;
......@@ -303,12 +332,28 @@ static void DumpPAT(void* p_data, dvbpsi_pat_t* p_pat)
fprintf( stderr, " | program_number @ [NIT|PMT]_PID\n");
while( p_program )
{
if (p_stream->pmt.handle)
{
dvbpsi_DetachPMT(p_stream->pmt.handle);
dvbpsi_DeleteHandle(p_stream->pmt.handle);
p_stream->pmt.handle = NULL;
}
p_stream->i_pmt++;
p_stream->pmt.i_number = p_program->i_number;
p_stream->pmt.pid_pmt = &p_stream->pid[p_program->i_pid];
p_stream->pmt.pid_pmt->i_pid = p_program->i_pid;
p_stream->pmt.handle = dvbpsi_AttachPMT( p_program->i_number, DumpPMT, p_stream );
p_stream->pmt.handle = dvbpsi_NewHandle(&message, DVBPSI_MSG_DEBUG);
if (p_stream->pmt.handle == NULL)
{
fprintf(stderr, "could not allocate new dvbpsi_t handle\n");
break;
}
if (!dvbpsi_AttachPMT(p_stream->pmt.handle, p_program->i_number, DumpPMT, p_stream ))
{
dvbpsi_DeleteHandle(p_stream->pmt.handle);
fprintf(stderr, "could not attach PMT\n");
break;
}
fprintf( stderr, " | %14d @ 0x%x (%d)\n",
p_program->i_number, p_program->i_pid, p_program->i_pid);
p_program = p_program->p_next;
......@@ -546,7 +591,7 @@ int main(int i_argc, char* pa_argv[])
uint8_t *p_data = NULL;
ts_stream_t *p_stream = NULL;
int i_len = 0;
int b_verbose = 0;
bool b_verbose = false;
/* parser commandline arguments */
do {
......@@ -581,7 +626,7 @@ int main(int i_argc, char* pa_argv[])
break;
#endif
case 'v':
b_verbose = 1;
b_verbose = true;
break;
case -1:
break;
......@@ -636,8 +681,13 @@ int main(int i_argc, char* pa_argv[])
report_Header( i_report );
#endif
p_stream->pat.handle = dvbpsi_NewHandle(&message, DVBPSI_MSG_DEBUG);
if (p_stream->pat.handle == NULL)
goto dvbpsi_out;
if (!dvbpsi_AttachPAT(p_stream->pat.handle, DumpPAT, p_stream))
goto dvbpsi_out;