[vlc-commits] dvb: use NIT-info from first found channel to scan rest of the channels

Ilkka Ollakka git at videolan.org
Thu Mar 17 14:24:29 CET 2011


vlc | branch: master | Ilkka Ollakka <ileoo at videolan.org> | Thu Mar 17 14:12:27 2011 +0200| [63e0c6d7453ce1f9cda68204f09585037dd18724] | committer: Ilkka Ollakka

dvb: use NIT-info from first found channel to scan rest of the channels

Speeds up channel scanning and actually should find all channels
without exhaustive scanning.

Patch fills pp_service with found configurations and DvbCNextFast
seeks first pp_service that doesn't have name and returns that for
next tune parameters. When tuning to that, we get SDT and fill names
for that freq.

This logic maybe belongs more on scan_Destroy where SDT-info is also
more parsed.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=63e0c6d7453ce1f9cda68204f09585037dd18724
---

 modules/access/dvb/scan.c |   88 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/modules/access/dvb/scan.c b/modules/access/dvb/scan.c
index 515cce1..017be0e 100644
--- a/modules/access/dvb/scan.c
+++ b/modules/access/dvb/scan.c
@@ -5,6 +5,7 @@
  *
  * Authors: Laurent Aimar <fenrir at videolan.org>
  *          David Kaplan <david at 2of1.org>
+ *          Ilkka Ollakka <ileoo at videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,6 +34,7 @@
 #include <vlc_dialog.h>
 #include <vlc_fs.h>
 #include <vlc_charset.h>
+#include <vlc_access.h>
 
 #include <sys/types.h>
 
@@ -50,6 +52,7 @@
 #   include <dvbpsi/nit.h>
 #endif
 
+#include "dvb.h"
 #include "scan.h"
 #include "../../demux/dvb-text.h"
 
@@ -507,12 +510,44 @@ static int ScanDvbTNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double
 static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
 {
     bool b_servicefound = false;
+#ifdef _DVBPSI_DR_44_H_
+    /* We iterate frequencies/modulations/symbolrates until we get first hit and find NIT,
+       from that we fill pp_service with configurations and after that we iterate over
+       pp_services for all that doesn't have name yet (tune to that cfg and get SDT and name
+       for channel).
+     */
     for( int i = 0; i < p_scan->i_service; i++ )
     {
-        b_servicefound = (p_scan->pp_service[i]->type != SERVICE_UNKNOWN);
+        /* We found radio/tv config that doesn't have a name,
+           lets tune to that mux
+         */
+        if( !p_scan->pp_service[i]->psz_name && ( p_scan->pp_service[i]->type != SERVICE_UNKNOWN ) )
+        {
+            p_cfg->i_frequency  = p_scan->pp_service[i]->cfg.i_frequency;
+            p_cfg->i_symbolrate = p_scan->pp_service[i]->cfg.i_symbolrate;
+            p_cfg->i_modulation = p_scan->pp_service[i]->cfg.i_modulation;
+            p_scan->i_index = i+1;
+            msg_Dbg( p_scan->p_obj, "iterating to freq: %u, symbolrate %u, modulation %u index %d/%d",
+                     p_cfg->i_frequency, p_cfg->i_symbolrate, p_cfg->i_modulation, p_scan->i_index, p_scan->i_service );
+            *pf_pos = (double)i/p_scan->i_service;
+            return VLC_SUCCESS;
+        }
+    }
+    /* We should have iterated all channels by now */
+    if( p_scan->i_service )
+        return VLC_EGENERIC;
+#else
+    /* fallback to old, so when we get one channe, use that
+       symbolrate/modulation until bitter end
+     */
+    for( int i=0; i < p_scan->i_service; i++ )
+    {
+        b_servicefound = p_scan->pp_service[i]->type != SERVICE_UNKNOWN;
         if( b_servicefound )
             break;
     }
+#endif
+
     if( !b_servicefound )
     {
         bool b_rotate=true;
@@ -742,6 +777,9 @@ static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
 static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
 {
     vlc_object_t *p_obj = p_session->p_obj;
+    access_t *p_access = (access_t*)p_obj;
+    access_sys_t *p_sys = p_access->p_sys;
+    scan_t *p_scan = p_sys->scan;
 
     msg_Dbg( p_obj, "NITCallBack" );
     msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d",
@@ -800,6 +838,9 @@ static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
 
         uint32_t i_private_data_id = 0;
         dvbpsi_descriptor_t *p_dsc;
+        scan_configuration_t *p_cfg = malloc(sizeof(*p_cfg));
+        if(!p_cfg) return VLC_ENOMEM;
+        memset(p_cfg,0,sizeof(*p_cfg));
         for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
         {
             if( p_dsc->i_tag == 0x41 )
@@ -810,6 +851,17 @@ static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
                     uint16_t i_service_id = GetWBE( &p_dsc->p_data[3*i+0] );
                     uint8_t  i_service_type = p_dsc->p_data[3*i+2];
                     msg_Dbg( p_obj, "           * service_id=%d type=%d", i_service_id, i_service_type );
+#ifdef _DVBPSI_DR_44_H_
+                    if( (ScanFindService( p_scan, 0, i_service_id ) == NULL) &&
+                         scan_service_type( i_service_type ) != SERVICE_UNKNOWN )
+                    {
+                       scan_service_t *s = scan_service_New( i_service_id, p_cfg );
+                       s->type          = scan_service_type( i_service_type );
+                       s->i_network_id  = p_nit->i_network_id;
+                       s->i_nit_version = p_nit->i_version;
+                       TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
+                    }
+#endif
                 }
             }
             else if( p_dsc->i_tag == 0x5a )
@@ -825,6 +877,24 @@ static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
                 msg_Dbg( p_obj, "           * transmission_mode %d", p_t->i_transmission_mode );
                 msg_Dbg( p_obj, "           * other_frequency_flag %d", p_t->i_other_frequency_flag );
             }
+#ifdef _DVBPSI_DR_44_H_
+            else if( p_dsc->i_tag == 0x44 )
+            {
+                dvbpsi_cable_deliv_sys_dr_t *p_t = dvbpsi_DecodeCableDelivSysDr( p_dsc );
+                msg_Dbg( p_obj, "       * Cable delivery system");
+
+                if( decode_BCD( p_t->i_frequency, &p_cfg->i_frequency ) < 0 )
+                    return;
+                p_cfg->i_frequency *= 100;
+                msg_Dbg( p_obj, "           * frequency %d", p_cfg->i_frequency );
+                if( decode_BCD( p_t->i_symbol_rate, &p_cfg->i_symbolrate ) < 0 )
+                    return;
+                p_cfg->i_symbolrate *= 100;
+                msg_Dbg( p_obj, "           * symbolrate %u", p_cfg->i_symbolrate );
+                p_cfg->i_modulation = (8 << p_t->i_modulation);
+                msg_Dbg( p_obj, "           * modulation %u", p_cfg->i_modulation );
+            }
+#endif
             else if( p_dsc->i_tag == 0x5f )
             {
                 msg_Dbg( p_obj, "       * private data specifier descriptor" );
@@ -839,6 +909,8 @@ static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
                     uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
                     int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
                     msg_Dbg( p_obj, "           * service_id=%d channel_number=%d", i_service_id, i_channel_number );
+                    scan_service_t *s = ScanFindService( p_scan, 0, i_service_id );
+                    if( s && s->i_channel < 0 ) s->i_channel = i_channel_number;
                 }
 
             }
