v4l2: Let the device object manage the pool
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 13 Jul 2011 14:33:58 +0000 (16:33 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 13 Jul 2011 14:33:58 +0000 (16:33 +0200)
Rename start and stop methods to open and close because that is what they do.
After setting the format on the device object, setup the bufferpools. Move this
code from the v4l2src_calls.c file, it is shared between source and sink.
Make new device start and stop method that merges various bits of common code
spread over several files.

sys/v4l2/gstv4l2bufferpool.h
sys/v4l2/gstv4l2object.c
sys/v4l2/gstv4l2object.h
sys/v4l2/gstv4l2radio.c
sys/v4l2/gstv4l2sink.c
sys/v4l2/gstv4l2sink.h
sys/v4l2/gstv4l2src.c
sys/v4l2/gstv4l2src.h
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index c0029d6..46246f5 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef __GSTV4L2BUFFER_H__
-#define __GSTV4L2BUFFER_H__
+#ifndef __GST_V4L2_BUFFER_POOL_H__
+#define __GST_V4L2_BUFFER_POOL_H__
 
 #include <gst/gst.h>
-#include "v4l2_calls.h"
+
+typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
+typedef struct _GstV4l2BufferPoolClass GstV4l2BufferPoolClass;
+typedef struct _GstMetaV4l2 GstMetaV4l2;
+
+#include "gstv4l2object.h"
+//#include "v4l2_calls.h"
 
 GST_DEBUG_CATEGORY_EXTERN (v4l2buffer_debug);
 
@@ -38,10 +44,6 @@ GType gst_v4l2_buffer_pool_get_type (void);
 #define GST_IS_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER_POOL))
 #define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool))
 
-typedef struct _GstV4l2BufferPool GstV4l2BufferPool;
-typedef struct _GstV4l2BufferPoolClass GstV4l2BufferPoolClass;
-typedef struct _GstMetaV4l2 GstMetaV4l2;
-
 #define GST_V4L2_BUFFER_POOL_LOCK(pool)     g_mutex_lock ((pool)->lock)
 #define GST_V4L2_BUFFER_POOL_UNLOCK(pool)   g_mutex_unlock ((pool)->lock)
 
@@ -91,4 +93,4 @@ gint                gst_v4l2_buffer_pool_available_buffers (GstV4l2BufferPool *p
 
 G_END_DECLS
 
-#endif /* __GSTV4L2BUFFER_H__ */
+#endif /*__GST_V4L2_BUFFER_POOL_H__ */
index b124a67..5b057dc 100644 (file)
@@ -751,7 +751,7 @@ gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
 }
 
 gboolean
-gst_v4l2_object_start (GstV4l2Object * v4l2object)
+gst_v4l2_object_open (GstV4l2Object * v4l2object)
 {
   if (gst_v4l2_open (v4l2object))
     gst_v4l2_set_defaults (v4l2object);
@@ -766,7 +766,7 @@ gst_v4l2_object_start (GstV4l2Object * v4l2object)
 }
 
 gboolean
-gst_v4l2_object_stop (GstV4l2Object * v4l2object)
+gst_v4l2_object_close (GstV4l2Object * v4l2object)
 {
 #ifdef HAVE_XVIDEO
   gst_v4l2_xoverlay_stop (v4l2object);
@@ -2041,6 +2041,65 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
   return TRUE;
 }
 
+static gboolean
+gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object)
+{
+  GST_DEBUG_OBJECT (v4l2object->element, "initializing the capture system");
+
+  GST_V4L2_CHECK_OPEN (v4l2object);
+  GST_V4L2_CHECK_NOT_ACTIVE (v4l2object);
+
+  if (v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
+    gboolean requeuebuf;
+
+    requeuebuf = v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    /* Map the buffers */
+    GST_LOG_OBJECT (v4l2object->element, "initiating buffer pool");
+
+    if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object,
+                v4l2object->num_buffers, requeuebuf)))
+      goto buffer_pool_new_failed;
+
+    GST_INFO_OBJECT (v4l2object->element, "capturing buffers via mmap()");
+    v4l2object->use_mmap = TRUE;
+
+    if (v4l2object->num_buffers != v4l2object->pool->buffer_count) {
+      v4l2object->num_buffers = v4l2object->pool->buffer_count;
+      g_object_notify (G_OBJECT (v4l2object->element), "queue-size");
+    }
+
+  } else if (v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
+    GST_INFO_OBJECT (v4l2object->element, "capturing buffers via read()");
+    v4l2object->use_mmap = FALSE;
+    v4l2object->pool = NULL;
+  } else {
+    goto no_supported_capture_method;
+  }
+
+  GST_V4L2_SET_ACTIVE (v4l2object);
+
+  return TRUE;
+
+  /* ERRORS */
+buffer_pool_new_failed:
+  {
+    GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
+        (_("Could not map buffers from device '%s'"),
+            v4l2object->videodev),
+        ("Failed to create buffer pool: %s", g_strerror (errno)));
+    return FALSE;
+  }
+no_supported_capture_method:
+  {
+    GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
+        (_("The driver of device '%s' does not support any known capture "
+                "method."), v4l2object->videodev), (NULL));
+    return FALSE;
+  }
+}
+
+
 /* Note about fraction simplification
  *  * n1/d1 == n2/d2  is also written as  n1 == ( n2 * d1 ) / d2
  *   */
