<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    All,<br>
    <br>
    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.<br>
    <br>
    This diff has been prepared against the latest git version.<br>
    <br>
    Pete<br>
    <br>
    diff -Naur dvblast.orig/demux.c dvblast/demux.c<br>
    --- dvblast.orig/demux.c        2011-12-02 11:08:22.000000000 +0000<br>
    +++ dvblast/demux.c     2011-12-02 11:26:50.000000000 +0000<br>
    @@ -135,6 +135,50 @@<br>
     static void HandlePSIPacket( uint8_t *p_ts, mtime_t i_dts );<br>
     static const char *get_pid_desc(uint16_t i_pid, uint16_t *i_sid);<br>
    <br>
    +/*<br>
    + * Remap an ES pid to a fixed value.<br>
    + * Multiple streams of the same type use sequential pids<br>
    + * Returns the new pid and updates the map tables<br>
    +*/<br>
    +uint16_t map_es_pid(output_t * p_output, uint16_t i_stream_type,
    uint16_t i_pid)<br>
    +{<br>
    +    uint16_t i_newpid = i_pid;<br>
    +<br>
    +    if(!i_do_remap) {<br>
    +       return i_pid;<br>
    +    }<br>
    +<br>
    +    switch (i_stream_type) {<br>
    +        case 0x3: /* audio MPEG-1 */<br>
    +        case 0x4: /* audio */<br>
    +        case 0xf: /* audio AAC ADTS */<br>
    +        case 0x11: /* audio AAC LATM */<br>
    +        case 0x81: /* ATSC AC-3 */<br>
    +        case 0x87: /* ATSC Enhanced AC-3 */<br>
    +           i_newpid = pi_newpids[I_APID];<br>
    +           break;<br>
    +        case 0x1: /* video MPEG-1 */<br>
    +        case 0x2: /* video */<br>
    +        case 0x10: /* video MPEG-4 */<br>
    +        case 0x1b: /* video H264 */<br>
    +           i_newpid = pi_newpids[I_VPID];<br>
    +           break;<br>
    +        case 0x06: /* Subtitles */<br>
    +            i_newpid = pi_newpids[I_SPUPID];<br>
    +            break;<br>
    +        default:<br>
    +            break;<br>
    +    }<br>
    +    /* Got the new base for the mapped pid. Find the next free one<br>
    +       we do this to ensure that multiple audios get unique pids */<br>
    +    while(UNUSED_PID != p_output->pi_freepids[i_newpid]) {<br>
    +       i_newpid++;<br>
    +    }<br>
    +    p_output->pi_freepids[i_newpid] = i_pid;  /* Mark as in use
    */<br>
    +    p_output->pi_newpids[i_pid] = i_newpid;     /* Save the new
    pid */<br>
    +    return i_newpid;<br>
    +}<br>
    +<br>
 /*****************************************************************************<br>
      * demux_Open<br>
     
*****************************************************************************/<br>
    @@ -986,6 +1030,11 @@<br>
     static void SendPMT( sid_t *p_sid, mtime_t i_dts )<br>
     {<br>
         int i;<br>
    +    int i_pmtpid = p_sid->i_pmt_pid;<br>
    +    if ( i_do_remap )<br>
    +    {<br>
    +       i_pmtpid = pi_newpids[I_PMTPID];<br>
    +    }<br>
    <br>
         for ( i = 0; i < i_nb_outputs; i++ )<br>
         {<br>
    @@ -995,7 +1044,7 @@<br>
                    && p_output->config.i_sid ==
    p_sid->i_sid<br>
                    && p_output->p_pmt_section != NULL )<br>
                 OutputPSISection( p_output, p_output->p_pmt_section,<br>
    -                              p_sid->i_pmt_pid,
    &p_output->i_pmt_cc, i_dts,<br>
    +                              i_pmtpid, &p_output->i_pmt_cc,
    i_dts,<br>
                                   NULL, NULL );<br>
         }<br>
     }<br>
    @@ -1144,7 +1193,15 @@<br>
         p = pat_get_program( p_output->p_pat_section, k++ );<br>
         patn_init( p );<br>
         patn_set_program( p, p_output->config.i_sid );<br>
    -    patn_set_pid( p, patn_get_pid( p_program ) );<br>
    +    if( i_do_remap)<br>
    +    {<br>
    +        msg_Dbg ( NULL, "Mapping PMT PID %d to %d\n", patn_get_pid(
    p_program ),                          pi_newpids[I_PMTPID]);<br>
    +        patn_set_pid( p, pi_newpids[I_PMTPID]);<br>
    +    }<br>
    +    else<br>
    +    {<br>
    +        patn_set_pid( p, patn_get_pid( p_program ) );<br>
    +    }<br>
    <br>
         p = pat_get_program( p_output->p_pat_section, k );<br>
         pat_set_length( p_output->p_pat_section,<br>
    @@ -1193,6 +1250,7 @@<br>
         uint8_t *p;<br>
         int i;<br>
         uint16_t j, k;<br>
    +    uint16_t i_pcrpid;<br>
    <br>
         free( p_output->p_pmt_section );<br>
         p_output->p_pmt_section = NULL;<br>
    @@ -1215,8 +1273,9 @@<br>
         pmt_set_program( p, p_output->config.i_sid );<br>
         psi_set_version( p, p_output->i_pmt_version );<br>
         psi_set_current( p );<br>
    -    pmt_set_pcrpid( p, pmt_get_pcrpid( p_current_pmt ) );<br>
         pmt_set_desclength( p, 0 );<br>
    +    init_Mapping(p_output);<br>
    +<br>
    <br>
         CopyDescriptors( pmt_get_descs( p ), pmt_get_descs(
    p_current_pmt ) );<br>
    <br>
    @@ -1236,13 +1295,20 @@<br>
             k++;<br>
             pmtn_init( p_es );<br>
             pmtn_set_streamtype( p_es, pmtn_get_streamtype(
    p_current_es ) );<br>
    -        pmtn_set_pid( p_es, i_pid );<br>
    +        pmtn_set_pid( p_es, map_es_pid(p_output,
    pmtn_get_streamtype( p_current_es ), i_pid) );<br>
             pmtn_set_desclength( p_es, 0 );<br>
    <br>
             CopyDescriptors( pmtn_get_descs( p_es ),<br>
                              pmtn_get_descs( p_current_es ) );<br>
         }<br>
    <br>
    +    /* Do the pcr pid after everything else as it may have been
    remapped */<br>
    +    i_pcrpid = pmt_get_pcrpid( p_current_pmt );<br>
    +    if(UNUSED_PID != p_output->pi_newpids[i_pcrpid]) {<br>
    +       printf("Mapping pcrpid from 0x%x to 0x%x\n", i_pcrpid, 
    p_output->pi_newpids[i_pcrpid]);<br>
    +       i_pcrpid = p_output->pi_newpids[i_pcrpid];<br>
    +    }<br>
    +    pmt_set_pcrpid( p, i_pcrpid );<br>
         p_es = pmt_get_es( p, k );<br>
         if ( p_es == NULL )<br>
             /* This shouldn't happen if the incoming PMT is valid */<br>
    diff -Naur dvblast.orig/dvblast.c dvblast/dvblast.c<br>
    --- dvblast.orig/dvblast.c      2011-12-02 11:08:22.000000000 +0000<br>
    +++ dvblast/dvblast.c   2011-12-02 11:34:48.000000000 +0000<br>
    @@ -114,6 +114,12 @@<br>
     /* TPS Input log filename */<br>
     char * psz_mrtg_file = NULL;<br>
    <br>
    +/* TPS pidmapping */<br>
    +int i_do_remap = 0;<br>
    +uint16_t pi_newpids[N_MAP_PIDS];  /* pmt, audio, video, spu */<br>
    +void init_Mapping( output_t *) ;<br>
    +<br>
    +<br>
     void (*pf_Open)( void ) = NULL;<br>
     block_t * (*pf_Read)( mtime_t i_poll_timeout ) = NULL;<br>
     void (*pf_Reset)( void ) = NULL;<br>
    @@ -597,10 +603,11 @@<br>
             { "help",            no_argument,       NULL, 'h' },<br>
             { "version",         no_argument,       NULL, 'V' },<br>
             { "mrtg-file",       required_argument, NULL, 'Z' },<br>
    +        { "pidmap",          required_argument, NULL, 'k' },<br>
             { 0, 0, 0, 0 }<br>
         };<br>
    <br>
    -    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 )<br>
    +    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 )<br>
         {<br>
             switch ( c )<br>
             {<br>
    @@ -853,6 +860,29 @@<br>
                 psz_mrtg_file = optarg;<br>
                 break;<br>
    <br>
    +        case 'k':<br>
    +            {<br>
    +               /* We expect a comma separated list of numbers.<br>
    +                   Put them into the pi_newpids array as they
    appear */<br>
    +                char * str1;<br>
    +                char * saveptr = NULL;<br>
    +                char * tok = NULL;<br>
    +                int    i, i_newpid;<br>
    +                for(i = 0, str1 = optarg; i < N_MAP_PIDS; i++,
    str1 = NULL)<br>
    +                {<br>
    +                   tok = strtok_r(str1, ",", &saveptr);<br>
    +                   if(tok == NULL)<br>
    +                       break;<br>
    +                   i_newpid = strtoul(tok, NULL, 0);<br>
    +                   if(0 == i_newpid) {<br>
    +                       msg_Err( NULL, "Invalid map pid string" );<br>
    +                        usage();<br>
    +                    }<br>
    +                   pi_newpids[i] = i_newpid;<br>
    +                }<br>
    +                i_do_remap = 1;<br>
    +            }<br>
    +            break;<br>
             case 'h':<br>
             default:<br>
                 usage();<br>
    diff -Naur dvblast.orig/dvblast.h dvblast/dvblast.h<br>
    --- dvblast.orig/dvblast.h      2011-12-02 11:08:22.000000000 +0000<br>
    +++ dvblast/dvblast.h   2011-12-02 11:32:23.000000000 +0000<br>
    @@ -43,6 +43,17 @@<br>
     #define DEFAULT_FRONTEND_TIMEOUT 30000000 /* 30 s */<br>
     #define EXIT_STATUS_FRONTEND_TIMEOUT 100<br>
    <br>
    +/* Defines for pid mapping */<br>
    +#define N_MAP_PIDS                 4<br>
    +/* Offsets in the command line args for the pid mapping */<br>
    +#define I_PMTPID 0<br>
    +#define I_APID   1<br>
    +#define I_VPID   2<br>
    +#define I_SPUPID 3<br>
    +/* Impossible PID value */<br>
    +#define UNUSED_PID           (MAX_PIDS + 1)<br>
    +<br>
    +<br>
 /*****************************************************************************<br>
      * Output configuration flags (for output_t -> i_config) - bit
    values<br>
      * Bit  0 : Set for watch mode<br>
    @@ -73,6 +84,7 @@<br>
         uint8_t p_ts[TS_SIZE];<br>
         int i_refcount;<br>
         mtime_t i_dts;<br>
    +    uint16_t tmp_pid;<br>
         struct block_t *p_next;<br>
     } block_t;<br>
    <br>
    @@ -131,6 +143,10 @@<br>
         block_t *p_eit_ts_buffer;<br>
         uint8_t i_eit_ts_buffer_offset, i_eit_cc;<br>
         uint16_t i_tsid;<br>
    +    // Arrays used for mapping pids.<br>
    +    // newpids is indexed using the original pid<br>
    +    uint16_t pi_newpids[MAX_PIDS];<br>
    +    uint16_t pi_freepids[MAX_PIDS];   // used where multiple
    streams of the same type are used<br>
     } output_t;<br>
    <br>
     typedef struct ts_pid_info {<br>
    @@ -191,6 +207,11 @@<br>
     extern const char *psz_dvb_charset;<br>
     extern enum print_type_t i_print_type;<br>
    <br>
    +/* TPS pid mapping */<br>
    +extern int i_do_remap;<br>
    +extern uint16_t pi_newpids[N_MAP_PIDS];<br>
    +void init_Mapping(output_t *);<br>
    +<br>
     extern void (*pf_Open)( void );<br>
     extern block_t * (*pf_Read)( mtime_t i_poll_timeout );<br>
     extern void (*pf_Reset)( void );<br>
    diff -Naur dvblast.orig/output.c dvblast/output.c<br>
    --- dvblast.orig/output.c       2011-12-02 11:08:22.000000000 +0000<br>
    +++ dvblast/output.c    2011-12-02 11:34:04.000000000 +0000<br>
    @@ -103,6 +103,16 @@<br>
         return p_output;<br>
     }<br>
    <br>
    +/* Init the mapped pids to unused */<br>
    +void init_Mapping( output_t * p_output)<br>
    +{<br>
    +    unsigned int i;<br>
    +    for(i = 0; i< MAX_PIDS; i++) {<br>
    +        p_output->pi_newpids[i] = UNUSED_PID;<br>
    +        p_output->pi_freepids[i] = UNUSED_PID;<br>
    +    }<br>
    +}<br>
    +<br>
 /*****************************************************************************<br>
      * output_Init : set up the output initial config<br>
     
*****************************************************************************/<br>
    @@ -135,6 +145,9 @@<br>
         if ( b_random_tsid )<br>
             p_output->i_tsid = rand() & 0xffff;<br>
    <br>
    +    /* Init the mapped pids to unused */<br>
    +    init_Mapping(p_output);<br>
    +<br>
         /* Init socket-related fields */<br>
         p_output->config.i_family = p_config->i_family;<br>
         memcpy( &p_output->config.connect_addr,
    &p_config->connect_addr,<br>
    @@ -273,6 +286,26 @@<br>
    <br>
         for ( i_block = 0; i_block < p_packet->i_depth; i_block++
    )<br>
         {<br>
    +        /* Do pid mapping here if needed.<br>
    +         * save the original pid in the block.<br>
    +         * set the pid to the new pid<br>
    +         * later we re-instate the old pid for the next output<br>
    +         */<br>
    +        if(i_do_remap) {<br>
    +            block_t * p_block = p_packet->pp_blocks[i_block];<br>
    +            uint16_t i_pid = (p_block->p_ts[1] & 0x1f)
    << 8 | p_block->p_ts[2];<br>
    +            p_block->tmp_pid = UNUSED_PID;<br>
    +            if(UNUSED_PID != p_output->pi_newpids[i_pid])<br>
    +            {<br>
    +                uint16_t i_newpid = 
    p_output->pi_newpids[i_pid];<br>
    +                /* Need to map this pid to the new pid */<br>
    +                p_block->p_ts[1] &= 0xe0;<br>
    +                p_block->p_ts[1] |= ((i_newpid >> 8) &
    0x1f);<br>
    +                p_block->p_ts[2] = i_newpid & 0xff;<br>
    +                p_block->tmp_pid = i_pid;<br>
    +            }<br>
    +        }<br>
    +<br>
             p_iov[i_iov].iov_base =
    p_packet->pp_blocks[i_block]->p_ts;<br>
             p_iov[i_iov].iov_len = TS_SIZE;<br>
             i_iov++;<br>
    @@ -298,6 +331,15 @@<br>
             p_packet->pp_blocks[i_block]->i_refcount--;<br>
             if ( !p_packet->pp_blocks[i_block]->i_refcount )<br>
                 block_Delete( p_packet->pp_blocks[i_block] );<br>
    +        else if(i_do_remap) {<br>
    +            /* still referenced so re-instate the orignial pid if
    remapped */<br>
    +            block_t * p_block = p_packet->pp_blocks[i_block];<br>
    +            if(p_block->tmp_pid != UNUSED_PID) {<br>
    +                p_block->p_ts[1] &= 0xe0;<br>
    +                p_block->p_ts[1] |= ((p_block->tmp_pid
    >> 8) & 0x1f);<br>
    +                p_block->p_ts[2] = p_block->tmp_pid &
    0xff;<br>
    +            }<br>
    +        }<br>
         }<br>
         p_output->p_packets = p_packet->p_next;<br>
         free( p_packet );<br>
    <br>
    <br>
    <div class="moz-signature">-- <br>
      <meta http-equiv="Content-Type" content="text/html;
        charset=ISO-8859-1">
      <title>Tripleplay Signature - Poole</title>
      <font style="candara"> <br>
        <font size="2">Best Regards,</font><br>
        <br>
        <b>Dr. Peter Martin</b><br>
        <font color="#404041" size="2">Chief Technical Officer</font><br>
        <br>
        Tripleplay Services Ltd<br>
        <br>
        Tel: +44 (0) 845 643 2057</font><br>
      Support: +44 (0) 845 094 3357<br>
      Mobile: +44 (0) 7810 876713<br>
      Mail: <a href="mailto:peter.martin@tripleplay-services.com">peter.martin@tripleplay-services.com</a><br>
      WWW: <a href="http://www.tripleplay-services.com">http://www.tripleplay-services.com</a><br>
      <br>
      <b><font color="#404041" size="2">Tripleplay Services Ltd.</font></b><br>
      <font color="#404041" size="2">Unit 3, Concept Park, Yarrow Road,
        POOLE, DORSET, BH12 4QT</font><br>
      <br>
      <i><font color="#404041" size="2">This message is for the
          designated recipient only and may contain privileged,
          proprietary, or otherwise private information. If you have
          received it in error, please notify the sender immediately and
          delete the original. Any review, retransmission, dissemination
          or other use of, or taking of any action in reliance upon,
          this information by persons or entities other than the
          intended recipient is prohibited </font></i><br>
      <br>
      <i><font color="#404041" size="2">Tripleplay Services Limited is a
          private limited liability company in England and Wales, whose
          registered office is Cromwell House, 14 Fulwood Place, London,
          WC1V 6HZ. Registered in England, number 4338092.</font></i> </div>
  </body>
</html>