access: dvb: scan: privatize scan session
authorFrancois Cartegnie <fcvlcdev@free.fr>
Wed, 20 Apr 2016 15:08:45 +0000 (17:08 +0200)
committerFrancois Cartegnie <fcvlcdev@free.fr>
Thu, 21 Apr 2016 18:22:48 +0000 (20:22 +0200)
Also removes the retuning which never can happen

modules/access/dvb/access.c
modules/access/dvb/scan.c
modules/access/dvb/scan.h

index 7763dc3..4f945e8 100644 (file)
@@ -96,8 +96,7 @@ static int Control( access_t *, int, va_list );
 
 static block_t *BlockScan( access_t * );
 
-#define DVB_SCAN_MAX_SIGNAL_TIME (1000*1000)
-#define DVB_SCAN_MAX_LOCK_TIME (5000*1000)
+#define DVB_SCAN_MAX_LOCK_TIME (2*CLOCK_FREQ)
 
 static void FilterUnset( access_t *, int i_max );
 static void FilterSet( access_t *, int i_pid, int i_type );
@@ -105,6 +104,10 @@ static void FilterSet( access_t *, int i_pid, int i_type );
 static void VarInit( access_t * );
 static int  ParseMRL( access_t * );
 
+static int ScanFrontendTuningHandler( scan_t *, void *, const scan_tuner_config_t * );
+static int ScanStatsCallback( scan_t *p_scan, void *p_privdata, int *pi_snr );
+static int ScanReadCallback( scan_t *, void *,  unsigned, size_t, uint8_t *, size_t *);
+
 /*****************************************************************************
  * Open: open the frontend device
  *****************************************************************************/
@@ -169,12 +172,17 @@ static int Open( vlc_object_t *p_this )
         FilterSet( p_access, 0x10, OTHER_TYPE );    // NIT
 
     if( FrontendFillScanParameter( p_access, &parameter ) ||
-            (p_scan = scan_New( VLC_OBJECT(p_access), &parameter )) == NULL )
+            (p_scan = scan_New( VLC_OBJECT(p_access), &parameter,
+                                ScanFrontendTuningHandler,
+                                ScanStatsCallback,
+                                ScanReadCallback,
+                                p_access )) == NULL )
     {
         scan_parameter_Clean( &parameter );
         Close( VLC_OBJECT(p_access) );
         return VLC_EGENERIC;
     }
+
     scan_parameter_Clean( &parameter );
     p_sys->scan = p_scan;
 
@@ -203,60 +211,56 @@ static void Close( vlc_object_t *p_this )
     free( p_sys );
 }
 
