update for allocation query changes
[platform/upstream/gstreamer.git] / sys / v4l2 / gstv4l2src.c
index dac2d6a..e8f30da 100644 (file)
@@ -50,6 +50,9 @@
 #include <sys/time.h>
 #include <unistd.h>
 
+#include "gst/video/gstvideometa.h"
+#include "gst/video/gstvideopool.h"
+
 #include "gstv4l2src.h"
 
 #include "gstv4l2colorbalance.h"
@@ -64,7 +67,6 @@
 GST_DEBUG_CATEGORY (v4l2src_debug);
 #define GST_CAT_DEFAULT v4l2src_debug
 
-#define PROP_DEF_QUEUE_SIZE         2
 #define PROP_DEF_ALWAYS_COPY        TRUE
 #define PROP_DEF_DECIMATE           1
 
@@ -74,12 +76,10 @@ enum
 {
   PROP_0,
   V4L2_STD_OBJECT_PROPS,
-  PROP_QUEUE_SIZE,
   PROP_ALWAYS_COPY,
   PROP_DECIMATE
 };
 
-GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SrcClass, gst_v4l2src);
 GST_IMPLEMENT_V4L2_COLOR_BALANCE_METHODS (GstV4l2Src, gst_v4l2src);
 GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Src, gst_v4l2src);
 #ifdef HAVE_XVIDEO
@@ -102,9 +102,7 @@ G_DEFINE_TYPE_WITH_CODE (GstV4l2Src, gst_v4l2src, GST_TYPE_PUSH_SRC,
     G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
         gst_v4l2src_color_balance_interface_init);
     G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_ORIENTATION,
-        gst_v4l2src_video_orientation_interface_init);
-    G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
-        gst_v4l2src_property_probe_interface_init));
+        gst_v4l2src_video_orientation_interface_init));
 
 static void gst_v4l2src_dispose (GObject * object);
 static void gst_v4l2src_finalize (GstV4l2Src * v4l2src);
@@ -121,8 +119,10 @@ static gboolean gst_v4l2src_stop (GstBaseSrc * src);
 static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
 static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter);
 static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
-static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
-static void gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
+static gboolean gst_v4l2src_decide_allocation (GstBaseSrc * src,
+    GstQuery * query);
+static GstFlowReturn gst_v4l2src_fill (GstPushSrc * src, GstBuffer * out);
+static GstCaps *gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
 static gboolean gst_v4l2src_negotiate (GstBaseSrc * basesrc);
 
 static void gst_v4l2src_set_property (GObject * object, guint prop_id,
@@ -152,11 +152,6 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
 
   gst_v4l2_object_install_properties_helper (gobject_class,
       DEFAULT_PROP_DEVICE);
-  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 in streaming mode",
-          GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, PROP_DEF_QUEUE_SIZE,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
       g_param_spec_boolean ("always-copy", "Always Copy",
           "If the buffer will or not be used directly from mmap",
@@ -193,8 +188,10 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
   basesrc_class->query = GST_DEBUG_FUNCPTR (gst_v4l2src_query);
   basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_v4l2src_fixate);
   basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
+  basesrc_class->decide_allocation =
+      GST_DEBUG_FUNCPTR (gst_v4l2src_decide_allocation);
 
-  pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
+  pushsrc_class->fill = GST_DEBUG_FUNCPTR (gst_v4l2src_fill);
 
   klass->v4l2_class_devices = NULL;
 
@@ -209,9 +206,6 @@ gst_v4l2src_init (GstV4l2Src * v4l2src)
       V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
 
-  /* number of buffers requested */
-  v4l2src->v4l2object->num_buffers = PROP_DEF_QUEUE_SIZE;
-
   v4l2src->v4l2object->always_copy = PROP_DEF_ALWAYS_COPY;
   v4l2src->decimate = PROP_DEF_DECIMATE;
 
@@ -250,9 +244,6 @@ 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->v4l2object->num_buffers = g_value_get_uint (value);
-        break;
       case PROP_ALWAYS_COPY:
         v4l2src->v4l2object->always_copy = g_value_get_boolean (value);
         break;
@@ -275,9 +266,6 @@ 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->v4l2object->num_buffers);
-        break;
       case PROP_ALWAYS_COPY:
         g_value_set_boolean (value, v4l2src->v4l2object->always_copy);
         break;
