dvbsrc: smarten-up delsys autodetection logic
authorReynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>
Wed, 4 May 2016 23:32:19 +0000 (16:32 -0700)
committerReynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>
Fri, 6 May 2016 23:15:36 +0000 (16:15 -0700)
When there's no explicit delivery system information
for a channel in the channel configuration file and
the user hasn't selected one via setting the delsys
property, we *guessed* it by selecting the last
supported delsys reported by the driver. This change
provides the basis for smarter delsys auto detection
and implements a rule for DVB-T2. Rules for other
delivery systems can be added in _guess_delsys() in
a similar way.

Additionally: Store list of adapter-supported
delivery systems instead of querying the driver each
time this information is needed.

Related to:

https://bugzilla.gnome.org/show_bug.cgi?id=765731

sys/dvb/gstdvbsrc.c
sys/dvb/gstdvbsrc.h

index e271fc1..2042a6b 100644 (file)
@@ -551,6 +551,7 @@ static void gst_dvbsrc_do_tune (GstDvbSrc * src);
 static gboolean gst_dvbsrc_tune (GstDvbSrc * object);
 static gboolean gst_dvbsrc_set_fe_params (GstDvbSrc * object,
     struct dtv_properties *props);
+static void gst_dvbsrc_guess_delsys (GstDvbSrc * object);
 static gboolean gst_dvbsrc_tune_fe (GstDvbSrc * object);
 
 static void gst_dvbsrc_set_pes_filters (GstDvbSrc * object);
@@ -1024,6 +1025,7 @@ gst_dvbsrc_init (GstDvbSrc * object)
 
   object->fd_frontend = -1;
   object->fd_dvr = -1;
+  object->supported_delsys = NULL;
 
   for (i = 0; i < MAX_FILTERS; i++) {
     object->pids[i] = G_MAXUINT16;
@@ -1049,7 +1051,6 @@ gst_dvbsrc_init (GstDvbSrc * object)
   object->inversion = DEFAULT_INVERSION;
   object->stats_interval = DEFAULT_STATS_REPORTING_INTERVAL;
   object->delsys = DEFAULT_DELSYS;
-  object->best_guess_delsys = DEFAULT_DELSYS;
   object->pilot = DEFAULT_PILOT;
   object->rolloff = DEFAULT_ROLLOFF;
   object->stream_id = DEFAULT_STREAM_ID;
@@ -1574,8 +1575,8 @@ gst_dvbsrc_open_frontend (GstDvbSrc * object, gboolean writable)
     return FALSE;
   }
 
-  if (object->best_guess_delsys != DEFAULT_DELSYS)
-    goto delsys_already_autodetected;
+  if (object->supported_delsys)
+    goto delsys_detection_done;
 
   /* Perform delivery system autodetection */
 
@@ -1626,107 +1627,125 @@ gst_dvbsrc_open_frontend (GstDvbSrc * object, gboolean writable)
 
   /* Capability delivery systems */
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBC_ANNEX_A)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBC_ANNEX_A));
     gst_structure_set (adapter_structure, "dvb-c-a", G_TYPE_STRING,
         "DVB-C ANNEX A", NULL);
-    object->best_guess_delsys = SYS_DVBC_ANNEX_A;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBC_ANNEX_B)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBC_ANNEX_B));
     gst_structure_set (adapter_structure, "dvb-c-b", G_TYPE_STRING,
         "DVB-C ANNEX C", NULL);
-    object->best_guess_delsys = SYS_DVBC_ANNEX_B;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBT)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBT));
     gst_structure_set (adapter_structure, "dvb-t", G_TYPE_STRING, "DVB-T",
         NULL);
-    object->best_guess_delsys = SYS_DVBT;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DSS)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DSS));
     gst_structure_set (adapter_structure, "dss", G_TYPE_STRING, "DSS", NULL);
-    object->best_guess_delsys = SYS_DSS;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBS)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBS));
     gst_structure_set (adapter_structure, "dvb-s", G_TYPE_STRING, "DVB-S",
         NULL);
