[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