v4l2: activate the pool in fallback
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 4 Aug 2011 11:50:01 +0000 (12:50 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 4 Aug 2011 11:56:47 +0000 (12:56 +0100)
When nobody is using our pool, activate it ourselves.
Avoid leaking the buffer array.
Set default pool configuration with caps.
Don't keep current_caps, core does that for us now.

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

index 3a5dc40..ea2159b 100644 (file)
@@ -339,6 +339,9 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
       GST_DEBUG_OBJECT (pool, "starting, requesting %d MMAP buffers",
           max_buffers);
 
+      if (max_buffers == 0)
+        max_buffers = 4;
+
       memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
       breq.type = obj->type;
       breq.count = max_buffers;
@@ -456,6 +459,9 @@ gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
     if (pool->buffers[n])
       gst_v4l2_buffer_pool_free_buffer (bpool, pool->buffers[n]);
   }
+  g_free (pool->buffers);
+  pool->buffers = NULL;
+
   return ret;
 
   /* ERRORS */
@@ -813,10 +819,7 @@ gst_v4l2_buffer_pool_finalize (GObject * object)
   if (pool->video_fd >= 0)
     v4l2_close (pool->video_fd);
 
-  if (pool->buffers) {
-    g_free (pool->buffers);
-    pool->buffers = NULL;
-  }
+  g_free (pool->buffers);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -851,8 +854,8 @@ gst_v4l2_buffer_pool_class_init (GstV4l2BufferPoolClass * klass)
  *
  * Returns: the new pool, use gst_object_unref() to free resources
  */
-GstV4l2BufferPool *
-gst_v4l2_buffer_pool_new (GstV4l2Object * obj)
+GstBufferPool *
+gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
 {
   GstV4l2BufferPool *pool;
   gint fd;
@@ -865,7 +868,10 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj)
   pool->video_fd = fd;
   pool->obj = obj;
 
-  return pool;
+  gst_buffer_pool_config_set (GST_BUFFER_POOL_CAST (pool)->config, caps,
+      obj->sizeimage, 2, 0, 0, 0);
+
+  return GST_BUFFER_POOL (pool);
 
   /* ERRORS */
 dup_failed:
@@ -1007,14 +1013,31 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer * buf)
           if (buf->pool == bpool) {
             /* nothing, we can queue directly */
             to_queue = buf;
+            GST_LOG_OBJECT (pool, "processing buffer from our pool");
           } else {
+            GST_LOG_OBJECT (pool, "alloc buffer from our pool");
+            if (!gst_buffer_pool_is_active (bpool)) {
+              GstStructure *config;
+
+              /* this pool was not activated, configure and activate */
+              GST_DEBUG_OBJECT (pool, "activating pool");
+
+              config = gst_buffer_pool_get_config (bpool);
+              gst_buffer_pool_config_add_option (config,
+                  GST_BUFFER_POOL_OPTION_META_VIDEO);
+              gst_buffer_pool_set_config (bpool, config);
+
+              if (!gst_buffer_pool_set_active (bpool, TRUE))
+                goto activate_failed;
+            }
+
             /* this can block if all buffers are outstanding which would be
              * strange because we would expect the upstream element to have
              * allocated them and returned to us.. */
             ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
                 &to_queue, NULL);
             if (ret != GST_FLOW_OK)
-              goto done;
+              goto acquire_failed;
 
             /* copy into it and queue */
             if (!gst_v4l2_object_copy (obj, to_queue, buf))
@@ -1058,6 +1081,17 @@ done:
   return ret;
 
   /* ERRORS */
+activate_failed:
+  {
+    GST_ERROR_OBJECT (obj->element, "failed to activate pool");
+    return GST_FLOW_ERROR;
+  }
+acquire_failed:
+  {
+    GST_WARNING_OBJECT (obj->element, "failed to acquire a buffer: %s",
+        gst_flow_get_name (ret));
+    return ret;
+  }
 copy_failed:
   {
     GST_ERROR_OBJECT (obj->element, "failed to copy data");
index 6a2e63d..17e04e3 100644 (file)
@@ -39,9 +39,10 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2buffer_debug);
 G_BEGIN_DECLS
 
 
-#define GST_TYPE_V4L2_BUFFER_POOL (gst_v4l2_buffer_pool_get_type())
-#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))
+#define GST_TYPE_V4L2_BUFFER_POOL      (gst_v4l2_buffer_pool_get_type())
+#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))
+#define GST_V4L2_BUFFER_POOL_CAST(obj) ((GstV4l2BufferPool*)(obj))
 
 struct _GstV4l2BufferPool
 {
@@ -84,7 +85,7 @@ const GstMetaInfo * gst_meta_v4l2_get_info (void);
 
 GType gst_v4l2_buffer_pool_get_type (void);
 
-GstV4l2BufferPool * gst_v4l2_buffer_pool_new     (GstV4l2Object *obj);
+GstBufferPool *     gst_v4l2_buffer_pool_new     (GstV4l2Object *obj, GstCaps *caps);
 
 GstFlowReturn       gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer * buf);
 