@@ -2198,6 +2257,10 @@ done:
   v4l2object->info = info;
   v4l2object->fmtdesc = fmtdesc;
 
+  /* now configure ther pools */
+  if (!gst_v4l2_object_setup_pool (v4l2object))
+    goto pool_failed;
+
   return TRUE;
 
   /* ERRORS */
@@ -2257,22 +2320,66 @@ get_parm_failed:
 set_parm_failed:
   {
     GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
-        (_("Video input device did not accept new frame rate setting.")),
+        (_("Video device did not accept new frame rate setting.")),
         GST_ERROR_SYSTEM);
     goto done;
   }
+pool_failed:
+  {
+    GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+        (_("Video device could not create buffer pool.")), GST_ERROR_SYSTEM);
+    return FALSE;
+  }
 }
 
 gboolean
-gst_v4l2_object_start_streaming (GstV4l2Object * v4l2object)
+gst_v4l2_object_start (GstV4l2Object * v4l2object)
 {
-  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_STREAMON,
-          &(v4l2object->type)) < 0)
-    goto start_failed;
+  GstBuffer *buf;
 
+  GST_DEBUG_OBJECT (v4l2object->element, "starting");
+
+  GST_V4L2_CHECK_OPEN (v4l2object);
+  GST_V4L2_CHECK_ACTIVE (v4l2object);
+
+  if (v4l2object->use_mmap) {
+    switch (v4l2object->type) {
+      case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        /* for capture, queue all the buffers so the device can start filling
+         * them */
+        while ((buf =
+                gst_v4l2_buffer_pool_get (v4l2object->pool, FALSE)) != NULL)
+          if (!gst_v4l2_buffer_pool_qbuf (v4l2object->pool, buf))
+            goto queue_failed;
+
+        if (!v4l2object->streaming) {
+          if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_STREAMON,
+                  &(v4l2object->type)) < 0)
+            goto start_failed;
+          v4l2object->streaming = TRUE;
+        }
+        break;
+      case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+        /* for output, do nothing. We will start streaming when we get the
+         * first buffer */
+        break;
+      default:
+        break;
+    }
+  }
   return TRUE;
 
   /* ERRORS */
+queue_failed:
+  {
+    GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ,
+        (_("Could not enqueue buffers in device '%s'."),
+            v4l2object->videodev),
+        ("enqueing buffer %d/%d failed: %s",
+            GST_META_V4L2_GET (buf)->vbuffer.index, v4l2object->num_buffers,
+            g_strerror (errno)));
+    return FALSE;
+  }
 start_failed:
   {
     GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, OPEN_READ,
@@ -2283,12 +2390,35 @@ start_failed:
 }
 
 gboolean
-gst_v4l2_object_stop_streaming (GstV4l2Object * v4l2object)
+gst_v4l2_object_stop (GstV4l2Object * v4l2object)
 {
-  if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_STREAMOFF,
-          &(v4l2object->type)) < 0)
-    goto stop_failed;
+  GST_DEBUG_OBJECT (v4l2object->element, "stopping");
+
+  if (!GST_V4L2_IS_OPEN (v4l2object))
+    goto done;
+  if (!GST_V4L2_IS_ACTIVE (v4l2object))
+    goto done;
+
+  if (v4l2object->use_mmap) {
+    if (v4l2object->streaming) {
+      /* we actually need to sync on all queued buffers but not
+       * on the non-queued ones */
+      if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_STREAMOFF,
+              &(v4l2object->type)) < 0)
+        goto stop_failed;
 
