瀏覽代碼

Use udev events in the v4l2 plugin.

This adds code to set up the udev monitoring library and use the events
to detect connects/disconnects of devices.
When the currently used device is disconnected the plugin will stop
recording and clean up, so that the device node is freed up.
On reconnection of the device the plugin will use the event to
automatically start the capture again.
fryshorts 11 年之前
父節點
當前提交
9a37b2ce9c
共有 1 個文件被更改,包括 57 次插入0 次删除
  1. 57 0
      plugins/linux-v4l2/v4l2-input.c

+ 57 - 0
plugins/linux-v4l2/v4l2-input.c

@@ -36,6 +36,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "v4l2-helpers.h"
 
+#if HAVE_UDEV
+#include "v4l2-udev.h"
+#endif
+
 #define V4L2_DATA(voidptr) struct v4l2_data *data = voidptr;
 
 #define timeval2ns(tv) \
@@ -58,6 +62,7 @@ struct v4l2_data {
 	obs_source_t *source;
 	pthread_t thread;
 	os_event_t *event;
+	void *udev;
 
 	int_fast32_t dev;
 	int width;
@@ -69,6 +74,10 @@ struct v4l2_data {
 	uint64_t frames;
 };
 
+/* forward declarations */
+static void v4l2_init(struct v4l2_data *data);
+static void v4l2_terminate(struct v4l2_data *data);
+
 /**
  * Prepare the output frame structure for obs and compute plane offsets
  *
@@ -504,6 +513,43 @@ static bool resolution_selected(obs_properties_t *props, obs_property_t *p,
 	return true;
 }
 
+#if HAVE_UDEV
+/**
+ * Device added callback
+ *
+ * If everything went fine we can start capturing again when the device is
+ * reconnected
+ */
+static void device_added(const char *dev, void *vptr)
+{
+	V4L2_DATA(vptr);
+
+	if (strcmp(data->device_id, dev))
+		return;
+
+	blog(LOG_INFO, "Device %s reconnected", dev);
+
+	v4l2_init(data);
+}
+/**
+ * Device removed callback
+ *
+ * We stop recording here so we don't block the device node
+ */
+static void device_removed(const char *dev, void *vptr)
+{
+	V4L2_DATA(vptr);
+
+	if (strcmp(data->device_id, dev))
+		return;
+
+	blog(LOG_INFO, "Device %s disconnected", dev);
+
+	v4l2_terminate(data);
+}
+
+#endif
+
 static obs_properties_t *v4l2_properties(void *unused)
 {
 	UNUSED_PARAMETER(unused);
@@ -567,6 +613,11 @@ static void v4l2_destroy(void *vptr)
 
 	if (data->device_id)
 		bfree(data->device_id);
+
+#if HAVE_UDEV
+	v4l2_unref_udev(data->udev);
+#endif
+
 	bfree(data);
 }
 
@@ -672,6 +723,12 @@ static void *v4l2_create(obs_data_t *settings, obs_source_t *source)
 
 	v4l2_update(data, settings);
 
+#if HAVE_UDEV
+	data->udev = v4l2_init_udev();
+	v4l2_set_device_added_callback(data->udev, &device_added, data);
+	v4l2_set_device_removed_callback(data->udev, &device_removed, data);
+#endif
+
 	return data;
 }