Commit 58845e9b authored by Andy Gatward's avatar Andy Gatward Committed by Christophe Massiot

* ALL: EPG pass-through support, with SDT regeneration.

parent 39709170
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Andy Gatward <a.j.gatward@reading.ac.uk>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -34,12 +35,17 @@ ...@@ -34,12 +35,17 @@
#include <dvbpsi/demux.h> #include <dvbpsi/demux.h>
#include <dvbpsi/pat.h> #include <dvbpsi/pat.h>
#include <dvbpsi/eit.h> #include <dvbpsi/eit.h>
#include <dvbpsi/sdt.h>
#include <dvbpsi/dr.h> #include <dvbpsi/dr.h>
#include <dvbpsi/psi.h> #include <dvbpsi/psi.h>
/***************************************************************************** /*****************************************************************************
* Local declarations * Local declarations
*****************************************************************************/ *****************************************************************************/
#define SDT_PID 0x11
#define EIT_PID 0x12
typedef struct ts_pid_t typedef struct ts_pid_t
{ {
int i_refcount; int i_refcount;
...@@ -63,6 +69,8 @@ static sid_t **pp_sids = NULL; ...@@ -63,6 +69,8 @@ static sid_t **pp_sids = NULL;
static int i_nb_sids = 0; static int i_nb_sids = 0;
static dvbpsi_handle p_pat_dvbpsi_handle; static dvbpsi_handle p_pat_dvbpsi_handle;
static dvbpsi_handle p_sdt_dvbpsi_handle;
static dvbpsi_handle p_eit_dvbpsi_handle;
static dvbpsi_pat_t *p_current_pat = NULL; static dvbpsi_pat_t *p_current_pat = NULL;
static int i_demux_fd; static int i_demux_fd;
...@@ -90,6 +98,9 @@ static void NewPAT( output_t *p_output ); ...@@ -90,6 +98,9 @@ static void NewPAT( output_t *p_output );
static void NewPMT( output_t *p_output ); static void NewPMT( output_t *p_output );
static void PATCallback( void *_unused, dvbpsi_pat_t *p_pat ); static void PATCallback( void *_unused, dvbpsi_pat_t *p_pat );
static void PMTCallback( void *_unused, dvbpsi_pmt_t *p_pmt ); static void PMTCallback( void *_unused, dvbpsi_pmt_t *p_pmt );
static void PSITableCallback( void *_unused, dvbpsi_handle h_dvbpsi,
uint8_t i_table_id, uint16_t i_extension );
static void SDTCallback( void *_unused, dvbpsi_sdt_t *p_sdt );
/***************************************************************************** /*****************************************************************************
* demux_Open * demux_Open
...@@ -113,6 +124,15 @@ void demux_Open( void ) ...@@ -113,6 +124,15 @@ void demux_Open( void )
SetPID(0); /* PAT */ SetPID(0); /* PAT */
p_pat_dvbpsi_handle = dvbpsi_AttachPAT( PATCallback, NULL ); p_pat_dvbpsi_handle = dvbpsi_AttachPAT( PATCallback, NULL );
if( b_enable_epg )
{
SetPID(SDT_PID); /* SDT */
p_sdt_dvbpsi_handle = dvbpsi_AttachDemux( PSITableCallback, NULL );
SetPID(EIT_PID); /* EIT */
p_eit_dvbpsi_handle = dvbpsi_AttachDemux( PSITableCallback, NULL );
}
} }
/***************************************************************************** /*****************************************************************************
...@@ -165,6 +185,14 @@ static void demux_Handle( block_t *p_ts ) ...@@ -165,6 +185,14 @@ static void demux_Handle( block_t *p_ts )
if ( block_UnitStart( p_ts ) ) if ( block_UnitStart( p_ts ) )
SendPAT(); SendPAT();
} }
else if ( i_pid == EIT_PID )
{
dvbpsi_PushPacket( p_eit_dvbpsi_handle, p_ts->p_ts );
}
else if (i_pid == SDT_PID )
{
dvbpsi_PushPacket( p_sdt_dvbpsi_handle, p_ts->p_ts );
}
else else
{ {
for ( i = 0; i < i_nb_sids; i++ ) for ( i = 0; i < i_nb_sids; i++ )
...@@ -655,8 +683,9 @@ static void SendPMT( sid_t *p_sid ) ...@@ -655,8 +683,9 @@ static void SendPMT( sid_t *p_sid )
for ( i = 0; i < i_nb_outputs; i++ ) for ( i = 0; i < i_nb_outputs; i++ )
{ {
if ( pp_outputs[i]->i_maddr && pp_outputs[i]->i_sid == p_sid->i_sid if ( pp_outputs[i]->i_maddr && pp_outputs[i]->i_sid == p_sid->i_sid )
&& pp_outputs[i]->p_pmt_section != NULL ) {
if ( pp_outputs[i]->p_pmt_section != NULL )
{ {
block_t *p_block; block_t *p_block;
...@@ -671,6 +700,57 @@ static void SendPMT( sid_t *p_sid ) ...@@ -671,6 +700,57 @@ static void SendPMT( sid_t *p_sid )
p_block = p_next; p_block = p_next;
} }
} }
if ( pp_outputs[i]->p_sdt_section != NULL )
{
block_t *p_block;
p_block = WritePSISection( pp_outputs[i]->p_sdt_section,
SDT_PID,
&pp_outputs[i]->i_sdt_cc );
while ( p_block != NULL )
{
block_t *p_next = p_block->p_next;
p_block->i_refcount--;
output_Put( pp_outputs[i], p_block );
p_block = p_next;
}
}
}
}
}
/*****************************************************************************
* SendEIT
*****************************************************************************/
static void SendEIT( dvbpsi_psi_section_t *p_section, uint16_t i_sid,
uint8_t i_table_id )
{
int i;
for( i = 0; i < i_nb_outputs; i++ )
{
if ( pp_outputs[i]->i_maddr && pp_outputs[i]->i_sid == i_sid )
{
p_section->p_data[8] = (i_sid >> 8) & 0xff;
p_section->p_data[9] = i_sid & 0xff;
p_section->p_data[13] = pp_outputs[i]->i_eit_last_table_id;
dvbpsi_BuildPSISection( p_section );
block_t *p_block;
p_block = WritePSISection( p_section,
EIT_PID,
&pp_outputs[i]->i_eit_cc );
while ( p_block != NULL )
{
block_t *p_next = p_block->p_next;
p_block->i_refcount--;
output_Put( pp_outputs[i], p_block );
p_block = p_next;
}
}
} }
} }
...@@ -1160,3 +1240,81 @@ static void PMTCallback( void *_unused, dvbpsi_pmt_t *p_pmt ) ...@@ -1160,3 +1240,81 @@ static void PMTCallback( void *_unused, dvbpsi_pmt_t *p_pmt )
UpdatePMT( p_pmt->i_program_number ); UpdatePMT( p_pmt->i_program_number );
} }
static void PSITableCallback( void *_unused, dvbpsi_handle h_dvbpsi,
uint8_t i_table_id, uint16_t i_extension )
{
/* EIT tables */
if ( i_table_id == 0x43 || ( i_table_id >= 0x50 && i_table_id <= 0x5f ) )
{
SendEIT( h_dvbpsi->p_current_section, i_extension, i_table_id );
}
/* SDT tables */
if ( i_table_id == 0x42 )
{
dvbpsi_AttachSDT( h_dvbpsi, i_table_id, i_extension, SDTCallback,
NULL );
}
}
static void SDTCallback( void *_unused, dvbpsi_sdt_t *p_sdt )
{
int i;
dvbpsi_sdt_service_t *p_service = p_sdt->p_first_service;
dvbpsi_descriptor_t *p_descriptor;
dvbpsi_sdt_t *p_new_sdt = NULL;
dvbpsi_sdt_service_t *p_new_service;
dvbpsi_psi_section_t *p_old_section;
msg_Dbg( NULL, "new SDT, version %d", p_sdt->i_version );
while ( p_service != NULL )
{
for ( i = 0; i < i_nb_outputs; i++ )
{
if ( pp_outputs[i]->i_maddr
&& pp_outputs[i]->i_sid == p_service->i_service_id )
{
p_new_sdt = malloc(sizeof(dvbpsi_sdt_t));
dvbpsi_InitSDT( p_new_sdt, p_service->i_service_id,
p_sdt->i_version, p_sdt->b_current_next,
p_sdt->i_network_id );
p_new_service = dvbpsi_SDTAddService( p_new_sdt,
p_service->i_service_id, p_service->b_eit_schedule,
p_service->b_eit_present, p_service->i_running_status, 0 );
p_descriptor = p_service->p_first_descriptor;
while ( p_descriptor != NULL )
{
dvbpsi_SDTServiceAddDescriptor( p_new_service,
p_descriptor->i_tag, p_descriptor->i_length,
p_descriptor->p_data );
p_descriptor = p_descriptor->p_next;
}
p_old_section = pp_outputs[i]->p_sdt_section;
pp_outputs[i]->p_sdt_section
= dvbpsi_GenSDTSections( p_new_sdt );
if ( p_old_section != NULL )
{
dvbpsi_DeletePSISections( p_old_section );
}
dvbpsi_DeleteSDT( p_new_sdt );
}
}
p_service = p_service->p_next;
}
dvbpsi_DeleteSDT( p_sdt );
}
...@@ -55,6 +55,7 @@ int i_bandwidth = 8; ...@@ -55,6 +55,7 @@ int i_bandwidth = 8;
char *psz_modulation = NULL; char *psz_modulation = NULL;
int b_budget_mode = 0; int b_budget_mode = 0;
int b_output_udp = 0; int b_output_udp = 0;
int b_enable_epg = 0;
volatile int b_hup_received = 0; volatile int b_hup_received = 0;
int i_verbose = DEFAULT_VERBOSITY; int i_verbose = DEFAULT_VERBOSITY;
...@@ -183,7 +184,7 @@ static void SigHandler( int i_signal ) ...@@ -183,7 +184,7 @@ static void SigHandler( int i_signal )
*****************************************************************************/ *****************************************************************************/
void usage() void usage()
{ {
msg_Raw( NULL, "Usage: dvblast [-q] -c <config file> [-r <remote socket>] [-t <ttl>] [-o <SSRC IP>] [-i <RT priority>] [-a <adapter>][-n <frontend_num>] -f <frequency> [-s <symbol rate>] [-v <0|13|18>] [-p] [-b <bandwidth>] [-m <modulation] [-u] [-U] [-d <dest IP:port>]" ); msg_Raw( NULL, "Usage: dvblast [-q] -c <config file> [-r <remote socket>] [-t <ttl>] [-o <SSRC IP>] [-i <RT priority>] [-a <adapter>][-n <frontend_num>] -f <frequency> [-s <symbol rate>] [-v <0|13|18>] [-p] [-b <bandwidth>] [-m <modulation] [-u] [-U] [-d <dest IP:port>] [-e]" );
msg_Raw( NULL, " -q: be quiet (less verbosity, repeat or use number for even quieter)" ); msg_Raw( NULL, " -q: be quiet (less verbosity, repeat or use number for even quieter)" );
msg_Raw( NULL, " -v: voltage to apply to the LNB (QPSK)" ); msg_Raw( NULL, " -v: voltage to apply to the LNB (QPSK)" );
msg_Raw( NULL, " -p: force 22kHz pulses for high-band selection (DVB-S)" ); msg_Raw( NULL, " -p: force 22kHz pulses for high-band selection (DVB-S)" );
...@@ -193,6 +194,7 @@ void usage() ...@@ -193,6 +194,7 @@ void usage()
msg_Raw( NULL, " -u: turn on budget mode (no hardware PID filtering)" ); msg_Raw( NULL, " -u: turn on budget mode (no hardware PID filtering)" );
msg_Raw( NULL, " -U: use raw UDP rather than RTP (required by some IPTV set top boxes)" ); msg_Raw( NULL, " -U: use raw UDP rather than RTP (required by some IPTV set top boxes)" );
msg_Raw( NULL, " -d: duplicate all received packets to a given port" ); msg_Raw( NULL, " -d: duplicate all received packets to a given port" );
msg_Raw( NULL, " -e: enable EPG pass through (EIT data)" );
exit(1); exit(1);
} }
...@@ -207,7 +209,7 @@ int main( int i_argc, char **pp_argv ) ...@@ -207,7 +209,7 @@ int main( int i_argc, char **pp_argv )
msg_Warn( NULL, "restarting" ); msg_Warn( NULL, "restarting" );
while ( ( c = getopt(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:s:v:pb:m:uUd:h")) != (char)EOF ) while ( ( c = getopt(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:s:v:pb:m:uUd:eh")) != (char)EOF )
{ {
switch ( c ) switch ( c )
{ {
...@@ -315,6 +317,10 @@ int main( int i_argc, char **pp_argv ) ...@@ -315,6 +317,10 @@ int main( int i_argc, char **pp_argv )
break; break;
} }
case 'e':
b_enable_epg = 1;
break;
case 'h': case 'h':
default: default:
usage(); usage();
......
...@@ -65,6 +65,9 @@ typedef struct output_t ...@@ -65,6 +65,9 @@ typedef struct output_t
uint8_t i_pat_version, i_pat_cc; uint8_t i_pat_version, i_pat_cc;
dvbpsi_psi_section_t *p_pmt_section; dvbpsi_psi_section_t *p_pmt_section;
uint8_t i_pmt_version, i_pmt_cc; uint8_t i_pmt_version, i_pmt_cc;
dvbpsi_psi_section_t *p_sdt_section;
uint8_t i_sdt_cc;
uint8_t i_eit_cc, i_eit_last_table_id;
/* configuration */ /* configuration */
uint16_t i_sid; /* 0 if raw mode */ uint16_t i_sid; /* 0 if raw mode */
...@@ -91,6 +94,7 @@ extern int i_bandwidth; ...@@ -91,6 +94,7 @@ extern int i_bandwidth;
extern char *psz_modulation; extern char *psz_modulation;
extern int b_budget_mode; extern int b_budget_mode;
extern int b_output_udp; extern int b_output_udp;
extern int b_enable_epg;
extern volatile int b_hup_received; extern volatile int b_hup_received;
extern mtime_t i_ca_timeout; extern mtime_t i_ca_timeout;
extern int i_comm_fd; extern int i_comm_fd;
...@@ -105,6 +109,7 @@ void msg_Dbg( void *_unused, const char *psz_format, ... ); ...@@ -105,6 +109,7 @@ void msg_Dbg( void *_unused, const char *psz_format, ... );
void msg_Raw( void *_unused, const char *psz_format, ... ); void msg_Raw( void *_unused, const char *psz_format, ... );
mtime_t mdate( void ); mtime_t mdate( void );
void msleep( mtime_t delay ); void msleep( mtime_t delay );
void hexDump( uint8_t *p_data, uint32_t i_len );
void dvb_Open( void ); void dvb_Open( void );
block_t * dvb_Read( void ); block_t * dvb_Read( void );
......
...@@ -87,12 +87,16 @@ int output_Init( output_t *p_output, in_addr_t i_maddr, uint16_t i_port ) ...@@ -87,12 +87,16 @@ int output_Init( output_t *p_output, in_addr_t i_maddr, uint16_t i_port )
p_output->i_cc = rand() & 0xffff; p_output->i_cc = rand() & 0xffff;
p_output->i_pat_cc = rand() & 0xf; p_output->i_pat_cc = rand() & 0xf;
p_output->i_pmt_cc = rand() & 0xf; p_output->i_pmt_cc = rand() & 0xf;
p_output->i_sdt_cc = rand() & 0xf;
p_output->i_eit_cc = rand() & 0xf;
p_output->i_pat_version = rand() & 0xff; p_output->i_pat_version = rand() & 0xff;
p_output->i_pmt_version = rand() & 0xff; p_output->i_pmt_version = rand() & 0xff;
p_output->p_pat_section = NULL; p_output->p_pat_section = NULL;
p_output->p_pmt_section = NULL; p_output->p_pmt_section = NULL;
p_output->p_sdt_section = NULL;
p_output->i_ref_timestamp = 0; p_output->i_ref_timestamp = 0;
p_output->i_ref_wallclock = mdate(); p_output->i_ref_wallclock = mdate();
p_output->i_eit_last_table_id = 0;
p_output->i_maddr = i_maddr; p_output->i_maddr = i_maddr;
p_output->i_port = i_port; p_output->i_port = i_port;
......
...@@ -142,3 +142,53 @@ void msleep( mtime_t delay ) ...@@ -142,3 +142,53 @@ void msleep( mtime_t delay )
nanosleep( &ts_delay, NULL ); nanosleep( &ts_delay, NULL );
} }
/*****************************************************************************
* hexDump
*****************************************************************************/
void hexDump( uint8_t *p_data, uint32_t i_len )
{
uint16_t i, j;
char *p_outline;
char *p_hrdata;
p_outline = malloc(69);
p_hrdata = malloc(17);
for( i = 0; i < i_len; i += 16 )
{
sprintf( p_outline, "%03x: ", i );
for( j = 0; j < 16; j++ )
{
if( i + j < i_len )
{
sprintf( &p_outline[5 + (3 * j)], "%02x ", p_data[i + j] );
if( p_data[i + j] >= 32 && p_data[i + j] <= 136 )
{
sprintf( &p_hrdata[j], "%c", p_data[i + j] );
}
else {
sprintf( &p_hrdata[j], "." );
}
}
else
{
sprintf( &p_outline[5 + (3 * j)], " " );
sprintf( &p_hrdata[j], " " );
}
}
sprintf( &p_outline[53], "%16s", p_hrdata );
msg_Dbg( NULL, p_outline );
}
free( p_hrdata );
free( p_outline );
}
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