+      v4l2object->streaming = FALSE;
+    }
+  }
+
+  if (v4l2object->pool) {
+    gst_v4l2_buffer_pool_destroy (v4l2object->pool);
+    v4l2object->pool = NULL;
+  }
+
+  GST_V4L2_SET_INACTIVE (v4l2object);
+
+done:
   return TRUE;
 
   /* ERRORS */
index a1ced8a..555d2b4 100644 (file)
 #include <gst/video/video.h>
 #include <gst/interfaces/propertyprobe.h>
 
+typedef struct _GstV4l2Object GstV4l2Object;
+typedef struct _GstV4l2ObjectClassHelper GstV4l2ObjectClassHelper;
+typedef struct _GstV4l2Xv GstV4l2Xv;
+
+#include <gstv4l2bufferpool.h>
 
 /* size of v4l2 buffer pool in streaming case */
 #define GST_V4L2_MAX_BUFFERS 16
 /* max frame width/height */
 #define GST_V4L2_MAX_SIZE (1<<15) /* 2^15 == 32768 */
 
-
-
 G_BEGIN_DECLS
 
 #define GST_V4L2_OBJECT(obj) (GstV4l2Object *)(obj)
 
-typedef struct _GstV4l2Object GstV4l2Object;
-typedef struct _GstV4l2ObjectClassHelper GstV4l2ObjectClassHelper;
-typedef struct _GstV4l2Xv GstV4l2Xv;
 
 typedef gboolean  (*GstV4l2GetInOutFunction)  (GstV4l2Object * v4l2object, gint * input);
 typedef gboolean  (*GstV4l2SetInOutFunction)  (GstV4l2Object * v4l2object, gint input);
@@ -104,15 +104,21 @@ struct _GstV4l2Object {
   gboolean can_poll_device;
 
   gboolean active;
+  gboolean streaming;
 
   /* the current format */
   struct v4l2_fmtdesc *fmtdesc;
   GstVideoInfo info;
-  guint32 bytesperline;
 
+  guint32 bytesperline;
   guint size;
   GstClockTime duration;
 
+  /* optional pool */
+  guint32 num_buffers;
+  gboolean use_mmap;
+  GstV4l2BufferPool *pool;
+
   /* the video device's capabilities */
   struct v4l2_capability vcap;
 
@@ -181,9 +187,9 @@ gboolean  gst_v4l2_object_set_property_helper       (GstV4l2Object *v4l2object,
 gboolean  gst_v4l2_object_get_property_helper       (GstV4l2Object *v4l2object,
                                                     guint prop_id, GValue * value,
                                                     GParamSpec * pspec);
-/* starting/stopping */
-gboolean  gst_v4l2_object_start             (GstV4l2Object *v4l2object);
-gboolean  gst_v4l2_object_stop              (GstV4l2Object *v4l2object);
+/* open/close */
+gboolean  gst_v4l2_object_open               (GstV4l2Object *v4l2object);
+gboolean  gst_v4l2_object_close              (GstV4l2Object *v4l2object);
 
 /* probing */
 const GList* gst_v4l2_probe_get_properties  (GstPropertyProbe * probe);
@@ -209,8 +215,8 @@ GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc);
 
 gboolean      gst_v4l2_object_set_format (GstV4l2Object *v4l2object, GstCaps * caps);
 
-gboolean      gst_v4l2_object_start_streaming (GstV4l2Object *v4l2object);
-gboolean      gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object);
+gboolean      gst_v4l2_object_start     (GstV4l2Object *v4l2object);
+gboolean      gst_v4l2_object_stop      (GstV4l2Object *v4l2object);
 
 
 #define GST_IMPLEMENT_V4L2_PROBE_METHODS(Type_Class, interface_as_function)                 \
