[dvblast-devel] PID remapping patch
Georgi Chorbadzhiyski
gf at unixsol.org
Mon Dec 5 10:39:25 CET 2011
On 12/2/11 5:36 PM, Peter Martin wrote:
> Georgi, thanks for the feedback. I have taken on board your comments below and
> created the patch as a git patch as requested. I've had to gzip it to get it
> past my emailer. Any other changes let me know.
Thanks for the attachment. More comments bellow.
- You seem to be using tabs with width 8. Replace each tab with 8 spaces.
- There are a lot of places that introduce white space at the end of lines,
please remove it.
> From aaf49a6e4e42dc2bbc730da2d4a91881adaab0df Mon Sep 17 00:00:00 2001
> From: Peter Martin <peter.martin at tripleplay-services.com>
> Date: Fri, 2 Dec 2011 15:25:49 +0000
> Subject: [PATCH] Add an options to map the ES pids to fixed values. This is useful when using legacy IP STBs which do not parse the PMT to obtain the PIDs.
>
> ---
> NEWS | 3 ++
> demux.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
> dvblast.1 | 5 +++-
> dvblast.c | 34 +++++++++++++++++++++++++++-
> dvblast.h | 22 +++++++++++++++++++
> output.c | 37 ++++++++++++++++++++++++++++++++
> 6 files changed, 164 insertions(+), 7 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index d085f9b..43048a7 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,3 +1,6 @@
> +Changes since 2.0:
> +------------------
> + * Add an option to allow the ES pids to be mapped to fixed values
We have not released 2.0 yet :) Put he news item on the bottom of
1.2 -> 2.0 changes.
> Changes between 1.2 and 2.0:
> ----------------------------
> diff --git a/demux.c b/demux.c
> index ee0e827..81daaa7 100644
> --- a/demux.c
> +++ b/demux.c
> @@ -135,6 +135,48 @@ static void NewSDT( output_t *p_output );
> static void HandlePSIPacket( uint8_t *p_ts, mtime_t i_dts );
> static const char *get_pid_desc(uint16_t i_pid, uint16_t *i_sid);
>
> +/*
> + * Remap an ES pid to a fixed value.
> + * Multiple streams of the same type use sequential pids
> + * Returns the new pid and updates the map tables
> +*/
> +uint16_t map_es_pid(output_t * p_output, uint16_t i_stream_type, uint16_t i_pid)
> +{
> + uint16_t i_newpid = i_pid;
> +
> + if(! i_do_remap )
> + return i_pid;
> +
> + switch (i_stream_type)
> + {
> + case 0x3: /* audio MPEG-1 */
> + case 0x4: /* audio */
> + case 0xf: /* audio AAC ADTS */
These (and bellow) would be better looking as:
case 0x03:
case 0x04:
> + case 0x11: /* audio AAC LATM */
> + case 0x81: /* ATSC AC-3 */
> + case 0x87: /* ATSC Enhanced AC-3 */
> + i_newpid = pi_newpids[I_APID];
> + break;
> + case 0x1: /* video MPEG-1 */
> + case 0x2: /* video */
> + case 0x10: /* video MPEG-4 */
> + case 0x1b: /* video H264 */
> + i_newpid = pi_newpids[I_VPID];
> + break;
> + case 0x06: /* Subtitles */
> + i_newpid = pi_newpids[I_SPUPID];
> + break;
> + }
> + /* Got the new base for the mapped pid. Find the next free one
> + we do this to ensure that multiple audios get unique pids */
> + while(p_output->pi_freepids[i_newpid] != UNUSED_PID)
> + i_newpid++;
> +
> + p_output->pi_freepids[i_newpid] = i_pid; /* Mark as in use */
> + p_output->pi_newpids[i_pid] = i_newpid; /* Save the new pid */
> + return i_newpid;
> +}
> +
> /*****************************************************************************
> * demux_Open
> *****************************************************************************/
> @@ -986,6 +1028,10 @@ static void SendPAT( mtime_t i_dts )
> static void SendPMT( sid_t *p_sid, mtime_t i_dts )
> {
> int i;
> + int i_pmt_pid = p_sid->i_pmt_pid;
> +
> + if ( i_do_remap )
> + i_pmt_pid = pi_newpids[I_PMTPID];
>
> for ( i = 0; i < i_nb_outputs; i++ )
> {
> @@ -995,7 +1041,7 @@ static void SendPMT( sid_t *p_sid, mtime_t i_dts )
> && p_output->config.i_sid == p_sid->i_sid
> && p_output->p_pmt_section != NULL )
> OutputPSISection( p_output, p_output->p_pmt_section,
> - p_sid->i_pmt_pid, &p_output->i_pmt_cc, i_dts,
> + i_pmt_pid, &p_output->i_pmt_cc, i_dts,
> NULL, NULL );
> }
> }
> @@ -1144,7 +1190,13 @@ static void NewPAT( output_t *p_output )
> p = pat_get_program( p_output->p_pat_section, k++ );
> patn_init( p );
> patn_set_program( p, p_output->config.i_sid );
> - patn_set_pid( p, patn_get_pid( p_program ) );
> + if( i_do_remap)
> + {
> + msg_Dbg ( NULL, "Mapping PMT PID %d to %d\n", patn_get_pid( p_program ), pi_newpids[I_PMTPID]);
> + patn_set_pid( p, pi_newpids[I_PMTPID]);
> + }
> + else
> + patn_set_pid( p, patn_get_pid( p_program ) );
>
> p = pat_get_program( p_output->p_pat_section, k );
> pat_set_length( p_output->p_pat_section,
> @@ -1193,6 +1245,7 @@ static void NewPMT( output_t *p_output )
> uint8_t *p;
> int i;
> uint16_t j, k;
> + uint16_t i_pcrpid;
>
> free( p_output->p_pmt_section );
> p_output->p_pmt_section = NULL;
> @@ -1215,8 +1268,9 @@ static void NewPMT( output_t *p_output )
> pmt_set_program( p, p_output->config.i_sid );
> psi_set_version( p, p_output->i_pmt_version );
> psi_set_current( p );
> - pmt_set_pcrpid( p, pmt_get_pcrpid( p_current_pmt ) );
> pmt_set_desclength( p, 0 );
> + init_Mapping(p_output);
> +
>
> CopyDescriptors( pmt_get_descs( p ), pmt_get_descs( p_current_pmt ) );
>
> @@ -1236,13 +1290,21 @@ static void NewPMT( output_t *p_output )
> k++;
> pmtn_init( p_es );
> pmtn_set_streamtype( p_es, pmtn_get_streamtype( p_current_es ) );
> - pmtn_set_pid( p_es, i_pid );
> + pmtn_set_pid( p_es, map_es_pid(p_output, pmtn_get_streamtype( p_current_es ), i_pid) );
> pmtn_set_desclength( p_es, 0 );
>
> CopyDescriptors( pmtn_get_descs( p_es ),
> pmtn_get_descs( p_current_es ) );
> }
>
> + /* Do the pcr pid after everything else as it may have been remapped */
> + i_pcrpid = pmt_get_pcrpid( p_current_pmt );
> + if(p_output->pi_newpids[i_pcrpid] != UNUSED_PID) {
> + msg_Dbg ( NULL, "Mapping pcrpid from 0x%x to 0x%x\n",
> + i_pcrpid, p_output->pi_newpids[i_pcrpid]);
> + i_pcrpid = p_output->pi_newpids[i_pcrpid];
> + }
> + pmt_set_pcrpid( p, i_pcrpid );
Add i_do_remap check in addition to UNUSED_PID?
> p_es = pmt_get_es( p, k );
> if ( p_es == NULL )
> /* This shouldn't happen if the incoming PMT is valid */
> diff --git a/dvblast.1 b/dvblast.1
> index 189d171..a205cfe 100644
> --- a/dvblast.1
> +++ b/dvblast.1
> @@ -22,7 +22,7 @@ DVBlast is designed to be the core of a custom IRD or CID, based on a PC with
> Linux-supported DVB cards.
>
> DVBlast does not do any kind of processing on the elementary streams, such as
> -transcoding, PID remapping or remultiplexing. it does not stream from plain
> +transcoding or remultiplexing. it does not stream from plain
> files, only DVB devices. If you were looking for these features, switch to VLC.
> .SH OPTIONS
> .PP
> @@ -191,6 +191,9 @@ pass through all ESs from the PMT, of any type
> \fB\-Z\fR, \fB\-\-mrtg-file\fR <mrtg_file>
> Every 10 seconds log statistics in <mrtg_file>. The file has 4 numbers in it
> and the format is: <passed_bytes> <error_packets> <packets_with_seq_errors> <scrambled_packets>
> +.TP
> +\fB\-k\fR, \fB\-\-pidmap\fR <pmtpid,audiopid,videopid,spupid>
> +Map the Elemntary Stream pids to the values given for all Elementary Streams. Where there are multiple audio pids, then these will be mapped to audiopid, auiopid+1, audiopid +2 and so on.
Word wrap at col 72. One day others should be done too.
> .SH SEE ALSO
> Read the README file for more information about the configuration of dvblast.
> .SH AUTHORS
> diff --git a/dvblast.c b/dvblast.c
> index a0e6a5d..7749eb9 100644
> --- a/dvblast.c
> +++ b/dvblast.c
> @@ -111,9 +111,15 @@ static mtime_t i_latency_global = DEFAULT_OUTPUT_LATENCY;
> static mtime_t i_retention_global = DEFAULT_MAX_RETENTION;
> static int i_ttl_global = 64;
>
> -/* TPS Input log filename */
> +/* Input log filename */
> char * psz_mrtg_file = NULL;
>
> +/* pidmapping */
> +bool i_do_remap = false;
bool b_do_remap. You have changed the type but not the name.
> +uint16_t pi_newpids[N_MAP_PIDS]; /* pmt, audio, video, spu */
> +void init_Mapping( output_t *) ;
> +
> +
One new line is enough.
> void (*pf_Open)( void ) = NULL;
> block_t * (*pf_Read)( mtime_t i_poll_timeout ) = NULL;
> void (*pf_Reset)( void ) = NULL;
> @@ -597,10 +603,11 @@ int main( int i_argc, char **pp_argv )
> { "help", no_argument, NULL, 'h' },
> { "version", no_argument, NULL, 'V' },
> { "mrtg-file", required_argument, NULL, 'Z' },
> + { "pidmap", required_argument, NULL, 'k' },
> { 0, 0, 0, 0 }
> };
>
> - while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:F:R:s:S:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:", long_options, NULL)) != -1 )
> + while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:F:R:s:S:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:k:", long_options, NULL)) != -1 )
> {
> switch ( c )
> {
> @@ -853,6 +860,29 @@ int main( int i_argc, char **pp_argv )
> psz_mrtg_file = optarg;
> break;
>
> + case 'k':
> + {
Move the brace next to the case and pull the code 4 spaces left.
> + /* We expect a comma separated list of numbers.
> + Put them into the pi_newpids array as they appear */
> + char * str1;
> + char * saveptr = NULL;
> + char * tok = NULL;
> + int i, i_newpid;
> + for(i = 0, str1 = optarg; i < N_MAP_PIDS; i++, str1 = NULL)
Umm, too much magic. optarg can't be null (getopt will take care of this).
> + {
> + tok = strtok_r(str1, ",", &saveptr);
> + if(tok == NULL)
> + break;
> + i_newpid = strtoul(tok, NULL, 0);
> + if(0 == i_newpid) {
> + msg_Err( NULL, "Invalid pidmap string" );
> + usage();
> + }
> + pi_newpids[i] = i_newpid;
> + }
> + i_do_remap = true;
> + }
> + break;
> case 'h':
> default:
> usage();
> diff --git a/dvblast.h b/dvblast.h
> index 40ce4c4..38c4292 100644
> --- a/dvblast.h
> +++ b/dvblast.h
> @@ -43,6 +43,18 @@
> #define DEFAULT_FRONTEND_TIMEOUT 30000000 /* 30 s */
> #define EXIT_STATUS_FRONTEND_TIMEOUT 100
>
> +/* Defines for pid mapping */
> +#define N_MAP_PIDS 4
> +/* Offsets in the command line args for the pid mapping */
> +typedef enum
> +{
> + I_PMTPID = 0, I_APID, I_VPID, I_SPUPID
> +} PidMapOffset;
Each value on a line, and maybe pidmap_offset_t?
> +/* Impossible PID value */
> +#define UNUSED_PID (MAX_PIDS + 1)
> +
> +
> /*****************************************************************************
> * Output configuration flags (for output_t -> i_config) - bit values
> * Bit 0 : Set for watch mode
> @@ -73,6 +85,7 @@ typedef struct block_t
> uint8_t p_ts[TS_SIZE];
> int i_refcount;
> mtime_t i_dts;
> + uint16_t tmp_pid;
> struct block_t *p_next;
> } block_t;
>
> @@ -131,6 +144,10 @@ typedef struct output_t
> block_t *p_eit_ts_buffer;
> uint8_t i_eit_ts_buffer_offset, i_eit_cc;
> uint16_t i_tsid;
> + // Arrays used for mapping pids.
> + // newpids is indexed using the original pid
> + uint16_t pi_newpids[MAX_PIDS];
> + uint16_t pi_freepids[MAX_PIDS]; // used where multiple streams of the same type are used
> } output_t;
>
> typedef struct ts_pid_info {
> @@ -191,6 +208,11 @@ extern const char *psz_native_charset;
> extern const char *psz_dvb_charset;
> extern enum print_type_t i_print_type;
>
> +/* pid mapping */
> +extern bool i_do_remap;
> +extern uint16_t pi_newpids[N_MAP_PIDS];
> +void init_Mapping(output_t *);
> +
> extern void (*pf_Open)( void );
> extern block_t * (*pf_Read)( mtime_t i_poll_timeout );
> extern void (*pf_Reset)( void );
> diff --git a/output.c b/output.c
> index 0cc5bf7..ba84a29 100644
> --- a/output.c
> +++ b/output.c
> @@ -103,6 +103,16 @@ output_t *output_Create( const output_config_t *p_config )
> return p_output;
> }
>
> +/* Init the mapped pids to unused */
> +void init_Mapping( output_t * p_output)
> +{
> + unsigned int i;
> + for(i = 0; i< MAX_PIDS; i++) {
> + p_output->pi_newpids[i] = UNUSED_PID;
> + p_output->pi_freepids[i] = UNUSED_PID;
> + }
> +}
> +
> /*****************************************************************************
> * output_Init : set up the output initial config
> *****************************************************************************/
> @@ -135,6 +145,9 @@ int output_Init( output_t *p_output, const output_config_t *p_config )
> if ( b_random_tsid )
> p_output->i_tsid = rand() & 0xffff;
>
> + /* Init the mapped pids to unused */
> + init_Mapping(p_output);
> +
> /* Init socket-related fields */
> p_output->config.i_family = p_config->i_family;
> memcpy( &p_output->config.connect_addr, &p_config->connect_addr,
> @@ -273,6 +286,24 @@ static void output_Flush( output_t *p_output )
>
> for ( i_block = 0; i_block < p_packet->i_depth; i_block++ )
> {
> + /* Do pid mapping here if needed.
> + * save the original pid in the block.
> + * set the pid to the new pid
> + * later we re-instate the old pid for the next output
> + */
> + if(i_do_remap) {
> + block_t * p_block = p_packet->pp_blocks[i_block];
> + uint16_t i_pid = (p_block->p_ts[1] & 0x1f) << 8 | p_block->p_ts[2];
> + p_block->tmp_pid = UNUSED_PID;
> + if(UNUSED_PID != p_output->pi_newpids[i_pid])
Variable order in the if.
> + {
> + uint16_t i_newpid = p_output->pi_newpids[i_pid];
> + /* Need to map this pid to the new pid */
> + ts_set_pid( p_block, i_newpid );
> + p_block->tmp_pid = i_pid;
> + }
> + }
> +
> p_iov[i_iov].iov_base = p_packet->pp_blocks[i_block]->p_ts;
> p_iov[i_iov].iov_len = TS_SIZE;
> i_iov++;
> @@ -298,6 +329,12 @@ static void output_Flush( output_t *p_output )
> p_packet->pp_blocks[i_block]->i_refcount--;
> if ( !p_packet->pp_blocks[i_block]->i_refcount )
> block_Delete( p_packet->pp_blocks[i_block] );
> + else if(i_do_remap) {
> + /* still referenced so re-instate the orignial pid if remapped */
> + block_t * p_block = p_packet->pp_blocks[i_block];
> + if(p_block->tmp_pid != UNUSED_PID)
> + ts_set_pid( p_block, p_block->tmp_pid );
> + }
Why do you change the pid and then return it back? Since pidmap is
initialized globally once the pid is changed it should be ok for other
outputs?
Thanks.
--
Georgi Chorbadzhiyski
http://georgi.unixsol.org/
More information about the dvblast-devel
mailing list