Merge branch 'upstream/1.16' into tizen_gst_1.16.2
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2src.c
index 88c813f..0b55b5d 100644 (file)
@@ -72,6 +72,9 @@ enum
 {
   PROP_0,
   V4L2_STD_OBJECT_PROPS,
+#ifdef TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID
+  PROP_CAMERA_ID,
+#endif /* TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID */
   PROP_LAST
 };
 
@@ -147,6 +150,19 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
   gst_v4l2_object_install_properties_helper (gobject_class,
       DEFAULT_PROP_DEVICE);
 
+#ifdef TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID
+  /**
+   * GstV4l2Src:camera-id:
+   *
+   * The value which is set by application will be used as a number of device node.
+   * ex) 1 -> /dev/video1
+   */
+  g_object_class_install_property (gobject_class, PROP_CAMERA_ID,
+      g_param_spec_uint ("camera-id", "Camera ID",
+          "Camera ID for device node", 0, G_MAXUINT, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif /* TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID */
+
   /**
    * GstV4l2Src::prepare-format:
    * @v4l2src: the v4l2src instance
@@ -226,6 +242,16 @@ gst_v4l2src_set_property (GObject * object,
   if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
           prop_id, value, pspec)) {
     switch (prop_id) {
+#ifdef TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID
+      case PROP_CAMERA_ID:
+        g_free (v4l2src->v4l2object->videodev);
+
+        v4l2src->camera_id = g_value_get_uint (value);
+        v4l2src->v4l2object->videodev = g_strdup_printf ("/dev/video%u", v4l2src->camera_id);
+
+        GST_INFO_OBJECT(v4l2src, "videodev [%s]", v4l2src->v4l2object->videodev);
+        break;
+#endif /* TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID */
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -242,6 +268,11 @@ gst_v4l2src_get_property (GObject * object,
   if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
           prop_id, value, pspec)) {
     switch (prop_id) {
+#ifdef TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID
+      case PROP_CAMERA_ID:
+        g_value_set_uint (value, v4l2src->camera_id);
+        break;
+#endif /* TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID */
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -308,13 +339,17 @@ gst_v4l2_src_parse_fixed_struct (GstStructure * s,
 
 /* TODO Consider framerate */
 static gint
-gst_v4l2src_fixed_caps_compare (GstStructure * a, GstStructure * b,
+gst_v4l2src_fixed_caps_compare (GstCaps * caps_a, GstCaps * caps_b,
     struct PreferedCapsInfo *pref)
 {
+  GstStructure *a, *b;
   gint aw = G_MAXINT, ah = G_MAXINT, ad = G_MAXINT;
   gint bw = G_MAXINT, bh = G_MAXINT, bd = G_MAXINT;
   gint ret;
 
+  a = gst_caps_get_structure (caps_a, 0);
+  b = gst_caps_get_structure (caps_b, 0);
+
   gst_v4l2_src_parse_fixed_struct (a, &aw, &ah, NULL, NULL);
   gst_v4l2_src_parse_fixed_struct (b, &bw, &bh, NULL, NULL);
 
@@ -402,8 +437,6 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
 
   GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
 
-  caps = gst_caps_make_writable (caps);
-
   /* We consider the first structure from peercaps to be a preference. This is
    * useful for matching a reported native display, or simply to avoid
    * transformation to happen downstream. */
@@ -418,17 +451,24 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
   GST_DEBUG_OBJECT (basesrc, "Prefered size %ix%i", pref.width, pref.height);
 
   /* Sort the structures to get the caps that is nearest to our preferences,
-   * first */
-  while ((s = gst_caps_steal_structure (caps, 0))) {
+   * first. Use single struct caps for sorting so we preserve the features.  */
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    GstCaps *tmp = gst_caps_copy_nth (caps, i);
+
+    s = gst_caps_get_structure (tmp, 0);
     gst_v4l2_src_fixate_struct_with_preference (s, &pref);
-    caps_list = g_list_insert_sorted_with_data (caps_list, s,
+
+    caps_list = g_list_insert_sorted_with_data (caps_list, tmp,
         (GCompareDataFunc) gst_v4l2src_fixed_caps_compare, &pref);
   }
 
+  gst_caps_unref (caps);
+  caps = gst_caps_new_empty ();
+
   while (caps_list) {
-    s = caps_list->data;
+    GstCaps *tmp = caps_list->data;
     caps_list = g_list_delete_link (caps_list, caps_list);
-    gst_caps_append_structure (caps, s);
+    gst_caps_append (caps, tmp);
   }
 
   GST_DEBUG_OBJECT (basesrc, "sorted and normalized caps %" GST_PTR_FORMAT,
@@ -446,33 +486,28 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps, GstStructure * pref_s)
 
     fcaps = gst_caps_copy_nth (caps, i);
 
-    if (GST_V4L2_IS_ACTIVE (obj)) {
-      /* try hard to avoid TRY_FMT since some UVC camera just crash when this
-       * is called at run-time. */
-      if (gst_v4l2_object_caps_is_subset (obj, fcaps)) {
-        gst_caps_unref (fcaps);
-        fcaps = gst_v4l2_object_get_current_caps (obj);
-        break;
-      }
+    /* try hard to avoid TRY_FMT since some UVC camera just crash when this
+     * is called at run-time. */
+    if (gst_v4l2_object_caps_is_subset (obj, fcaps)) {
+      gst_caps_unref (fcaps);
+      fcaps = gst_v4l2_object_get_current_caps (obj);
+      break;
+    }
 
-      /* Just check if the format is acceptable, once we know
-       * no buffers should be outstanding we try S_FMT.
-       *
-       * Basesrc will do an allocation query that
-       * should indirectly reclaim buffers, after that we can
-       * set the format and then configure our pool */
-      if (gst_v4l2_object_try_format (obj, fcaps, &error)) {
-        /* make sure the caps changed before doing anything */
-        if (gst_v4l2_object_caps_equal (obj, fcaps))
-          break;
-
-        v4l2src->renegotiation_adjust = v4l2src->offset + 1;
-        v4l2src->pending_set_fmt = TRUE;
-        break;
-      }
-    } else {
-      if (gst_v4l2src_set_format (v4l2src, fcaps, &error))
+    /* Just check if the format is acceptable, once we know
+     * no buffers should be outstanding we try S_FMT.
+     *
+     * Basesrc will do an allocation query that
+     * should indirectly reclaim buffers, after that we can
+     * set the format and then configure our pool */
+    if (gst_v4l2_object_try_format (obj, fcaps, &error)) {
+      /* make sure the caps changed before doing anything */
+      if (gst_v4l2_object_caps_equal (obj, fcaps))
         break;
+
+      v4l2src->renegotiation_adjust = v4l2src->offset + 1;
+      v4l2src->pending_set_fmt = TRUE;
+      break;
     }
 
     /* Only EIVAL make sense, report any other errors, this way we don't keep