index d747631..66aa043 100644 (file)
@@ -417,7 +417,7 @@ gst_v4l2radio_start (GstV4l2Radio * radio)
 static gboolean
 gst_v4l2radio_stop (GstV4l2Radio * radio)
 {
-  if (!gst_v4l2_object_stop (radio->v4l2object))
+  if (!gst_v4l2_object_close (radio->v4l2object))
     return FALSE;
 
   return TRUE;
index ee4970b..c8681d0 100644 (file)
@@ -246,7 +246,7 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink)
   g_object_set (v4l2sink, "device", "/dev/video1", NULL);
 
   /* number of buffers requested */
-  v4l2sink->num_buffers = PROP_DEF_QUEUE_SIZE;
+  v4l2sink->v4l2object->num_buffers = PROP_DEF_QUEUE_SIZE;
   v4l2sink->min_queued_bufs = PROP_DEF_MIN_QUEUED_BUFS;
 
   v4l2sink->probed_caps = NULL;
@@ -254,7 +254,6 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink)
 
   v4l2sink->overlay_fields_set = 0;
   v4l2sink->crop_fields_set = 0;
-  v4l2sink->state = 0;
 }
 
 
@@ -285,16 +284,6 @@ gst_v4l2sink_finalize (GstV4l2Sink * v4l2sink)
 
 
 /*
- * State values
- */
-enum
-{
-  STATE_OFF = 0,
-  STATE_PENDING_STREAMON,
-  STATE_STREAMING
-};
-
-/*
  * flags to indicate which overlay/crop properties the user has set (and
  * therefore which ones should override the defaults from the driver)
  */
@@ -405,7 +394,7 @@ gst_v4l2sink_set_property (GObject * object,
           prop_id, value, pspec)) {
     switch (prop_id) {
       case PROP_QUEUE_SIZE:
-        v4l2sink->num_buffers = g_value_get_uint (value);
+        v4l2sink->v4l2object->num_buffers = g_value_get_uint (value);
         break;
       case PROP_MIN_QUEUED_BUFS:
         v4l2sink->min_queued_bufs = g_value_get_uint (value);
@@ -468,7 +457,7 @@ gst_v4l2sink_get_property (GObject * object,
           prop_id, value, pspec)) {
     switch (prop_id) {
       case PROP_QUEUE_SIZE:
-        g_value_set_uint (value, v4l2sink->num_buffers);
+        g_value_set_uint (value, v4l2sink->v4l2object->num_buffers);
         break;
       case PROP_MIN_QUEUED_BUFS:
         g_value_set_uint (value, v4l2sink->min_queued_bufs);
@@ -517,7 +506,7 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       /* open the device */
-      if (!gst_v4l2_object_start (v4l2sink->v4l2object))
+      if (!gst_v4l2_object_open (v4l2sink->v4l2object))
         return GST_STATE_CHANGE_FAILURE;
       break;
     default:
@@ -528,21 +517,19 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+#if 0
       if (v4l2sink->state == STATE_STREAMING) {
         if (!gst_v4l2_object_stop_streaming (v4l2sink->v4l2object)) {
           return GST_STATE_CHANGE_FAILURE;
         }
         v4l2sink->state = STATE_PENDING_STREAMON;
       }
+#endif
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
-      if (NULL != v4l2sink->pool)
-        gst_v4l2_buffer_pool_destroy (v4l2sink->pool);
-      v4l2sink->pool = NULL;
       /* close the device */
-      if (!gst_v4l2_object_stop (v4l2sink->v4l2object))
+      if (!gst_v4l2_object_close (v4l2sink->v4l2object))
         return GST_STATE_CHANGE_FAILURE;
-      v4l2sink->state = STATE_OFF;
       break;
     default:
       break;
@@ -617,7 +604,7 @@ static gboolean
 gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
 {
   GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
-  GstV4l2BufferPool *newpool;
+  GstV4l2Object *obj = v4l2sink->v4l2object;
 
   LOG_CAPS (v4l2sink, caps);
 
@@ -636,31 +623,12 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
     GST_DEBUG_OBJECT (v4l2sink, "no they aren't!");
   }
 
-  if (v4l2sink->pool) {
-    /* we have a pool already, stop and destroy the old pool */
-    if (v4l2sink->state == STATE_STREAMING) {
-      if (!gst_v4l2_object_stop_streaming (v4l2sink->v4l2object))
-        goto stop_failed;
-
-      v4l2sink->state = STATE_PENDING_STREAMON;
-    }
-    gst_v4l2_buffer_pool_destroy (v4l2sink->pool);
-    v4l2sink->pool = NULL;
-  }
+  if (!gst_v4l2_object_stop (obj))
+    goto stop_failed;
 
   if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, caps))
     goto invalid_format;
 
-  if (!(v4l2sink->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING))
-    goto no_streaming;
-
-  newpool = gst_v4l2_buffer_pool_new (v4l2sink->v4l2object,
-      v4l2sink->num_buffers, FALSE);
-  if (newpool == NULL)
-    goto no_pool;
-
-  v4l2sink->pool = newpool;
-
   gst_v4l2sink_sync_overlay_fields (v4l2sink);
   gst_v4l2sink_sync_crop_fields (v4l2sink);
 
@@ -668,15 +636,8 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
   gst_v4l2_xoverlay_prepare_xwindow_id (v4l2sink->v4l2object, TRUE);
 #endif
 
-  v4l2sink->state = STATE_PENDING_STREAMON;
-
   GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()");
 
-  if (v4l2sink->num_buffers != v4l2sink->pool->buffer_count) {
-    v4l2sink->num_buffers = v4l2sink->pool->buffer_count;
-    g_object_notify (G_OBJECT (v4l2sink), "queue-size");
-  }
-
   v4l2sink->video_width = GST_V4L2_WIDTH (v4l2sink->v4l2object);
   v4l2sink->video_height = GST_V4L2_HEIGHT (v4l2sink->v4l2object);
 
@@ -702,16 +663,6 @@ invalid_format:
     GST_DEBUG_OBJECT (v4l2sink, "can't set format");
     return FALSE;
   }