-/*****************************************************************************
- * BlockScan:
- *****************************************************************************/
-static block_t *BlockScan( access_t *p_access )
+static int ScanFrontendTuningHandler( scan_t *p_scan, void *p_privdata,
+                                      const scan_tuner_config_t *p_cfg )
 {
-    access_sys_t *p_sys = p_access->p_sys;
-    scan_t *p_scan = p_sys->scan;
-    scan_tuner_config_t cfg;
+    access_t *p_access = (access_t *) p_privdata;
+    VLC_UNUSED(p_scan);
 
-    /* */
-    if( scan_Next( p_scan, &cfg ) )
-    {
-        const bool b_first_eof = !p_access->info.b_eof;
+    var_SetInteger( p_access, "dvb-frequency", p_cfg->i_frequency );
+    var_SetInteger( p_access, "dvb-bandwidth", p_cfg->i_bandwidth );
 
-        if( b_first_eof )
-            msg_Warn( p_access, "Scanning finished" );
+    if ( p_cfg->c_polarization )
+        var_SetInteger( p_access, "dvb-voltage", p_cfg->c_polarization == 'H' ? 18 : 13 );
 
-        /* */
-        p_access->info.b_eof = true;
-        return b_first_eof ? scan_GetM3U( p_scan ) : NULL;
-    }
+    if ( p_cfg->i_symbolrate )
+        var_SetInteger( p_access, "dvb-srate", p_cfg->i_symbolrate );
 
-    /* */
-    scan_session_t *session = scan_session_New( p_scan, &cfg );
-    if( session == NULL )
-        return NULL;
-
-    /* */
-    msg_Dbg( p_access, "Scanning frequency %d", cfg.i_frequency );
-    var_SetInteger( p_access, "dvb-frequency", cfg.i_frequency );
-    msg_Dbg( p_access, " bandwidth %d", cfg.i_bandwidth );
-    var_SetInteger( p_access, "dvb-bandwidth", cfg.i_bandwidth );
-    if ( cfg.c_polarization )
-        var_SetInteger( p_access, "dvb-voltage", cfg.c_polarization == 'H' ? 18 : 13 );
-
-    if ( cfg.i_symbolrate )
-        var_SetInteger( p_access, "dvb-srate", cfg.i_symbolrate );
+    msg_Dbg( p_access, "Scanning frequency %d", p_cfg->i_frequency );
+    msg_Dbg( p_access, " bandwidth %d", p_cfg->i_bandwidth );
 
     /* Setting frontend parameters for tuning the hardware */
     if( FrontendSet( p_access ) < 0 )
     {
         msg_Err( p_access, "Failed to tune the frontend" );
-        //p_access->info.b_eof = true;
-        scan_session_Destroy( p_scan, session );
-        return NULL;
+        return VLC_EGENERIC;
     }
 
-    /* */
-    int64_t i_scan_start = mdate();
-    int64_t i_probe_start = 0;
+    return VLC_SUCCESS;
+}
+
+static int ScanStatsCallback( scan_t *p_scan, void *p_privdata, int *pi_snr )
+{
+    access_t *p_access = (access_t *) p_privdata;
+    VLC_UNUSED(p_scan);
+
+    frontend_statistic_t stat;
+    if( !FrontendGetStatistic( p_access, &stat ) )
+    {
+        *pi_snr = stat.i_snr;
+        return VLC_SUCCESS;
+    }
+
+    return VLC_EGENERIC;
+}
 
