sys/v4l2/: Fix EIO handing when capturing. Add new property to specify the number...
authorStefan Kost <ensonic@users.sourceforge.net>
Wed, 17 Jan 2007 14:30:50 +0000 (14:30 +0000)
committerStefan Kost <ensonic@users.sourceforge.net>
Wed, 17 Jan 2007 14:30:50 +0000 (14:30 +0000)
Original commit message from CVS:
* sys/v4l2/gstv4l2object.c:
(gst_v4l2_object_install_properties_helper),
(gst_v4l2_object_set_property_helper),
(gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
* sys/v4l2/gstv4l2object.h:
* sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
(gst_v4l2src_init), (gst_v4l2src_set_property),
(gst_v4l2src_get_property), (gst_v4l2src_set_caps):
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
(gst_v4l2src_grab_frame), (gst_v4l2src_set_capture),
(gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
(gst_v4l2src_capture_deinit):
Fix EIO handing when capturing. Add new property to specify the number of
buffers to enque (and remove the borked num-buffers usage).

ChangeLog
sys/v4l2/gstv4l2object.c
sys/v4l2/gstv4l2object.h
sys/v4l2/gstv4l2src.c
sys/v4l2/v4l2src_calls.c

index ae37a80..5d77475 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2007-01-17  Stefan Kost  <ensonic@users.sf.net>
+
+       * sys/v4l2/gstv4l2object.c:
+       (gst_v4l2_object_install_properties_helper),
+       (gst_v4l2_object_set_property_helper),
+       (gst_v4l2_object_get_property_helper), (gst_v4l2_set_defaults):
+       * sys/v4l2/gstv4l2object.h:
+       * sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init),
+       (gst_v4l2src_init), (gst_v4l2src_set_property),
+       (gst_v4l2src_get_property), (gst_v4l2src_set_caps):
+       * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list),
+       (gst_v4l2src_grab_frame), (gst_v4l2src_set_capture),
+       (gst_v4l2src_capture_init), (gst_v4l2src_capture_start),
+       (gst_v4l2src_capture_deinit):
+         Fix EIO handing when capturing. Add new property to specify the number of
+         buffers to enque (and remove the borked num-buffers usage).
+
+2007-01-16  Stefan Kost  <ensonic@users.sf.net>
+
+       * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query),
+       (gst_avi_demux_parse_index), (gst_avi_demux_stream_index),
+       (gst_avi_demux_sync), (gst_avi_demux_next_data_buffer),
+       (gst_avi_demux_stream_scan), (gst_avi_demux_massage_index),
+       (gst_avi_demux_calculate_durations_from_index),
+       (gst_avi_demux_push_event), (gst_avi_demux_stream_header_pull),
+       (gst_avi_demux_handle_seek), (gst_avi_demux_stream_data),
+       (gst_avi_demux_loop):
+         Fix hanging when demuxing fuzzed file (#397229). Add some more debug.
+
 2007-01-16  Stefan Kost  <ensonic@users.sf.net>
 
        Patch by: Sebastian Dröge <slomo circular-chaos org>
index 32d1a55..7f8df17 100644 (file)
@@ -244,20 +244,6 @@ gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class)
   g_object_class_install_property (gobject_class, PROP_FLAGS,
       g_param_spec_flags ("flags", "Flags", "Device type flags",
           GST_TYPE_V4L2_DEVICE_FLAGS, DEFAULT_PROP_FLAGS, G_PARAM_READABLE));
-/* FIXME norm, channel, frequency are part of the tuner interface, so they
-   should be removed from the properties
-  g_object_class_install_property (gobject_class, PROP_NORM,
-      g_param_spec_string ("norm", "Norm", "Standard norm to use",
-          DEFAULT_PROP_NORM, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_CHANNEL,
-      g_param_spec_string ("channel", "Channel",
-          "Input/output channel to switch to", DEFAULT_PROP_CHANNEL,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_FREQUENCY,
-      g_param_spec_ulong ("frequency", "Frequency",
-          "Frequency to tune to (in Hz)", 0, G_MAXULONG, DEFAULT_PROP_FREQUENCY,
-          G_PARAM_READWRITE));
-*/
 }
 
 GstV4l2Object *