@@ -292,7 +280,7 @@ gst_v4l2src_get_property (GObject * object,
 }
 
 /* this function is a bit of a last resort */
-static void
+static GstCaps *
 gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
 {
   GstStructure *structure;
@@ -300,9 +288,9 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
 
   GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
 
-  for (i = 0; i < gst_caps_get_size (caps); ++i) {
-    const GValue *v;
+  caps = gst_caps_make_writable (caps);
 
+  for (i = 0; i < gst_caps_get_size (caps); ++i) {
     structure = gst_caps_get_structure (caps, i);
 
     /* We are fixating to a resonable 320x200 resolution
@@ -311,19 +299,14 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
     gst_structure_fixate_field_nearest_int (structure, "height", 200);
     gst_structure_fixate_field_nearest_fraction (structure, "framerate",
         G_MAXINT, 1);
-
-    v = gst_structure_get_value (structure, "format");
-    if (v && G_VALUE_TYPE (v) != G_TYPE_STRING) {
-      const gchar *format;
-
-      g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
-
-      format = g_value_get_string (gst_value_list_get_value (v, 0));
-      gst_structure_set (structure, "format", G_TYPE_STRING, format, NULL);
-    }
+    gst_structure_fixate_field (structure, "format");
   }
 
   GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
+
+  caps = GST_BASE_SRC_CLASS (parent_class)->fixate (basesrc, caps);
+
+  return caps;
 }
 
 
@@ -336,7 +319,7 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
   gboolean result = FALSE;
 
   /* first see what is possible on our source pad */
-  thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc), NULL);
+  thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
   GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
   LOG_CAPS (basesrc, thiscaps);
 
@@ -345,7 +328,7 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
     goto no_nego_needed;
 
   /* get the peer caps */
-  peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc), thiscaps);
+  peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), thiscaps);
   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
   LOG_CAPS (basesrc, peercaps);
   if (peercaps && !gst_caps_is_any (peercaps)) {
@@ -409,18 +392,18 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
       }
     }
     gst_caps_unref (thiscaps);
-    gst_caps_unref (peercaps);
   } else {
     /* no peer or peer have ANY caps, work with our own caps then */
     caps = thiscaps;
   }
+  if (peercaps)
+    gst_caps_unref (peercaps);
   if (caps) {
-    caps = gst_caps_make_writable (caps);
-    gst_caps_truncate (caps);
+    caps = gst_caps_truncate (caps);
 
     /* now fixate */
     if (!gst_caps_is_empty (caps)) {
-      gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
+      caps = gst_v4l2src_fixate (basesrc, caps);
       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
       LOG_CAPS (basesrc, caps);
 
@@ -430,9 +413,7 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
         result = TRUE;
       } else if (gst_caps_is_fixed (caps)) {
         /* yay, fixed caps, use those then */
-        gst_pad_push_event (GST_BASE_SRC_PAD (basesrc),
-            gst_event_new_caps (caps));
-        result = gst_v4l2src_set_caps (basesrc, caps);
+        result = gst_base_src_set_caps (basesrc, caps);
       }
     }
     gst_caps_unref (caps);
@@ -521,11 +502,96 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
     /* error already posted */
     return FALSE;
 