-    bool b_has_dvb_signal = false;
-    bool b_has_lock = false;
-    int i_best_snr = -1;
+static int ScanReadCallback( scan_t *p_scan, void *p_privdata,
+                             unsigned i_probe_timeout, size_t i_packets_max,
+                             uint8_t *p_packet, size_t *pi_count )
+{
+    access_t *p_access = (access_t *) p_privdata;
+    access_sys_t *p_sys = p_access->p_sys;
+    *pi_count = 0;
 
     /* Initialize file descriptor sets */
     struct pollfd ufds[2];
@@ -266,105 +270,96 @@ static block_t *BlockScan( access_t *p_access )
     ufds[1].fd = p_sys->i_frontend_handle;
     ufds[1].events = POLLPRI;
 
-    for ( ; ; )
-    {
-        frontend_status_t status;
-        FrontendGetStatus( p_access, &status );
-        b_has_dvb_signal |= status.b_has_carrier;
-        b_has_lock |= status.b_has_lock;
+    frontend_status_t status;
+    FrontendGetStatus( p_access, &status );
+    bool b_has_lock = status.b_has_lock;
 
-        int64_t i_scan_end;
-        if( i_probe_start )
-        {
-            i_scan_end = i_probe_start + scan_session_GetTablesTimeout( session );
-        }
-        else
-        {
-            i_scan_end = i_scan_start;
-            if( !b_has_dvb_signal )
-                i_scan_end += DVB_SCAN_MAX_SIGNAL_TIME;
-            else if( !b_has_lock )
-                i_scan_end += DVB_SCAN_MAX_LOCK_TIME;
-        }
+    mtime_t i_scan_start = mdate();
 
+    for( ; *pi_count == 0; )
+    {
         /* Find if some data is available */
         int i_ret;
 
+        mtime_t i_timeout = b_has_lock ? i_probe_timeout:
+                                         DVB_SCAN_MAX_LOCK_TIME;
+
         do
         {
-            int64_t timeout = i_scan_end - mdate();
+            mtime_t i_poll_timeout = i_scan_start - mdate() + i_timeout;
 
             i_ret = 0;
 
             if( vlc_killed() || scan_IsCancelled( p_scan ) )
                 break;
 
-            if( timeout >= 0 )
-                i_ret = vlc_poll_i11e( ufds, 2, timeout / 1000 );
+            if( i_poll_timeout >= 0 )
+                i_ret = vlc_poll_i11e( ufds, 2, i_poll_timeout / 1000 );
         }
         while( i_ret < 0 && errno == EINTR );
 
         if( i_ret < 0 )
         {
-            msg_Err( p_access, "poll error: %s", vlc_strerror_c(errno) );
-            p_access->info.b_eof = true;
-            break;
+            return VLC_EGENERIC;
         }
-
-        if( i_ret == 0 )
+        else if( i_ret == 0 )
         {
-            msg_Dbg( p_access,
-                     "timed out scanning current frequency (s=%d l=%d)",
-                     b_has_dvb_signal, b_has_lock );
-            break;
+            return VLC_ENOITEM;
         }
 
         if( ufds[1].revents )
         {
-            frontend_statistic_t stat;
-
             FrontendPoll( p_access );
 
-            if( !FrontendGetStatistic( p_access, &stat ) )
+            FrontendGetStatus( p_access, &status );
+            if( status.b_has_lock && !b_has_lock )
             {
-                if( stat.i_snr > i_best_snr )
-                {
-                    i_best_snr = stat.i_snr;
-                    scan_session_SetSNR( session, i_best_snr );
-                }
+                i_scan_start = mdate();
+                b_has_lock = true;
             }
         }
 
-        if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
-        {
-            msg_Warn( p_access, "no lock, tuning again" );
-            FrontendSet( p_access );
-        }
-
         if ( ufds[0].revents )
         {
-            if( i_probe_start == 0 )
-                i_probe_start = mdate();
-
-            ssize_t i_read = read( p_sys->i_handle, &p_sys->packet, TS_PACKET_SIZE );
-            if( i_read <= 0 )
+            for( size_t i=0; i<i_packets_max; i++ )
             {
-                msg_Warn( p_access, "read failed: %s", vlc_strerror_c(errno) );
-                continue;
+                ssize_t i_read = read( p_sys->i_handle, p_packet, TS_PACKET_SIZE * i_packets_max );
+                if( i_read < 0 )
+                {
+                    msg_Warn( p_access, "read failed: %s", vlc_strerror_c(errno) );
+                    break;
+                }
+                else if ( i_read == TS_PACKET_SIZE )
+                {
+                    *pi_count = i_read / TS_PACKET_SIZE;
+                }
             }
+        }
+    }
 
-            /* */
-            if( i_read == TS_PACKET_SIZE &&
-                scan_session_Push( session, &p_sys->packet ) )
-            {
-                msg_Dbg( p_access, "finished scanning current frequency" );
-                break;
-            }
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * BlockScan:
+ *****************************************************************************/
+static block_t *BlockScan( access_t *p_access )
+{
+    access_sys_t *p_sys = p_access->p_sys;
+    scan_t *p_scan = p_sys->scan;
+    block_t *p_block = NULL;
+
+    if( scan_Run( p_scan ) != VLC_SUCCESS )
+    {
+        if( !p_access->info.b_eof )
+        {
+             msg_Warn( p_access, "Scanning finished" );
+             p_block = scan_GetM3U( p_scan );
         }
+        p_access->info.b_eof = true;
     }
 
-    scan_session_Destroy( p_scan, session );
-    return NULL;
+    return p_block;
 }
 
 /*****************************************************************************
index ce44d70..c757013 100644 (file)
@@ -107,6 +107,11 @@ struct scan_multiplex_t
 struct scan_t
 {
     vlc_object_t *p_obj;
+    scan_frontend_tune_cb pf_tune;
+    scan_frontend_stats_cb pf_stats;
+    scan_demux_read_cb   pf_read;
+    void *p_cbdata;
+
     vlc_dialog_id *p_dialog_id;
     uint64_t i_index;
     scan_parameter_t parameter;
@@ -123,7 +128,7 @@ struct scan_t
     const scan_list_entry_t *p_current;
 };
 
-struct scan_session_t
+typedef struct
 {
     vlc_object_t *p_obj;
 
@@ -152,7 +157,12 @@ struct scan_session_t
     dvbpsi_t *p_pathandle;
     dvbpsi_t *p_sdthandle;
     dvbpsi_t *p_nithandle;
-};
+} scan_session_t;
+
+static scan_session_t * scan_session_New( scan_t *p_scan, const scan_tuner_config_t *p_cfg );
+static void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session );
+static bool scan_session_Push( scan_session_t *p_scan, const uint8_t *p_packet );
+static unsigned scan_session_GetTablesTimeout( const scan_session_t *p_session );
 
 /* */
 static void scan_tuner_config_Init( scan_tuner_config_t *p_cfg )
@@ -361,7 +371,11 @@ static void scan_Debug_Parameters( vlc_object_t *p_obj, const scan_parameter_t *
 }
 
 /* */
-scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter )
+scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter,
+                  scan_frontend_tune_cb pf_frontend,
+                  scan_frontend_stats_cb pf_status,
+                  scan_demux_read_cb pf_read,
+                  void *p_cbdata )
 {
     if( p_parameter->type == SCAN_NONE )
         return NULL;
@@ -371,6 +385,10 @@ scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter )
         return NULL;
 
     p_scan->p_obj = VLC_OBJECT(p_obj);
