diff -ruN trunk/demux.c ajg2/demux.c --- trunk/demux.c 2009-07-10 20:59:18.000000000 +0100 +++ ajg2/demux.c 2009-07-20 21:46:58.000000000 +0100 @@ -5,6 +5,7 @@ * $Id: demux.c 3 2009-05-11 13:19:16Z massiot $ * * Authors: Christophe Massiot + * Andy Gatward * * 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 #include #include +#include #include #include /***************************************************************************** * Local declarations *****************************************************************************/ + +#define SDT_PID 0x11 +#define EIT_PID 0x12 + typedef struct ts_pid_t { int i_refcount; @@ -63,6 +69,8 @@ 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 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 @@ 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 @@ 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,68 @@ 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) & 0x1f; + 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; @@ -674,6 +756,7 @@ } } + /***************************************************************************** * NewPAT *****************************************************************************/ @@ -1160,3 +1243,74 @@ 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, 0, 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 ); +} diff -ruN trunk/dvblast.c ajg2/dvblast.c --- trunk/dvblast.c 2009-07-10 20:59:18.000000000 +0100 +++ ajg2/dvblast.c 2009-07-20 21:03:41.000000000 +0100 @@ -55,6 +55,7 @@ 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 @@ *****************************************************************************/ void usage() { - msg_Raw( NULL, "Usage: dvblast [-q] -c [-r ] [-t ] [-o ] [-i ] [-a ][-n ] -f [-s ] [-v <0|13|18>] [-p] [-b ] [-m ]" ); + msg_Raw( NULL, "Usage: dvblast [-q] -c [-r ] [-t ] [-o ] [-i ] [-a ][-n ] -f [-s ] [-v <0|13|18>] [-p] [-b ] [-m ] [-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 @@ 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 @@ 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 @@ break; } + case 'e': + b_enable_epg = 1; + break; + case 'h': default: usage(); diff -ruN trunk/dvblast.h ajg2/dvblast.h --- trunk/dvblast.h 2009-07-10 20:59:18.000000000 +0100 +++ ajg2/dvblast.h 2009-07-20 21:04:09.000000000 +0100 @@ -65,6 +65,9 @@ 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 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_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 ); diff -ruN trunk/Makefile ajg2/Makefile --- trunk/Makefile 2009-07-10 20:59:18.000000000 +0100 +++ ajg2/Makefile 2009-07-20 20:57:10.000000000 +0100 @@ -6,7 +6,7 @@ CFLAGS += -I/usr/src/kernel/linux-2.6.29.1/include LDFLAGS_DVBLAST += -ldvbpsi -lpthread -OBJ_DVBLAST = dvblast.o util.o dvb.o demux.o output.o en50221.o comm.o +OBJ_DVBLAST = dvblast.o util.o dvb.o demux.o output.o en50221.o comm.o OBJ_DVBLASTCTL = util.o dvblastctl.o all: dvblast dvblastctl diff -ruN trunk/output.c ajg2/output.c --- trunk/output.c 2009-07-10 20:59:18.000000000 +0100 +++ ajg2/output.c 2009-07-20 20:29:14.000000000 +0100 @@ -87,12 +87,16 @@ 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; diff -ruN trunk/util.c ajg2/util.c --- trunk/util.c 2009-07-10 20:59:18.000000000 +0100 +++ ajg2/util.c 2009-07-18 22:01:23.000000000 +0100 @@ -142,3 +142,53 @@ 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 ); +} +