[dvblast-devel] Simplify pid selection on PMT changes.

Georgi Chorbadzhiyski git at videolan.org
Mon Jul 29 19:01:16 CEST 2013


dvblast | branch: master | Georgi Chorbadzhiyski <gf at unixsol.org> | Mon Jul 29 19:29:52 2013 +0300| [4abec2509a4f729a96fbc252aef5de33b3859874] | committer: Georgi Chorbadzhiyski

Simplify pid selection on PMT changes.

Consider the following PMT log:

> Enable ECM pids 6206 and 7306 and ES pids 2256, 2530, 2531.

debug: setting filter on PID 2256
debug: setting filter on PID 2530
debug: setting filter on PID 2531
debug: setting filter on PID 6306
debug: setting filter on PID 7306
debug: new PMT program=6411 version=7 pcrpid=2256
debug:   * ES pid=2256 streamtype=0x02 streamtype_txt="13818-2 video (MPEG-2)"
debug:     - desc 52 stream_identifier component_tag=1
debug:     - desc 09 ca sysid=0xd00 pid=6306
debug:     - desc 09 ca sysid=0x664 pid=7306
debug:   * ES pid=2530 streamtype=0x06 streamtype_txt="13818-1 PES private data"
debug:     - desc 52 stream_identifier component_tag=6
debug:     - desc 59 subtitling language=tur type=0x10 composition=2 ancillary=2
debug:     - desc 09 ca sysid=0xd00 pid=6306
debug:     - desc 09 ca sysid=0x664 pid=7306
debug:   * ES pid=2531 streamtype=0x06 streamtype_txt="13818-1 PES private data"
debug:     - desc 52 stream_identifier component_tag=7
debug:     - desc 59 subtitling language=eng type=0x10 composition=2 ancillary=2
debug:     - desc 09 ca sysid=0xd00 pid=6306
debug:     - desc 09 ca sysid=0x664 pid=7306
debug: end PMT

> Enable pids 6206 and 7306 but disable them again because they are not
> mentioned in the ES desc loop and in the global desc loop of the old PMT.

debug: setting filter on PID 6306
debug: setting filter on PID 7306
debug: unsetting filter on PID 6306
debug: unsetting filter on PID 7306
debug: new PMT program=6411 version=14 pcrpid=2256
debug:     - desc 09 ca sysid=0xd00 pid=6306
debug:     - desc 09 ca sysid=0x664 pid=7306
debug:   * ES pid=2256 streamtype=0x02 streamtype_txt="13818-2 video (MPEG-2)"
debug:     - desc 52 stream_identifier component_tag=1
debug:   * ES pid=2530 streamtype=0x06 streamtype_txt="13818-1 PES private data"
debug:     - desc 52 stream_identifier component_tag=6
debug:     - desc 59 subtitling language=tur type=0x10 composition=2 ancillary=2
debug:   * ES pid=2531 streamtype=0x06 streamtype_txt="13818-1 PES private data"
debug:     - desc 52 stream_identifier component_tag=7
debug:     - desc 59 subtitling language=eng type=0x10 composition=2 ancillary=2
debug: end PMT

Commit 34f232f7e8d1fbe2a2930b597e40fb410c9ac5d6 added checks for global
descriptor loop but it was not enough. Instead of adding "yet more checks"
because ECM pids can be described in two places, I used the opportunity to
simplify the code that deals with pid selection in PMT.

Now we have only one place that parses the PMT and we use a table to mark
the pids in the new and in the old table.

50 lines of code were removed and the code was made a lot simpler and easy
to follow for the price of 8k stack space. As a bonus the bug described above
was fixed.

> http://git.videolan.org/gitweb.cgi/dvblast.git/?a=commit;h=4abec2509a4f729a96fbc252aef5de33b3859874
---

 demux.c |  186 +++++++++++++++++++++++----------------------------------------
 1 file changed, 68 insertions(+), 118 deletions(-)

diff --git a/demux.c b/demux.c
index 173f734..f2c8486 100644
--- a/demux.c
+++ b/demux.c
@@ -2199,6 +2199,52 @@ static void HandleCATSection( uint16_t i_pid, uint8_t *p_section,
     HandleCAT( i_dts );
 }
 