index e0fa836..bcfbb54 100644 (file)
@@ -2124,7 +2124,7 @@ gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
   /* Map the buffers */
   GST_LOG_OBJECT (v4l2object->element, "initiating buffer pool");
 
-  if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object)))
+  if (!(v4l2object->pool = gst_v4l2_buffer_pool_new (v4l2object, caps)))
     goto buffer_pool_new_failed;
 
   GST_V4L2_SET_ACTIVE (v4l2object);
index 8c0e70b..aae6a8d 100644 (file)
@@ -126,7 +126,7 @@ struct _GstV4l2Object {
 
   /* optional pool */
   gboolean always_copy;
-  GstV4l2BufferPool *pool;
+  GstBufferPool *pool;
 
   /* the video device's capabilities */
   struct v4l2_capability vcap;
index 2df5f4a..f2d9909 100644 (file)
@@ -236,7 +236,6 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink)
   g_object_set (v4l2sink, "device", "/dev/video1", NULL);
 
   v4l2sink->probed_caps = NULL;
-  v4l2sink->current_caps = NULL;
 
   v4l2sink->overlay_fields_set = 0;
   v4l2sink->crop_fields_set = 0;
@@ -252,10 +251,6 @@ gst_v4l2sink_dispose (GObject * object)
     gst_caps_unref (v4l2sink->probed_caps);
   }
 
-  if (v4l2sink->current_caps) {
-    gst_caps_unref (v4l2sink->current_caps);
-  }
-
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -584,16 +579,6 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
     return FALSE;
   }
 
-  if (v4l2sink->current_caps) {
-    GST_DEBUG_OBJECT (v4l2sink, "already have caps set.. are they equal?");
-    LOG_CAPS (v4l2sink, v4l2sink->current_caps);
-    if (gst_caps_is_equal (v4l2sink->current_caps, caps)) {
-      GST_DEBUG_OBJECT (v4l2sink, "yes they are!");
-      return TRUE;
-    }
-    GST_DEBUG_OBJECT (v4l2sink, "no they aren't!");
-  }
-
   if (!gst_v4l2_object_stop (obj))
     goto stop_failed;
 
@@ -618,8 +603,6 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
   GST_VIDEO_SINK_WIDTH (v4l2sink) = v4l2sink->video_width;
   GST_VIDEO_SINK_HEIGHT (v4l2sink) = v4l2sink->video_height;
 
-  v4l2sink->current_caps = gst_caps_ref (caps);
-
   return TRUE;
 
   /* ERRORS */
@@ -642,9 +625,8 @@ gst_v4l2sink_setup_allocation (GstBaseSink * bsink, GstQuery * query)
   GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
   GstV4l2Object *obj = v4l2sink->v4l2object;
   GstBufferPool *pool;
-  GstStructure *config;
+  gsize size = 0;
   GstCaps *caps;
-  guint size = 0;
   gboolean need_pool;
 
   gst_query_parse_allocation (query, &caps, &need_pool);
@@ -652,11 +634,12 @@ gst_v4l2sink_setup_allocation (GstBaseSink * bsink, GstQuery * query)
   if (caps == NULL)
     goto no_caps;
 
-  if ((pool = GST_BUFFER_POOL_CAST (obj->pool)))
+  if ((pool = obj->pool))
     gst_object_ref (pool);
 
   if (pool != NULL) {
     const GstCaps *pcaps;
+    GstStructure *config;
 
     /* we had a pool, check caps */
     config = gst_buffer_pool_get_config (pool);
@@ -670,7 +653,7 @@ gst_v4l2sink_setup_allocation (GstBaseSink * bsink, GstQuery * query)
     }
   }
   /* we need at least 2 buffers to operate */
-  gst_query_set_allocation_params (query, size, 2, 0, 0, 15, pool);
+  gst_query_set_allocation_params (query, size, 2, 0, 0, 0, pool);
 
   /* we also support various metadata */
   gst_query_add_allocation_meta (query, GST_META_API_VIDEO);
@@ -708,7 +691,8 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
   if (G_UNLIKELY (obj->pool == NULL))
     goto not_negotiated;
 
-  ret = gst_v4l2_buffer_pool_process (obj->pool, buf);
+  ret =
+      gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool), buf);
 
   return ret;
 
index 05061cd..b461e2c 100644 (file)
@@ -55,7 +55,6 @@ struct _GstV4l2Sink {
   /*< private >*/
   GstV4l2Object * v4l2object;
   GstCaps *probed_caps;         /* all supported caps of underlying v4l2 device */
-  GstCaps *current_caps;        /* the current negotiated caps */
 
   gint video_width, video_height;      /* original (unscaled) video w/h */
 
index a9df8ef..eed82d1 100644 (file)
@@ -633,7 +633,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 = obj->pool->max_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,
@@ -759,7 +760,8 @@ gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf)
   }
 #endif
 
-  ret = gst_v4l2_buffer_pool_process (obj->pool, buf);
+  ret =
+      gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL_CAST (obj->pool), buf);
 
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto error;