v4l2: Move output details to device object
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 14 Jul 2011 14:12:15 +0000 (16:12 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 14 Jul 2011 14:12:15 +0000 (16:12 +0200)
Move the details of how a buffer is rendered to the device object.

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

index 46246f5..47c628a 100644 (file)
@@ -86,6 +86,8 @@ GstV4l2BufferPool * gst_v4l2_buffer_pool_new     (GstV4l2Object *obj, gint num_b
 void                gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool);
 
 GstBuffer *         gst_v4l2_buffer_pool_get     (GstV4l2BufferPool *pool, gboolean blocking);
+
+
 gboolean            gst_v4l2_buffer_pool_qbuf    (GstV4l2BufferPool *pool, GstBuffer *buf);
 GstBuffer *         gst_v4l2_buffer_pool_dqbuf   (GstV4l2BufferPool *pool);
 
index 243edc2..168e5bb 100644 (file)
@@ -2689,5 +2689,76 @@ gst_v4l2_object_get_buffer (GstV4l2Object * v4l2object, GstBuffer ** buf)
 GstFlowReturn
 gst_v4l2_object_output_buffer (GstV4l2Object * v4l2object, GstBuffer * buf)
 {
-  return GST_FLOW_ERROR;
+  GstBuffer *newbuf = NULL;
+  GstMetaV4l2 *meta;
+
+  meta = GST_META_V4L2_GET (buf);
+
+  if (meta == NULL || meta->pool != v4l2object->pool) {
+    guint8 *data;
+    gsize size;
+
+    /* not our buffer */
+    GST_DEBUG_OBJECT (v4l2object->element, "slow-path.. need to memcpy");
+    newbuf = gst_v4l2_buffer_pool_get (v4l2object->pool, TRUE);
+
+    if (v4l2object->info.finfo) {
+      GstVideoFrame src_frame, dest_frame;
+
+      GST_DEBUG_OBJECT (v4l2object->element, "copy video frame");
+      /* we have raw video, use videoframe copy to get strides right */
+      gst_video_frame_map (&src_frame, &v4l2object->info, buf, GST_MAP_READ);
+      gst_video_frame_map (&dest_frame, &v4l2object->info, newbuf,
+          GST_MAP_WRITE);
+
+      gst_video_frame_copy (&dest_frame, &src_frame);
+
+      gst_video_frame_unmap (&src_frame);
+      gst_video_frame_unmap (&dest_frame);
+    } else {
+      GST_DEBUG_OBJECT (v4l2object->element, "copy raw bytes");
+      data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+      gst_buffer_fill (newbuf, 0, data, size);
+      gst_buffer_unmap (buf, data, size);
+    }
+    GST_DEBUG_OBJECT (v4l2object->element, "render copied buffer: %p", newbuf);
+    buf = newbuf;
+  }
+
+  if (!gst_v4l2_buffer_pool_qbuf (v4l2object->pool, buf))
+    goto queue_failed;
+
+  if (!v4l2object->streaming) {
+    if (!gst_v4l2_object_start (v4l2object)) {
+      return GST_FLOW_ERROR;
+    }
+  }
+  if (!newbuf)
+    gst_buffer_ref (buf);
+
+  /* if the driver has more than one buffer, ie. more than just the one we
+   * just queued, then dequeue one immediately to make it available via
+   * _buffer_alloc():
+   */
+  if (gst_v4l2_buffer_pool_available_buffers (v4l2object->pool) >
+      v4l2object->min_queued_bufs) {
+    GstBuffer *v4l2buf = gst_v4l2_buffer_pool_dqbuf (v4l2object->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
+     * reference to it, and if no one else holds a ref it will be returned
+     * to the pool of available buffers..  and if not, we keep looping.
+     */
+    if (v4l2buf) {
+      gst_buffer_unref (v4l2buf);
+    }
+  }
+  return GST_FLOW_OK;
+
+  /* ERRORS */
+queue_failed:
+  {
+    GST_DEBUG_OBJECT (v4l2object->element, "failed to queue buffer");
+    return GST_FLOW_ERROR;
+  }
 }
index 218d43f..0b72f0f 100644 (file)
@@ -116,6 +116,7 @@ struct _GstV4l2Object {
 
   /* optional pool */
   guint32 num_buffers;
+  guint32 min_queued_bufs;
   gboolean always_copy;
   gboolean use_mmap;
   GstV4l2BufferPool *pool;
index 6c9ffb4..1ec96bd 100644 (file)
@@ -247,7 +247,7 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink)
 
   /* number of buffers requested */
   v4l2sink->v4l2object->num_buffers = PROP_DEF_QUEUE_SIZE;
-  v4l2sink->min_queued_bufs = PROP_DEF_MIN_QUEUED_BUFS;
+  v4l2sink->v4l2object->min_queued_bufs = PROP_DEF_MIN_QUEUED_BUFS;
 
   v4l2sink->probed_caps = NULL;
   v4l2sink->current_caps = NULL;
@@ -397,7 +397,7 @@ gst_v4l2sink_set_property (GObject * object,
         v4l2sink->v4l2object->num_buffers = g_value_get_uint (value);
         break;
       case PROP_MIN_QUEUED_BUFS:
-        v4l2sink->min_queued_bufs = g_value_get_uint (value);
+        v4l2sink->v4l2object->min_queued_bufs = g_value_get_uint (value);
         break;
       case PROP_OVERLAY_TOP:
         v4l2sink->overlay.top = g_value_get_int (value);
@@ -460,7 +460,7 @@ gst_v4l2sink_get_property (GObject * object,
         g_value_set_uint (value, v4l2sink->v4l2object->num_buffers);
         break;
       case PROP_MIN_QUEUED_BUFS:
-        g_value_set_uint (value, v4l2sink->min_queued_bufs);
+        g_value_set_uint (value, v4l2sink->v4l2object->min_queued_bufs);
         break;
       case PROP_OVERLAY_TOP:
         g_value_set_int (value, v4l2sink->overlay.top);
@@ -666,84 +666,15 @@ invalid_format:
 static GstFlowReturn
 gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
 {
+  GstFlowReturn ret;
   GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
-  GstBuffer *newbuf = NULL;
-  GstMetaV4l2 *meta;
   GstV4l2Object *obj = v4l2sink->v4l2object;
 
   GST_DEBUG_OBJECT (v4l2sink, "render buffer: %p", buf);
 
-  meta = GST_META_V4L2_GET (buf);
+  ret = gst_v4l2_object_output_buffer (obj, buf);
 
-  if (meta == NULL || meta->pool != obj->pool) {
-    guint8 *data;
-    gsize size;
-
-    /* not our buffer */
-    GST_DEBUG_OBJECT (v4l2sink, "slow-path.. need to memcpy");
-    newbuf = gst_v4l2_buffer_pool_get (obj->pool, TRUE);
-
-    if (obj->info.finfo) {
-      GstVideoFrame src_frame, dest_frame;
-
-      GST_DEBUG_OBJECT (v4l2sink, "copy video frame");
-      /* we have raw video, use videoframe copy to get strides right */
-      gst_video_frame_map (&src_frame, &obj->info, buf, GST_MAP_READ);
-      gst_video_frame_map (&dest_frame, &obj->info, newbuf, GST_MAP_WRITE);
-
-      gst_video_frame_copy (&dest_frame, &src_frame);
-
-      gst_video_frame_unmap (&src_frame);
-      gst_video_frame_unmap (&dest_frame);
-    } else {
-      GST_DEBUG_OBJECT (v4l2sink, "copy raw bytes");
-      data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
-      gst_buffer_fill (newbuf, 0, data, size);
-      gst_buffer_unmap (buf, data, size);
-    }
-    GST_DEBUG_OBJECT (v4l2sink, "render copied buffer: %p", newbuf);
-    buf = newbuf;
-  }
-
-  if (!gst_v4l2_buffer_pool_qbuf (obj->pool, buf))
-    goto queue_failed;
-
-  if (!obj->streaming) {
-    if (!gst_v4l2_object_start (obj)) {
-      return GST_FLOW_ERROR;
-    }
-  }
-
-  if (!newbuf) {
-    gst_buffer_ref (buf);
-  }
-
-  /* if the driver has more than one buffer, ie. more than just the one we
-   * just queued, then dequeue one immediately to make it available via
-   * _buffer_alloc():
-   */
-  if (gst_v4l2_buffer_pool_available_buffers (obj->pool) >
-      v4l2sink->min_queued_bufs) {
-    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
-     * reference to it, and if no one else holds a ref it will be returned
-     * to the pool of available buffers..  and if not, we keep looping.
-     */
-    if (v4l2buf) {
-      gst_buffer_unref (v4l2buf);
-    }
-  }
-
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-queue_failed:
-  {
-    GST_DEBUG_OBJECT (v4l2sink, "failed to queue buffer");
-    return GST_FLOW_ERROR;
-  }
+  return ret;
 }
 
 #ifdef HAVE_XVIDEO
index 9ac5902..05061cd 100644 (file)
@@ -57,8 +57,6 @@ struct _GstV4l2Sink {
   GstCaps *probed_caps;         /* all supported caps of underlying v4l2 device */
   GstCaps *current_caps;        /* the current negotiated caps */
 
-  guint32 min_queued_bufs;
-
   gint video_width, video_height;      /* original (unscaled) video w/h */
 
   /*