+    p_scan->pf_tune = pf_frontend;
+    p_scan->pf_stats = pf_status;
+    p_scan->pf_read = pf_read;
+    p_scan->p_cbdata = p_cbdata;
     p_scan->i_index = 0;
     p_scan->p_dialog_id = NULL;
     p_scan->i_multiplex = 0;
@@ -741,7 +759,7 @@ static int Scan_GetNextTunerConfig( scan_t *p_scan, scan_tuner_config_t *p_cfg,
     return VLC_ENOITEM;
 }
 
-int scan_Next( scan_t *p_scan, scan_tuner_config_t *p_cfg )
+static int scan_Next( scan_t *p_scan, scan_tuner_config_t *p_cfg )
 {
     double f_position;
     int i_ret;
@@ -797,6 +815,57 @@ bool scan_IsCancelled( scan_t *p_scan )
     return vlc_dialog_is_cancelled( p_scan->p_obj, p_scan->p_dialog_id );
 }
 
+int scan_Run( scan_t *p_scan )
+{
+    scan_tuner_config_t cfg;
+    if( scan_Next( p_scan, &cfg ) )
+        return VLC_ENOITEM;
+
+    scan_session_t *session = scan_session_New( p_scan, &cfg );
+    if( unlikely(session == NULL) )
+        return VLC_EGENERIC;
+
+    if( p_scan->pf_tune( p_scan, p_scan->p_cbdata, &cfg ) != VLC_SUCCESS )
+    {
+        scan_session_Destroy( p_scan, session );
+        return VLC_EGENERIC;
+    }
+
+    /* */
+    uint8_t packet[TS_PACKET_SIZE * SCAN_READ_BUFFER_COUNT];
+    int64_t i_scan_start = mdate();
+
+    for( ;; )
+    {
+        unsigned i_timeout = scan_session_GetTablesTimeout( session );
+        mtime_t i_remaining = mdate() - i_scan_start;
+        if( i_remaining > i_timeout )
+            break;
+
+        size_t i_packet_count = 0;
+        int i_ret = p_scan->pf_read( p_scan, p_scan->p_cbdata,
+                                     i_timeout - i_remaining,
+                                     SCAN_READ_BUFFER_COUNT,
+                                     (uint8_t *) &packet, &i_packet_count );
+        if ( i_ret != VLC_SUCCESS )
+            break;
+
+        if( p_scan->pf_stats )
+            p_scan->pf_stats( p_scan, p_scan->p_cbdata, &session->i_snr );
+
+        for( size_t i=0; i< i_packet_count; i++ )
+        {
+            if( scan_session_Push( session,
+                                   &packet[i * TS_PACKET_SIZE] ) )
+                break;
+        }
+    }
+
+    scan_session_Destroy( p_scan, session );
+
+    return VLC_SUCCESS;
+}
+
 static bool GetOtherNetworkNIT( scan_session_t *p_session, uint16_t i_network_id,
                                 dvbpsi_nit_t ***ppp_nit )
 {
@@ -1302,7 +1371,7 @@ static void PSINewTableCallBack( dvbpsi_t *h, uint8_t i_table_id, uint16_t i_ext
     }
 }
 
