From: Wim Taymans Date: Wed, 13 Jul 2011 16:32:00 +0000 (+0200) Subject: v4l2: move capture code to device object X-Git-Tag: 1.19.3~509^2~7755 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7c5f5b1b7f200689238ec9201a72b13d1bae3d36;p=platform%2Fupstream%2Fgstreamer.git v4l2: move capture code to device object Move the details of how to capture to the device object. Remove the v4l2src_calls.[ch] files because they are empty now. Provide two simple methods to get and return a buffer to the device. Also do a slow copy when the buffer is not from our pool. --- diff --git a/sys/v4l2/Makefile.am b/sys/v4l2/Makefile.am index 9cebead..edf336e 100644 --- a/sys/v4l2/Makefile.am +++ b/sys/v4l2/Makefile.am @@ -17,7 +17,6 @@ libgstvideo4linux2_la_SOURCES = gstv4l2.c \ gstv4l2tuner.c \ gstv4l2vidorient.c \ v4l2_calls.c \ - v4l2src_calls.c \ $(xv_source) libgstvideo4linux2_la_SOURCES += gstv4l2sink.c @@ -53,5 +52,4 @@ noinst_HEADERS = \ gstv4l2tuner.h \ gstv4l2vidorient.h \ gstv4l2xoverlay.h \ - v4l2_calls.h \ - v4l2src_calls.h + v4l2_calls.h diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index 583a094..243edc2 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -52,9 +52,9 @@ #endif GST_DEBUG_CATEGORY_EXTERN (v4l2_debug); +GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); #define GST_CAT_DEFAULT v4l2_debug - #define DEFAULT_PROP_DEVICE_NAME NULL #define DEFAULT_PROP_DEVICE_FD -1 #define DEFAULT_PROP_FLAGS 0 @@ -2430,3 +2430,264 @@ stop_failed: return FALSE; } } + +static GstFlowReturn +gst_v4l2_object_get_read (GstV4l2Object * v4l2object, GstBuffer ** buf) +{ + GstFlowReturn res; + gint amount; + gint ret; + gpointer data; + gint buffersize; + + buffersize = v4l2object->size; + + /* In case the size per frame is unknown assume it's a streaming format (e.g. + * mpegts) and grab a reasonable default size instead */ + if (buffersize == 0) + buffersize = 4096; + + *buf = gst_buffer_new_and_alloc (buffersize); + data = gst_buffer_map (*buf, NULL, NULL, GST_MAP_WRITE); + + do { + ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE); + if (G_UNLIKELY (ret < 0)) { + if (errno == EBUSY) + goto stopped; + if (errno == ENXIO) { + GST_DEBUG_OBJECT (v4l2object->element, + "v4l2 device doesn't support polling. Disabling"); + v4l2object->can_poll_device = FALSE; + } else { + if (errno != EAGAIN && errno != EINTR) + goto select_error; + } + } + amount = v4l2_read (v4l2object->video_fd, data, buffersize); + + if (amount == buffersize) { + break; + } else if (amount == -1) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } else + goto read_error; + } else { + /* short reads can happen if a signal interrupts the read */ + continue; + } + } while (TRUE); + + gst_buffer_unmap (*buf, data, amount); + + return GST_FLOW_OK; + + /* ERRORS */ +select_error: + { + GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ, (NULL), + ("select error %d: %s (%d)", ret, g_strerror (errno), errno)); + res = GST_FLOW_ERROR; + goto cleanup; + } +stopped: + { + GST_DEBUG ("stop called"); + res = GST_FLOW_WRONG_STATE; + goto cleanup; + } +read_error: + { + GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ, + (_("Error reading %d bytes from device '%s'."), + buffersize, v4l2object->videodev), GST_ERROR_SYSTEM); + res = GST_FLOW_ERROR; + goto cleanup; + } +cleanup: + { + gst_buffer_unmap (*buf, data, 0); + gst_buffer_unref (*buf); + return res; + } +} + +static GstFlowReturn +gst_v4l2_object_grab_frame (GstV4l2Object * v4l2object, GstBuffer ** buf) +{ +#define NUM_TRIALS 50 + GstV4l2BufferPool *pool; + gint32 trials = NUM_TRIALS; + GstBuffer *pool_buffer; + gboolean need_copy; + gint ret; + + pool = v4l2object->pool; + if (!pool) + goto no_buffer_pool; + + GST_DEBUG_OBJECT (v4l2object->element, "grab frame"); + + for (;;) { + if (v4l2object->can_poll_device) { + ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE); + if (G_UNLIKELY (ret < 0)) { + if (errno == EBUSY) + goto stopped; + if (errno == ENXIO) { + GST_DEBUG_OBJECT (v4l2object->element, + "v4l2 device doesn't support polling. Disabling"); + v4l2object->can_poll_device = FALSE; + } else { + if (errno != EAGAIN && errno != EINTR) + goto select_error; + } + } + } + + pool_buffer = gst_v4l2_buffer_pool_dqbuf (pool); + if (pool_buffer) + break; + + GST_WARNING_OBJECT (v4l2object->element, "trials=%d", trials); + + /* if the sync() got interrupted, we can retry */ + switch (errno) { + case EINVAL: + case ENOMEM: + /* fatal */ + return GST_FLOW_ERROR; + + case EAGAIN: + case EIO: + case EINTR: + default: + /* try again, until too many trials */ + break; + } + + /* check nr. of attempts to capture */ + if (--trials == -1) { + goto too_many_trials; + } + } + + /* if we are handing out the last buffer in the pool, we need to make a + * copy and bring the buffer back in the pool. */ + need_copy = v4l2object->always_copy + || !gst_v4l2_buffer_pool_available_buffers (pool); + + if (G_UNLIKELY (need_copy)) { + if (!v4l2object->always_copy) { + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2object->element, + "running out of buffers, making a copy to reuse current one"); + } + *buf = gst_buffer_copy (pool_buffer); + /* this will requeue */ + gst_buffer_unref (pool_buffer); + } else { + *buf = pool_buffer; + } + + return GST_FLOW_OK; + + /* ERRORS */ +no_buffer_pool: + { + GST_DEBUG_OBJECT (v4l2object->element, "no buffer pool"); + return GST_FLOW_WRONG_STATE; + } +select_error: + { + GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ, (NULL), + ("select error %d: %s (%d)", ret, g_strerror (errno), errno)); + return GST_FLOW_ERROR; + } +stopped: + { + GST_DEBUG ("stop called"); + return GST_FLOW_WRONG_STATE; + } +too_many_trials: + { + GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, FAILED, + (_("Failed trying to get video frames from device '%s'."), + v4l2object->videodev), + (_("Failed after %d tries. device %s. system error: %s"), + NUM_TRIALS, v4l2object->videodev, g_strerror (errno))); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +gst_v4l2_object_get_mmap (GstV4l2Object * v4l2object, GstBuffer ** buf) +{ + GstBuffer *temp; + GstFlowReturn ret; + guint size; + guint count = 0; + +again: + ret = gst_v4l2_object_grab_frame (v4l2object, &temp); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto done; + + if (v4l2object->size > 0) { + size = gst_buffer_get_size (temp); + + /* if size does not match what we expected, try again */ + if (size != v4l2object->size) { + GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, READ, + (_("Got unexpected frame size of %u instead of %u."), + size, v4l2object->size), (NULL)); + gst_buffer_unref (temp); + if (count++ > 50) + goto size_error; + + goto again; + } + } + + *buf = temp; +done: + return ret; + + /* ERRORS */ +size_error: + { + GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ, + (_("Error reading %d bytes on device '%s'."), + v4l2object->size, v4l2object->videodev), (NULL)); + return GST_FLOW_ERROR; + } +} + +GstFlowReturn +gst_v4l2_object_get_buffer (GstV4l2Object * v4l2object, GstBuffer ** buf) +{ + GstFlowReturn ret; + + switch (v4l2object->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (v4l2object->use_mmap) { + ret = gst_v4l2_object_get_mmap (v4l2object, buf); + } else { + ret = gst_v4l2_object_get_read (v4l2object, buf); + } + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + ret = GST_FLOW_ERROR; + break; + default: + ret = GST_FLOW_ERROR; + break; + } + return ret; +} + +GstFlowReturn +gst_v4l2_object_output_buffer (GstV4l2Object * v4l2object, GstBuffer * buf) +{ + return GST_FLOW_ERROR; +} diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index 555d2b4..218d43f 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -116,6 +116,7 @@ struct _GstV4l2Object { /* optional pool */ guint32 num_buffers; + gboolean always_copy; gboolean use_mmap; GstV4l2BufferPool *pool; @@ -215,8 +216,14 @@ GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc); gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, GstCaps * caps); -gboolean gst_v4l2_object_start (GstV4l2Object *v4l2object); -gboolean gst_v4l2_object_stop (GstV4l2Object *v4l2object); +gboolean gst_v4l2_object_start (GstV4l2Object *v4l2object); +gboolean gst_v4l2_object_stop (GstV4l2Object *v4l2object); + + +/* capture returns a filled buffer, output returns an empty buffer */ +GstFlowReturn gst_v4l2_object_get_buffer (GstV4l2Object * v4l2object, GstBuffer ** buf); +/* output the filled buffer */ +GstFlowReturn gst_v4l2_object_output_buffer (GstV4l2Object * v4l2object, GstBuffer * buf); #define GST_IMPLEMENT_V4L2_PROBE_METHODS(Type_Class, interface_as_function) \ diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c index 3ba2fbc..6c9ffb4 100644 --- a/sys/v4l2/gstv4l2sink.c +++ b/sys/v4l2/gstv4l2sink.c @@ -675,7 +675,7 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) meta = GST_META_V4L2_GET (buf); - if (meta == NULL) { + if (meta == NULL || meta->pool != obj->pool) { guint8 *data; gsize size; diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 6e6e95a..dac2d6a 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -48,9 +48,10 @@ #include #include -#include "v4l2src_calls.h" #include +#include "gstv4l2src.h" + #include "gstv4l2colorbalance.h" #include "gstv4l2tuner.h" #ifdef HAVE_XVIDEO @@ -129,12 +130,6 @@ static void gst_v4l2src_set_property (GObject * object, guint prop_id, static void gst_v4l2src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -/* get_frame io methods */ -static GstFlowReturn -gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf); -static GstFlowReturn -gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf); - static void gst_v4l2src_class_init (GstV4l2SrcClass * klass) { @@ -217,7 +212,7 @@ gst_v4l2src_init (GstV4l2Src * v4l2src) /* number of buffers requested */ v4l2src->v4l2object->num_buffers = PROP_DEF_QUEUE_SIZE; - v4l2src->always_copy = PROP_DEF_ALWAYS_COPY; + v4l2src->v4l2object->always_copy = PROP_DEF_ALWAYS_COPY; v4l2src->decimate = PROP_DEF_DECIMATE; gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME); @@ -259,7 +254,7 @@ gst_v4l2src_set_property (GObject * object, v4l2src->v4l2object->num_buffers = g_value_get_uint (value); break; case PROP_ALWAYS_COPY: - v4l2src->always_copy = g_value_get_boolean (value); + v4l2src->v4l2object->always_copy = g_value_get_boolean (value); break; case PROP_DECIMATE: v4l2src->decimate = g_value_get_int (value); @@ -284,7 +279,7 @@ gst_v4l2src_get_property (GObject * object, g_value_set_uint (value, v4l2src->v4l2object->num_buffers); break; case PROP_ALWAYS_COPY: - g_value_set_boolean (value, v4l2src->always_copy); + g_value_set_boolean (value, v4l2src->v4l2object->always_copy); break; case PROP_DECIMATE: g_value_set_int (value, v4l2src->decimate); @@ -526,12 +521,6 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) /* error already posted */ return FALSE; - if (obj->use_mmap) { - v4l2src->get_frame = gst_v4l2src_get_mmap; - } else { - v4l2src->get_frame = gst_v4l2src_get_read; - } - if (!gst_v4l2_object_start (obj)) return FALSE; @@ -690,151 +679,23 @@ gst_v4l2src_change_state (GstElement * element, GstStateChange transition) } static GstFlowReturn -gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf) -{ - GstFlowReturn res; - gint amount; - gint ret; - gpointer data; - gint buffersize; - - buffersize = v4l2src->frame_byte_size; - /* In case the size per frame is unknown assume it's a streaming format (e.g. - * mpegts) and grab a reasonable default size instead */ - if (buffersize == 0) - buffersize = GST_BASE_SRC (v4l2src)->blocksize; - - *buf = gst_buffer_new_and_alloc (buffersize); - data = gst_buffer_map (*buf, NULL, NULL, GST_MAP_WRITE); - - do { - ret = gst_poll_wait (v4l2src->v4l2object->poll, GST_CLOCK_TIME_NONE); - if (G_UNLIKELY (ret < 0)) { - if (errno == EBUSY) - goto stopped; - if (errno == ENXIO) { - GST_DEBUG_OBJECT (v4l2src, - "v4l2 device doesn't support polling. Disabling"); - v4l2src->v4l2object->can_poll_device = FALSE; - } else { - if (errno != EAGAIN && errno != EINTR) - goto select_error; - } - } - amount = v4l2_read (v4l2src->v4l2object->video_fd, data, buffersize); - - if (amount == buffersize) { - break; - } else if (amount == -1) { - if (errno == EAGAIN || errno == EINTR) { - continue; - } else - goto read_error; - } else { - /* short reads can happen if a signal interrupts the read */ - continue; - } - } while (TRUE); - - gst_buffer_unmap (*buf, data, amount); - - /* we set the buffer metadata in gst_v4l2src_create() */ - - return GST_FLOW_OK; - - /* ERRORS */ -select_error: - { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), - ("select error %d: %s (%d)", ret, g_strerror (errno), errno)); - res = GST_FLOW_ERROR; - goto cleanup; - } -stopped: - { - GST_DEBUG ("stop called"); - res = GST_FLOW_WRONG_STATE; - goto cleanup; - } -read_error: - { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, - (_("Error reading %d bytes from device '%s'."), - buffersize, v4l2src->v4l2object->videodev), GST_ERROR_SYSTEM); - res = GST_FLOW_ERROR; - goto cleanup; - } -cleanup: - { - gst_buffer_unmap (*buf, data, 0); - gst_buffer_unref (*buf); - return res; - } -} - -static GstFlowReturn -gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf) -{ - GstBuffer *temp; - GstFlowReturn ret; - guint size; - guint count = 0; - -again: - ret = gst_v4l2src_grab_frame (v4l2src, &temp); - if (G_UNLIKELY (ret != GST_FLOW_OK)) - goto done; - - if (v4l2src->frame_byte_size > 0) { - size = gst_buffer_get_size (temp); - - /* if size does not match what we expected, try again */ - if (size != v4l2src->frame_byte_size) { - GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ, - (_("Got unexpected frame size of %u instead of %u."), - size, v4l2src->frame_byte_size), (NULL)); - gst_buffer_unref (temp); - if (count++ > 50) - goto size_error; - - goto again; - } - } - - *buf = temp; -done: - return ret; - - /* ERRORS */ -size_error: - { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, - (_("Error reading %d bytes on device '%s'."), - v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL)); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf) { GstV4l2Src *v4l2src = GST_V4L2SRC (src); + GstV4l2Object *obj = v4l2src->v4l2object; int i; GstFlowReturn ret; - if (v4l2src->get_frame == NULL) - goto not_negotiated; - /* decimate, just capture and throw away frames */ for (i = 0; i < v4l2src->decimate - 1; i++) { - ret = v4l2src->get_frame (v4l2src, buf); + ret = gst_v4l2_object_get_buffer (obj, buf); if (ret != GST_FLOW_OK) { return ret; } gst_buffer_unref (*buf); } - ret = v4l2src->get_frame (v4l2src, buf); + ret = gst_v4l2_object_get_buffer (obj, buf); /* set buffer metadata */ if (G_LIKELY (ret == GST_FLOW_OK && *buf)) { @@ -857,7 +718,7 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf) } GST_OBJECT_UNLOCK (v4l2src); - duration = v4l2src->v4l2object->duration; + duration = obj->duration; if (G_LIKELY (clock)) { /* the time now is the time of the clock minus the base time */ @@ -891,13 +752,6 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf) GST_BUFFER_DURATION (*buf) = duration; } return ret; - - /* ERRORS */ -not_negotiated: - { - GST_DEBUG_OBJECT (src, "we are not negotiated"); - return GST_FLOW_NOT_NEGOTIATED; - } } diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h index 95aaaf3..03fd0dd 100644 --- a/sys/v4l2/gstv4l2src.h +++ b/sys/v4l2/gstv4l2src.h @@ -45,8 +45,6 @@ G_BEGIN_DECLS typedef struct _GstV4l2Src GstV4l2Src; typedef struct _GstV4l2SrcClass GstV4l2SrcClass; -typedef GstFlowReturn (*GstV4l2SrcGetFunc)(GstV4l2Src * v4l2src, GstBuffer ** buf); - /** * GstV4l2Src: * @@ -64,16 +62,11 @@ struct _GstV4l2Src guint32 frame_byte_size; - /* if the buffer will be or not used from directly mmap */ - gboolean always_copy; - int decimate; guint64 offset; GstClockTime ctrl_time; - - GstV4l2SrcGetFunc get_frame; }; struct _GstV4l2SrcClass diff --git a/sys/v4l2/gstv4l2tuner.c b/sys/v4l2/gstv4l2tuner.c index a805396..c885dc6 100644 --- a/sys/v4l2/gstv4l2tuner.c +++ b/sys/v4l2/gstv4l2tuner.c @@ -30,7 +30,6 @@ #include "gstv4l2tuner.h" #include "gstv4l2object.h" #include "v4l2_calls.h" -#include "v4l2src_calls.h" static void gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass * klass); diff --git a/sys/v4l2/gstv4l2vidorient.c b/sys/v4l2/gstv4l2vidorient.c index 1fa47e7..ee765b6 100644 --- a/sys/v4l2/gstv4l2vidorient.c +++ b/sys/v4l2/gstv4l2vidorient.c @@ -29,7 +29,6 @@ #include "gstv4l2vidorient.h" #include "gstv4l2object.h" #include "v4l2_calls.h" -#include "v4l2src_calls.h" GST_DEBUG_CATEGORY_STATIC (v4l2vo_debug); #define GST_CAT_DEFAULT v4l2vo_debug diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c deleted file mode 100644 index 148a5b7..0000000 --- a/sys/v4l2/v4l2src_calls.c +++ /dev/null @@ -1,167 +0,0 @@ -/* GStreamer - * - * Copyright (C) 2002 Ronald Bultje - * 2006 Edgard Lima - * - * v4l2src.c - system calls - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include "v4l2src_calls.h" -#include -#include -#ifdef __sun -/* Needed on older Solaris Nevada builds (72 at least) */ -#include -#include -#endif - -#include "gstv4l2tuner.h" -#include "gstv4l2bufferpool.h" - -#include "gst/gst-i18n-plugin.h" - -#define GST_CAT_DEFAULT v4l2src_debug -GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); - - -/****************************************************** - * gst_v4l2src_grab_frame (): - * grab a frame for capturing - * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR - ******************************************************/ -GstFlowReturn -gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf) -{ -#define NUM_TRIALS 50 - GstV4l2Object *v4l2object; - GstV4l2BufferPool *pool; - gint32 trials = NUM_TRIALS; - GstBuffer *pool_buffer; - gboolean need_copy; - gint ret; - - v4l2object = v4l2src->v4l2object; - pool = v4l2object->pool; - if (!pool) - goto no_buffer_pool; - - GST_DEBUG_OBJECT (v4l2src, "grab frame"); - - for (;;) { - if (v4l2object->can_poll_device) { - ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE); - if (G_UNLIKELY (ret < 0)) { - if (errno == EBUSY) - goto stopped; - if (errno == ENXIO) { - GST_DEBUG_OBJECT (v4l2src, - "v4l2 device doesn't support polling. Disabling"); - v4l2object->can_poll_device = FALSE; - } else { - if (errno != EAGAIN && errno != EINTR) - goto select_error; - } - } - } - - pool_buffer = gst_v4l2_buffer_pool_dqbuf (pool); - if (pool_buffer) - break; - - GST_WARNING_OBJECT (v4l2src, "trials=%d", trials); - - /* if the sync() got interrupted, we can retry */ - switch (errno) { - case EINVAL: - case ENOMEM: - /* fatal */ - return GST_FLOW_ERROR; - - case EAGAIN: - case EIO: - case EINTR: - default: - /* try again, until too many trials */ - break; - } - - /* check nr. of attempts to capture */ - if (--trials == -1) { - goto too_many_trials; - } - } - - /* if we are handing out the last buffer in the pool, we need to make a - * copy and bring the buffer back in the pool. */ - need_copy = v4l2src->always_copy - || !gst_v4l2_buffer_pool_available_buffers (pool); - - if (G_UNLIKELY (need_copy)) { - if (!v4l2src->always_copy) { - GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2src, - "running out of buffers, making a copy to reuse current one"); - } - *buf = gst_buffer_copy (pool_buffer); - /* this will requeue */ - gst_buffer_unref (pool_buffer); - } else { - *buf = pool_buffer; - } - /* we set the buffer metadata in gst_v4l2src_create() */ - - return GST_FLOW_OK; - - /* ERRORS */ -no_buffer_pool: - { - GST_DEBUG ("no buffer pool"); - return GST_FLOW_WRONG_STATE; - } -select_error: - { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL), - ("select error %d: %s (%d)", ret, g_strerror (errno), errno)); - return GST_FLOW_ERROR; - } -stopped: - { - GST_DEBUG ("stop called"); - return GST_FLOW_WRONG_STATE; - } -too_many_trials: - { - GST_ELEMENT_ERROR (v4l2src, RESOURCE, FAILED, - (_("Failed trying to get video frames from device '%s'."), - v4l2object->videodev), - (_("Failed after %d tries. device %s. system error: %s"), - NUM_TRIALS, v4l2object->videodev, g_strerror (errno))); - return GST_FLOW_ERROR; - } -} diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h deleted file mode 100644 index 5aa1d23..0000000 --- a/sys/v4l2/v4l2src_calls.h +++ /dev/null @@ -1,32 +0,0 @@ -/* GStreamer - * - * Copyright (C) 2002 Ronald Bultje - * 2006 Edgard Lima - * - * v4l2src.h - system calls - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __V4L2SRC_CALLS_H__ -#define __V4L2SRC_CALLS_H__ - -#include "gstv4l2src.h" -#include "v4l2_calls.h" - -GstFlowReturn gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer **buf); - -#endif /* __V4L2SRC_CALLS_H__ */