mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-12 10:25:33 +00:00
v4l2: Move output details to device object
Move the details of how a buffer is rendered to the device object.
This commit is contained in:
parent
7c5f5b1b7f
commit
33d93069c1
5 changed files with 81 additions and 78 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ struct _GstV4l2Object {
|
|||
|
||||
/* optional pool */
|
||||
guint32 num_buffers;
|
||||
guint32 min_queued_bufs;
|
||||
gboolean always_copy;
|
||||
gboolean use_mmap;
|
||||
GstV4l2BufferPool *pool;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue