[dvblast-devel] PID remapping patch

Georgi Chorbadzhiyski gf at unixsol.org
Fri Dec 2 14:12:38 CET 2011


Around 12/02/2011 02:25 PM, Peter Martin scribbled:
> Here is a patch I am using to allow me to remap ES pids to fixed values. This is 
> needed by some legacy IP STBs which don't understand how to use PMTs. The 
> command line flag -k is followed by four pids, which map the PMT, Audio, Video 
> and Spu pids respectively. It has been designed to impose a minimal overhead and 
> supports transponders which share pids between different programmes and 
> programmes with multiple audio or spu pids.
> 
> This diff has been prepared against the latest git version.

Please send it as attachment create by git format-patch because currently it is
unusable.

Partial review bellow.

- Missing man page text describing the parameter and possibly example uses
  so we test the patch.
- Missing NEWS entry.

> diff -Naur dvblast.orig/demux.c dvblast/demux.c
> --- dvblast.orig/demux.c 2011-12-02 11:08:22.000000000 +0000
> +++ dvblast/demux.c 2011-12-02 11:26:50.000000000 +0000
> @@ -135,6 +135,50 @@
> 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;
> + }

Braces are unneeded. Shouldn't do_remap be boolean?

> + switch (i_stream_type) {
> + case 0x3: /* audio MPEG-1 */
> + case 0x4: /* audio */
> + case 0xf: /* audio AAC ADTS */
> + 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;
> + default:
> + break;
> + }

The default is unneeded.

> + /* 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(UNUSED_PID != p_output->pi_freepids[i_newpid]) {
> + i_newpid++;
> + }

Please use while(p_output->pi_freepids[i_newpid] != UNUSED_PID)
I know it is the same but parsing it backwards hurts my head :)

> + 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 +1030,11 @@
> static void SendPMT( sid_t *p_sid, mtime_t i_dts )
> {
> int i;
> + int i_pmtpid = p_sid->i_pmt_pid;
> + if ( i_do_remap )
> + {
> + i_pmtpid = pi_newpids[I_PMTPID];
> + }

Braces... i_pmt_pid please, not i_pmtpid.

> for ( i = 0; i < i_nb_outputs; i++ )
> {
> @@ -995,7 +1044,7 @@
> && 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_pmtpid, &p_output->i_pmt_cc, i_dts,
> NULL, NULL );
> }
> }
> @@ -1144,7 +1193,15 @@
> 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 +1250,7 @@
> 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 +1273,9 @@
> 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);
> +

Where does pmt_set_pcrpid() go?

> CopyDescriptors( pmt_get_descs( p ), pmt_get_descs( p_current_pmt ) );
> 
> @@ -1236,13 +1295,20 @@
> 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(UNUSED_PID != p_output->pi_newpids[i_pcrpid]) {

Variable order.

> + printf("Mapping pcrpid from 0x%x to 0x%x\n", i_pcrpid, 
> p_output->pi_newpids[i_pcrpid]);

No printfs please. msg_Dbg ot something.

> + i_pcrpid = p_output->pi_newpids[i_pcrpid];
> + }
> + pmt_set_pcrpid( p, i_pcrpid );
> p_es = pmt_get_es( p, k );
> if ( p_es == NULL )
> /* This shouldn't happen if the incoming PMT is valid */
> diff -Naur dvblast.orig/dvblast.c dvblast/dvblast.c
> --- dvblast.orig/dvblast.c 2011-12-02 11:08:22.000000000 +0000
> +++ dvblast/dvblast.c 2011-12-02 11:34:48.000000000 +0000
> @@ -114,6 +114,12 @@
> /* TPS Input log filename */
> char * psz_mrtg_file = NULL;
> 
> +/* TPS pidmapping */

What is TPS?

> +int i_do_remap = 0;

Boolean;

> +uint16_t pi_newpids[N_MAP_PIDS]; /* pmt, audio, video, spu */
> +void init_Mapping( output_t *) ;
> +
> +
> void (*pf_Open)( void ) = NULL;
> block_t * (*pf_Read)( mtime_t i_poll_timeout ) = NULL;
> void (*pf_Reset)( void ) = NULL;
> @@ -597,10 +603,11 @@
> { "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 @@
> psz_mrtg_file = optarg;
> break;
> 
> + case 'k':
> + {
> + /* 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)
> + {
> + tok = strtok_r(str1, ",", &saveptr);
> + if(tok == NULL)
> + break;
> + i_newpid = strtoul(tok, NULL, 0);
> + if(0 == i_newpid) {
> + msg_Err( NULL, "Invalid map pid string" );

pidmap, map pid, choose one :)

> + usage();
> + }
> + pi_newpids[i] = i_newpid;
> + }
> + i_do_remap = 1;
> + }
> + break;
> case 'h':
> default:
> usage();
> diff -Naur dvblast.orig/dvblast.h dvblast/dvblast.h
> --- dvblast.orig/dvblast.h 2011-12-02 11:08:22.000000000 +0000
> +++ dvblast/dvblast.h 2011-12-02 11:32:23.000000000 +0000
> @@ -43,6 +43,17 @@
> #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 */
> +#define I_PMTPID 0
> +#define I_APID 1
> +#define I_VPID 2
> +#define I_SPUPID 3

Make it an enum.

> +/* 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 +84,7 @@
> 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 +143,10 @@
> 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 +207,11 @@
> extern const char *psz_dvb_charset;
> extern enum print_type_t i_print_type;
> 
> +/* TPS pid mapping */
> +extern int 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 -Naur dvblast.orig/output.c dvblast/output.c
> --- dvblast.orig/output.c 2011-12-02 11:08:22.000000000 +0000
> +++ dvblast/output.c 2011-12-02 11:34:04.000000000 +0000
> @@ -103,6 +103,16 @@
> 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;

memset ?

> + }
> +}
> +
> /*****************************************************************************
> * output_Init : set up the output initial config
> *****************************************************************************/
> @@ -135,6 +145,9 @@
> 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,26 @@
> 
> 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])
> + {
> + uint16_t i_newpid = p_output->pi_newpids[i_pid];
> + /* Need to map this pid to the new pid */
> + p_block->p_ts[1] &= 0xe0;
> + p_block->p_ts[1] |= ((i_newpid >> 8) & 0x1f);
> + p_block->p_ts[2] = i_newpid & 0xff;
> + p_block->tmp_pid = i_pid;

Use ts_set_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 +331,15 @@
> 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) {
> + p_block->p_ts[1] &= 0xe0;
> + p_block->p_ts[1] |= ((p_block->tmp_pid >> 8) & 0x1f);
> + p_block->p_ts[2] = p_block->tmp_pid & 0xff;

Use ts_set_pid()

> + }
> + }
> }
> p_output->p_packets = p_packet->p_next;
> free( p_packet );

-- 
Georgi Chorbadzhiyski
http://georgi.unixsol.org/


More information about the dvblast-devel mailing list