{
PROP_0,
V4L2_STD_OBJECT_PROPS,
+#ifdef TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID
+ PROP_CAMERA_ID,
+#endif /* TIZEN_FEATURE_V4L2SRC_SUPPORT_CAMERA_ID */
+#ifdef TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE
+ PROP_AUTO_SCAN_DEVICE,
+#endif /* TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE */
PROP_LAST
};
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 */
+
+#ifdef TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE
+ /**
+ * GstV4l2Src:auto-scan-device:
+ */
+ g_object_class_install_property (gobject_class, PROP_AUTO_SCAN_DEVICE,
+ g_param_spec_boolean ("auto-scan-device", "Scan device automatically",
+ "Scan all device nodes automatically until device open success.",
+ TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif /* TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE */
+
/**
* GstV4l2Src::prepare-format:
* @v4l2src: the v4l2src instance
* happen prior to the format being set.
* This is mostly useful for UVC H264 encoding cameras which need the H264
* Probe & Commit to happen prior to the normal Probe & Commit.
- *
- * Since: 0.10.32
*/
gst_v4l2_signals[SIGNAL_PRE_SET_FORMAT] = g_signal_new ("prepare-format",
G_TYPE_FROM_CLASS (klass),
/* Avoid the slow probes */
v4l2src->v4l2object->skip_try_fmt_probes = TRUE;
+#ifdef TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE
+ v4l2src->v4l2object->auto_scan_device = TRUE;
+#endif /* TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE */
gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
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 */
+#ifdef TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE
+ case PROP_AUTO_SCAN_DEVICE:
+ v4l2src->v4l2object->auto_scan_device = g_value_get_boolean (value);
+ GST_INFO_OBJECT (v4l2src, "auto scan device [%d]", v4l2src->v4l2object->auto_scan_device);
+ break;
+#endif /* TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
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 */
+#ifdef TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE
+ case PROP_AUTO_SCAN_DEVICE:
+ GST_INFO_OBJECT (v4l2src, "auto scan device [%d]", v4l2src->v4l2object->auto_scan_device);
+ g_value_set_boolean (value, v4l2src->v4l2object->auto_scan_device);
+ break;
+#endif /* TIZEN_FEATURE_V4L2SRC_AUTO_SCAN_DEVICE_NODE */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
/* 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);
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. */
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,
fcaps = gst_caps_copy_nth (caps, i);
- if (GST_V4L2_IS_ACTIVE (obj)) {
- /* 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))
+ /* 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;
}
/* Only EIVAL make sense, report any other errors, this way we don't keep