Cache and reuse probed caps
authorJussi Saavalainen <jussi.saavalainen@ixonos.com>
Wed, 13 Feb 2013 12:00:07 +0000 (14:00 +0200)
committerJussi Saavalainen <jussi.saavalainen@ixonos.com>
Wed, 13 Feb 2013 12:00:07 +0000 (14:00 +0200)
Only probe each (sensor, mode, format) combination once. The
distinction is necessary since the lower stack may have different
caps for each.

Change-Id: Ida40f72f3803299a5cbec6ec476cbc8b5a567aed

gst/mfldv4l2cam/gstv4l2camsrc.c
gst/mfldv4l2cam/gstv4l2camsrc.h

index 3018020..cf7eecb 100644 (file)
@@ -361,6 +361,18 @@ gst_v4l2camsrc_is_active (GstCameraSrc * camsrc)
   return GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc);
 }
 
+static gint caps_cache_cmp(struct cached_gst_caps *a, struct cached_gst_caps *b)
+{
+  int r;
+  r = a->input - b->input;
+  if(r)
+    return r;
+  r = a->mode - b->mode;
+  if(r)
+    return r;
+  return (long)(a->pixelformat) - (long)(b->pixelformat);
+}
+
 /*
  * gst_v4l2camsrc_v4l2fourcc_to_structure:
  *
@@ -622,10 +634,28 @@ gst_v4l2camsrc_get_caps (GstCameraSrc * camsrc)
 
   for (walk = v4l2camsrc->formats; walk; walk = walk->next) {
     struct v4l2_fmtdesc *format;
+    GSList *it;
 
     /* FIXME: Introduce own format structure */
     format = (struct v4l2_fmtdesc *) walk->data;
 
+    struct cached_gst_caps *val, key = {
+      .input = v4l2camsrc->input_sensor,
+      .mode = v4l2camsrc->capture_mode,
+      .pixelformat = format->pixelformat
+    };
+
+    it = g_slist_find_custom(v4l2camsrc->caps_cache, &key, (GCompareFunc)caps_cache_cmp);
+    if(it) {
+      val = (struct cached_gst_caps *) it->data;
+      gst_caps_append(ret, gst_caps_ref(val->caps));
+      GST_DEBUG_OBJECT(v4l2camsrc, "Using cached caps for (sensor=%d,mode=%d,format=%0.4s)",
+                         val->input,val->mode,(char*)&val->pixelformat);
+      continue;
+    }
+
+    GST_DEBUG_OBJECT(v4l2camsrc, "Now probing for (sensor=%d,mode=%d,format=%0.4s)",
+      key.input,key.mode,(char*)&key.pixelformat);
     template = gst_v4l2camsrc_v4l2fourcc_to_structure (format->pixelformat);
 
     if (template) {
@@ -633,8 +663,13 @@ gst_v4l2camsrc_get_caps (GstCameraSrc * camsrc)
 
       tmp = gst_v4l2camsrc_probe_caps_for_format (v4l2camsrc,
           format->pixelformat, template);
-      if (tmp)
+      if (tmp) {
+        val = malloc(sizeof *val);
+        memcpy(val, &key, sizeof *val);
+        val->caps = gst_caps_ref(tmp);
+        v4l2camsrc->caps_cache = g_slist_prepend(v4l2camsrc->caps_cache, val);
         gst_caps_append (ret, tmp);
+      }
 
       gst_structure_free (template);
     } else {
@@ -647,8 +682,7 @@ gst_v4l2camsrc_get_caps (GstCameraSrc * camsrc)
 
   v4l2camsrc->probed_caps = gst_caps_ref (ret);
 
-  GST_INFO_OBJECT(v4l2camsrc, "use GST_DEBUG >= 5 for probed caps");
-  GST_LOG_OBJECT (v4l2camsrc, "probed caps: %" GST_PTR_FORMAT, ret);
+  GST_INFO_OBJECT (v4l2camsrc, "caps: %" GST_PTR_FORMAT, ret);
 
   return ret;
 }
@@ -1088,6 +1122,8 @@ gst_v4l2camsrc_init (GstMFLDV4l2CamSrc * v4l2camsrc,
 
   v4l2camsrc->device_mutex = g_mutex_new ();
 
+  v4l2camsrc->caps_cache = NULL;
+
   v4l2camsrc->mfldadvci = gst_v4l2camsrc_mfldadvci_wrapper_load (v4l2camsrc);
 
   v4l2camsrc->input_sensor = GST_CAMERA_INPUT_SENSOR_PRIMARY;
@@ -1111,12 +1147,24 @@ gst_v4l2camsrc_init (GstMFLDV4l2CamSrc * v4l2camsrc,
   GST_DEBUG ("initialized to commit %s", MFLD_V4L2CAMSRC_VERSION);
 }
 
+static void caps_cache_destroy_value(struct cached_gst_caps *val)
+{
+  if(!val)
+    return;
+  if(val->caps)
+    gst_caps_unref(val->caps);
+  free(val);
+}
 
 static void
 gst_v4l2camsrc_dispose (GObject * object)
 {
   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (object);
 
+  if (v4l2camsrc->caps_cache)
+    g_slist_free_full(v4l2camsrc->caps_cache, (GDestroyNotify) caps_cache_destroy_value);
+  v4l2camsrc->caps_cache = NULL;
+
   if (v4l2camsrc->formats) {
     gst_v4l2camsrc_clear_format_list (v4l2camsrc);
   }
index f5e6df2..4b084ed 100644 (file)
@@ -216,6 +216,13 @@ struct _GstMFLDV4l2CamSrcBufferPool
   gboolean is_vaapi_sharing;
 };
 
+struct cached_gst_caps {
+  GstCameraInputSensor input;
+  GstCameraSrcCaptureMode mode;
+  guint32 pixelformat;
+  GstCaps *caps;
+};
+
 /**
 * GstMFLDV4l2CamSrc:
 * @element: the parent element.
@@ -300,6 +307,8 @@ struct _GstMFLDV4l2CamSrc {
 
   gboolean disable_low_res_crop;
   gboolean draw_corner_markers;
+
+  GSList *caps_cache;
 };