-  if (!gst_v4l2_object_start (obj))
-    return FALSE;
+  return TRUE;
+}
+
+static gboolean
+gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
+{
+  GstV4l2Src *src;
+  GstV4l2Object *obj;
+  GstBufferPool *pool;
+  guint size, min, max;
+  gboolean update;
+
+  src = GST_V4L2SRC (bsrc);
+  obj = src->v4l2object;
+
+  if (gst_query_get_n_allocation_pools (query) > 0) {
+    gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
+    update = TRUE;
+  } else {
+    pool = NULL;
+    min = max = 0;
+    size = 0;
+    update = FALSE;
+  }
+
+  GST_DEBUG_OBJECT (src, "allocation: size:%u min:%u max:%u pool:%"
+      GST_PTR_FORMAT, size, min, max, pool);
+
+  if (min != 0) {
+    /* if there is a min-buffers suggestion, use it. We add 1 because we need 1
+     * buffer extra to capture while the other two buffers are downstream */
+    min += 1;
+  } else {
+    min = 2;
+  }
+
+  /* select a pool */
+  switch (obj->mode) {
+    case GST_V4L2_IO_RW:
+      if (pool == NULL) {
+        /* no downstream pool, use our own then */
+        GST_DEBUG_OBJECT (src,
+            "read/write mode: no downstream pool, using our own");
+        pool = GST_BUFFER_POOL_CAST (obj->pool);
+        size = obj->sizeimage;
+      } else {
+        /* in READ/WRITE mode, prefer a downstream pool because our own pool
+         * doesn't help much, we have to write to it as well */
+        GST_DEBUG_OBJECT (src, "read/write mode: using downstream pool");
+        /* use the bigest size, when we use our own pool we can't really do any
+         * other size than what the hardware gives us but for downstream pools
+         * we can try */
+        size = MAX (size, obj->sizeimage);
+      }
+      break;
+    case GST_V4L2_IO_MMAP:
+    case GST_V4L2_IO_USERPTR:
+      /* in streaming mode, prefer our own pool */
+      pool = GST_BUFFER_POOL_CAST (obj->pool);
+      size = obj->sizeimage;
+      GST_DEBUG_OBJECT (src,
+          "streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
+      break;
+    case GST_V4L2_IO_AUTO:
+    default:
+      GST_WARNING_OBJECT (src, "unhandled mode");
+      break;
+  }
+
+  if (pool) {
+    GstStructure *config;
+    const GstCaps *caps;
 
-  /* now store the expected output size */
-  v4l2src->frame_byte_size = obj->size;
+    config = gst_buffer_pool_get_config (pool);
+    gst_buffer_pool_config_get (config, &caps, NULL, NULL, NULL, NULL, NULL,
+        NULL);
+    gst_buffer_pool_config_set (config, caps, size, min, max, 0, 0, 0);
+
+    /* if downstream supports video metadata, add this to the pool config */
+    if (gst_query_has_allocation_meta (query, GST_VIDEO_META_API_TYPE))
+      gst_buffer_pool_config_add_option (config,
+          GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+    gst_buffer_pool_set_config (pool, config);
+  }
+
+  if (update)
+    gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
+  else
+    gst_query_add_allocation_pool (query, pool, size, min, max);
 
   return TRUE;
 }
@@ -534,10 +600,11 @@ static gboolean
 gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
 {
   GstV4l2Src *src;
-
+  GstV4l2Object *obj;
   gboolean res = FALSE;
 
   src = GST_V4L2SRC (bsrc);
+  obj = src->v4l2object;
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_LATENCY:{
@@ -545,14 +612,14 @@ gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
       guint32 fps_n, fps_d;
 
       /* device must be open */
-      if (!GST_V4L2_IS_OPEN (src->v4l2object)) {
+      if (!GST_V4L2_IS_OPEN (obj)) {
         GST_WARNING_OBJECT (src,
             "Can't give latency since device isn't open !");
         goto done;
       }
 
-      fps_n = GST_V4L2_FPS_N (src->v4l2object);
-      fps_d = GST_V4L2_FPS_D (src->v4l2object);
+      fps_n = GST_V4L2_FPS_N (obj);
+      fps_d = GST_V4L2_FPS_D (obj);
 
       /* we must have a framerate */
       if (fps_n <= 0 || fps_d <= 0) {
@@ -565,7 +632,8 @@ gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
       min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
 
       /* max latency is total duration of the frame buffer */
-      max_latency = src->v4l2object->num_buffers * min_latency;
+      max_latency =
+          GST_V4L2_BUFFER_POOL_CAST (obj->pool)->max_buffers * min_latency;
 
       GST_DEBUG_OBJECT (bsrc,
           "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
@@ -601,7 +669,7 @@ gst_v4l2src_start (GstBaseSrc * src)
 
   /* activate settings for first frame */
   v4l2src->ctrl_time = 0;
-  gst_object_sync_values (G_OBJECT (src), v4l2src->ctrl_time);
+  gst_object_sync_values (GST_OBJECT (src), v4l2src->ctrl_time);
 
   return TRUE;
 }
@@ -610,22 +678,14 @@ static gboolean
 gst_v4l2src_unlock (GstBaseSrc * src)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (src);
-
-  GST_LOG_OBJECT (src, "Flushing");
-  gst_poll_set_flushing (v4l2src->v4l2object->poll, TRUE);
-
-  return TRUE;
+  return gst_v4l2_object_unlock (v4l2src->v4l2object);
 }
 
 static gboolean
 gst_v4l2src_unlock_stop (GstBaseSrc * src)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (src);
-
-  GST_LOG_OBJECT (src, "No longer flushing");
-  gst_poll_set_flushing (v4l2src->v4l2object->poll, FALSE);
-
-  return TRUE;
+  return gst_v4l2_object_unlock_stop (v4l2src->v4l2object);
 }
 
 static gboolean
@@ -679,79 +739,90 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
 }
 
 static GstFlowReturn
-gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
+gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (src);
   GstV4l2Object *obj = v4l2src->v4l2object;
-  int i;
   GstFlowReturn ret;
+  GstClock *clock;
+  GstClockTime timestamp, duration;
 
+#if 0
+  int i;
   /* decimate, just capture and throw away frames */
   for (i = 0; i < v4l2src->decimate - 1; i++) {
-    ret = gst_v4l2_object_get_buffer (obj, buf);
+    ret = gst_v4l2_buffer_pool_process (obj, buf);
     if (ret != GST_FLOW_OK) {
       return ret;
     }
     gst_buffer_unref (*buf);
   }
+#endif
 
-  ret = gst_v4l2_object_get_buffer (obj, buf);
+  ret =
+      gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool), buf);
 
-  /* set buffer metadata */
-  if (G_LIKELY (ret == GST_FLOW_OK && *buf)) {
-    GstClock *clock;
-    GstClockTime timestamp, duration;
-
-    GST_BUFFER_OFFSET (*buf) = v4l2src->offset++;
-    GST_BUFFER_OFFSET_END (*buf) = v4l2src->offset;
-
-    /* timestamps, LOCK to get clock and base time. */
-    /* FIXME: element clock and base_time is rarely changing */
-    GST_OBJECT_LOCK (v4l2src);
-    if ((clock = GST_ELEMENT_CLOCK (v4l2src))) {
-      /* we have a clock, get base time and ref clock */
-      timestamp = GST_ELEMENT (v4l2src)->base_time;
-      gst_object_ref (clock);
-    } else {
-      /* no clock, can't set timestamps */
-      timestamp = GST_CLOCK_TIME_NONE;
-    }
-    GST_OBJECT_UNLOCK (v4l2src);
+  if (G_UNLIKELY (ret != GST_FLOW_OK))
+    goto error;
 
-    duration = obj->duration;
+  /* set buffer metadata */
+  GST_BUFFER_OFFSET (buf) = v4l2src->offset++;
+  GST_BUFFER_OFFSET_END (buf) = v4l2src->offset;
+
+  /* timestamps, LOCK to get clock and base time. */
+  /* FIXME: element clock and base_time is rarely changing */
+  GST_OBJECT_LOCK (v4l2src);
+  if ((clock = GST_ELEMENT_CLOCK (v4l2src))) {
+    /* we have a clock, get base time and ref clock */
+    timestamp = GST_ELEMENT (v4l2src)->base_time;
+    gst_object_ref (clock);
+  } else {
+    /* no clock, can't set timestamps */
+    timestamp = GST_CLOCK_TIME_NONE;
+  }
+  GST_OBJECT_UNLOCK (v4l2src);
 
-    if (G_LIKELY (clock)) {
-      /* the time now is the time of the clock minus the base time */
-      timestamp = gst_clock_get_time (clock) - timestamp;
-      gst_object_unref (clock);
+  duration = obj->duration;
 
-      /* if we have a framerate adjust timestamp for frame latency */
-      if (GST_CLOCK_TIME_IS_VALID (duration)) {
-        if (timestamp > duration)
-          timestamp -= duration;
-        else
-          timestamp = 0;
-      }
-    }
+  if (G_LIKELY (clock)) {
+    /* the time now is the time of the clock minus the base time */
+    timestamp = gst_clock_get_time (clock) - timestamp;
+    gst_object_unref (clock);
 
-    /* activate settings for next frame */
+    /* if we have a framerate adjust timestamp for frame latency */
     if (GST_CLOCK_TIME_IS_VALID (duration)) {
-      v4l2src->ctrl_time += duration;
-    } else {
-      /* this is not very good (as it should be the next timestamp),
-       * still good enough for linear fades (as long as it is not -1)
-       */
-      v4l2src->ctrl_time = timestamp;
+      if (timestamp > duration)
+        timestamp -= duration;
+      else
+        timestamp = 0;
     }
-    gst_object_sync_values (G_OBJECT (src), v4l2src->ctrl_time);
-    GST_INFO_OBJECT (src, "sync to %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (v4l2src->ctrl_time));
+  }
 
-    /* FIXME: use the timestamp from the buffer itself! */
-    GST_BUFFER_TIMESTAMP (*buf) = timestamp;
-    GST_BUFFER_DURATION (*buf) = duration;
+  /* activate settings for next frame */
+  if (GST_CLOCK_TIME_IS_VALID (duration)) {
+    v4l2src->ctrl_time += duration;
+  } else {
+    /* this is not very good (as it should be the next timestamp),
+     * still good enough for linear fades (as long as it is not -1)
+     */
+    v4l2src->ctrl_time = timestamp;
   }
+  gst_object_sync_values (GST_OBJECT (src), v4l2src->ctrl_time);
+  GST_INFO_OBJECT (src, "sync to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (v4l2src->ctrl_time));
+
+  /* FIXME: use the timestamp from the buffer itself! */
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;
+  GST_BUFFER_DURATION (buf) = duration;
+
   return ret;
+
+  /* ERROR */
+error:
+  {
+    GST_ERROR_OBJECT (src, "error processing buffer");
+    return ret;
+  }
 }
 
 
@@ -762,34 +833,29 @@ gst_v4l2src_uri_get_type (GType type)
   return GST_URI_SRC;
 }
 
-static gchar **
+static const gchar *const *
 gst_v4l2src_uri_get_protocols (GType type)
 {
-  static gchar *protocols[] = { (char *) "v4l2", NULL };
+  static const gchar *protocols[] = { "v4l2", NULL };
 
   return protocols;
 }
 
-static const gchar *
+static gchar *
 gst_v4l2src_uri_get_uri (GstURIHandler * handler)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (handler);
 
   if (v4l2src->v4l2object->videodev != NULL) {
-    gchar uri[256];
-
-    /* need to return a const string, but also don't want to leak the generated
-     * string, so just intern it - there's a limited number of video devices
-     * after all */
-    g_snprintf (uri, sizeof (uri), "v4l2://%s", v4l2src->v4l2object->videodev);
-    return g_intern_string (uri);
+    return g_strdup_printf ("v4l2://%s", v4l2src->v4l2object->videodev);
   }
 
-  return "v4l2://";
+  return g_strdup ("v4l2://");
 }
 
 static gboolean
-gst_v4l2src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
+gst_v4l2src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
+    GError ** error)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (handler);
   const gchar *device = DEFAULT_PROP_DEVICE;