-no_streaming:
-  {
-    GST_DEBUG_OBJECT (v4l2sink, "we don't support streaming");
-    return FALSE;
-  }
-no_pool:
-  {
-    GST_DEBUG_OBJECT (v4l2sink, "can't create new pool");
-    return FALSE;
-  }
 }
 
 /* called after A/V sync to render frame */
@@ -733,7 +684,7 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
 
     /* not our buffer */
     GST_DEBUG_OBJECT (v4l2sink, "slow-path.. need to memcpy");
-    newbuf = gst_v4l2_buffer_pool_get (v4l2sink->pool, TRUE);
+    newbuf = gst_v4l2_buffer_pool_get (obj->pool, TRUE);
 
     if (obj->info.finfo) {
       GstVideoFrame src_frame, dest_frame;
@@ -757,14 +708,13 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
     buf = newbuf;
   }
 
-  if (!gst_v4l2_buffer_pool_qbuf (v4l2sink->pool, buf))
+  if (!gst_v4l2_buffer_pool_qbuf (obj->pool, buf))
     goto queue_failed;
 
-  if (v4l2sink->state == STATE_PENDING_STREAMON) {
-    if (!gst_v4l2_object_start_streaming (v4l2sink->v4l2object)) {
+  if (!obj->streaming) {
+    if (!gst_v4l2_object_start (obj)) {
       return GST_FLOW_ERROR;
     }
-    v4l2sink->state = STATE_STREAMING;
   }
 
   if (!newbuf) {
@@ -775,9 +725,9 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
    * just queued, then dequeue one immediately to make it available via
    * _buffer_alloc():
    */
-  if (gst_v4l2_buffer_pool_available_buffers (v4l2sink->pool) >
+  if (gst_v4l2_buffer_pool_available_buffers (obj->pool) >
       v4l2sink->min_queued_bufs) {
-    GstBuffer *v4l2buf = gst_v4l2_buffer_pool_dqbuf (v4l2sink->pool);
+    GstBuffer *v4l2buf = gst_v4l2_buffer_pool_dqbuf (obj->pool);
 
     /* note: if we get a buf, we don't want to use it directly (because
      * someone else could still hold a ref).. but instead we release our
index 8fe8222..9ac5902 100644 (file)
@@ -56,8 +56,7 @@ struct _GstV4l2Sink {
   GstV4l2Object * v4l2object;
   GstCaps *probed_caps;         /* all supported caps of underlying v4l2 device */
   GstCaps *current_caps;        /* the current negotiated caps */
-  GstV4l2BufferPool *pool;
-  guint32 num_buffers;
+
   guint32 min_queued_bufs;
 
   gint video_width, video_height;      /* original (unscaled) video w/h */
@@ -73,8 +72,6 @@ struct _GstV4l2Sink {
    * setting properties:
    */
   guint8 overlay_fields_set, crop_fields_set;
-
-  guint8 state;
 };
 
 struct _GstV4l2SinkClass {
index 1d135e9..6e6e95a 100644 (file)
@@ -215,13 +215,11 @@ gst_v4l2src_init (GstV4l2Src * v4l2src)
       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
 
   /* number of buffers requested */
-  v4l2src->num_buffers = PROP_DEF_QUEUE_SIZE;
+  v4l2src->v4l2object->num_buffers = PROP_DEF_QUEUE_SIZE;
 
   v4l2src->always_copy = PROP_DEF_ALWAYS_COPY;
   v4l2src->decimate = PROP_DEF_DECIMATE;
 
-  v4l2src->is_capturing = FALSE;
-
   gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
   gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
 }
@@ -258,7 +256,7 @@ gst_v4l2src_set_property (GObject * object,
           prop_id, value, pspec)) {
     switch (prop_id) {
       case PROP_QUEUE_SIZE:
-        v4l2src->num_buffers = g_value_get_uint (value);
+        v4l2src->v4l2object->num_buffers = g_value_get_uint (value);
         break;
       case PROP_ALWAYS_COPY:
         v4l2src->always_copy = g_value_get_boolean (value);
@@ -283,7 +281,7 @@ gst_v4l2src_get_property (GObject * object,
           prop_id, value, pspec)) {
     switch (prop_id) {
       case PROP_QUEUE_SIZE:
-        g_value_set_uint (value, v4l2src->num_buffers);
+        g_value_set_uint (value, v4l2src->v4l2object->num_buffers);
         break;
       case PROP_ALWAYS_COPY:
         g_value_set_boolean (value, v4l2src->always_copy);
@@ -458,12 +456,16 @@ no_nego_needed:
 static GstCaps *
 gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter)
 {
-  GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+  GstV4l2Src *v4l2src;
+  GstV4l2Object *obj;
   GstCaps *ret;
   GSList *walk;
   GSList *formats;
 
-  if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
+  v4l2src = GST_V4L2SRC (src);
+  obj = v4l2src->v4l2object;
+
+  if (!GST_V4L2_IS_OPEN (obj)) {
     /* FIXME: copy? */
     return
         gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
@@ -473,7 +475,7 @@ gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter)
   if (v4l2src->probed_caps)
     return gst_caps_ref (v4l2src->probed_caps);
 
-  formats = gst_v4l2_object_get_format_list (v4l2src->v4l2object);
+  formats = gst_v4l2_object_get_format_list (obj);
 
   ret = gst_caps_new_empty ();
 
@@ -489,7 +491,7 @@ gst_v4l2src_get_caps (GstBaseSrc * src, GstCaps * filter)
       GstCaps *tmp;
 
       tmp =
-          gst_v4l2_object_probe_caps_for_format (v4l2src->v4l2object,
+          gst_v4l2_object_probe_caps_for_format (obj,
           format->pixelformat, template);
       if (tmp)
         gst_caps_append (ret, tmp);
@@ -511,40 +513,30 @@ static gboolean
 gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
 {
   GstV4l2Src *v4l2src;
+  GstV4l2Object *obj;
 
   v4l2src = GST_V4L2SRC (src);
-
-  /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
-  if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object))
-    return FALSE;
+  obj = v4l2src->v4l2object;
 
   /* 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))
-      return FALSE;
-  }
-
-  if (!gst_v4l2_object_set_format (v4l2src->v4l2object, caps))
-    /* error already posted */
+  if (!gst_v4l2_object_stop (obj))
     return FALSE;
 
-  if (!gst_v4l2src_capture_init (v4l2src))
+  if (!gst_v4l2_object_set_format (obj, caps))
+    /* error already posted */
     return FALSE;
 
-  if (v4l2src->use_mmap) {
+  if (obj->use_mmap) {
     v4l2src->get_frame = gst_v4l2src_get_mmap;
   } else {
     v4l2src->get_frame = gst_v4l2src_get_read;
   }
 
-  if (!gst_v4l2src_capture_start (v4l2src))
+  if (!gst_v4l2_object_start (obj))
     return FALSE;
 
   /* now store the expected output size */
-  v4l2src->frame_byte_size = v4l2src->v4l2object->size;
+  v4l2src->frame_byte_size = obj->size;
 
   return TRUE;
 }
@@ -584,7 +576,7 @@ 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->num_buffers * min_latency;
+      max_latency = src->v4l2object->num_buffers * min_latency;
 
       GST_DEBUG_OBJECT (bsrc,
           "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
@@ -651,11 +643,10 @@ static gboolean
 gst_v4l2src_stop (GstBaseSrc * src)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+  GstV4l2Object *obj = v4l2src->v4l2object;
 
-  if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
-    if (!gst_v4l2src_capture_stop (v4l2src))
-      return FALSE;
-    if (!gst_v4l2src_capture_deinit (v4l2src))
+  if (GST_V4L2_IS_ACTIVE (obj)) {
+    if (!gst_v4l2_object_stop (obj))
       return FALSE;
   }
   return TRUE;
@@ -666,11 +657,12 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
 {
   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
   GstV4l2Src *v4l2src = GST_V4L2SRC (element);
+  GstV4l2Object *obj = v4l2src->v4l2object;
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       /* open the device */
-      if (!gst_v4l2_object_start (v4l2src->v4l2object))
+      if (!gst_v4l2_object_open (obj))
         return GST_STATE_CHANGE_FAILURE;
       break;
     default:
@@ -682,7 +674,7 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_NULL:
       /* close the device */
-      if (!gst_v4l2_object_stop (v4l2src->v4l2object))
+      if (!gst_v4l2_object_close (obj))
         return GST_STATE_CHANGE_FAILURE;
 
       if (v4l2src->probed_caps) {
index 8f38263..95aaaf3 100644 (file)
@@ -62,11 +62,6 @@ struct _GstV4l2Src
   /* pads */
   GstCaps *probed_caps;
 
-  /* buffer handling */
-  GstV4l2BufferPool *pool;
-
-  guint32 num_buffers;
-  gboolean use_mmap;
   guint32 frame_byte_size;
 
   /* if the buffer will be or not used from directly mmap */
@@ -74,10 +69,6 @@ struct _GstV4l2Src
 
   int decimate;
 
-  /* True if we want to stop */
-  gboolean quit;
-  gboolean is_capturing;
-
   guint64 offset;
 
   GstClockTime ctrl_time;
index 329cdf2..148a5b7 100644 (file)
 #define GST_CAT_DEFAULT v4l2src_debug
 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
 
-/* Local functions */
-
-static gboolean
-gst_v4l2src_buffer_pool_activate (GstV4l2BufferPool * pool,
-    GstV4l2Src * v4l2src)
-{
-  GstBuffer *buf;
-
-  while ((buf = gst_v4l2_buffer_pool_get (pool, FALSE)) != NULL)
-    if (!gst_v4l2_buffer_pool_qbuf (pool, buf))
-      goto queue_failed;
-
-  return TRUE;
-
-  /* ERRORS */
-queue_failed:
-  {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
-        (_("Could not enqueue buffers in device '%s'."),
-            v4l2src->v4l2object->videodev),
-        ("enqueing buffer %d/%d failed: %s",
-            GST_META_V4L2_GET (buf)->vbuffer.index, v4l2src->num_buffers,
-            g_strerror (errno)));
-    return FALSE;
-  }
-}
 
 /******************************************************
  * gst_v4l2src_grab_frame ():
@@ -94,7 +68,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
   gint ret;
 
   v4l2object = v4l2src->v4l2object;
-  pool = v4l2src->pool;
+  pool = v4l2object->pool;
   if (!pool)
     goto no_buffer_pool;
 
@@ -191,152 +165,3 @@ too_many_trials:
     return GST_FLOW_ERROR;
   }
 }
-
-/******************************************************
- * gst_v4l2src_capture_init():
- *   initialize the capture system
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-gboolean
-gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
-{
-  GST_DEBUG_OBJECT (v4l2src, "initializing the capture system");
-
-  GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
-  GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
-
-  if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
-
-    /* Map the buffers */
-    GST_LOG_OBJECT (v4l2src, "initiating buffer pool");
-
-    if (!(v4l2src->pool = gst_v4l2_buffer_pool_new (v4l2src->v4l2object,
-                v4l2src->num_buffers, TRUE)))
-      goto buffer_pool_new_failed;
-
-    GST_INFO_OBJECT (v4l2src, "capturing buffers via mmap()");
-    v4l2src->use_mmap = TRUE;
-
-    if (v4l2src->num_buffers != v4l2src->pool->buffer_count) {
-      v4l2src->num_buffers = v4l2src->pool->buffer_count;
-      g_object_notify (G_OBJECT (v4l2src), "queue-size");
-    }
-
-  } else if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_READWRITE) {
-    GST_INFO_OBJECT (v4l2src, "capturing buffers via read()");
-    v4l2src->use_mmap = FALSE;
-    v4l2src->pool = NULL;
-  } else {
-    goto no_supported_capture_method;
-  }
-
-  GST_V4L2_SET_ACTIVE (v4l2src->v4l2object);
-
-  return TRUE;
-
-  /* ERRORS */
-buffer_pool_new_failed:
-  {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
-        (_("Could not map buffers from device '%s'"),
-            v4l2src->v4l2object->videodev),
-        ("Failed to create buffer pool: %s", g_strerror (errno)));
-    return FALSE;
-  }
-no_supported_capture_method:
-  {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
-        (_("The driver of device '%s' does not support any known capture "
-                "method."), v4l2src->v4l2object->videodev), (NULL));
-    return FALSE;
-  }
-}
-
-
-/******************************************************
- * gst_v4l2src_capture_start():
- *   start streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-gboolean
-gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
-{
-  GST_DEBUG_OBJECT (v4l2src, "starting the capturing");
-  //GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
-  GST_V4L2_CHECK_ACTIVE (v4l2src->v4l2object);
-
-  v4l2src->quit = FALSE;
-
-  if (v4l2src->use_mmap) {
-    if (!gst_v4l2src_buffer_pool_activate (v4l2src->pool, v4l2src)) {
-      return FALSE;
-    }
-
-    if (!gst_v4l2_object_start_streaming (v4l2src->v4l2object)) {
-      return FALSE;
-    }
-  }
-
-  v4l2src->is_capturing = TRUE;
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4l2src_capture_stop():
- *   stop streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-gboolean
-gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
-{
-  GST_DEBUG_OBJECT (v4l2src, "stopping capturing");
-
-  if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object))
-    goto done;
-  if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object))
-    goto done;
-
-  if (v4l2src->use_mmap) {
-    /* we actually need to sync on all queued buffers but not
-     * on the non-queued ones */
-    if (!gst_v4l2_object_stop_streaming (v4l2src->v4l2object)) {
-      return FALSE;
-    }
-  }
-
-done:
-
-  /* make an optional pending wait stop */
-  v4l2src->quit = TRUE;
-  v4l2src->is_capturing = FALSE;
-
-  return TRUE;
-}
-
-/******************************************************
- * gst_v4l2src_capture_deinit():
- *   deinitialize the capture system
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-gboolean
-gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
-{
-  GST_DEBUG_OBJECT (v4l2src, "deinitting capture system");
-
-  if (!GST_V4L2_IS_OPEN (v4l2src->v4l2object)) {
-    return TRUE;
-  }
-  if (!GST_V4L2_IS_ACTIVE (v4l2src->v4l2object)) {
-    return TRUE;
-  }
-
-  if (v4l2src->pool) {
-    gst_v4l2_buffer_pool_destroy (v4l2src->pool);
-    v4l2src->pool = NULL;
-  }
-
-  GST_V4L2_SET_INACTIVE (v4l2src->v4l2object);
-
-  return TRUE;
-}
index 367103f..5aa1d23 100644 (file)
 #include "gstv4l2src.h"
 #include "v4l2_calls.h"
 
-gboolean   gst_v4l2src_capture_init      (GstV4l2Src * v4l2src);
-gboolean   gst_v4l2src_capture_start     (GstV4l2Src * v4l2src);
-
 GstFlowReturn gst_v4l2src_grab_frame     (GstV4l2Src * v4l2src, GstBuffer **buf);
 
-gboolean   gst_v4l2src_capture_stop      (GstV4l2Src * v4l2src);
-gboolean   gst_v4l2src_capture_deinit    (GstV4l2Src * v4l2src);
-
-
 #endif /* __V4L2SRC_CALLS_H__ */