@@ -314,6 +300,7 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
       g_free (v4l2object->videodev);
       v4l2object->videodev = g_value_dup_string (value);
       break;
+#if 0
     case PROP_NORM:
       if (GST_V4L2_IS_OPEN (v4l2object)) {
         GstTuner *tuner = GST_TUNER (v4l2object->element);
@@ -363,6 +350,7 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
         v4l2object->frequency = g_value_get_ulong (value);
       }
       break;
+#endif
     default:
       return FALSE;
       break;
@@ -407,15 +395,6 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
       g_value_set_flags (value, flags);
       break;
     }
-    case PROP_NORM:
-      g_value_set_string (value, v4l2object->norm);
-      break;
-    case PROP_CHANNEL:
-      g_value_set_string (value, v4l2object->channel);
-      break;
-    case PROP_FREQUENCY:
-      g_value_set_ulong (value, v4l2object->frequency);
-      break;
     default:
       return FALSE;
       break;
@@ -441,9 +420,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
       g_free (v4l2object->norm);
       v4l2object->norm = g_strdup (norm->label);
       gst_tuner_norm_changed (tuner, norm);
-/* FIXME: remove
-      g_object_notify (G_OBJECT (v4l2object->element), "norm");
-*/
     }
   }
 
@@ -458,9 +434,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
     g_free (v4l2object->channel);
     v4l2object->channel = g_strdup (channel->label);
     gst_tuner_channel_changed (tuner, channel);
-/* FIXME: remove
-    g_object_notify (G_OBJECT (v4l2object->element), "channel");
-*/
   }
 
   if (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
@@ -472,9 +445,6 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
         /* guess */
         gst_tuner_set_frequency (tuner, channel, 1000);
       } else {
-/* FIXME: remove
-        g_object_notify (G_OBJECT (v4l2object->element), "frequency");
-*/
       }
     }
   }
index 3447073..906cff9 100644 (file)
@@ -105,16 +105,12 @@ struct _GstV4l2ObjectClassHelper {
   GList *devices;
 };
 
-GType gst_v4l2_object_get_type(void);
-
-#define V4L2_STD_OBJECT_PROPS                  \
-    PROP_DEVICE,                               \
-    PROP_DEVICE_NAME,                          \
-    PROP_FLAGS,                                        \
-    PROP_NORM,                                 \
-    PROP_CHANNEL,                                      \
-    PROP_FREQUENCY
+GType gst_v4l2_object_get_type (void);
 
