فهرست منبع

linux-v4l2: Improve error and debug logging

The capture loop errors are now logged as such.
Increased the amount of information logged in debug mode, including
state of all buffers on timeout.
Add device name to all capture loop debug output, especially useful when
debugging issues with multiple v4l2 video streams.
Piotr Esden-Tempski 4 سال پیش
والد
کامیت
bb264b2b33
3فایلهای تغییر یافته به همراه75 افزوده شده و 6 حذف شده
  1. 28 0
      plugins/linux-v4l2/v4l2-helpers.c
  2. 14 0
      plugins/linux-v4l2/v4l2-helpers.h
  3. 33 6
      plugins/linux-v4l2/v4l2-input.c

+ 28 - 0
plugins/linux-v4l2/v4l2-helpers.c

@@ -61,6 +61,34 @@ int_fast32_t v4l2_stop_capture(int_fast32_t dev)
 	return 0;
 	return 0;
 }
 }
 
 
+#ifdef _DEBUG
+int_fast32_t v4l2_query_all_buffers(int_fast32_t dev,
+				    struct v4l2_buffer_data *buf_data)
+{
+	struct v4l2_buffer buf;
+
+	blog(LOG_DEBUG, "attempting to read buffer data for %ld buffers",
+	     buf_data->count);
+
+	for (uint_fast32_t i = 0; i < buf_data->count; i++) {
+		buf.index = i;
+		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		buf.memory = V4L2_MEMORY_MMAP;
+		if (v4l2_ioctl(dev, VIDIOC_QUERYBUF, &buf) < 0) {
+			blog(LOG_DEBUG,
+			     "failed to read buffer data for buffer #%ld", i);
+		} else {
+			blog(LOG_DEBUG,
+			     "query buf #%ld info: ts: %06ld buf id #%d, flags 0x%08X, seq #%d, len %d, used %d",
+			     i, buf.timestamp.tv_usec, buf.index, buf.flags,
+			     buf.sequence, buf.length, buf.bytesused);
+		}
+	}
+
+	return 0;
+}
+#endif
+
 int_fast32_t v4l2_create_mmap(int_fast32_t dev, struct v4l2_buffer_data *buf)
 int_fast32_t v4l2_create_mmap(int_fast32_t dev, struct v4l2_buffer_data *buf)
 {
 {
 	struct v4l2_requestbuffers req;
 	struct v4l2_requestbuffers req;

+ 14 - 0
plugins/linux-v4l2/v4l2-helpers.h

@@ -184,6 +184,20 @@ int_fast32_t v4l2_start_capture(int_fast32_t dev, struct v4l2_buffer_data *buf);
  */
  */
 int_fast32_t v4l2_stop_capture(int_fast32_t dev);
 int_fast32_t v4l2_stop_capture(int_fast32_t dev);
 
 
+#ifdef _DEBUG
+/**
+ * Query the status of all buffers.
+ * Only used for debug purposes.
+ *
+ * @param dev handle for the v4l2 device
+ * @param buf_data buffer data
+ *
+ * @return negative on failure
+ */
+int_fast32_t v4l2_query_all_buffers(int_fast32_t dev,
+				    struct v4l2_buffer_data *buf_data);
+#endif
+
 /**
 /**
  * Create memory mapping for buffers
  * Create memory mapping for buffers
  *
  *

+ 33 - 6
plugins/linux-v4l2/v4l2-input.c

@@ -162,13 +162,19 @@ static void *v4l2_thread(void *vptr)
 	struct obs_source_frame out;
 	struct obs_source_frame out;
 	size_t plane_offsets[MAX_AV_PLANES];
 	size_t plane_offsets[MAX_AV_PLANES];
 
 
+	blog(LOG_DEBUG, "%s: new capture thread", data->device_id);
+
 	if (v4l2_start_capture(data->dev, &data->buffers) < 0)
 	if (v4l2_start_capture(data->dev, &data->buffers) < 0)
 		goto exit;
 		goto exit;
 
 
+	blog(LOG_DEBUG, "%s: new capture started", data->device_id);
+
 	frames = 0;
 	frames = 0;
 	first_ts = 0;
 	first_ts = 0;
 	v4l2_prep_obs_frame(data, &out, plane_offsets);
 	v4l2_prep_obs_frame(data, &out, plane_offsets);
 
 
+	blog(LOG_DEBUG, "%s: obs frame prepared", data->device_id);
+
 	while (os_event_try(data->event) == EAGAIN) {
 	while (os_event_try(data->event) == EAGAIN) {
 		FD_ZERO(&fds);
 		FD_ZERO(&fds);
 		FD_SET(data->dev, &fds);
 		FD_SET(data->dev, &fds);
@@ -179,10 +185,20 @@ static void *v4l2_thread(void *vptr)
 		if (r < 0) {
 		if (r < 0) {
 			if (errno == EINTR)
 			if (errno == EINTR)
 				continue;
 				continue;
-			blog(LOG_DEBUG, "select failed");
+			blog(LOG_ERROR, "%s: select failed", data->device_id);
 			break;
 			break;
 		} else if (r == 0) {
 		} else if (r == 0) {
-			blog(LOG_DEBUG, "select timeout");
+			blog(LOG_ERROR, "%s: select timed out",
+			     data->device_id);
+
+#ifdef _DEBUG
+			v4l2_query_all_buffers(data->dev, &data->buffers);
+#endif
+
+			if (v4l2_ioctl(data->dev, VIDIOC_LOG_STATUS) < 0) {
+				blog(LOG_ERROR, "%s: failed to log status",
+				     data->device_id);
+			}
 			continue;
 			continue;
 		}
 		}
 
 
@@ -190,12 +206,21 @@ static void *v4l2_thread(void *vptr)
 		buf.memory = V4L2_MEMORY_MMAP;
 		buf.memory = V4L2_MEMORY_MMAP;
 
 
 		if (v4l2_ioctl(data->dev, VIDIOC_DQBUF, &buf) < 0) {
 		if (v4l2_ioctl(data->dev, VIDIOC_DQBUF, &buf) < 0) {
-			if (errno == EAGAIN)
+			if (errno == EAGAIN) {
+				blog(LOG_DEBUG, "%s: ioctl dqbuf eagain",
+				     data->device_id);
 				continue;
 				continue;
-			blog(LOG_DEBUG, "failed to dequeue buffer");
+			}
+			blog(LOG_ERROR, "%s: failed to dequeue buffer",
+			     data->device_id);
 			break;
 			break;
 		}
 		}
 
 
+		blog(LOG_DEBUG,
+		     "%s: ts: %06ld buf id #%d, flags 0x%08X, seq #%d, len %d, used %d",
+		     data->device_id, buf.timestamp.tv_usec, buf.index,
+		     buf.flags, buf.sequence, buf.length, buf.bytesused);
+
 		out.timestamp = timeval2ns(buf.timestamp);
 		out.timestamp = timeval2ns(buf.timestamp);
 		if (!frames)
 		if (!frames)
 			first_ts = out.timestamp;
 			first_ts = out.timestamp;
@@ -207,14 +232,16 @@ static void *v4l2_thread(void *vptr)
 		obs_source_output_video(data->source, &out);
 		obs_source_output_video(data->source, &out);
 
 
 		if (v4l2_ioctl(data->dev, VIDIOC_QBUF, &buf) < 0) {
 		if (v4l2_ioctl(data->dev, VIDIOC_QBUF, &buf) < 0) {
-			blog(LOG_DEBUG, "failed to enqueue buffer");
+			blog(LOG_ERROR, "%s: failed to enqueue buffer",
+			     data->device_id);
 			break;
 			break;
 		}
 		}
 
 
 		frames++;
 		frames++;
 	}
 	}
 
 
-	blog(LOG_INFO, "Stopped capture after %" PRIu64 " frames", frames);
+	blog(LOG_INFO, "%s: Stopped capture after %" PRIu64 " frames",
+	     data->device_id, frames);
 
 
 exit:
 exit:
 	v4l2_stop_capture(data->dev);
 	v4l2_stop_capture(data->dev);