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 @@
* $Id$
*
* 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
* it under the terms of the GNU General Public License as published by
......@@ -34,12 +35,17 @@
#include <dvbpsi/demux.h>
#include <dvbpsi/pat.h>
#include <dvbpsi/eit.h>
#include <dvbpsi/sdt.h>
#include <dvbpsi/dr.h>
#include <dvbpsi/psi.h>
/*****************************************************************************
* Local declarations
*****************************************************************************/
#define SDT_PID 0x11
#define EIT_PID 0x12
typedef struct ts_pid_t
{
int i_refcount;
......@@ -63,6 +69,8 @@ static sid_t **pp_sids = NULL;
static int i_nb_sids = 0;
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 int i_demux_fd;
......@@ -90,6 +98,9 @@ static void NewPAT( output_t *p_output );
static void NewPMT( output_t *p_output );
static void PATCallback( void *_unused, dvbpsi_pat_t *p_pat );
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
......@@ -113,6 +124,15 @@ void demux_Open( void )
SetPID(0); /* PAT */
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 )
if ( block_UnitStart( p_ts ) )
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
{
for ( i = 0; i < i_nb_sids; i++ )
......@@ -655,14 +683,66 @@ static void SendPMT( sid_t *p_sid )
for ( i = 0; i < i_nb_outputs; i++ )
{
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]->i_maddr && pp_outputs[i]->i_sid == p_sid->i_sid )
{
if ( pp_outputs[i]->p_pmt_section != NULL )
{
block_t *p_block;
p_block = WritePSISection( pp_outputs[i]->p_pmt_section,
p_sid->i_pmt_pid,
&pp_outputs[i]->i_pmt_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;
}
}
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( pp_outputs[i]->p_pmt_section,
p_sid->i_pmt_pid,
&pp_outputs[i]->i_pmt_cc );
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;
......@@ -891,7 +971,7 @@ static int PMTNeedsDescrambling( dvbpsi_pmt_t *p_pmt )
for( p_dr = p_pmt->p_first_descriptor; p_dr != NULL; p_dr = p_dr->p_next )
if( p_dr->i_tag == 0x9 )
return 1;
for( p_es = p_pmt->p_first_es; p_es != NULL; p_es = p_es->p_next )
for( p_dr = p_es->p_first_descriptor; p_dr != NULL;
p_dr = p_dr->p_next )
......@@ -1160,3 +1240,81 @@ static void PMTCallback( void *_unused, dvbpsi_pmt_t *p_pmt )
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;
char *psz_modulation = NULL;
int b_budget_mode = 0;
int b_output_udp = 0;
int b_enable_epg = 0;
volatile int b_hup_received = 0;
int i_verbose = DEFAULT_VERBOSITY;
......@@ -183,7 +184,7 @@ static void SigHandler( int i_signal )
*****************************************************************************/
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, " -v: voltage to apply to the LNB (QPSK)" );
msg_Raw( NULL, " -p: force 22kHz pulses for high-band selection (DVB-S)" );
......@@ -193,6 +194,7 @@ void usage()
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, " -d: duplicate all received packets to a given port" );
msg_Raw( NULL, " -e: enable EPG pass through (EIT data)" );
exit(1);
}
......@@ -207,7 +209,7 @@ int main( int i_argc, char **pp_argv )
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 )
{
......@@ -315,6 +317,10 @@ int main( int i_argc, char **pp_argv )
break;
}
case 'e':
b_enable_epg = 1;
break;
case 'h':
default:
usage();
......
......@@ -65,6 +65,9 @@ typedef struct output_t
uint8_t i_pat_version, i_pat_cc;
dvbpsi_psi_section_t *p_pmt_section;
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 */
uint16_t i_sid; /* 0 if raw mode */
......@@ -91,6 +94,7 @@ extern int i_bandwidth;
extern char *psz_modulation;
extern int b_budget_mode;
extern int b_output_udp;
extern int b_enable_epg;
extern volatile int b_hup_received;
extern mtime_t i_ca_timeout;
extern int i_comm_fd;
......@@ -105,6 +109,7 @@ void msg_Dbg( void *_unused, const char *psz_format, ... );
void msg_Raw( void *_unused, const char *psz_format, ... );
mtime_t mdate( void );
void msleep( mtime_t delay );
void hexDump( uint8_t *p_data, uint32_t i_len );
void dvb_Open( 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 )
p_output->i_cc = rand() & 0xffff;
p_output->i_pat_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_pmt_version = rand() & 0xff;
p_output->p_pat_section = NULL;
p_output->p_pmt_section = NULL;
p_output->p_sdt_section = NULL;
p_output->i_ref_timestamp = 0;
p_output->i_ref_wallclock = mdate();
p_output->i_eit_last_table_id = 0;
p_output->i_maddr = i_maddr;
p_output->i_port = i_port;
......
......@@ -142,3 +142,53 @@ void msleep( mtime_t delay )
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