+#define V4L2_STD_OBJECT_PROPS          \
+    PROP_DEVICE,                       \
+    PROP_DEVICE_NAME,                  \
+    PROP_FLAGS
 
 /* create/destroy */
 GstV4l2Object *        gst_v4l2_object_new              (GstElement * element,
index 3b28475..862114b 100644 (file)
@@ -58,7 +58,6 @@ GST_ELEMENT_DETAILS ("Video (video4linux2/raw) Source",
     "Ronald Bultje <rbultje@ronald.bitfreak.net>,"
     " Edgard Lima <edgard.lima@indt.org.br>");
 
-
 GST_DEBUG_CATEGORY (v4l2src_debug);
 #define GST_CAT_DEFAULT v4l2src_debug
 
@@ -66,6 +65,7 @@ enum
 {
   PROP_0,
   V4L2_STD_OBJECT_PROPS,
+  PROP_QUEUE_SIZE
 };
 
 static const guint32 gst_v4l2_formats[] = {
@@ -274,6 +274,11 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
   gobject_class->get_property = gst_v4l2src_get_property;
 
   gst_v4l2_object_install_properties_helper (gobject_class);
+  g_object_class_install_property (gobject_class, PROP_QUEUE_SIZE,
+      g_param_spec_uint ("queue-size", "Queue size",
+          "Number of buffers to be enqueud in the driver",
+          GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS,
+          G_PARAM_READWRITE));
 
   basesrc_class->get_caps = gst_v4l2src_get_caps;
   basesrc_class->set_caps = gst_v4l2src_set_caps;
@@ -289,6 +294,7 @@ gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
   v4l2src->v4l2object = gst_v4l2_object_new (GST_ELEMENT (v4l2src),
       gst_v4l2_get_input, gst_v4l2_set_input, gst_v4l2src_update_fps);
 
+  /* number of buffers requested */
   v4l2src->breq.count = 0;
 
   v4l2src->formats = NULL;
@@ -332,6 +338,9 @@ gst_v4l2src_set_property (GObject * object,
   if (!gst_v4l2_object_set_property_helper (v4l2src->v4l2object,
           prop_id, value, pspec)) {
     switch (prop_id) {
+      case PROP_QUEUE_SIZE:
+        v4l2src->breq.count = g_value_get_uint (value);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -352,6 +361,9 @@ gst_v4l2src_get_property (GObject * object,
   if (!gst_v4l2_object_get_property_helper (v4l2src->v4l2object,
           prop_id, value, pspec)) {
     switch (prop_id) {
+      case PROP_QUEUE_SIZE:
+        g_value_set_uint (value, v4l2src->breq.count);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -776,6 +788,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
 
   /* make sure we stop capturing and dealloc buffers */
   if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
+    /* both will throw an element-error on failure */
     if (!gst_v4l2src_capture_stop (v4l2src))
       return FALSE;
     if (!gst_v4l2src_capture_deinit (v4l2src))
@@ -786,6 +799,8 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
 
   /* we want our own v4l2 type of fourcc codes */
   if (!(format = gst_v4l2_caps_to_v4l2fourcc (v4l2src, structure))) {
+    GST_DEBUG_OBJECT (v4l2src, "can't get capture format from caps %"
+        GST_PTR_FORMAT, caps);
     return FALSE;
   }
 
index 79b9f69..fd956ae 100644 (file)
@@ -150,7 +150,7 @@ qbuf_failed:
 gint
 gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
 {
-#define NUM_TRIALS 100
+#define NUM_TRIALS 50
   struct v4l2_buffer buffer;
   gint32 trials = NUM_TRIALS;
 
@@ -158,6 +158,12 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
   buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   buffer.memory = v4l2src->breq.memory;
   while (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_DQBUF, &buffer) < 0) {
+
+    GST_LOG_OBJECT (v4l2src,
+        "problem grabbing frame %ld (ix=%ld), trials=%ld, pool-ct=%d, buf.flags=%d",
+        buffer.sequence, buffer.index, trials, v4l2src->pool->refcount,
+        buffer.flags);
+
     /* if the sync() got interrupted, we can retry */
     switch (errno) {
       case EAGAIN:
@@ -169,14 +175,31 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
       case EINVAL:
         goto einval;
       case ENOMEM:
-        goto nomem;
+        goto enomem;
       case EIO:
-        GST_WARNING_OBJECT (v4l2src,
+        GST_INFO_OBJECT (v4l2src,
             "VIDIOC_DQBUF failed due to an internal error."
             " Can also indicate temporary problems like signal loss."
             " Note the driver might dequeue an (empty) buffer despite"
             " returning an error, or even stop capturing."
             " device %s", v4l2src->v4l2object->videodev);
+        /* have we de-queued a buffer ? */
+        if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
+          /* this fails
+             if ((buffer.index >= 0) && (buffer.index < v4l2src->breq.count)) {
+             GST_DEBUG_OBJECT (v4l2src, "reenqueing buffer (ix=%ld)", buffer.index);
+             gst_v4l2src_queue_frame (v4l2src, buffer.index);
+             }
+             else {
+           */
+          GST_DEBUG_OBJECT (v4l2src, "reenqueing buffer");
+          if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QBUF, &buffer) < 0) {
+            GST_WARNING_OBJECT (v4l2src,
+                "Error queueing buffer on device %s. system error: %s",
+                v4l2src->v4l2object->videodev, g_strerror (errno));
+          }
+          /*} */
+        }
         break;
       case EINTR:
         GST_WARNING_OBJECT (v4l2src,
@@ -194,15 +217,14 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
     if (--trials == -1) {
       goto too_many_trials;
     } else {
-      if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_QBUF, &buffer) < 0)
-        goto qbuf_failed;
       memset (&buffer, 0x00, sizeof (buffer));
       buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
       buffer.memory = v4l2src->breq.memory;
     }
   }
 
-  GST_LOG_OBJECT (v4l2src, "grabbed frame %d", buffer.index);
+  GST_LOG_OBJECT (v4l2src, "grabbed frame %ld (ix=%ld), pool-ct=%d",
+      buffer.sequence, buffer.index, v4l2src->pool->refcount);
 
   return buffer.index;
 
@@ -218,7 +240,7 @@ einval:
             v4l2src->v4l2object->videodev));
     return -1;
   }
-nomem:
+enomem:
   {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED,
         (_("Failed trying to get video frames from device '%s'. Not enough memory."), v4l2src->v4l2object->videodev), (_("insufficient memory to enqueue a user pointer buffer. device %s."), v4l2src->v4l2object->videodev));
@@ -233,15 +255,6 @@ too_many_trials:
             NUM_TRIALS, v4l2src->v4l2object->videodev, g_strerror (errno)));
     return -1;
   }