-scan_session_t *scan_session_New( scan_t *p_scan, const scan_tuner_config_t *p_cfg )
+static scan_session_t *scan_session_New( scan_t *p_scan, const scan_tuner_config_t *p_cfg )
 {
     scan_session_t *p_session = malloc( sizeof( *p_session ) );
     if( unlikely(p_session == NULL) )
@@ -1360,7 +1429,7 @@ static void scan_session_Delete( scan_session_t *p_session )
     free( p_session );
 }
 
-void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session )
+static void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session )
 {
     dvbpsi_pat_t *p_pat = p_session->local.p_pat;
     dvbpsi_sdt_t *p_sdt = p_session->local.p_sdt;
@@ -1525,7 +1594,7 @@ block_t *scan_GetM3U( scan_t *p_scan )
 
 #define dvbpsi_packet_push(a,b) dvbpsi_packet_push(a, (uint8_t *)b)
 
-bool scan_session_Push( scan_session_t *p_scan, const uint8_t *p_packet )
+static bool scan_session_Push( scan_session_t *p_scan, const uint8_t *p_packet )
 {
     if( p_packet[0] != 0x47 )
         return false;
@@ -1595,12 +1664,7 @@ bool scan_session_Push( scan_session_t *p_scan, const uint8_t *p_packet )
             (!p_scan->b_use_nit || p_scan->local.p_nit);
 }
 
-void scan_session_SetSNR( scan_session_t *p_session, int i_snr )
-{
-    p_session->i_snr = i_snr;
-}
-
-unsigned scan_session_GetTablesTimeout( const scan_session_t *p_session )
+static unsigned scan_session_GetTablesTimeout( const scan_session_t *p_session )
 {
     unsigned i_time = 0;
     if( !p_session->local.p_pat )
index dc5ce7a..577753e 100644 (file)
@@ -73,23 +73,25 @@ typedef struct scan_parameter_t
 
 } scan_parameter_t;
 
+#define SCAN_READ_BUFFER_COUNT 20
+
 typedef struct scan_t scan_t;
+typedef int (*scan_frontend_tune_cb)( scan_t *, void *, const scan_tuner_config_t * );
+typedef int (*scan_frontend_stats_cb)( scan_t *, void *, int * );
+typedef int (*scan_demux_filter_cb)( scan_t *, void *, uint16_t );
+typedef int (*scan_demux_read_cb)( scan_t *, void *, unsigned, size_t, uint8_t *, size_t * );
 
 void scan_parameter_Init( scan_parameter_t * );
 void scan_parameter_Clean( scan_parameter_t * );
 
-scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter );
+scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter,
+                  scan_frontend_tune_cb,
+                  scan_frontend_stats_cb,
+                  scan_demux_read_cb,
+                  void * );
 void scan_Destroy( scan_t *p_scan );
 
-int scan_Next( scan_t *p_scan, scan_tuner_config_t *p_cfg );
+int scan_Run( scan_t *p_scan );
 
 block_t *scan_GetM3U( scan_t *p_scan );
 bool scan_IsCancelled( scan_t *p_scan );
-
-typedef struct scan_session_t scan_session_t;
-
-scan_session_t *scan_session_New( scan_t *, const scan_tuner_config_t * );
-void scan_session_Destroy( scan_t *, scan_session_t * );
-bool scan_session_Push( scan_session_t *p_scan, const uint8_t * );
-void scan_session_SetSNR( scan_session_t *p_scan, int i_snr );
-unsigned scan_session_GetTablesTimeout( const scan_session_t * );