-    object->best_guess_delsys = SYS_DVBS;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBS2)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBS2));
     gst_structure_set (adapter_structure, "dvb-s2", G_TYPE_STRING, "DVB-S2",
         NULL);
-    object->best_guess_delsys = SYS_DVBS2;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBH)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBH));
     gst_structure_set (adapter_structure, "dvb-h", G_TYPE_STRING, "DVB-H",
         NULL);
-    object->best_guess_delsys = SYS_DVBH;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_ISDBT)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_ISDBT));
     gst_structure_set (adapter_structure, "isdb-t", G_TYPE_STRING, "ISDB-T",
         NULL);
-    object->best_guess_delsys = SYS_ISDBT;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_ISDBS)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_ISDBS));
     gst_structure_set (adapter_structure, "isdb-s", G_TYPE_STRING, "ISDB-S",
         NULL);
-    object->best_guess_delsys = SYS_ISDBS;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_ISDBC)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_ISDBC));
     gst_structure_set (adapter_structure, "isdb-c", G_TYPE_STRING, "ISDB-C",
         NULL);
-    object->best_guess_delsys = SYS_ISDBC;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_ATSC)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_ATSC));
     gst_structure_set (adapter_structure, "atsc", G_TYPE_STRING, "ATSC", NULL);
-    object->best_guess_delsys = SYS_ATSC;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_ATSCMH)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_ATSCMH));
     gst_structure_set (adapter_structure, "atsc-mh", G_TYPE_STRING, "ATSC-MH",
         NULL);
-    object->best_guess_delsys = SYS_ATSCMH;
   }
 #if HAVE_V5_MINOR(7)
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DTMB)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DTMB));
     gst_structure_set (adapter_structure, "dtmb", G_TYPE_STRING, "DTMB", NULL);
-    object->best_guess_delsys = SYS_DTMB;
   }
 #endif
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_CMMB)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_CMMB));
     gst_structure_set (adapter_structure, "cmmb", G_TYPE_STRING, "CMMB", NULL);
-    object->best_guess_delsys = SYS_CMMB;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DAB)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DAB));
     gst_structure_set (adapter_structure, "dab", G_TYPE_STRING, "DAB", NULL);
-    object->best_guess_delsys = SYS_DAB;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBT2)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBT2));
     gst_structure_set (adapter_structure, "dvb-t2", G_TYPE_STRING, "DVB-T2",
         NULL);
-    object->best_guess_delsys = SYS_DVBT2;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_TURBO)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_TURBO));
     gst_structure_set (adapter_structure, "turbo", G_TYPE_STRING, "TURBO",
         NULL);
-    object->best_guess_delsys = SYS_TURBO;
   }
 
   if (gst_dvbsrc_check_delsys (&dvb_prop[0], SYS_DVBC_ANNEX_C)) {
+    object->supported_delsys = g_list_append (object->supported_delsys,
+        GINT_TO_POINTER (SYS_DVBC_ANNEX_C));
     gst_structure_set (adapter_structure, "dvb-c-c", G_TYPE_STRING,
         "DVB-C ANNEX C", NULL);
-    object->best_guess_delsys = SYS_DVBC_ANNEX_C;
   }
 
   GST_INFO_OBJECT (object, "DVB card: %s ", adapter_name);
@@ -1736,7 +1755,7 @@ gst_dvbsrc_open_frontend (GstDvbSrc * object, gboolean writable)
       (GST_OBJECT (object), adapter_structure));
   g_free (adapter_name);
 
-delsys_already_autodetected:
+delsys_detection_done:
   g_free (frontend_dev);
 
   return TRUE;
@@ -1993,6 +2012,8 @@ gst_dvbsrc_stop (GstBaseSrc * bsrc)
   GstDvbSrc *src = GST_DVBSRC (bsrc);
 
   gst_dvbsrc_close_devices (src);