+static void mark_pmt_pids( uint8_t *p_pmt, uint8_t pid_map[], uint8_t marker )
+{
+    uint16_t j, k;
+    uint8_t *p_es;
+    uint8_t *p_desc;
+
+    uint16_t i_pcr_pid = pmt_get_pcrpid( p_pmt );
+
+    if ( b_enable_ecm )
+    {
+        j = 0;
+        while ( (p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j++ )) != NULL )
+        {
+            if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
+                continue;
+            pid_map[ desc09_get_pid( p_desc ) ] |= marker;
+        }
+    }
+
+    if ( i_pcr_pid != PADDING_PID )
+        pid_map[ i_pcr_pid ] |= marker;
+
+    j = 0;
+    while ( (p_es = pmt_get_es( p_pmt, j )) != NULL )
+    {
+        uint16_t i_pid = pmtn_get_pid( p_es );
+        j++;
+
+        if ( PIDWouldBeSelected( p_es ) )
+            pid_map[ i_pid ] |= marker;
+
+        p_pids[i_pid].b_pes = PIDCarriesPES( p_es );
+
+        if ( b_enable_ecm )
+        {
+            k = 0;
+            while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL )
+            {
+                if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
+                    continue;
+                pid_map[ desc09_get_pid( p_desc ) ] |= marker;
+            }
+        }
+    }
+}
+
 /*****************************************************************************
  * HandlePMT
  *****************************************************************************/
@@ -2207,11 +2253,7 @@ static void HandlePMT( uint16_t i_pid, uint8_t *p_pmt, mtime_t i_dts )
     uint16_t i_sid = pmt_get_program( p_pmt );
     sid_t *p_sid;
     bool b_needs_descrambling, b_needed_descrambling, b_is_selected;
-    uint16_t i_pcr_pid;
-    uint8_t *p_es;
-    uint8_t *p_desc;
-    uint16_t j;
-    uint16_t k;
+    uint8_t pid_map[MAX_PIDS];
 
     p_sid = FindSID( i_sid );
     if ( p_sid == NULL )
@@ -2261,136 +2303,44 @@ static void HandlePMT( uint16_t i_pid, uint8_t *p_pmt, mtime_t i_dts )
         goto out_pmt;
     }
 
+    memset( pid_map, 0, sizeof(pid_map) );
+
     b_needs_descrambling = PMTNeedsDescrambling( p_pmt );
     b_needed_descrambling = p_sid->p_current_pmt != NULL ?
                             PMTNeedsDescrambling( p_sid->p_current_pmt ) :
                             false;
     b_is_selected = SIDIsSelected( i_sid );
-    i_pcr_pid = pmt_get_pcrpid( p_pmt );
 
     if ( i_ca_handle && b_is_selected &&
          !b_needs_descrambling && b_needed_descrambling )
         en50221_DeletePMT( p_sid->p_current_pmt );
 
-    if ( b_enable_ecm )
+    if ( p_sid->p_current_pmt != NULL )
     {
-        j = 0;
-        while ( (p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j++ )) != NULL )
-        {
-            if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
-                continue;
-            SelectPID( i_sid, desc09_get_pid( p_desc ) );
-        }
+        mark_pmt_pids( p_sid->p_current_pmt, pid_map, 0x02 );
+        free( p_sid->p_current_pmt );
     }
 
-    if ( p_sid->p_current_pmt == NULL
-          || i_pcr_pid != pmt_get_pcrpid( p_sid->p_current_pmt ) )
-    {
-        if ( i_pcr_pid != PADDING_PID
-              && i_pcr_pid != p_sid->i_pmt_pid )
-            SelectPID( i_sid, i_pcr_pid );
-    }
+    mark_pmt_pids( p_pmt, pid_map, 0x01 );
 