@@ -856,7 +928,7 @@ static void PSINewTableCallBack( scan_session_t *p_session, dvbpsi_handle h, uin
     if( i_table_id == 0x42 )
         dvbpsi_AttachSDT( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_session );
 #ifdef DVBPSI_USE_NIT
-    else if( i_table_id == 0x40 )
+    else if( i_table_id == 0x40 || i_table_id == 0x41 )
         dvbpsi_AttachNIT( h, i_table_id, i_extension, (dvbpsi_nit_callback)NITCallBack, p_session );
 #endif
 }
@@ -902,8 +974,12 @@ void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session )
             if( p_program->i_number == 0 )  /* NIT */
                 continue;
 
-            scan_service_t *s = scan_service_New( p_program->i_number, &p_session->cfg );
-            TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
+            scan_service_t *s = ScanFindService( p_scan, 0, p_program->i_number );
+            if( s == NULL )
+            {
+                s = scan_service_New( p_program->i_number, &p_session->cfg );
+                TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
+            }
         }
     }
     /* Parse SDT */
@@ -912,7 +988,7 @@ void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session )
         dvbpsi_sdt_service_t *p_srv;
         for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
         {
-            scan_service_t *s = ScanFindService( p_scan, i_service_start, p_srv->i_service_id );
+            scan_service_t *s = ScanFindService( p_scan, 0, p_srv->i_service_id );
             dvbpsi_descriptor_t *p_dr;
 
             if( s )
@@ -1137,7 +1213,7 @@ bool scan_session_Push( scan_session_t *p_scan, block_t *p_block )
         if( p_scan->sdt )
             dvbpsi_PushPacket( p_scan->sdt, p_block->p_buffer );
     }
-    else if( i_pid == p_scan->i_nit_pid )
+    else /*if( i_pid == p_scan->i_nit_pid )*/
     {
 #ifdef DVBPSI_USE_NIT
         if( !p_scan->nit )



More information about the vlc-commits mailing list