+  g_list_free (src->supported_delsys);
+  src->supported_delsys = NULL;
   if (src->poll) {
     gst_poll_free (src->poll);
     src->poll = NULL;
@@ -2215,26 +2236,13 @@ gst_dvbsrc_tune_fe (GstDvbSrc * object)
     return FALSE;
   }
 
-  /* If there's no delivery system set yet, proceed with the autodetected
-   * one, otherwise confirm the one set is supported */
-  if (object->delsys == SYS_UNDEFINED)
-    object->delsys = object->best_guess_delsys;
-  else {
+  /* If set, confirm the choosen delivery system is actually
+   * supported by the hardware */
+  if (object->delsys != SYS_UNDEFINED) {
     GST_DEBUG_OBJECT (object, "Confirming delsys '%u' is supported",
         object->delsys);
-
-    dvb_prop[0].cmd = DTV_ENUM_DELSYS;
-    props.num = 1;
-    props.props = dvb_prop;
-
-    LOOP_WHILE_EINTR (err, ioctl (object->fd_frontend,
-            FE_GET_PROPERTY, &props));
-    if (err) {
-      GST_WARNING_OBJECT (object, "Error enumerating delsys: %s",
-          g_strerror (errno));
-      return FALSE;
-    }
-    if (!gst_dvbsrc_check_delsys (&dvb_prop[0], object->delsys)) {
+    if (!g_list_find (object->supported_delsys,
+            GINT_TO_POINTER (object->delsys))) {
       GST_WARNING_OBJECT (object, "Adapter does not support delsys '%u'",
           object->delsys);
       return FALSE;
@@ -2247,6 +2255,8 @@ gst_dvbsrc_tune_fe (GstDvbSrc * object)
 
   memset (dvb_prop, 0, sizeof (dvb_prop));
   dvb_prop[0].cmd = DTV_CLEAR;
+  props.num = 1;
+  props.props = dvb_prop;
 
   LOOP_WHILE_EINTR (err, ioctl (object->fd_frontend, FE_SET_PROPERTY, &props));
   if (err) {
@@ -2313,6 +2323,35 @@ fail:
   return FALSE;
 }
 
+static void
+gst_dvbsrc_guess_delsys (GstDvbSrc * object)
+{
+  GList *delsys;
+
+  /* If adapter only supports one delivery system, there's no real choice */
+  if (g_list_length (object->supported_delsys) == 1)
+    goto go_with_default;
+
+  /* Add delivery system specific rules here */
+
+  /* DVB-T/T2 on QAM_256 channel? has to be DVB-T2 */
+  if (object->modulation == QAM_256 &&
+      g_list_find (object->supported_delsys, GINT_TO_POINTER (SYS_DVBT2))) {
+    object->delsys = SYS_DVBT2;
+    goto autoselection_done;
+  }
+
+  /* No rule provided a match so we default to the last device-reported
+   * supported delivery system */
+go_with_default:
+  delsys = g_list_last (object->supported_delsys);
+  object->delsys = *(guchar *) delsys->data;
+
+autoselection_done:
+  GST_INFO_OBJECT (object, "Automatically selecting delivery system '%u'",
+      object->delsys);
+}
+
 static gboolean
 gst_dvbsrc_set_fe_params (GstDvbSrc * object, struct dtv_properties *props)
 {
@@ -2323,6 +2362,10 @@ gst_dvbsrc_set_fe_params (GstDvbSrc * object, struct dtv_properties *props)
   int n;
   gint err;
 
+  /* If delsys hasn't been set, ask for it to be automatically selected */
+  if (object->delsys == SYS_UNDEFINED)
+    gst_dvbsrc_guess_delsys (object);
+
   /* first 3 entries are reserved */
   n = 3;
 
index 27a27b7..e504ea8 100644 (file)
@@ -64,8 +64,8 @@ struct _GstDvbSrc
   GMutex tune_mutex;
   gboolean need_tune;
 
+  GList * supported_delsys;
   guchar delsys;
-  guchar best_guess_delsys;
 
   int adapter_number;
   int frontend_number;