-qbuf_failed:
-  {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, WRITE,
-        (_("Could not exchange data with device '%s'."),
-            v4l2src->v4l2object->videodev),
-        ("Error queueing buffer on device %s. system error: %s",
-            v4l2src->v4l2object->videodev, g_strerror (errno)));
-    return -1;
-  }
 }
 
 
@@ -390,7 +403,7 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
   guint buffers;
   GstV4l2Buffer *buffer;
 
-  GST_DEBUG_OBJECT (v4l2src, "initting the capture system");
+  GST_DEBUG_OBJECT (v4l2src, "initializing the capture system");
 
   GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
   GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
@@ -398,10 +411,8 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
   /* request buffer info */
   buffers = v4l2src->breq.count;
 
-  if (v4l2src->breq.count > GST_V4L2_MAX_BUFFERS)
-    v4l2src->breq.count = GST_V4L2_MAX_BUFFERS;
-  else if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS)
-    v4l2src->breq.count = GST_V4L2_MIN_BUFFERS;
+  v4l2src->breq.count = CLAMP (v4l2src->breq.count, GST_V4L2_MIN_BUFFERS,
+      GST_V4L2_MAX_BUFFERS);
 
   v4l2src->breq.type = v4l2src->format.type;
   if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
@@ -429,7 +440,7 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
       goto no_buffers;
 
     if (v4l2src->breq.count != buffers)
-      g_object_notify (G_OBJECT (v4l2src), "num_buffers");
+      g_object_notify (G_OBJECT (v4l2src), "queue-size");
 
     GST_INFO_OBJECT (v4l2src,
         "Got %d buffers (%" GST_FOURCC_FORMAT ") of size %d KB",
@@ -532,6 +543,11 @@ mmap_failed:
   }
 queue_failed:
   {
+    GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+        (_("Could not enqueue buffers in device '%s'."),
+            v4l2src->v4l2object->videodev),
+        ("enqueing buffer %d/%d failed. (%d - %s)",
+            n, v4l2src->breq.count, errno, g_strerror (errno)));
     gst_v4l2src_capture_deinit (v4l2src);
     return FALSE;
   }
@@ -549,6 +565,7 @@ gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
   gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
   GST_DEBUG_OBJECT (v4l2src, "starting the capturing");
+  //GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
   GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
 
   v4l2src->quit = FALSE;
@@ -680,7 +697,8 @@ gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
     if (try_reinit) {
       gst_v4l2src_capture_start (v4l2src);
       if (!gst_v4l2src_capture_stop (v4l2src)) {
-        GST_DEBUG_OBJECT (v4l2src, "failed reinit device");
+        /* stop throws an element-error on failure */
+        GST_WARNING_OBJECT (v4l2src, "failed reinit device");
         return FALSE;
       }
     }