-    j = 0;
-    while ( (p_es = pmt_get_es( p_pmt, j )) != NULL )
+    /* Start to stream PIDs */
+    int pid;
+    for ( pid = 0; pid < MAX_PIDS; pid++ )
     {
-        uint16_t i_pid = pmtn_get_pid( p_es );
-        j++;
-
-        if ( PIDWouldBeSelected( p_es ) )
-            SelectPID( i_sid, i_pid );
-        p_pids[i_pid].b_pes = PIDCarriesPES( p_es );
-
-        if ( b_enable_ecm )
-        {
-            k = 0;
-            while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL )
-            {
-                if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
-                    continue;
-                SelectPID( i_sid, desc09_get_pid( p_desc ) );
-            }
-        }
-    }
-
-    if ( p_sid->p_current_pmt != NULL )
-    {
-        if ( b_enable_ecm )
-        {
-            j = 0;
-            while ((p_desc = descs_get_desc( pmt_get_descs( p_sid->p_current_pmt ), j++ )) != NULL)
-            {
-                if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
-                    continue;
-                if ( ca_desc_find( pmt_get_descs(p_pmt) + DESCS_HEADER_SIZE, descs_get_length(pmt_get_descs(p_pmt)), desc09_get_pid( p_desc ) ) == NULL )
-                    UnselectPID( i_sid, desc09_get_pid( p_desc ) );
-            }
-        }
-
-        uint16_t i_current_pcr_pid = pmt_get_pcrpid( p_sid->p_current_pmt );
-        if ( i_current_pcr_pid != i_pcr_pid
-              && i_current_pcr_pid != PADDING_PID )
-        {
-            if ( pmt_find_es( p_pmt, i_current_pcr_pid ) == NULL )
-                UnselectPID( i_sid, i_current_pcr_pid );
-        }
-
-        j = 0;
-        while ( (p_es = pmt_get_es( p_sid->p_current_pmt, j )) != NULL )
-        {
-            j++;
-
-            if ( PIDWouldBeSelected( p_es ) )
-            {
-                uint16_t i_current_pid = pmtn_get_pid( p_es );
-
-                if ( pmt_find_es( p_pmt, i_current_pid ) == NULL )
-                    UnselectPID( i_sid, i_current_pid );
-            }
+        /* The pid does not exist in the old PMT and in the new PMT. Ignore this pid. */
+        if ( !pid_map[ pid ] )
+            continue;
 
-            if ( b_enable_ecm )
-            {
-                k = 0;
-                while ((p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL)
-                {
-                    if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
-                        continue;
-                    uint16_t f = 0;
-                    uint8_t *p_pmt_es;
-                    int pid_found = 0;
-                    while ( (p_pmt_es = pmt_get_es( p_pmt, f++ )) != NULL )
-                    {
-                        if ( ca_desc_find( pmtn_get_descs( p_pmt_es ) + DESCS_HEADER_SIZE,
-                                           descs_get_length( pmtn_get_descs( p_pmt_es ) ),
-                                           desc09_get_pid( p_desc ) ) != NULL )
-                        {
-                            pid_found = 1;
-                            break;
-                        }
-                        if ( !pid_found )
-                        {
-                            /* Check if PID is described in the global PMT descriptors */
-                            int r = 0;
-                            uint8_t *p_g_desc;
-                            while ( (p_g_desc = descs_get_desc( pmt_get_descs( p_sid->p_current_pmt ), r++ )) != NULL)
-                            {
-                                if ( desc_get_tag( p_g_desc ) != 0x09 || !desc09_validate( p_g_desc ) )
-                                    continue;
-                                if ( ca_desc_find( pmt_get_descs( p_pmt ) + DESCS_HEADER_SIZE, descs_get_length( pmt_get_descs( p_pmt ) ), desc09_get_pid( p_desc ) ) != NULL )
-                                {
-                                    pid_found = 1;
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    if ( !pid_found )
-                        UnselectPID( i_sid, desc09_get_pid( p_desc ) );
-                }
-            }
+        switch ( pid_map[ pid ] & 0x03 ) {
+        case 0x03: /* The pid exists in the old PMT and in the new PMT. The pid was already selected in case 0x01. */
+            continue;
+        case 0x02: /* The pid does not exist in the new PMT but exists in the old PMT. Unselect it. */
+            UnselectPID( i_sid, pid );
+            break;
+        case 0x01: /* The pid exists in new PMT. Select it. */
+            SelectPID( i_sid, pid );
+            break;
         }
-
-        free( p_sid->p_current_pmt );
     }
 
     p_sid->p_current_pmt = p_pmt;



More information about the dvblast-devel mailing list